Repository: cxf Updated Branches: refs/heads/master c33e0e75c -> 25671bd28
[CXF-5902] Prototyping the code for making AecCbcHmac encryption work in a streaming mode Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/25671bd2 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/25671bd2 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/25671bd2 Branch: refs/heads/master Commit: 25671bd28d08bf78f64e5edc292d58d75dd7296f Parents: c33e0e7 Author: Sergey Beryozkin <[email protected]> Authored: Fri Aug 1 17:56:17 2014 +0300 Committer: Sergey Beryozkin <[email protected]> Committed: Fri Aug 1 17:56:17 2014 +0300 ---------------------------------------------------------------------- .../oauth2/jwe/AbstractJweEncryption.java | 12 +++- .../oauth2/jwe/AesCbcHmacJweEncryption.java | 67 ++++++++++++++++---- .../oauth2/jwe/AuthenticationTagProducer.java | 24 +++++++ .../security/oauth2/jwe/JweEncryptionState.java | 17 +++-- .../rs/security/oauth2/jwe/JweOutputStream.java | 22 +++++-- .../oauth2/jwt/jaxrs/JweWriterInterceptor.java | 2 +- 6 files changed, 115 insertions(+), 29 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/25671bd2/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/AbstractJweEncryption.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/AbstractJweEncryption.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/AbstractJweEncryption.java index 133b432..1d0f8eb 100644 --- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/AbstractJweEncryption.java +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/AbstractJweEncryption.java @@ -117,10 +117,16 @@ public abstract class AbstractJweEncryption implements JweEncryptionProvider { JweEncryptionInternal state = getInternalState(contentType); Cipher c = CryptoUtils.initCipher(createCekSecretKey(state), state.keyProps, Cipher.ENCRYPT_MODE); - return new JweEncryptionState(c, getAuthTagLen(), state.theHeaders, state.jweContentEncryptionKey, - state.theIv, state.keyProps.isCompressionSupported()); + return new JweEncryptionState(c, + state.theHeaders, + state.jweContentEncryptionKey, + state.theIv, + getAuthenticationTagProducer(state), + state.keyProps.isCompressionSupported()); + } + protected AuthenticationTagProducer getAuthenticationTagProducer(JweEncryptionInternal state) { + return null; } - protected SecretKey createCekSecretKey(JweEncryptionInternal state) { return CryptoUtils.createSecretKeySpec(getActualCek(state.secretKey), state.keyProps.getKeyAlgo()); } http://git-wip-us.apache.org/repos/asf/cxf/blob/25671bd2/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/AesCbcHmacJweEncryption.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/AesCbcHmacJweEncryption.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/AesCbcHmacJweEncryption.java index 3f16b15..c40a7dc 100644 --- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/AesCbcHmacJweEncryption.java +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/AesCbcHmacJweEncryption.java @@ -82,6 +82,28 @@ public class AesCbcHmacJweEncryption extends AbstractJweEncryption { } protected JweCompactProducer getJweCompactProducer(JweEncryptionInternal state, byte[] cipher) { + final MacState macState = getInitializedMacState(state); + + macState.mac.update(cipher); + macState.mac.update(macState.al); + byte[] sig = macState.mac.doFinal(); + byte[] authTag = getTagFromSignature(sig); + + return new JweCompactProducer(macState.headersJson, + state.jweContentEncryptionKey, + state.theIv, + cipher, + authTag); + } + + private byte[] getTagFromSignature(byte[] sig) { + int authTagLen = getAuthTagLen() / 8; + byte[] authTag = new byte[authTagLen]; + System.arraycopy(sig, 0, authTag, 0, authTagLen); + return authTag; + } + + private MacState getInitializedMacState(final JweEncryptionInternal state) { int size = getCekKeySize() / 2; byte[] macKey = new byte[size]; System.arraycopy(state.secretKey, 0, macKey, 0, size); @@ -92,24 +114,37 @@ public class AesCbcHmacJweEncryption extends AbstractJweEncryption { String headersJson = getJwtHeadersWriter().headersToJson(state.theHeaders); byte[] aad = JweHeaders.toCipherAdditionalAuthData(headersJson); ByteBuffer buf = ByteBuffer.allocate(8); - byte[] al = buf.putInt(0).putInt(aad.length * 8).array(); + final byte[] al = buf.putInt(0).putInt(aad.length * 8).array(); mac.update(aad); mac.update(state.theIv); - mac.update(cipher); - mac.update(al); - byte[] sig = mac.doFinal(); - int authTagLen = getAuthTagLen() / 8; - byte[] authTag = new byte[authTagLen]; - System.arraycopy(sig, 0, authTag, 0, authTagLen); - - return new JweCompactProducer(headersJson, - state.jweContentEncryptionKey, - state.theIv, - cipher, - authTag); + MacState macState = new MacState(); + macState.mac = mac; + macState.al = al; + macState.headersJson = headersJson; + return macState; } + protected AuthenticationTagProducer getAuthenticationTagProducer(final JweEncryptionInternal state) { + final MacState macState = getInitializedMacState(state); + + + return new AuthenticationTagProducer() { + + @Override + public void update(byte[] cipher, int off, int len) { + macState.mac.update(cipher, off, len); + } + + @Override + public byte[] getTag() { + macState.mac.update(macState.al); + byte[] sig = macState.mac.doFinal(); + return getTagFromSignature(sig); + } + + }; + } protected byte[] getEncryptedContentEncryptionKey(byte[] theCek) { return getKeyEncryptionAlgo().getEncryptedContentEncryptionKey(getJweHeaders(), theCek); @@ -128,4 +163,10 @@ public class AesCbcHmacJweEncryption extends AbstractJweEncryption { return null; } } + + private static class MacState { + private Mac mac; + private byte[] al; + private String headersJson; + } } http://git-wip-us.apache.org/repos/asf/cxf/blob/25671bd2/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/AuthenticationTagProducer.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/AuthenticationTagProducer.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/AuthenticationTagProducer.java new file mode 100644 index 0000000..676d7a3 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/AuthenticationTagProducer.java @@ -0,0 +1,24 @@ +/** + * 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.jwe; + +public interface AuthenticationTagProducer { + void update(byte[] cipher, int off, int len); + byte[] getTag(); +} http://git-wip-us.apache.org/repos/asf/cxf/blob/25671bd2/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweEncryptionState.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweEncryptionState.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweEncryptionState.java index 98db5f0..9397549 100644 --- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweEncryptionState.java +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweEncryptionState.java @@ -22,20 +22,23 @@ import javax.crypto.Cipher; public class JweEncryptionState { private Cipher cipher; - private int authTagLen; private JweHeaders headers; private byte[] contentEncryptionKey; private byte[] iv; private boolean compressionSupported; + private AuthenticationTagProducer authTagProducer; - public JweEncryptionState(Cipher cipher, int authTagLen, JweHeaders headers, - byte[] contentEncryptionKey, - byte[] iv, boolean compressionSupported) { + public JweEncryptionState(Cipher cipher, + JweHeaders headers, + byte[] contentEncryptionKey, + byte[] iv, + AuthenticationTagProducer authTagProducer, + boolean compressionSupported) { this.cipher = cipher; - this.authTagLen = authTagLen; this.headers = headers; this.contentEncryptionKey = contentEncryptionKey; this.iv = iv; + this.authTagProducer = authTagProducer; this.compressionSupported = compressionSupported; } public Cipher getCipher() { @@ -53,8 +56,8 @@ public class JweEncryptionState { public boolean isCompressionSupported() { return compressionSupported; } - public int getAuthTagLen() { - return authTagLen; + public AuthenticationTagProducer getAuthTagProducer() { + return authTagProducer; } } http://git-wip-us.apache.org/repos/asf/cxf/blob/25671bd2/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 324ca22..4730a51 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 @@ -30,15 +30,17 @@ import org.apache.cxf.rs.security.oauth2.utils.Base64UrlUtility; public class JweOutputStream extends FilterOutputStream { private Cipher encryptingCipher; private int blockSize; - private int authTagLengthBits; + private AuthenticationTagProducer authTagProducer; private byte[] lastRawDataChunk; private byte[] lastEncryptedDataChunk; private boolean flushed; - public JweOutputStream(OutputStream out, Cipher encryptingCipher, int authTagLengthBits) { + public JweOutputStream(OutputStream out, + Cipher encryptingCipher, + AuthenticationTagProducer authTagProducer) { super(out); this.encryptingCipher = encryptingCipher; this.blockSize = encryptingCipher.getBlockSize(); - this.authTagLengthBits = authTagLengthBits; + this.authTagProducer = authTagProducer; } @Override @@ -106,9 +108,19 @@ public class JweOutputStream extends FilterOutputStream { byte[] finalBytes = lastRawDataChunk == null ? encryptingCipher.doFinal() : encryptingCipher.doFinal(lastRawDataChunk, 0, lastRawDataChunk.length); - encodeAndWrite(finalBytes, 0, finalBytes.length - authTagLengthBits / 8, true); + final int authTagLengthBits = 128; + if (authTagProducer == null) { + encodeAndWrite(finalBytes, 0, finalBytes.length - authTagLengthBits / 8, true); + } else { + authTagProducer.update(finalBytes, 0, finalBytes.length); + } out.write(new byte[]{'.'}); - encodeAndWrite(finalBytes, finalBytes.length - authTagLengthBits / 8, authTagLengthBits / 8, true); + if (authTagProducer == null) { + encodeAndWrite(finalBytes, finalBytes.length - authTagLengthBits / 8, authTagLengthBits / 8, true); + } else { + byte[] authTag = authTagProducer.getTag(); + encodeAndWrite(authTag, 0, authTagLengthBits / 8, true); + } } catch (Exception ex) { throw new SecurityException(); } http://git-wip-us.apache.org/repos/asf/cxf/blob/25671bd2/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JweWriterInterceptor.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JweWriterInterceptor.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JweWriterInterceptor.java index 7fcf683..238c8a2 100644 --- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JweWriterInterceptor.java +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/jaxrs/JweWriterInterceptor.java @@ -88,7 +88,7 @@ public class JweWriterInterceptor implements WriterInterceptor { throw new SecurityException(ex); } OutputStream jweStream = new JweOutputStream(actualOs, encryption.getCipher(), - encryption.getAuthTagLen()); + encryption.getAuthTagProducer()); if (encryption.isCompressionSupported()) { jweStream = new DeflaterOutputStream(jweStream); }
