http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractJweDecryption.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractJweDecryption.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractJweDecryption.java new file mode 100644 index 0000000..e2e1ac7 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractJweDecryption.java @@ -0,0 +1,108 @@ +/** + * 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.jose.jwe; + +import java.security.Key; +import java.security.spec.AlgorithmParameterSpec; + +import org.apache.cxf.rs.security.jose.jwa.Algorithm; +import org.apache.cxf.rs.security.jose.jwt.JwtConstants; +import org.apache.cxf.rs.security.jose.jwt.JwtHeadersReader; +import org.apache.cxf.rs.security.jose.jwt.JwtTokenReaderWriter; +import org.apache.cxf.rs.security.oauth2.utils.crypto.CryptoUtils; +import org.apache.cxf.rs.security.oauth2.utils.crypto.KeyProperties; + +public abstract class AbstractJweDecryption implements JweDecryptionProvider { + private JweCryptoProperties props; + private KeyDecryptionAlgorithm keyDecryptionAlgo; + private ContentDecryptionAlgorithm contentDecryptionAlgo; + private JwtHeadersReader reader = new JwtTokenReaderWriter(); + protected AbstractJweDecryption(JweCryptoProperties props, + JwtHeadersReader theReader, + KeyDecryptionAlgorithm keyDecryptionAlgo, + ContentDecryptionAlgorithm contentDecryptionAlgo) { + this.props = props; + if (theReader != null) { + reader = theReader; + } + this.keyDecryptionAlgo = keyDecryptionAlgo; + this.contentDecryptionAlgo = contentDecryptionAlgo; + } + + protected byte[] getContentEncryptionKey(JweCompactConsumer consumer) { + return this.keyDecryptionAlgo.getDecryptedContentEncryptionKey(consumer); + } + + public JweDecryptionOutput decrypt(String content) { + JweCompactConsumer consumer = new JweCompactConsumer(content, reader); + return doDecrypt(consumer); + } + public byte[] decrypt(JweCompactConsumer consumer) { + return doDecrypt(consumer).getContent(); + } + + protected JweDecryptionOutput doDecrypt(JweCompactConsumer consumer) { + consumer.enforceJweCryptoProperties(props); + byte[] cek = getContentEncryptionKey(consumer); + return doDecrypt(consumer, cek); + } + protected JweDecryptionOutput doDecrypt(JweCompactConsumer consumer, byte[] cek) { + KeyProperties keyProperties = new KeyProperties(getContentEncryptionAlgorithm(consumer)); + keyProperties.setAdditionalData(getContentEncryptionCipherAAD(consumer)); + AlgorithmParameterSpec spec = getContentEncryptionCipherSpec(consumer); + keyProperties.setAlgoSpec(spec); + boolean compressionSupported = + JwtConstants.DEFLATE_ZIP_ALGORITHM.equals(consumer.getJweHeaders().getZipAlgorithm()); + keyProperties.setCompressionSupported(compressionSupported); + byte[] actualCek = getActualCek(cek, consumer.getJweHeaders().getContentEncryptionAlgorithm()); + Key secretKey = CryptoUtils.createSecretKeySpec(actualCek, keyProperties.getKeyAlgo()); + byte[] bytes = + CryptoUtils.decryptBytes(getEncryptedContentWithAuthTag(consumer), secretKey, keyProperties); + return new JweDecryptionOutput(consumer.getJweHeaders(), bytes); + } + protected byte[] getEncryptedContentEncryptionKey(JweCompactConsumer consumer) { + return consumer.getEncryptedContentEncryptionKey(); + } + protected AlgorithmParameterSpec getContentEncryptionCipherSpec(JweCompactConsumer consumer) { + return contentDecryptionAlgo.getAlgorithmParameterSpec(getContentEncryptionCipherInitVector(consumer)); + } + protected String getContentEncryptionAlgorithm(JweCompactConsumer consumer) { + return Algorithm.toJavaName(consumer.getJweHeaders().getContentEncryptionAlgorithm()); + } + protected byte[] getContentEncryptionCipherAAD(JweCompactConsumer consumer) { + return contentDecryptionAlgo.getAdditionalAuthenticationData(consumer.getDecodedJsonHeaders()); + } + protected byte[] getEncryptedContentWithAuthTag(JweCompactConsumer consumer) { + return contentDecryptionAlgo.getEncryptedSequence(consumer.getEncryptedContent(), + getEncryptionAuthenticationTag(consumer)); + } + protected byte[] getContentEncryptionCipherInitVector(JweCompactConsumer consumer) { + return consumer.getContentDecryptionCipherInitVector(); + } + protected byte[] getEncryptionAuthenticationTag(JweCompactConsumer consumer) { + return consumer.getEncryptionAuthenticationTag(); + } + protected int getEncryptionAuthenticationTagLenBits(JweCompactConsumer consumer) { + return getEncryptionAuthenticationTag(consumer).length * 8; + } + protected byte[] getActualCek(byte[] theCek, String algoJwt) { + return theCek; + } + +}
http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractJweEncryption.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractJweEncryption.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractJweEncryption.java new file mode 100644 index 0000000..747d996 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractJweEncryption.java @@ -0,0 +1,184 @@ +/** + * 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.jose.jwe; + +import java.security.spec.AlgorithmParameterSpec; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; + +import org.apache.cxf.rs.security.jose.jwa.Algorithm; +import org.apache.cxf.rs.security.jose.jwt.JwtConstants; +import org.apache.cxf.rs.security.jose.jwt.JwtHeadersWriter; +import org.apache.cxf.rs.security.jose.jwt.JwtTokenReaderWriter; +import org.apache.cxf.rs.security.oauth2.utils.crypto.CryptoUtils; +import org.apache.cxf.rs.security.oauth2.utils.crypto.KeyProperties; + +public abstract class AbstractJweEncryption implements JweEncryptionProvider { + protected static final int DEFAULT_AUTH_TAG_LENGTH = 128; + private JweHeaders headers; + private JwtHeadersWriter writer; + private ContentEncryptionAlgorithm contentEncryptionAlgo; + private KeyEncryptionAlgorithm keyEncryptionAlgo; + + protected AbstractJweEncryption(JweHeaders headers, + ContentEncryptionAlgorithm contentEncryptionAlgo, + KeyEncryptionAlgorithm keyEncryptionAlgo) { + this(headers, contentEncryptionAlgo, keyEncryptionAlgo, null); + } + protected AbstractJweEncryption(JweHeaders headers, + ContentEncryptionAlgorithm contentEncryptionAlgo, + KeyEncryptionAlgorithm keyEncryptionAlgo, + JwtHeadersWriter writer) { + this.headers = headers; + this.writer = writer; + if (this.writer == null) { + this.writer = new JwtTokenReaderWriter(); + } + this.keyEncryptionAlgo = keyEncryptionAlgo; + this.contentEncryptionAlgo = contentEncryptionAlgo; + } + + protected AlgorithmParameterSpec getAlgorithmParameterSpec(byte[] theIv) { + return contentEncryptionAlgo.getAlgorithmParameterSpec(theIv); + } + + protected byte[] getContentEncryptionKey() { + byte[] cek = getProvidedContentEncryptionKey(); + if (cek == null) { + String algoJava = getContentEncryptionAlgoJava(); + String algoJwt = getContentEncryptionAlgoJwt(); + cek = CryptoUtils.getSecretKey(Algorithm.stripAlgoProperties(algoJava), + getCekSize(algoJwt)).getEncoded(); + } + return cek; + } + + protected int getCekSize(String algoJwt) { + return Algorithm.valueOf(algoJwt.replace('-', '_')).getKeySizeBits(); + } + + protected byte[] getProvidedContentEncryptionKey() { + return contentEncryptionAlgo.getContentEncryptionKey(headers); + } + + protected byte[] getEncryptedContentEncryptionKey(byte[] theCek) { + return keyEncryptionAlgo.getEncryptedContentEncryptionKey(headers, theCek); + } + + protected String getContentEncryptionAlgoJwt() { + return headers.getContentEncryptionAlgorithm(); + } + protected String getContentEncryptionAlgoJava() { + return Algorithm.toJavaName(getContentEncryptionAlgoJwt()); + } + protected byte[] getAAD(JweHeaders theHeaders) { + return contentEncryptionAlgo.getAdditionalAuthenticationData(writer.headersToJson(theHeaders)); + } + public String encrypt(byte[] content, String contentType) { + JweEncryptionInternal state = getInternalState(contentType); + + byte[] cipher = CryptoUtils.encryptBytes(content, createCekSecretKey(state), state.keyProps); + + + JweCompactProducer producer = getJweCompactProducer(state, cipher); + return producer.getJweContent(); + } + + protected JweCompactProducer getJweCompactProducer(JweEncryptionInternal state, byte[] cipher) { + return new JweCompactProducer(state.theHeaders, + getJwtHeadersWriter(), + state.jweContentEncryptionKey, + state.theIv, + cipher, + DEFAULT_AUTH_TAG_LENGTH); + } + + protected JwtHeadersWriter getJwtHeadersWriter() { + return writer; + } + protected JweHeaders getJweHeaders() { + return headers; + } + @Override + public JweEncryptionState createJweEncryptionState(String contentType) { + JweEncryptionInternal state = getInternalState(contentType); + Cipher c = CryptoUtils.initCipher(createCekSecretKey(state), state.keyProps, + Cipher.ENCRYPT_MODE); + 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, this.getContentEncryptionAlgoJwt()), + state.keyProps.getKeyAlgo()); + } + + protected byte[] getActualCek(byte[] theCek, String algoJwt) { + return theCek; + } + + private JweEncryptionInternal getInternalState(String contentType) { + byte[] theCek = getContentEncryptionKey(); + String contentEncryptionAlgoJavaName = Algorithm.toJavaName(headers.getContentEncryptionAlgorithm()); + KeyProperties keyProps = new KeyProperties(contentEncryptionAlgoJavaName); + keyProps.setCompressionSupported(compressionRequired(headers)); + + byte[] theIv = contentEncryptionAlgo.getInitVector(); + AlgorithmParameterSpec specParams = getAlgorithmParameterSpec(theIv); + keyProps.setAlgoSpec(specParams); + byte[] jweContentEncryptionKey = getEncryptedContentEncryptionKey(theCek); + + JweHeaders theHeaders = headers; + if (contentType != null) { + theHeaders = new JweHeaders(theHeaders.asMap()); + theHeaders.setContentType(contentType); + } + byte[] additionalEncryptionParam = getAAD(theHeaders); + keyProps.setAdditionalData(additionalEncryptionParam); + + + JweEncryptionInternal state = new JweEncryptionInternal(); + state.theHeaders = theHeaders; + state.jweContentEncryptionKey = jweContentEncryptionKey; + state.keyProps = keyProps; + state.secretKey = theCek; + state.theIv = theIv; + return state; + } + private boolean compressionRequired(JweHeaders theHeaders) { + return JwtConstants.DEFLATE_ZIP_ALGORITHM.equals(theHeaders.getZipAlgorithm()); + } + protected KeyEncryptionAlgorithm getKeyEncryptionAlgo() { + return keyEncryptionAlgo; + } + protected static class JweEncryptionInternal { + JweHeaders theHeaders; + byte[] jweContentEncryptionKey; + byte[] theIv; + KeyProperties keyProps; + byte[] secretKey; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractWrapKeyEncryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractWrapKeyEncryptionAlgorithm.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractWrapKeyEncryptionAlgorithm.java new file mode 100644 index 0000000..162a8df --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractWrapKeyEncryptionAlgorithm.java @@ -0,0 +1,96 @@ +/** + * 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.jose.jwe; + +import java.security.Key; +import java.security.spec.AlgorithmParameterSpec; +import java.util.Set; + +import org.apache.cxf.rs.security.jose.jwa.Algorithm; +import org.apache.cxf.rs.security.oauth2.utils.crypto.CryptoUtils; +import org.apache.cxf.rs.security.oauth2.utils.crypto.KeyProperties; + +public abstract class AbstractWrapKeyEncryptionAlgorithm implements KeyEncryptionAlgorithm { + private Key keyEncryptionKey; + private boolean wrap; + private String algorithm; + private Set<String> supportedAlgorithms; + protected AbstractWrapKeyEncryptionAlgorithm(Key key, Set<String> supportedAlgorithms) { + this(key, null, true, supportedAlgorithms); + } + protected AbstractWrapKeyEncryptionAlgorithm(Key key, boolean wrap, Set<String> supportedAlgorithms) { + this(key, null, wrap, supportedAlgorithms); + } + protected AbstractWrapKeyEncryptionAlgorithm(Key key, String jweAlgo, Set<String> supportedAlgorithms) { + this(key, jweAlgo, true, supportedAlgorithms); + } + protected AbstractWrapKeyEncryptionAlgorithm(Key key, String jweAlgo, boolean wrap, + Set<String> supportedAlgorithms) { + this.keyEncryptionKey = key; + this.algorithm = jweAlgo; + this.wrap = wrap; + this.supportedAlgorithms = supportedAlgorithms; + } + @Override + public byte[] getEncryptedContentEncryptionKey(JweHeaders headers, byte[] cek) { + checkAlgorithms(headers, algorithm); + KeyProperties secretKeyProperties = new KeyProperties(getKeyEncryptionAlgoJava(headers)); + AlgorithmParameterSpec spec = getAlgorithmParameterSpec(headers); + if (spec != null) { + secretKeyProperties.setAlgoSpec(spec); + } + if (!wrap) { + return CryptoUtils.encryptBytes(cek, keyEncryptionKey, secretKeyProperties); + } else { + return CryptoUtils.wrapSecretKey(cek, + getContentEncryptionAlgoJava(headers), + keyEncryptionKey, + secretKeyProperties); + } + } + protected String getKeyEncryptionAlgoJava(JweHeaders headers) { + return Algorithm.toJavaName(headers.getKeyEncryptionAlgorithm()); + } + protected String getContentEncryptionAlgoJava(JweHeaders headers) { + return Algorithm.toJavaName(headers.getContentEncryptionAlgorithm()); + } + protected AlgorithmParameterSpec getAlgorithmParameterSpec(JweHeaders headers) { + return null; + } + protected String checkAlgorithm(String algo) { + if (algo != null && !supportedAlgorithms.contains(algo)) { + throw new SecurityException(); + } + return algo; + } + protected void checkAlgorithms(JweHeaders headers, String defaultAlgo) { + String providedAlgo = headers.getKeyEncryptionAlgorithm(); + if ((providedAlgo == null && defaultAlgo == null) + || (providedAlgo != null && defaultAlgo != null && !providedAlgo.equals(defaultAlgo))) { + throw new SecurityException(); + } + if (providedAlgo != null) { + checkAlgorithm(providedAlgo); + } else if (defaultAlgo != null) { + headers.setKeyEncryptionAlgorithm(defaultAlgo); + checkAlgorithm(defaultAlgo); + } + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesCbcHmacJweDecryption.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesCbcHmacJweDecryption.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesCbcHmacJweDecryption.java new file mode 100644 index 0000000..518b006 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesCbcHmacJweDecryption.java @@ -0,0 +1,76 @@ +/** + * 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.jose.jwe; + +import java.security.spec.AlgorithmParameterSpec; +import java.util.Arrays; + +import javax.crypto.spec.IvParameterSpec; + +import org.apache.cxf.rs.security.jose.jwt.JwtHeadersReader; + +public class AesCbcHmacJweDecryption extends AbstractJweDecryption { + public AesCbcHmacJweDecryption(KeyDecryptionAlgorithm keyDecryptionAlgo) { + this(keyDecryptionAlgo, null, null); + } + public AesCbcHmacJweDecryption(KeyDecryptionAlgorithm keyDecryptionAlgo, + JweCryptoProperties props, + JwtHeadersReader reader) { + super(props, reader, keyDecryptionAlgo, new AesCbcContentDecryptionAlgorithm()); + } + protected JweDecryptionOutput doDecrypt(JweCompactConsumer consumer, byte[] cek) { + validateAuthenticationTag(consumer, cek); + return super.doDecrypt(consumer, cek); + } + @Override + protected byte[] getActualCek(byte[] theCek, String algoJwt) { + return AesCbcHmacJweEncryption.doGetActualCek(theCek, algoJwt); + } + protected void validateAuthenticationTag(JweCompactConsumer consumer, byte[] theCek) { + byte[] actualAuthTag = consumer.getEncryptionAuthenticationTag(); + + final AesCbcHmacJweEncryption.MacState macState = + AesCbcHmacJweEncryption.getInitializedMacState(theCek, + consumer.getContentDecryptionCipherInitVector(), + consumer.getJweHeaders(), + consumer.getDecodedJsonHeaders()); + macState.mac.update(consumer.getEncryptedContent()); + byte[] expectedAuthTag = AesCbcHmacJweEncryption.signAndGetTag(macState); + if (!Arrays.equals(actualAuthTag, expectedAuthTag)) { + throw new SecurityException(); + } + + } + private static class AesCbcContentDecryptionAlgorithm extends AbstractContentEncryptionCipherProperties + implements ContentDecryptionAlgorithm { + @Override + public AlgorithmParameterSpec getAlgorithmParameterSpec(byte[] theIv) { + return new IvParameterSpec(theIv); + } + @Override + public byte[] getAdditionalAuthenticationData(String headersJson) { + return null; + } + @Override + public byte[] getEncryptedSequence(byte[] cipher, byte[] authTag) { + return cipher; + } + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesCbcHmacJweEncryption.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesCbcHmacJweEncryption.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesCbcHmacJweEncryption.java new file mode 100644 index 0000000..40bba7d --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesCbcHmacJweEncryption.java @@ -0,0 +1,194 @@ +/** + * 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.jose.jwe; + +import java.nio.ByteBuffer; +import java.security.spec.AlgorithmParameterSpec; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.crypto.Mac; +import javax.crypto.spec.IvParameterSpec; + +import org.apache.cxf.rs.security.jose.jwa.Algorithm; +import org.apache.cxf.rs.security.jose.jwt.JwtHeadersWriter; +import org.apache.cxf.rs.security.oauth2.utils.crypto.HmacUtils; + +public class AesCbcHmacJweEncryption extends AbstractJweEncryption { + private static final Set<String> SUPPORTED_CEK_ALGORITHMS = new HashSet<String>( + Arrays.asList(Algorithm.A128CBC_HS256.getJwtName(), + Algorithm.A192CBC_HS384.getJwtName(), + Algorithm.A256CBC_HS512.getJwtName())); + private static final Map<String, String> AES_HMAC_MAP; + private static final Map<String, Integer> AES_CEK_SIZE_MAP; + static { + AES_HMAC_MAP = new HashMap<String, String>(); + AES_HMAC_MAP.put(Algorithm.A128CBC_HS256.getJwtName(), Algorithm.HMAC_SHA_256_JAVA); + AES_HMAC_MAP.put(Algorithm.A192CBC_HS384.getJwtName(), Algorithm.HMAC_SHA_384_JAVA); + AES_HMAC_MAP.put(Algorithm.A256CBC_HS512.getJwtName(), Algorithm.HMAC_SHA_512_JAVA); + + AES_CEK_SIZE_MAP = new HashMap<String, Integer>(); + AES_CEK_SIZE_MAP.put(Algorithm.A128CBC_HS256.getJwtName(), 32); + AES_CEK_SIZE_MAP.put(Algorithm.A192CBC_HS384.getJwtName(), 48); + AES_CEK_SIZE_MAP.put(Algorithm.A256CBC_HS512.getJwtName(), 64); + } + public AesCbcHmacJweEncryption(String keyAlgo, + String cekAlgoJwt, + KeyEncryptionAlgorithm keyEncryptionAlgorithm) { + this(new JweHeaders(keyAlgo, validateCekAlgorithm(cekAlgoJwt)), + null, null, keyEncryptionAlgorithm); + } + public AesCbcHmacJweEncryption(JweHeaders headers, + KeyEncryptionAlgorithm keyEncryptionAlgorithm) { + this(headers, null, null, keyEncryptionAlgorithm); + } + public AesCbcHmacJweEncryption(JweHeaders headers, byte[] cek, + byte[] iv, KeyEncryptionAlgorithm keyEncryptionAlgorithm) { + this(headers, cek, iv, keyEncryptionAlgorithm, null); + } + public AesCbcHmacJweEncryption(JweHeaders headers, + byte[] cek, + byte[] iv, + KeyEncryptionAlgorithm keyEncryptionAlgorithm, + JwtHeadersWriter writer) { + super(headers, new AesCbcContentEncryptionAlgorithm(cek, iv), keyEncryptionAlgorithm, writer); + validateCekAlgorithm(headers.getContentEncryptionAlgorithm()); + } + @Override + protected byte[] getActualCek(byte[] theCek, String algoJwt) { + return doGetActualCek(theCek, algoJwt); + } + @Override + protected int getCekSize(String algoJwt) { + return getFullCekKeySize(algoJwt) * 8; + } + protected static byte[] doGetActualCek(byte[] theCek, String algoJwt) { + int size = getFullCekKeySize(algoJwt) / 2; + byte[] actualCek = new byte[size]; + System.arraycopy(theCek, size, actualCek, 0, size); + return actualCek; + } + + protected static int getFullCekKeySize(String algoJwt) { + return AES_CEK_SIZE_MAP.get(algoJwt); + } + + protected JweCompactProducer getJweCompactProducer(JweEncryptionInternal state, byte[] cipher) { + final MacState macState = getInitializedMacState(state); + macState.mac.update(cipher); + byte[] authTag = signAndGetTag(macState); + return new JweCompactProducer(macState.headersJson, + state.jweContentEncryptionKey, + state.theIv, + cipher, + authTag); + } + + protected static byte[] signAndGetTag(MacState macState) { + macState.mac.update(macState.al); + byte[] sig = macState.mac.doFinal(); + + int authTagLen = DEFAULT_AUTH_TAG_LENGTH / 8; + byte[] authTag = new byte[authTagLen]; + System.arraycopy(sig, 0, authTag, 0, authTagLen); + return authTag; + } + private MacState getInitializedMacState(final JweEncryptionInternal state) { + String headersJson = getJwtHeadersWriter().headersToJson(state.theHeaders); + return getInitializedMacState(state.secretKey, state.theIv, state.theHeaders, headersJson); + } + protected static MacState getInitializedMacState(byte[] secretKey, + byte[] theIv, + JweHeaders theHeaders, + String headersJson) { + String algoJwt = theHeaders.getContentEncryptionAlgorithm(); + int size = getFullCekKeySize(algoJwt) / 2; + byte[] macKey = new byte[size]; + System.arraycopy(secretKey, 0, macKey, 0, size); + + String hmacAlgoJava = AES_HMAC_MAP.get(algoJwt); + Mac mac = HmacUtils.getInitializedMac(macKey, hmacAlgoJava, null); + + + byte[] aad = JweHeaders.toCipherAdditionalAuthData(headersJson); + ByteBuffer buf = ByteBuffer.allocate(8); + final byte[] al = buf.putInt(0).putInt(aad.length * 8).array(); + + mac.update(aad); + mac.update(theIv); + 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() { + return signAndGetTag(macState); + } + + }; + } + + protected byte[] getEncryptedContentEncryptionKey(byte[] theCek) { + return getKeyEncryptionAlgo().getEncryptedContentEncryptionKey(getJweHeaders(), theCek); + } + + private static class AesCbcContentEncryptionAlgorithm extends AbstractContentEncryptionAlgorithm { + public AesCbcContentEncryptionAlgorithm(byte[] cek, byte[] iv) { + super(cek, iv); + } + @Override + public AlgorithmParameterSpec getAlgorithmParameterSpec(byte[] theIv) { + return new IvParameterSpec(theIv); + } + @Override + public byte[] getAdditionalAuthenticationData(String headersJson) { + return null; + } + } + + protected static class MacState { + protected Mac mac; + private byte[] al; + private String headersJson; + } + + private static String validateCekAlgorithm(String cekAlgo) { + if (!SUPPORTED_CEK_ALGORITHMS.contains(cekAlgo)) { + throw new SecurityException(); + } + return cekAlgo; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmContentDecryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmContentDecryptionAlgorithm.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmContentDecryptionAlgorithm.java new file mode 100644 index 0000000..05d77ea --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmContentDecryptionAlgorithm.java @@ -0,0 +1,30 @@ +/** + * 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.jose.jwe; + + + +public class AesGcmContentDecryptionAlgorithm extends AbstractContentEncryptionCipherProperties + implements ContentDecryptionAlgorithm { + + @Override + public byte[] getEncryptedSequence(byte[] cipher, byte[] authTag) { + return JweCompactConsumer.getCipherWithAuthTag(cipher, authTag); + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmContentEncryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmContentEncryptionAlgorithm.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmContentEncryptionAlgorithm.java new file mode 100644 index 0000000..87774e9 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmContentEncryptionAlgorithm.java @@ -0,0 +1,43 @@ +/** + * 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.jose.jwe; + +import javax.crypto.SecretKey; + +import org.apache.cxf.rs.security.oauth2.utils.crypto.CryptoUtils; + + +public class AesGcmContentEncryptionAlgorithm extends AbstractContentEncryptionAlgorithm { + private static final int DEFAULT_IV_SIZE = 96; + public AesGcmContentEncryptionAlgorithm() { + this((byte[])null, null); + } + public AesGcmContentEncryptionAlgorithm(String encodedCek, String encodedIv) { + this((byte[])CryptoUtils.decodeSequence(encodedCek), CryptoUtils.decodeSequence(encodedIv)); + } + public AesGcmContentEncryptionAlgorithm(SecretKey key, byte[] iv) { + this(key.getEncoded(), iv); + } + public AesGcmContentEncryptionAlgorithm(byte[] cek, byte[] iv) { + super(cek, iv); + } + protected int getIvSize() { + return DEFAULT_IV_SIZE; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmWrapKeyDecryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmWrapKeyDecryptionAlgorithm.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmWrapKeyDecryptionAlgorithm.java new file mode 100644 index 0000000..0b2c824 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmWrapKeyDecryptionAlgorithm.java @@ -0,0 +1,57 @@ +/** + * 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.jose.jwe; + +import java.security.spec.AlgorithmParameterSpec; + +import javax.crypto.SecretKey; + +import org.apache.cxf.rs.security.jose.jwa.Algorithm; +import org.apache.cxf.rs.security.oauth2.utils.Base64UrlUtility; +import org.apache.cxf.rs.security.oauth2.utils.crypto.CryptoUtils; + +public class AesGcmWrapKeyDecryptionAlgorithm extends WrappedKeyDecryptionAlgorithm { + public AesGcmWrapKeyDecryptionAlgorithm(String encodedKey) { + this(CryptoUtils.decodeSequence(encodedKey)); + } + public AesGcmWrapKeyDecryptionAlgorithm(byte[] secretKey) { + this(CryptoUtils.createSecretKeySpec(secretKey, Algorithm.AES_ALGO_JAVA)); + } + public AesGcmWrapKeyDecryptionAlgorithm(SecretKey secretKey) { + super(secretKey, true); + } + @Override + protected byte[] getEncryptedContentEncryptionKey(JweCompactConsumer consumer) { + byte[] encryptedCekKey = super.getEncryptedContentEncryptionKey(consumer); + byte[] tag = getDecodedBytes(consumer, "tag"); + return JweCompactConsumer.getCipherWithAuthTag(encryptedCekKey, tag); + } + protected AlgorithmParameterSpec getAlgorithmParameterSpec(JweCompactConsumer consumer) { + byte[] iv = getDecodedBytes(consumer, "iv"); + return CryptoUtils.getContentEncryptionCipherSpec(128, iv); + } + private byte[] getDecodedBytes(JweCompactConsumer consumer, String headerName) { + try { + Object ivHeader = consumer.getJweHeaders().getHeader(headerName); + return Base64UrlUtility.decode(ivHeader.toString()); + } catch (Exception ex) { + throw new SecurityException(ex); + } + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmWrapKeyEncryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmWrapKeyEncryptionAlgorithm.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmWrapKeyEncryptionAlgorithm.java new file mode 100644 index 0000000..220763a --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmWrapKeyEncryptionAlgorithm.java @@ -0,0 +1,64 @@ +/** + * 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.jose.jwe; + +import java.security.spec.AlgorithmParameterSpec; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import javax.crypto.SecretKey; + +import org.apache.cxf.rs.security.jose.jwa.Algorithm; +import org.apache.cxf.rs.security.oauth2.utils.Base64UrlUtility; +import org.apache.cxf.rs.security.oauth2.utils.crypto.CryptoUtils; + +public class AesGcmWrapKeyEncryptionAlgorithm extends AbstractWrapKeyEncryptionAlgorithm { + private static final Set<String> SUPPORTED_ALGORITHMS = new HashSet<String>( + Arrays.asList(Algorithm.A128GCMKW.getJwtName(), + Algorithm.A192GCMKW.getJwtName(), + Algorithm.A256GCMKW.getJwtName())); + public AesGcmWrapKeyEncryptionAlgorithm(String encodedKey, String keyAlgoJwt) { + this(CryptoUtils.decodeSequence(encodedKey), keyAlgoJwt); + } + public AesGcmWrapKeyEncryptionAlgorithm(byte[] keyBytes, String keyAlgoJwt) { + this(CryptoUtils.createSecretKeySpec(keyBytes, Algorithm.AES_ALGO_JAVA), + keyAlgoJwt); + } + public AesGcmWrapKeyEncryptionAlgorithm(SecretKey key, String keyAlgoJwt) { + super(key, keyAlgoJwt, true, SUPPORTED_ALGORITHMS); + } + + @Override + public byte[] getEncryptedContentEncryptionKey(JweHeaders headers, byte[] cek) { + byte[] wrappedKeyAndTag = super.getEncryptedContentEncryptionKey(headers, cek); + byte[] wrappedKey = new byte[wrappedKeyAndTag.length - 128 / 8]; + System.arraycopy(wrappedKeyAndTag, 0, wrappedKey, 0, wrappedKeyAndTag.length - 128 / 8); + String encodedTag = Base64UrlUtility.encodeChunk(wrappedKeyAndTag, + wrappedKeyAndTag.length - 128 / 8, 128 / 8); + headers.setHeader("tag", encodedTag); + return wrappedKey; + } + protected AlgorithmParameterSpec getAlgorithmParameterSpec(JweHeaders headers) { + byte[] iv = CryptoUtils.generateSecureRandomBytes(96 / 8); + String encodedIv = Base64UrlUtility.encode(iv); + headers.setHeader("iv", encodedIv); + return CryptoUtils.getContentEncryptionCipherSpec(128, iv); + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesWrapKeyDecryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesWrapKeyDecryptionAlgorithm.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesWrapKeyDecryptionAlgorithm.java new file mode 100644 index 0000000..14c273f --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesWrapKeyDecryptionAlgorithm.java @@ -0,0 +1,38 @@ +/** + * 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.jose.jwe; + +import javax.crypto.SecretKey; + +import org.apache.cxf.rs.security.jose.jwa.Algorithm; +import org.apache.cxf.rs.security.oauth2.utils.crypto.CryptoUtils; + +public class AesWrapKeyDecryptionAlgorithm extends WrappedKeyDecryptionAlgorithm { + public AesWrapKeyDecryptionAlgorithm(String encodedKey) { + this(CryptoUtils.decodeSequence(encodedKey)); + } + public AesWrapKeyDecryptionAlgorithm(byte[] secretKey) { + this(CryptoUtils.createSecretKeySpec(secretKey, Algorithm.AES_WRAP_ALGO_JAVA)); + } + public AesWrapKeyDecryptionAlgorithm(SecretKey secretKey) { + super(secretKey, true); + } + + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesWrapKeyEncryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesWrapKeyEncryptionAlgorithm.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesWrapKeyEncryptionAlgorithm.java new file mode 100644 index 0000000..a0b01b9 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesWrapKeyEncryptionAlgorithm.java @@ -0,0 +1,48 @@ +/** + * 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.jose.jwe; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import javax.crypto.SecretKey; + +import org.apache.cxf.rs.security.jose.jwa.Algorithm; +import org.apache.cxf.rs.security.oauth2.utils.crypto.CryptoUtils; + +public class AesWrapKeyEncryptionAlgorithm extends AbstractWrapKeyEncryptionAlgorithm { + private static final Set<String> SUPPORTED_ALGORITHMS = new HashSet<String>( + Arrays.asList(Algorithm.A128KW.getJwtName(), + Algorithm.A192KW.getJwtName(), + Algorithm.A256KW.getJwtName())); + public AesWrapKeyEncryptionAlgorithm(String encodedKey, String keyAlgoJwt) { + this(CryptoUtils.decodeSequence(encodedKey), keyAlgoJwt); + } + public AesWrapKeyEncryptionAlgorithm(byte[] keyBytes, String keyAlgoJwt) { + this(CryptoUtils.createSecretKeySpec(keyBytes, Algorithm.toJavaName(keyAlgoJwt)), + keyAlgoJwt); + } + public AesWrapKeyEncryptionAlgorithm(SecretKey key, String keyAlgoJwt) { + super(key, keyAlgoJwt, SUPPORTED_ALGORITHMS); + } + + + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AuthenticationTagProducer.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AuthenticationTagProducer.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/AuthenticationTagProducer.java new file mode 100644 index 0000000..897e68c --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/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.jose.jwe; + +public interface AuthenticationTagProducer { + void update(byte[] cipher, int off, int len); + byte[] getTag(); +} http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentDecryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentDecryptionAlgorithm.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentDecryptionAlgorithm.java new file mode 100644 index 0000000..eaf6f61 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentDecryptionAlgorithm.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.jose.jwe; + + +interface ContentDecryptionAlgorithm extends ContentEncryptionCipherProperties { + byte[] getEncryptedSequence(byte[] cipher, byte[] authTag); +} http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentEncryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentEncryptionAlgorithm.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentEncryptionAlgorithm.java new file mode 100644 index 0000000..6f53f53 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentEncryptionAlgorithm.java @@ -0,0 +1,26 @@ +/** + * 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.jose.jwe; + + + +public interface ContentEncryptionAlgorithm extends ContentEncryptionCipherProperties { + byte[] getInitVector(); + byte[] getContentEncryptionKey(JweHeaders headers); +} http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentEncryptionCipherProperties.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentEncryptionCipherProperties.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentEncryptionCipherProperties.java new file mode 100644 index 0000000..54da6fd --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentEncryptionCipherProperties.java @@ -0,0 +1,27 @@ +/** + * 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.jose.jwe; + +import java.security.spec.AlgorithmParameterSpec; + + +public interface ContentEncryptionCipherProperties { + byte[] getAdditionalAuthenticationData(String headersJson); + AlgorithmParameterSpec getAlgorithmParameterSpec(byte[] iv); +} http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyDecryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyDecryptionAlgorithm.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyDecryptionAlgorithm.java new file mode 100644 index 0000000..c1803c6 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyDecryptionAlgorithm.java @@ -0,0 +1,39 @@ +/** + * 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.jose.jwe; + +import java.security.Key; + +public class DirectKeyDecryptionAlgorithm implements KeyDecryptionAlgorithm { + private byte[] contentDecryptionKey; + public DirectKeyDecryptionAlgorithm(Key contentDecryptionKey) { + this(contentDecryptionKey.getEncoded()); + } + public DirectKeyDecryptionAlgorithm(byte[] contentDecryptionKey) { + this.contentDecryptionKey = contentDecryptionKey; + } + @Override + public byte[] getDecryptedContentEncryptionKey(JweCompactConsumer consumer) { + byte[] encryptedCEK = consumer.getEncryptedContentEncryptionKey(); + if (encryptedCEK != null && encryptedCEK.length > 0) { + throw new SecurityException(); + } + return contentDecryptionKey; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyEncryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyEncryptionAlgorithm.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyEncryptionAlgorithm.java new file mode 100644 index 0000000..8bbfd29 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyEncryptionAlgorithm.java @@ -0,0 +1,29 @@ +/** + * 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.jose.jwe; + + +public class DirectKeyEncryptionAlgorithm implements KeyEncryptionAlgorithm { + public byte[] getEncryptedContentEncryptionKey(JweHeaders headers, byte[] theCek) { + if (headers.getKeyEncryptionAlgorithm() != null) { + throw new SecurityException(); + } + return new byte[0]; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyJweDecryption.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyJweDecryption.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyJweDecryption.java new file mode 100644 index 0000000..0f1611e --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyJweDecryption.java @@ -0,0 +1,45 @@ +/** + * 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.jose.jwe; + +import java.security.Key; + +import org.apache.cxf.rs.security.jose.jwt.JwtHeadersReader; + +public class DirectKeyJweDecryption extends AbstractJweDecryption { + public DirectKeyJweDecryption(Key contentDecryptionKey) { + this(contentDecryptionKey, null); + } + public DirectKeyJweDecryption(Key contentDecryptionKey, JweCryptoProperties props) { + this(contentDecryptionKey, props, null); + } + public DirectKeyJweDecryption(Key contentDecryptionKey, JweCryptoProperties props, + JwtHeadersReader reader) { + this(contentDecryptionKey, props, reader, + new AesGcmContentDecryptionAlgorithm()); + } + public DirectKeyJweDecryption(Key contentDecryptionKey, + JweCryptoProperties props, + JwtHeadersReader reader, + ContentDecryptionAlgorithm cipherProps) { + super(props, reader, new DirectKeyDecryptionAlgorithm(contentDecryptionKey), + cipherProps); + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyJweEncryption.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyJweEncryption.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyJweEncryption.java new file mode 100644 index 0000000..69e4ed9 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyJweEncryption.java @@ -0,0 +1,47 @@ +/** + * 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.jose.jwe; + +import javax.crypto.SecretKey; + +import org.apache.cxf.rs.security.jose.jwa.Algorithm; + +public class DirectKeyJweEncryption extends AbstractJweEncryption { + public DirectKeyJweEncryption(SecretKey cek, byte[] iv) { + this(new JweHeaders(Algorithm.toJwtName(cek.getAlgorithm(), + cek.getEncoded().length * 8)), cek.getEncoded(), iv); + } + public DirectKeyJweEncryption(JweHeaders headers, byte[] cek, byte[] iv) { + this(headers, new AesGcmContentEncryptionAlgorithm(cek, iv)); + } + public DirectKeyJweEncryption(JweHeaders headers, ContentEncryptionAlgorithm ceAlgo) { + super(headers, ceAlgo, new DirectKeyEncryptionAlgorithm()); + } + protected byte[] getProvidedContentEncryptionKey() { + return validateCek(super.getProvidedContentEncryptionKey()); + } + private static byte[] validateCek(byte[] cek) { + if (cek == null) { + // to prevent the cek from being auto-generated which + // does not make sense for the direct key case + throw new NullPointerException("CEK must not be null"); + } + return cek; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCompactConsumer.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCompactConsumer.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCompactConsumer.java new file mode 100644 index 0000000..5cfe012 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCompactConsumer.java @@ -0,0 +1,113 @@ +/** + * 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.jose.jwe; + +import java.io.UnsupportedEncodingException; + +import org.apache.cxf.common.util.Base64Exception; +import org.apache.cxf.rs.security.jose.jwt.JwtHeadersReader; +import org.apache.cxf.rs.security.jose.jwt.JwtTokenReaderWriter; +import org.apache.cxf.rs.security.oauth2.utils.Base64UrlUtility; + + +public class JweCompactConsumer { + private String headersJson; + private byte[] encryptedCEK; + private byte[] initVector; + private byte[] encryptedContent; + private byte[] authTag; + private JweHeaders jweHeaders; + public JweCompactConsumer(String jweContent) { + this(jweContent, new JwtTokenReaderWriter()); + } + public JweCompactConsumer(String jweContent, JwtHeadersReader reader) { + String[] parts = jweContent.split("\\."); + if (parts.length != 5) { + throw new SecurityException("5 JWE parts are expected"); + } + try { + headersJson = new String(Base64UrlUtility.decode(parts[0])); + encryptedCEK = Base64UrlUtility.decode(parts[1]); + initVector = Base64UrlUtility.decode(parts[2]); + + encryptedContent = Base64UrlUtility.decode(parts[3]); + authTag = Base64UrlUtility.decode(parts[4]); + jweHeaders = new JweHeaders(reader.fromJsonHeaders(headersJson).asMap()); + } catch (Base64Exception ex) { + throw new SecurityException(ex); + } + } + + public void enforceJweCryptoProperties(JweCryptoProperties props) { + if (props != null) { + //TODO + } + } + + public String getDecodedJsonHeaders() { + return headersJson; + } + + public JweHeaders getJweHeaders() { + return jweHeaders; + } + + public byte[] getEncryptedContentEncryptionKey() { + return encryptedCEK; + } + + public byte[] getContentDecryptionCipherInitVector() { + return initVector; + } + + public byte[] getContentEncryptionCipherAAD() { + return JweHeaders.toCipherAdditionalAuthData(headersJson); + } + + public byte[] getEncryptionAuthenticationTag() { + return authTag; + } + + public byte[] getEncryptedContent() { + return encryptedContent; + } + + public byte[] getEncryptedContentWithAuthTag() { + return getCipherWithAuthTag(encryptedContent, authTag); + } + + public static byte[] getCipherWithAuthTag(byte[] cipher, byte[] authTag) { + byte[] encryptedContentWithTag = new byte[cipher.length + authTag.length]; + System.arraycopy(cipher, 0, encryptedContentWithTag, 0, cipher.length); + System.arraycopy(authTag, 0, encryptedContentWithTag, cipher.length, authTag.length); + return encryptedContentWithTag; + } + + public byte[] getDecryptedContent(JweDecryptionProvider decryption) { + return decryption.decrypt(this); + } + public String getDecryptedContentText(JweDecryptionProvider decryption) { + try { + return new String(getDecryptedContent(decryption), "UTF-8"); + } catch (UnsupportedEncodingException ex) { + throw new SecurityException(ex); + } + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCompactProducer.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCompactProducer.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCompactProducer.java new file mode 100644 index 0000000..ca0cda8 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCompactProducer.java @@ -0,0 +1,155 @@ +/** + * 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.jose.jwe; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.cxf.rs.security.jose.jwt.JwtHeadersWriter; +import org.apache.cxf.rs.security.jose.jwt.JwtTokenReaderWriter; +import org.apache.cxf.rs.security.oauth2.utils.Base64UrlUtility; + + +public class JweCompactProducer { + private StringBuilder jweContentBuilder; + private String encodedEncryptedContent; + private String encodedAuthTag; + public JweCompactProducer(JweHeaders headers, + byte[] encryptedContentEncryptionKey, + byte[] cipherInitVector, + byte[] encryptedContentNoTag, + byte[] authenticationTag) { + this(headers, null, encryptedContentEncryptionKey, + cipherInitVector, encryptedContentNoTag, authenticationTag); + } + + public JweCompactProducer(JweHeaders headers, + JwtHeadersWriter writer, + byte[] encryptedContentEncryptionKey, + byte[] cipherInitVector, + byte[] encryptedContentNoTag, + byte[] authenticationTag) { + this(getHeadersJson(headers, writer), + encryptedContentEncryptionKey, + cipherInitVector, + encryptedContentNoTag, + authenticationTag); + } + public JweCompactProducer(String headersJson, + byte[] encryptedContentEncryptionKey, + byte[] cipherInitVector, + byte[] encryptedContentNoTag, + byte[] authenticationTag) { + jweContentBuilder = startJweContent(new StringBuilder(), headersJson, + encryptedContentEncryptionKey, cipherInitVector); + this.encodedEncryptedContent = Base64UrlUtility.encode(encryptedContentNoTag); + this.encodedAuthTag = Base64UrlUtility.encode(authenticationTag); + + } + + public JweCompactProducer(JweHeaders headers, + byte[] encryptedContentEncryptionKey, + byte[] cipherInitVector, + byte[] encryptedContentWithTag, + int authTagLengthBits) { + this(headers, null, encryptedContentEncryptionKey, + cipherInitVector, encryptedContentWithTag, authTagLengthBits); + } + public JweCompactProducer(JweHeaders headers, + JwtHeadersWriter writer, + byte[] encryptedContentEncryptionKey, + byte[] cipherInitVector, + byte[] encryptedContentWithTag, + int authTagLengthBits) { + jweContentBuilder = startJweContent(new StringBuilder(), headers, writer, + encryptedContentEncryptionKey, cipherInitVector); + this.encodedEncryptedContent = Base64UrlUtility.encodeChunk( + encryptedContentWithTag, + 0, + encryptedContentWithTag.length - authTagLengthBits / 8); + this.encodedAuthTag = Base64UrlUtility.encodeChunk( + encryptedContentWithTag, + encryptedContentWithTag.length - authTagLengthBits / 8, + authTagLengthBits / 8); + + } + public static String startJweContent(JweHeaders headers, + JwtHeadersWriter writer, + byte[] encryptedContentEncryptionKey, + byte[] cipherInitVector) { + return startJweContent(new StringBuilder(), + headers, writer, encryptedContentEncryptionKey, cipherInitVector).toString(); + } + public static StringBuilder startJweContent(StringBuilder sb, + JweHeaders headers, + JwtHeadersWriter writer, + byte[] encryptedContentEncryptionKey, + byte[] cipherInitVector) { + return startJweContent(sb, + getHeadersJson(headers, writer), + encryptedContentEncryptionKey, + cipherInitVector); + } + private static String getHeadersJson(JweHeaders headers, + JwtHeadersWriter writer) { + writer = writer == null ? new JwtTokenReaderWriter() : writer; + return writer.headersToJson(headers); + + } + public static StringBuilder startJweContent(StringBuilder sb, + String headersJson, + byte[] encryptedContentEncryptionKey, + byte[] cipherInitVector) { + String encodedHeaders = Base64UrlUtility.encode(headersJson); + String encodedContentEncryptionKey = Base64UrlUtility.encode(encryptedContentEncryptionKey); + String encodedInitVector = Base64UrlUtility.encode(cipherInitVector); + sb.append(encodedHeaders) + .append('.') + .append(encodedContentEncryptionKey == null ? "" : encodedContentEncryptionKey) + .append('.') + .append(encodedInitVector == null ? "" : encodedInitVector) + .append('.'); + return sb; + } + + public static void startJweContent(OutputStream os, + JweHeaders headers, + JwtHeadersWriter writer, + byte[] encryptedContentEncryptionKey, + byte[] cipherInitVector) throws IOException { + writer = writer == null ? new JwtTokenReaderWriter() : writer; + byte[] jsonBytes = writer.headersToJson(headers).getBytes("UTF-8"); + Base64UrlUtility.encodeAndStream(jsonBytes, 0, jsonBytes.length, os); + byte[] dotBytes = new byte[]{'.'}; + os.write(dotBytes); + Base64UrlUtility.encodeAndStream(encryptedContentEncryptionKey, 0, + encryptedContentEncryptionKey.length, os); + os.write(dotBytes); + Base64UrlUtility.encodeAndStream(cipherInitVector, 0, cipherInitVector.length, os); + os.write(dotBytes); + } + + public String getJweContent() { + return jweContentBuilder.append(encodedEncryptedContent) + .append('.') + .append(encodedAuthTag) + .toString(); + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCryptoProperties.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCryptoProperties.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCryptoProperties.java new file mode 100644 index 0000000..54150e4 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCryptoProperties.java @@ -0,0 +1,22 @@ +/** + * 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.jose.jwe; + +public class JweCryptoProperties { +} http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionOutput.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionOutput.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionOutput.java new file mode 100644 index 0000000..f3cf255 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionOutput.java @@ -0,0 +1,43 @@ +/** + * 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.jose.jwe; + +import java.io.UnsupportedEncodingException; + +public class JweDecryptionOutput { + private JweHeaders headers; + private byte[] content; + public JweDecryptionOutput(JweHeaders headers, byte[] content) { + this.headers = headers; + this.content = content; + } + public JweHeaders getHeaders() { + return headers; + } + public byte[] getContent() { + return content; + } + public String getContentText() { + try { + return new String(getContent(), "UTF-8"); + } catch (UnsupportedEncodingException ex) { + throw new SecurityException(ex); + } + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionProvider.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionProvider.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionProvider.java new file mode 100644 index 0000000..d20401b --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionProvider.java @@ -0,0 +1,26 @@ +/** + * 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.jose.jwe; + + + +public interface JweDecryptionProvider { + JweDecryptionOutput decrypt(String jweContent); + byte[] decrypt(JweCompactConsumer consumer); +} http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionProvider.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionProvider.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionProvider.java new file mode 100644 index 0000000..5b9afee --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionProvider.java @@ -0,0 +1,26 @@ +/** + * 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.jose.jwe; + + + +public interface JweEncryptionProvider { + String encrypt(byte[] jweContent, String contentType); + JweEncryptionState createJweEncryptionState(String contentType); +} http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionState.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionState.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionState.java new file mode 100644 index 0000000..0732250 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionState.java @@ -0,0 +1,63 @@ +/** + * 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.jose.jwe; + +import javax.crypto.Cipher; + +public class JweEncryptionState { + private Cipher cipher; + private JweHeaders headers; + private byte[] contentEncryptionKey; + private byte[] iv; + private boolean compressionSupported; + private AuthenticationTagProducer authTagProducer; + + public JweEncryptionState(Cipher cipher, + JweHeaders headers, + byte[] contentEncryptionKey, + byte[] iv, + AuthenticationTagProducer authTagProducer, + boolean compressionSupported) { + this.cipher = cipher; + this.headers = headers; + this.contentEncryptionKey = contentEncryptionKey; + this.iv = iv; + this.authTagProducer = authTagProducer; + this.compressionSupported = compressionSupported; + } + public Cipher getCipher() { + return cipher; + } + public JweHeaders getHeaders() { + return headers; + } + public byte[] getContentEncryptionKey() { + return contentEncryptionKey; + } + public byte[] getIv() { + return iv; + } + public boolean isCompressionSupported() { + return compressionSupported; + } + public AuthenticationTagProducer getAuthTagProducer() { + return authTagProducer; + } + +}