You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2014/07/10 14:42:16 UTC

git commit: [CXF-5311] Quick prototyping of JwsOutputStream, refactorings will follow

Repository: cxf
Updated Branches:
  refs/heads/master 7683d0551 -> 22dbf10ed


[CXF-5311] Quick prototyping of JwsOutputStream, refactorings will follow


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/22dbf10e
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/22dbf10e
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/22dbf10e

Branch: refs/heads/master
Commit: 22dbf10ed281f3ec94b159829e21333f4afc0bf9
Parents: 7683d05
Author: Sergey Beryozkin <sb...@talend.com>
Authored: Thu Jul 10 13:41:56 2014 +0100
Committer: Sergey Beryozkin <sb...@talend.com>
Committed: Thu Jul 10 13:41:56 2014 +0100

----------------------------------------------------------------------
 .../security/oauth2/jwe/JweCompactProducer.java |  7 +-
 .../rs/security/oauth2/jwe/JweOutputStream.java |  2 +-
 .../jws/AbstractJwsSignatureProvider.java       | 33 ++++++-
 .../oauth2/jws/HmacJwsSignatureProvider.java    | 21 ++++-
 .../rs/security/oauth2/jws/JwsOutputStream.java | 98 ++++++++++++++++++++
 .../oauth2/jws/JwsSignatureProvider.java        |  5 +-
 .../oauth2/jws/JwsSignatureProviderWorker.java  | 25 +++++
 .../jws/PrivateKeyJwsSignatureProvider.java     | 33 ++++++-
 .../oauth2/jwt/jaxrs/JwsWriterInterceptor.java  | 33 +++++--
 .../oauth2/utils/crypto/CryptoUtils.java        | 14 ++-
 10 files changed, 250 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/22dbf10e/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweCompactProducer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweCompactProducer.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweCompactProducer.java
index 72d3d84..365a986 100644
--- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweCompactProducer.java
+++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweCompactProducer.java
@@ -112,12 +112,13 @@ public class JweCompactProducer {
         writer = writer == null ? new JwtTokenReaderWriter() : writer;
         byte[] jsonBytes = writer.headersToJson(headers).getBytes("UTF-8");
         Base64UrlUtility.encodeAndStream(jsonBytes, 0, jsonBytes.length, os);
-        os.write('.');
+        byte[] dotBytes = new byte[]{'.'};
+        os.write(dotBytes);
         Base64UrlUtility.encodeAndStream(encryptedContentEncryptionKey, 0, 
                                          encryptedContentEncryptionKey.length, os);
-        os.write('.');
+        os.write(dotBytes);
         Base64UrlUtility.encodeAndStream(cipherInitVector, 0, cipherInitVector.length, os);
-        os.write('.');         
+        os.write(dotBytes);         
     }
     
     public String getJweContent() {

http://git-wip-us.apache.org/repos/asf/cxf/blob/22dbf10e/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweOutputStream.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweOutputStream.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweOutputStream.java
index ebf80df..91b68b0 100644
--- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweOutputStream.java
+++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweOutputStream.java
@@ -106,7 +106,7 @@ public class JweOutputStream extends FilterOutputStream {
                 ? encryptingCipher.doFinal()
                 : encryptingCipher.doFinal(lastRawDataChunk, 0, lastRawDataChunk.length);
             encodeAndWrite(finalBytes, 0, finalBytes.length - authTagLengthBits / 8, true);
-            out.write('.');
+            out.write(new byte[]{'.'});
             encodeAndWrite(finalBytes, finalBytes.length - authTagLengthBits / 8, authTagLengthBits / 8, true);
         } catch (Exception ex) {
             throw new SecurityException();

http://git-wip-us.apache.org/repos/asf/cxf/blob/22dbf10e/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/AbstractJwsSignatureProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/AbstractJwsSignatureProvider.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/AbstractJwsSignatureProvider.java
index 83563be..dc63a1e 100644
--- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/AbstractJwsSignatureProvider.java
+++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/AbstractJwsSignatureProvider.java
@@ -18,27 +18,54 @@
  */
 package org.apache.cxf.rs.security.oauth2.jws;
 
+import java.io.OutputStream;
 import java.util.Set;
 
+import org.apache.cxf.common.util.Base64Utility;
 import org.apache.cxf.rs.security.oauth2.jwt.JwtHeaders;
+import org.apache.cxf.rs.security.oauth2.jwt.JwtTokenReaderWriter;
 
 public abstract class AbstractJwsSignatureProvider implements JwsSignatureProvider {
     private Set<String> supportedAlgorithms;
     private String defaultJwtAlgorithm;
     
-    public AbstractJwsSignatureProvider(Set<String> supportedAlgorithms) {
+    protected AbstractJwsSignatureProvider(Set<String> supportedAlgorithms) {
         this.supportedAlgorithms = supportedAlgorithms;
     }
     @Override
-    public void prepareHeaders(JwtHeaders headers) {
+    public JwtHeaders prepareHeaders(JwtHeaders headers) {
+        if (headers == null) {
+            headers = new JwtHeaders();
+        }
         String algo = headers.getAlgorithm();
         if (algo != null) {
             checkAlgorithm(algo);
         } else {
             headers.setAlgorithm(defaultJwtAlgorithm);
         }
-        
+        return headers;
+    }
+    
+    @Override
+    public JwsOutputStream createJwsStream(OutputStream os, String contentType) {
+        JwtHeaders headers = new JwtHeaders();
+        if (contentType != null) {
+            headers.setContentType(contentType);
+        }
+        headers = prepareHeaders(headers);
+        JwsSignatureProviderWorker worker = createJwsSignatureWorker(headers);
+        try {
+            byte[] headerBytes = new JwtTokenReaderWriter().headersToJson(headers).getBytes("UTF-8");
+            Base64Utility.encodeAndStream(headerBytes, 0, headerBytes.length, os);
+            os.write(new byte[]{'.'});
+        } catch (Exception ex) {
+            throw new SecurityException(ex);
+        }
+        return new JwsOutputStream(os, worker);
     }
+    
+    protected abstract JwsSignatureProviderWorker createJwsSignatureWorker(JwtHeaders headers);
+    
     public void setDefaultJwtAlgorithm(String algo) {
         this.defaultJwtAlgorithm = algo;
     }

http://git-wip-us.apache.org/repos/asf/cxf/blob/22dbf10e/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/HmacJwsSignatureProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/HmacJwsSignatureProvider.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/HmacJwsSignatureProvider.java
index ed4c00f..6bb1e0d 100644
--- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/HmacJwsSignatureProvider.java
+++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/HmacJwsSignatureProvider.java
@@ -22,6 +22,8 @@ import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Set;
 
+import javax.crypto.Mac;
+
 import org.apache.cxf.common.util.Base64Exception;
 import org.apache.cxf.rs.security.oauth2.jwt.Algorithm;
 import org.apache.cxf.rs.security.oauth2.jwt.JwtHeaders;
@@ -50,7 +52,7 @@ public class HmacJwsSignatureProvider extends AbstractJwsSignatureProvider imple
     
     @Override
     public byte[] sign(JwtHeaders headers, String unsignedText) {
-        checkAlgorithm(headers.getAlgorithm());
+        headers = prepareHeaders(headers);
         return computeMac(headers, unsignedText);
     }
     
@@ -65,5 +67,22 @@ public class HmacJwsSignatureProvider extends AbstractJwsSignatureProvider imple
                                      Algorithm.toJavaName(headers.getAlgorithm()), 
                                      text);
     }
+    @Override
+    protected JwsSignatureProviderWorker createJwsSignatureWorker(JwtHeaders headers) {
+        final Mac mac = HmacUtils.getMac(Algorithm.toJavaName(headers.getAlgorithm()));
+        return new JwsSignatureProviderWorker() {
+
+            @Override
+            public void update(byte[] src, int off, int len) {
+                mac.update(src, off, len);
+            }
+
+            @Override
+            public byte[] sign() {
+                return mac.doFinal();
+            }
+            
+        };
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/22dbf10e/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/JwsOutputStream.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/JwsOutputStream.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/JwsOutputStream.java
new file mode 100644
index 0000000..8c7734d
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/JwsOutputStream.java
@@ -0,0 +1,98 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.oauth2.jws;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+import org.apache.cxf.rs.security.oauth2.utils.Base64UrlUtility;
+
+public class JwsOutputStream extends FilterOutputStream {
+    private byte[] lastNonEncodedDataChunk;
+    private boolean flushed;
+    private JwsSignatureProviderWorker signature;
+    public JwsOutputStream(OutputStream out, JwsSignatureProviderWorker signature) {
+        super(out);
+        this.signature = signature;
+    }
+
+    @Override
+    public void write(int value) throws IOException {
+        byte[] bytes = ByteBuffer.allocate(Integer.SIZE / 8).putInt(value).array();
+        write(bytes, 0, bytes.length);
+    }
+    
+    @Override
+    public void write(byte b[], int off, int len) throws IOException {
+        try {
+            signature.update(b, off, len);
+        } catch (Throwable ex) {
+            throw new SecurityException();
+        }
+        encodeAndWrite(b, off, len, false);
+    }
+    
+    private void encodeAndWrite(byte[] encryptedChunk, int off, int len, boolean finalWrite) throws IOException {
+        byte[] theChunk = lastNonEncodedDataChunk;
+        int lenToEncode = len;
+        if (theChunk != null) {
+            theChunk = newArray(theChunk, 0, theChunk.length, encryptedChunk, off, len);
+            lenToEncode = theChunk.length;
+            off = 0;
+        } else {
+            theChunk = encryptedChunk;
+        }
+        int rem = finalWrite ? 0 : lenToEncode % 3; 
+        Base64UrlUtility.encodeAndStream(theChunk, off, lenToEncode - rem, out);
+        
+        if (rem > 0) {
+            lastNonEncodedDataChunk = newArray(theChunk, lenToEncode - rem, rem);
+        } else {
+            lastNonEncodedDataChunk = null;
+        }
+    }
+    
+    @Override
+    public void flush() throws IOException {
+        if (flushed) {
+            return;
+        }
+        try {
+            byte[] finalBytes = signature.sign();
+            out.write('.');
+            encodeAndWrite(finalBytes, 0, finalBytes.length, true);
+        } catch (Exception ex) {
+            throw new SecurityException();
+        }
+        flushed = true;
+    }
+    private byte[] newArray(byte[] src, int srcPos, int srcLen) {
+        byte[] buf = new byte[srcLen];
+        System.arraycopy(src, srcPos, buf, 0, srcLen);
+        return buf;
+    }
+    private byte[] newArray(byte[] src, int srcPos, int srcLen, byte[] src2, int srcPos2, int srcLen2) {
+        byte[] buf = new byte[srcLen + srcLen2];
+        System.arraycopy(src, srcPos, buf, 0, srcLen);
+        System.arraycopy(src2, srcPos2, buf, srcLen, srcLen2);
+        return buf;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/22dbf10e/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/JwsSignatureProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/JwsSignatureProvider.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/JwsSignatureProvider.java
index 6fe5e3c..4f97f91 100644
--- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/JwsSignatureProvider.java
+++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/JwsSignatureProvider.java
@@ -18,9 +18,12 @@
  */
 package org.apache.cxf.rs.security.oauth2.jws;
 
+import java.io.OutputStream;
+
 import org.apache.cxf.rs.security.oauth2.jwt.JwtHeaders;
 
 public interface JwsSignatureProvider {
-    void prepareHeaders(JwtHeaders headers);
+    JwtHeaders prepareHeaders(JwtHeaders headers);
     byte[] sign(JwtHeaders headers, String unsignedText);
+    JwsOutputStream createJwsStream(OutputStream os, String contentType);
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/22dbf10e/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/JwsSignatureProviderWorker.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/JwsSignatureProviderWorker.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/JwsSignatureProviderWorker.java
new file mode 100644
index 0000000..ca768d5
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/JwsSignatureProviderWorker.java
@@ -0,0 +1,25 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.oauth2.jws;
+
+
+public interface JwsSignatureProviderWorker {
+    void update(byte[] src, int off, int len);
+    byte[] sign();
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/22dbf10e/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/PrivateKeyJwsSignatureProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/PrivateKeyJwsSignatureProvider.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/PrivateKeyJwsSignatureProvider.java
index cbfd21e..7d34fac 100644
--- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/PrivateKeyJwsSignatureProvider.java
+++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jws/PrivateKeyJwsSignatureProvider.java
@@ -20,6 +20,8 @@ package org.apache.cxf.rs.security.oauth2.jws;
 
 import java.security.PrivateKey;
 import java.security.SecureRandom;
+import java.security.Signature;
+import java.security.SignatureException;
 import java.security.spec.AlgorithmParameterSpec;
 import java.util.Arrays;
 import java.util.HashSet;
@@ -51,10 +53,9 @@ public class PrivateKeyJwsSignatureProvider extends AbstractJwsSignatureProvider
         this.signatureSpec = spec;
     }
     
-    
     @Override
     public byte[] sign(JwtHeaders headers, String unsignedText) {
-        checkAlgorithm(headers.getAlgorithm());
+        headers = prepareHeaders(headers);
         try {
             return CryptoUtils.signData(unsignedText.getBytes("UTF-8"), 
                                         key, 
@@ -65,6 +66,34 @@ public class PrivateKeyJwsSignatureProvider extends AbstractJwsSignatureProvider
             throw new SecurityException(ex);
         }
     }
+    @Override
+    protected JwsSignatureProviderWorker createJwsSignatureWorker(JwtHeaders headers) {
+        final Signature s = CryptoUtils.getSignature(key, 
+                                                     Algorithm.toJavaName(headers.getAlgorithm()),
+                                                     random,
+                                                     signatureSpec);
+        return new JwsSignatureProviderWorker() {
+
+            @Override
+            public void update(byte[] src, int off, int len) {
+                try {
+                    s.update(src, off, len);
+                } catch (SignatureException ex) {
+                    throw new SecurityException();
+                }
+            }
+
+            @Override
+            public byte[] sign() {
+                try {
+                    return s.sign();
+                } catch (SignatureException ex) {
+                    throw new SecurityException();
+                }
+            }
+            
+        };
+    }
     
 
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/22dbf10e/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsWriterInterceptor.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsWriterInterceptor.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsWriterInterceptor.java
index 62c4126..c672e29 100644
--- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsWriterInterceptor.java
+++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JwsWriterInterceptor.java
@@ -30,30 +30,47 @@ import javax.ws.rs.ext.WriterInterceptorContext;
 import org.apache.cxf.io.CachedOutputStream;
 import org.apache.cxf.jaxrs.utils.JAXRSUtils;
 import org.apache.cxf.rs.security.oauth2.jws.JwsCompactProducer;
+import org.apache.cxf.rs.security.oauth2.jws.JwsOutputStream;
 import org.apache.cxf.rs.security.oauth2.jwt.JwtHeaders;
 
 @Priority(Priorities.JWS_WRITE_PRIORITY)
 public class JwsWriterInterceptor extends AbstractJwsWriterProvider implements WriterInterceptor {
     private boolean contentTypeRequired = true;
+    private boolean useJwsOutputStream;
     @Override
     public void aroundWriteTo(WriterInterceptorContext ctx) throws IOException, WebApplicationException {
         OutputStream actualOs = ctx.getOutputStream();
-        CachedOutputStream cos = new CachedOutputStream(); 
-        ctx.setOutputStream(cos);
-        ctx.proceed();
-        
-        JwtHeaders headers = new JwtHeaders();
+        String ctString = null;
         if (contentTypeRequired) {
             MediaType mt = ctx.getMediaType();
             if (mt != null) {
-                headers.setContentType(JAXRSUtils.mediaTypeToString(mt));
+                ctString = JAXRSUtils.mediaTypeToString(mt);
+            }
+        }
+        if (useJwsOutputStream) {
+            JwsOutputStream cos = getInitializedSigProvider().createJwsStream(actualOs, ctString);
+            ctx.setOutputStream(cos);
+            ctx.proceed();
+            cos.flush();
+        } else {
+            CachedOutputStream cos = new CachedOutputStream(); 
+            ctx.setOutputStream(cos);
+            ctx.proceed();
+            
+            JwtHeaders headers = new JwtHeaders();
+            if (ctString != null) {
+                headers.setContentType(ctString);
             }
+            JwsCompactProducer p = new JwsCompactProducer(headers, new String(cos.getBytes(), "UTF-8"));
+            writeJws(p, actualOs);
         }
-        JwsCompactProducer p = new JwsCompactProducer(headers, new String(cos.getBytes(), "UTF-8"));
-        writeJws(p, actualOs);
     }
     public void setContentTypeRequired(boolean contentTypeRequired) {
         this.contentTypeRequired = contentTypeRequired;
     }
+    
+    public void setUseJwsOutputStream(boolean useJwsOutputStream) {
+        this.useJwsOutputStream = useJwsOutputStream;
+    }
         
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/22dbf10e/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/crypto/CryptoUtils.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/crypto/CryptoUtils.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/crypto/CryptoUtils.java
index 76b62aa..1030240 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/crypto/CryptoUtils.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/crypto/CryptoUtils.java
@@ -303,6 +303,17 @@ public final class CryptoUtils {
     public static byte[] signData(byte[] data, PrivateKey key, String signAlgo, SecureRandom random,
                            AlgorithmParameterSpec params) {
         try {
+            Signature s = getSignature(key, signAlgo, random, params);
+            s.update(data);
+            return s.sign();
+        } catch (Exception ex) {
+            throw new SecurityException(ex);
+        }
+    }
+    
+    public static Signature getSignature(PrivateKey key, String signAlgo, SecureRandom random,
+                                  AlgorithmParameterSpec params) {
+        try {
             Signature s = Signature.getInstance(signAlgo);
             if (random == null) {
                 s.initSign(key);
@@ -312,8 +323,7 @@ public final class CryptoUtils {
             if (params != null) {
                 s.setParameter(params);
             }
-            s.update(data);
-            return s.sign();
+            return s;
         } catch (Exception ex) {
             throw new SecurityException(ex);
         }