http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwa/KeyAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwa/KeyAlgorithm.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwa/KeyAlgorithm.java new file mode 100644 index 0000000..46bccf3 --- /dev/null +++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwa/KeyAlgorithm.java @@ -0,0 +1,78 @@ +/** + * 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.jwa; + + + + +public enum KeyAlgorithm { + RSA_OAEP(AlgorithmUtils.RSA_OAEP_ALGO, "RSA/ECB/OAEPWithSHA-1AndMGF1Padding", -1), + RSA_OAEP_256(AlgorithmUtils.RSA_OAEP_256_ALGO, "RSA/ECB/OAEPWithSHA-256AndMGF1Padding", -1), + RSA1_5(AlgorithmUtils.RSA1_5_ALGO, "RSA/ECB/PKCS1Padding", -1), + A128KW(AlgorithmUtils.A128KW_ALGO, "AESWrap", 128), + A192KW(AlgorithmUtils.A192KW_ALGO, "AESWrap", 192), + A256KW(AlgorithmUtils.A256KW_ALGO, "AESWrap", 256), + A128GCMKW(AlgorithmUtils.A128GCMKW_ALGO, "AES/GCM/NoPadding", 128), + A192GCMKW(AlgorithmUtils.A192GCMKW_ALGO, "AES/GCM/NoPadding", 192), + A256GCMKW(AlgorithmUtils.A256GCMKW_ALGO, "AES/GCM/NoPadding", 256), + PBES2_HS256_A128KW(AlgorithmUtils.PBES2_HS256_A128KW_ALGO, "AESWrap", 128), + PBES2_HS384_A192KW(AlgorithmUtils.PBES2_HS384_A192KW_ALGO, "AESWrap", 192), + PBES2_HS512_A256KW(AlgorithmUtils.PBES2_HS512_A256KW_ALGO, "AESWrap", 256), + ECDH_ES_A128KW(AlgorithmUtils.ECDH_ES_A128KW_ALGO, "AESWrap", 128), + ECDH_ES_A192KW(AlgorithmUtils.ECDH_ES_A192KW_ALGO, "AESWrap", 192), + ECDH_ES_A256KW(AlgorithmUtils.ECDH_ES_A256KW_ALGO, "AESWrap", 256), + ECDH_ES_DIRECT(AlgorithmUtils.ECDH_ES_DIRECT_ALGO, null, -1); + + private final String jwaName; + private final String javaName; + private final int keySizeBits; + + KeyAlgorithm(String jwaName, String javaName, int keySizeBits) { + this.jwaName = jwaName; + this.javaName = javaName; + this.keySizeBits = keySizeBits; + } + + public String getJwaName() { + return jwaName; + } + + public String getJavaName() { + return javaName == null ? name() : javaName; + } + + public String getJavaAlgoName() { + return AlgorithmUtils.stripAlgoProperties(getJavaName()); + } + + public int getKeySizeBits() { + return keySizeBits; + } + public static KeyAlgorithm getAlgorithm(String algo) { + if (algo == null) { + return null; + } + return KeyAlgorithm.valueOf(algo.replace('-', '_') + .replace('+', '_')); + + } + + +} \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwa/SignatureAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwa/SignatureAlgorithm.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwa/SignatureAlgorithm.java new file mode 100644 index 0000000..574e7c5 --- /dev/null +++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwa/SignatureAlgorithm.java @@ -0,0 +1,83 @@ +/** + * 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.jwa; + + + + +public enum SignatureAlgorithm { + HS256(AlgorithmUtils.HMAC_SHA_256_ALGO, AlgorithmUtils.HMAC_SHA_256_JAVA, 256), + HS384(AlgorithmUtils.HMAC_SHA_384_ALGO, AlgorithmUtils.HMAC_SHA_384_JAVA, 384), + HS512(AlgorithmUtils.HMAC_SHA_512_ALGO, AlgorithmUtils.HMAC_SHA_512_JAVA, 512), + + RS256(AlgorithmUtils.RS_SHA_256_ALGO, AlgorithmUtils.RS_SHA_256_JAVA, 256), + RS384(AlgorithmUtils.RS_SHA_384_ALGO, AlgorithmUtils.RS_SHA_384_JAVA, 384), + RS512(AlgorithmUtils.RS_SHA_512_ALGO, AlgorithmUtils.RS_SHA_512_JAVA, 512), + + PS256(AlgorithmUtils.PS_SHA_256_ALGO, AlgorithmUtils.PS_SHA_256_JAVA, 256), + PS384(AlgorithmUtils.PS_SHA_384_ALGO, AlgorithmUtils.PS_SHA_384_JAVA, 384), + PS512(AlgorithmUtils.PS_SHA_512_ALGO, AlgorithmUtils.PS_SHA_512_JAVA, 512), + + ES256(AlgorithmUtils.ES_SHA_256_ALGO, AlgorithmUtils.ES_SHA_256_JAVA, 256), + ES384(AlgorithmUtils.ES_SHA_384_ALGO, AlgorithmUtils.ES_SHA_384_JAVA, 384), + ES512(AlgorithmUtils.ES_SHA_512_ALGO, AlgorithmUtils.ES_SHA_512_JAVA, 512), + + NONE(AlgorithmUtils.NONE_TEXT_ALGO, null, -1); + + + private final String jwaName; + private final String javaName; + private final int keySizeBits; + + SignatureAlgorithm(String jwaName, String javaName, int keySizeBits) { + this.jwaName = jwaName; + this.javaName = javaName; + this.keySizeBits = keySizeBits; + } + + public String getJwaName() { + return jwaName; + } + + public String getJavaName() { + return javaName == null ? name() : javaName; + } + + public String getJavaAlgoName() { + return AlgorithmUtils.stripAlgoProperties(getJavaName()); + } + + public int getKeySizeBits() { + return keySizeBits; + } + + public static SignatureAlgorithm getAlgorithm(String algo) { + if (algo == null) { + return null; + } + if (AlgorithmUtils.NONE_TEXT_ALGO.equals(algo)) { + return NONE; + } + return SignatureAlgorithm.valueOf(algo.replace('-', '_') + .replace('+', '_')); + + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractContentEncryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractContentEncryptionAlgorithm.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractContentEncryptionAlgorithm.java new file mode 100644 index 0000000..355a21b --- /dev/null +++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractContentEncryptionAlgorithm.java @@ -0,0 +1,60 @@ +/** + * 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.concurrent.atomic.AtomicInteger; + +import org.apache.cxf.rs.security.jose.jwa.ContentAlgorithm; +import org.apache.cxf.rt.security.crypto.CryptoUtils; + + +public abstract class AbstractContentEncryptionAlgorithm extends AbstractContentEncryptionCipherProperties + implements ContentEncryptionProvider { + private static final int DEFAULT_IV_SIZE = 128; + private byte[] cek; + private byte[] iv; + private AtomicInteger providedIvUsageCount; + + + protected AbstractContentEncryptionAlgorithm(byte[] cek, byte[] iv, ContentAlgorithm algo) { + super(algo); + this.cek = cek; + this.iv = iv; + if (iv != null && iv.length > 0) { + providedIvUsageCount = new AtomicInteger(); + } + } + + public byte[] getContentEncryptionKey(JweHeaders headers) { + return cek; + } + public byte[] getInitVector() { + if (iv == null) { + return CryptoUtils.generateSecureRandomBytes(getIvSize() / 8); + } else if (iv.length > 0 && providedIvUsageCount.addAndGet(1) > 1) { + LOG.warning("Custom IV is recommeded to be used once"); + throw new JweException(JweException.Error.CUSTOM_IV_REUSED); + } else { + return iv; + } + } + protected int getIvSize() { + return DEFAULT_IV_SIZE; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractContentEncryptionCipherProperties.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractContentEncryptionCipherProperties.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractContentEncryptionCipherProperties.java new file mode 100644 index 0000000..b683c77 --- /dev/null +++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractContentEncryptionCipherProperties.java @@ -0,0 +1,51 @@ +/** + * 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.logging.Logger; + +import org.apache.cxf.common.logging.LogUtils; +import org.apache.cxf.rs.security.jose.jwa.ContentAlgorithm; +import org.apache.cxf.rt.security.crypto.CryptoUtils; + + +public abstract class AbstractContentEncryptionCipherProperties implements ContentEncryptionCipherProperties { + protected static final Logger LOG = LogUtils.getL7dLogger(AbstractContentEncryptionCipherProperties.class); + + private static final int DEFAULT_AUTH_TAG_LENGTH = 128; + private int authTagLen = DEFAULT_AUTH_TAG_LENGTH; + private ContentAlgorithm algo; + public AbstractContentEncryptionCipherProperties(ContentAlgorithm algo) { + this.algo = algo; + } + public AlgorithmParameterSpec getAlgorithmParameterSpec(byte[] theIv) { + return CryptoUtils.getContentEncryptionCipherSpec(getAuthTagLen(), theIv); + } + public byte[] getAdditionalAuthenticationData(String headersJson, byte[] aad) { + return JweUtils.getAdditionalAuthenticationData(headersJson, aad); + } + protected int getAuthTagLen() { + return authTagLen; + } + @Override + public ContentAlgorithm getAlgorithm() { + return algo; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractJweDecryption.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractJweDecryption.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractJweDecryption.java new file mode 100644 index 0000000..1af9424 --- /dev/null +++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractJweDecryption.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.security.Key; +import java.security.spec.AlgorithmParameterSpec; +import java.util.logging.Logger; + +import org.apache.cxf.common.logging.LogUtils; +import org.apache.cxf.rs.security.jose.JoseConstants; +import org.apache.cxf.rs.security.jose.jwa.AlgorithmUtils; +import org.apache.cxf.rs.security.jose.jwa.ContentAlgorithm; +import org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm; +import org.apache.cxf.rs.security.jose.jws.JwsUtils; +import org.apache.cxf.rt.security.crypto.CryptoUtils; +import org.apache.cxf.rt.security.crypto.KeyProperties; + +public abstract class AbstractJweDecryption implements JweDecryptionProvider { + protected static final Logger LOG = LogUtils.getL7dLogger(JwsUtils.class); + + private KeyDecryptionProvider keyDecryptionAlgo; + private ContentDecryptionProvider contentDecryptionAlgo; + protected AbstractJweDecryption(KeyDecryptionProvider keyDecryptionAlgo, + ContentDecryptionProvider contentDecryptionAlgo) { + this.keyDecryptionAlgo = keyDecryptionAlgo; + this.contentDecryptionAlgo = contentDecryptionAlgo; + } + + protected byte[] getContentEncryptionKey(JweDecryptionInput jweDecryptionInput) { + return keyDecryptionAlgo.getDecryptedContentEncryptionKey(jweDecryptionInput); + } + + public JweDecryptionOutput decrypt(String content) { + JweCompactConsumer consumer = new JweCompactConsumer(content); + byte[] cek = getContentEncryptionKey(consumer.getJweDecryptionInput()); + return doDecrypt(consumer.getJweDecryptionInput(), cek); + } + public byte[] decrypt(JweDecryptionInput jweDecryptionInput) { + byte[] cek = getContentEncryptionKey(jweDecryptionInput); + return doDecrypt(jweDecryptionInput, cek).getContent(); + } + protected JweDecryptionOutput doDecrypt(JweDecryptionInput jweDecryptionInput, byte[] cek) { + KeyProperties keyProperties = new KeyProperties(getContentEncryptionAlgorithm(jweDecryptionInput)); + keyProperties.setAdditionalData(getContentEncryptionCipherAAD(jweDecryptionInput)); + AlgorithmParameterSpec spec = getContentEncryptionCipherSpec(jweDecryptionInput); + keyProperties.setAlgoSpec(spec); + boolean compressionSupported = + JoseConstants.JWE_DEFLATE_ZIP_ALGORITHM.equals(jweDecryptionInput.getJweHeaders().getZipAlgorithm()); + keyProperties.setCompressionSupported(compressionSupported); + byte[] actualCek = getActualCek(cek, + jweDecryptionInput.getJweHeaders().getContentEncryptionAlgorithm().getJwaName()); + Key secretKey = CryptoUtils.createSecretKeySpec(actualCek, keyProperties.getKeyAlgo()); + byte[] bytes = + CryptoUtils.decryptBytes(getEncryptedContentWithAuthTag(jweDecryptionInput), secretKey, keyProperties); + return new JweDecryptionOutput(jweDecryptionInput.getJweHeaders(), bytes); + } + protected byte[] getEncryptedContentEncryptionKey(JweCompactConsumer consumer) { + return consumer.getEncryptedContentEncryptionKey(); + } + protected AlgorithmParameterSpec getContentEncryptionCipherSpec(JweDecryptionInput jweDecryptionInput) { + return contentDecryptionAlgo.getAlgorithmParameterSpec( + getContentEncryptionCipherInitVector(jweDecryptionInput)); + } + protected String getContentEncryptionAlgorithm(JweDecryptionInput jweDecryptionInput) { + return AlgorithmUtils.toJavaName(jweDecryptionInput.getJweHeaders() + .getContentEncryptionAlgorithm().getJwaName()); + } + protected byte[] getContentEncryptionCipherAAD(JweDecryptionInput jweDecryptionInput) { + return contentDecryptionAlgo.getAdditionalAuthenticationData( + jweDecryptionInput.getDecodedJsonHeaders(), jweDecryptionInput.getAad()); + } + protected byte[] getEncryptedContentWithAuthTag(JweDecryptionInput jweDecryptionInput) { + return contentDecryptionAlgo.getEncryptedSequence(jweDecryptionInput.getJweHeaders(), + jweDecryptionInput.getEncryptedContent(), + getEncryptionAuthenticationTag(jweDecryptionInput)); + } + protected byte[] getContentEncryptionCipherInitVector(JweDecryptionInput jweDecryptionInput) { + return jweDecryptionInput.getInitVector(); + } + protected byte[] getEncryptionAuthenticationTag(JweDecryptionInput jweDecryptionInput) { + return jweDecryptionInput.getAuthTag(); + } + protected int getEncryptionAuthenticationTagLenBits(JweDecryptionInput jweDecryptionInput) { + return getEncryptionAuthenticationTag(jweDecryptionInput).length * 8; + } + protected byte[] getActualCek(byte[] theCek, String algoJwt) { + return theCek; + } + @Override + public KeyAlgorithm getKeyAlgorithm() { + return keyDecryptionAlgo.getAlgorithm(); + } + @Override + public ContentAlgorithm getContentAlgorithm() { + return contentDecryptionAlgo.getAlgorithm(); + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractJweEncryption.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractJweEncryption.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractJweEncryption.java new file mode 100644 index 0000000..07e60c4 --- /dev/null +++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractJweEncryption.java @@ -0,0 +1,243 @@ +/** + * 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.NoSuchAlgorithmException; +import java.security.spec.AlgorithmParameterSpec; +import java.util.Arrays; +import java.util.logging.Logger; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; + +import org.apache.cxf.common.logging.LogUtils; +import org.apache.cxf.jaxrs.provider.json.JsonMapObjectReaderWriter; +import org.apache.cxf.rs.security.jose.JoseConstants; +import org.apache.cxf.rs.security.jose.jwa.AlgorithmUtils; +import org.apache.cxf.rs.security.jose.jwa.ContentAlgorithm; +import org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm; +import org.apache.cxf.rt.security.crypto.CryptoUtils; +import org.apache.cxf.rt.security.crypto.KeyProperties; + +public abstract class AbstractJweEncryption implements JweEncryptionProvider { + protected static final Logger LOG = LogUtils.getL7dLogger(AbstractJweEncryption.class); + protected static final int DEFAULT_AUTH_TAG_LENGTH = 128; + private ContentEncryptionProvider contentEncryptionAlgo; + private KeyEncryptionProvider keyEncryptionAlgo; + private JsonMapObjectReaderWriter writer = new JsonMapObjectReaderWriter(); + protected AbstractJweEncryption(ContentEncryptionProvider contentEncryptionAlgo, + KeyEncryptionProvider keyEncryptionAlgo) { + this.keyEncryptionAlgo = keyEncryptionAlgo; + this.contentEncryptionAlgo = contentEncryptionAlgo; + } + protected ContentEncryptionProvider getContentEncryptionAlgorithm() { + return contentEncryptionAlgo; + } + protected AlgorithmParameterSpec getAlgorithmParameterSpec(byte[] theIv) { + return getContentEncryptionAlgorithm().getAlgorithmParameterSpec(theIv); + } + + protected byte[] getContentEncryptionKey(JweHeaders headers) { + byte[] cek = getProvidedContentEncryptionKey(headers); + if (cek == null) { + String algoJava = getContentEncryptionAlgoJava(); + String algoJwt = getContentEncryptionAlgoJwt(); + cek = CryptoUtils.getSecretKey(AlgorithmUtils.stripAlgoProperties(algoJava), + getCekSize(algoJwt)).getEncoded(); + } + return cek; + } + + protected int getCekSize(String algoJwt) { + return ContentAlgorithm.valueOf(algoJwt.replace('-', '_')).getKeySizeBits(); + } + + protected byte[] getProvidedContentEncryptionKey(JweHeaders headers) { + return getContentEncryptionAlgorithm().getContentEncryptionKey(headers); + } + + protected byte[] getEncryptedContentEncryptionKey(JweHeaders headers, byte[] theCek) { + return getKeyEncryptionAlgo().getEncryptedContentEncryptionKey(headers, theCek); + } + + protected String getContentEncryptionAlgoJwt() { + return getContentEncryptionAlgorithm().getAlgorithm().getJwaName(); + } + protected String getContentEncryptionAlgoJava() { + return getContentEncryptionAlgorithm().getAlgorithm().getJavaName(); + } + protected byte[] getAAD(String protectedHeaders, byte[] aad) { + return getContentEncryptionAlgorithm().getAdditionalAuthenticationData(protectedHeaders, aad); + } + @Override + public String encrypt(byte[] content, JweHeaders jweHeaders) { + JweEncryptionInternal state = getInternalState(jweHeaders, null); + + byte[] encryptedContent = encryptInternal(state, content); + byte[] cipher = getActualCipher(encryptedContent); + byte[] authTag = getAuthenticationTag(state, encryptedContent); + JweCompactProducer producer = new JweCompactProducer(state.protectedHeadersJson, + state.jweContentEncryptionKey, + state.theIv, + cipher, + authTag); + return producer.getJweContent(); + } + @Override + public JweEncryptionOutput getEncryptionOutput(JweEncryptionInput jweInput) { + JweEncryptionInternal state = getInternalState(jweInput.getJweHeaders(), jweInput); + Cipher c = null; + AuthenticationTagProducer authTagProducer = null; + byte[] cipher = null; + byte[] authTag = null; + if (jweInput.getContent() == null) { + c = CryptoUtils.initCipher(createCekSecretKey(state), state.keyProps, + Cipher.ENCRYPT_MODE); + authTagProducer = getAuthenticationTagProducer(state); + } else { + byte[] encryptedContent = encryptInternal(state, jweInput.getContent()); + cipher = getActualCipher(encryptedContent); + authTag = getAuthenticationTag(state, encryptedContent); + } + return new JweEncryptionOutput(c, + state.theHeaders, + state.jweContentEncryptionKey, + state.theIv, + authTagProducer, + state.keyProps, + cipher, + authTag); + } + protected byte[] encryptInternal(JweEncryptionInternal state, byte[] content) { + try { + return CryptoUtils.encryptBytes(content, createCekSecretKey(state), state.keyProps); + } catch (SecurityException ex) { + if (ex.getCause() instanceof NoSuchAlgorithmException) { + LOG.warning("Unsupported algorithm: " + state.keyProps.getKeyAlgo()); + throw new JweException(JweException.Error.INVALID_CONTENT_ALGORITHM); + } + throw new JweException(JweException.Error.CONTENT_ENCRYPTION_FAILURE); + } + } + protected byte[] getActualCipher(byte[] cipher) { + return Arrays.copyOf(cipher, cipher.length - DEFAULT_AUTH_TAG_LENGTH / 8); + } + protected byte[] getAuthenticationTag(JweEncryptionInternal state, byte[] cipher) { + return Arrays.copyOfRange(cipher, cipher.length - DEFAULT_AUTH_TAG_LENGTH / 8, cipher.length); + } + @Override + public KeyAlgorithm getKeyAlgorithm() { + KeyAlgorithm keyAlgo = getKeyEncryptionAlgo().getAlgorithm(); + return keyAlgo != null ? keyAlgo : null; + } + @Override + public ContentAlgorithm getContentAlgorithm() { + return getContentEncryptionAlgorithm().getAlgorithm(); + } + protected JsonMapObjectReaderWriter getJwtHeadersWriter() { + return writer; + } + + 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(JweHeaders jweInHeaders, JweEncryptionInput jweInput) { + JweHeaders theHeaders = new JweHeaders(); + if (getKeyAlgorithm() != null) { + theHeaders.setKeyEncryptionAlgorithm(getKeyAlgorithm()); + } + theHeaders.setContentEncryptionAlgorithm(getContentEncryptionAlgorithm().getAlgorithm()); + + JweHeaders protectedHeaders = null; + if (jweInHeaders != null) { + if (jweInHeaders.getKeyEncryptionAlgorithm() != null + && (getKeyAlgorithm() == null + || !getKeyAlgorithm().equals(jweInHeaders.getKeyEncryptionAlgorithm()))) { + LOG.warning("Invalid key encryption algorithm"); + throw new JweException(JweException.Error.INVALID_KEY_ALGORITHM); + } + if (jweInHeaders.getContentEncryptionAlgorithm() != null + && !getContentEncryptionAlgoJwt().equals(jweInHeaders.getContentEncryptionAlgorithm().getJwaName())) { + LOG.warning("Invalid content encryption algorithm"); + throw new JweException(JweException.Error.INVALID_CONTENT_ALGORITHM); + } + theHeaders.asMap().putAll(jweInHeaders.asMap()); + protectedHeaders = jweInHeaders.getProtectedHeaders() != null + ? jweInHeaders.getProtectedHeaders() : theHeaders; + } else { + protectedHeaders = theHeaders; + } + + + + byte[] theCek = jweInput != null && jweInput.getCek() != null + ? jweInput.getCek() : getContentEncryptionKey(theHeaders); + String contentEncryptionAlgoJavaName = getContentEncryptionAlgoJava(); + KeyProperties keyProps = new KeyProperties(contentEncryptionAlgoJavaName); + keyProps.setCompressionSupported(compressionRequired(theHeaders)); + + byte[] theIv = jweInput != null && jweInput.getIv() != null + ? jweInput.getIv() : getContentEncryptionAlgorithm().getInitVector(); + AlgorithmParameterSpec specParams = getAlgorithmParameterSpec(theIv); + keyProps.setAlgoSpec(specParams); + byte[] jweContentEncryptionKey = + getEncryptedContentEncryptionKey(theHeaders, theCek); + + + String protectedHeadersJson = writer.toJson(protectedHeaders); + + byte[] additionalEncryptionParam = getAAD(protectedHeadersJson, + jweInput == null ? null : jweInput.getAad()); + keyProps.setAdditionalData(additionalEncryptionParam); + + JweEncryptionInternal state = new JweEncryptionInternal(); + state.theHeaders = theHeaders; + state.jweContentEncryptionKey = jweContentEncryptionKey; + state.keyProps = keyProps; + state.secretKey = theCek; + state.theIv = theIv; + state.protectedHeadersJson = protectedHeadersJson; + state.aad = jweInput != null ? jweInput.getAad() : null; + return state; + } + private boolean compressionRequired(JweHeaders theHeaders) { + return JoseConstants.JWE_DEFLATE_ZIP_ALGORITHM.equals(theHeaders.getZipAlgorithm()); + } + protected KeyEncryptionProvider getKeyEncryptionAlgo() { + return keyEncryptionAlgo; + } + protected static class JweEncryptionInternal { + JweHeaders theHeaders; + byte[] jweContentEncryptionKey; + byte[] theIv; + KeyProperties keyProps; + byte[] secretKey; + String protectedHeadersJson; + byte[] aad; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractWrapKeyEncryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractWrapKeyEncryptionAlgorithm.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractWrapKeyEncryptionAlgorithm.java new file mode 100644 index 0000000..ffb971f --- /dev/null +++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AbstractWrapKeyEncryptionAlgorithm.java @@ -0,0 +1,105 @@ +/** + * 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 java.util.logging.Logger; + +import org.apache.cxf.common.logging.LogUtils; +import org.apache.cxf.rs.security.jose.jwa.AlgorithmUtils; +import org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm; +import org.apache.cxf.rt.security.crypto.CryptoUtils; +import org.apache.cxf.rt.security.crypto.KeyProperties; + +public abstract class AbstractWrapKeyEncryptionAlgorithm implements KeyEncryptionProvider { + protected static final Logger LOG = LogUtils.getL7dLogger(AbstractWrapKeyEncryptionAlgorithm.class); + private Key keyEncryptionKey; + private boolean wrap; + private KeyAlgorithm 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, KeyAlgorithm jweAlgo, Set<String> supportedAlgorithms) { + this(key, jweAlgo, true, supportedAlgorithms); + } + protected AbstractWrapKeyEncryptionAlgorithm(Key key, KeyAlgorithm jweAlgo, boolean wrap, + Set<String> supportedAlgorithms) { + this.keyEncryptionKey = key; + this.algorithm = jweAlgo; + this.wrap = wrap; + this.supportedAlgorithms = supportedAlgorithms; + } + @Override + public KeyAlgorithm getAlgorithm() { + return algorithm; + } + @Override + public byte[] getEncryptedContentEncryptionKey(JweHeaders headers, byte[] cek) { + checkAlgorithms(headers); + 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 AlgorithmUtils.toJavaName(headers.getKeyEncryptionAlgorithm().getJwaName()); + } + protected String getContentEncryptionAlgoJava(JweHeaders headers) { + return AlgorithmUtils.toJavaName(headers.getContentEncryptionAlgorithm().getJwaName()); + } + protected AlgorithmParameterSpec getAlgorithmParameterSpec(JweHeaders headers) { + return null; + } + protected String checkAlgorithm(String algo) { + if (algo != null && !supportedAlgorithms.contains(algo)) { + LOG.warning("Invalid key encryption algorithm: " + algo); + throw new JweException(JweException.Error.INVALID_KEY_ALGORITHM); + } + return algo; + } + protected void checkAlgorithms(JweHeaders headers) { + KeyAlgorithm providedAlgo = headers.getKeyEncryptionAlgorithm(); + if (providedAlgo != null && !providedAlgo.equals(algorithm)) { + LOG.warning("Invalid key encryption algorithm: " + providedAlgo); + throw new JweException(JweException.Error.INVALID_KEY_ALGORITHM); + } + if (providedAlgo != null) { + checkAlgorithm(providedAlgo.getJwaName()); + } else { + checkAlgorithm(algorithm.getJwaName()); + headers.setKeyEncryptionAlgorithm(algorithm); + } + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesCbcHmacJweDecryption.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesCbcHmacJweDecryption.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesCbcHmacJweDecryption.java new file mode 100644 index 0000000..ee7a91f --- /dev/null +++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesCbcHmacJweDecryption.java @@ -0,0 +1,91 @@ +/** + * 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.jwa.AlgorithmUtils; +import org.apache.cxf.rs.security.jose.jwa.ContentAlgorithm; + +public class AesCbcHmacJweDecryption extends JweDecryption { + private String supportedAlgo; + public AesCbcHmacJweDecryption(KeyDecryptionProvider keyDecryptionAlgo) { + this(keyDecryptionAlgo, null); + } + public AesCbcHmacJweDecryption(KeyDecryptionProvider keyDecryptionAlgo, + ContentAlgorithm supportedAlgo) { + super(keyDecryptionAlgo, new AesCbcContentDecryptionAlgorithm(supportedAlgo)); + this.supportedAlgo = supportedAlgo == null ? null : supportedAlgo.getJwaName(); + } + protected JweDecryptionOutput doDecrypt(JweDecryptionInput jweDecryptionInput, byte[] cek) { + validateAuthenticationTag(jweDecryptionInput, cek); + return super.doDecrypt(jweDecryptionInput, cek); + } + @Override + protected byte[] getActualCek(byte[] theCek, String algoJwt) { + validateCekAlgorithm(algoJwt); + return AesCbcHmacJweEncryption.doGetActualCek(theCek, algoJwt); + } + protected void validateAuthenticationTag(JweDecryptionInput jweDecryptionInput, byte[] theCek) { + byte[] actualAuthTag = jweDecryptionInput.getAuthTag(); + + final AesCbcHmacJweEncryption.MacState macState = + AesCbcHmacJweEncryption.getInitializedMacState(theCek, + jweDecryptionInput.getInitVector(), + jweDecryptionInput.getAad(), + jweDecryptionInput.getJweHeaders(), + jweDecryptionInput.getDecodedJsonHeaders()); + macState.mac.update(jweDecryptionInput.getEncryptedContent()); + byte[] expectedAuthTag = AesCbcHmacJweEncryption.signAndGetTag(macState); + if (!Arrays.equals(actualAuthTag, expectedAuthTag)) { + LOG.warning("Invalid authentication tag"); + throw new JweException(JweException.Error.CONTENT_DECRYPTION_FAILURE); + } + + } + private static class AesCbcContentDecryptionAlgorithm extends AbstractContentEncryptionCipherProperties + implements ContentDecryptionProvider { + AesCbcContentDecryptionAlgorithm(ContentAlgorithm supportedAlgo) { + super(supportedAlgo); + } + @Override + public AlgorithmParameterSpec getAlgorithmParameterSpec(byte[] theIv) { + return new IvParameterSpec(theIv); + } + @Override + public byte[] getAdditionalAuthenticationData(String headersJson, byte[] aad) { + return null; + } + @Override + public byte[] getEncryptedSequence(JweHeaders headers, byte[] cipher, byte[] authTag) { + return cipher; + } + } + private String validateCekAlgorithm(String cekAlgo) { + if (!AlgorithmUtils.isAesCbcHmac(cekAlgo) + || supportedAlgo != null && !supportedAlgo.equals(cekAlgo)) { + LOG.warning("Invalid content encryption algorithm"); + throw new JweException(JweException.Error.INVALID_CONTENT_ALGORITHM); + } + return cekAlgo; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesCbcHmacJweEncryption.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesCbcHmacJweEncryption.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesCbcHmacJweEncryption.java new file mode 100644 index 0000000..8f1e4bc --- /dev/null +++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesCbcHmacJweEncryption.java @@ -0,0 +1,175 @@ +/** + * 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.HashMap; +import java.util.Map; + +import javax.crypto.Mac; +import javax.crypto.spec.IvParameterSpec; + +import org.apache.cxf.rs.security.jose.jwa.AlgorithmUtils; +import org.apache.cxf.rs.security.jose.jwa.ContentAlgorithm; +import org.apache.cxf.rt.security.crypto.HmacUtils; + +public class AesCbcHmacJweEncryption extends JweEncryption { + 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(ContentAlgorithm.A128CBC_HS256.getJwaName(), AlgorithmUtils.HMAC_SHA_256_JAVA); + AES_HMAC_MAP.put(ContentAlgorithm.A192CBC_HS384.getJwaName(), AlgorithmUtils.HMAC_SHA_384_JAVA); + AES_HMAC_MAP.put(ContentAlgorithm.A256CBC_HS512.getJwaName(), AlgorithmUtils.HMAC_SHA_512_JAVA); + + AES_CEK_SIZE_MAP = new HashMap<String, Integer>(); + AES_CEK_SIZE_MAP.put(ContentAlgorithm.A128CBC_HS256.getJwaName(), 32); + AES_CEK_SIZE_MAP.put(ContentAlgorithm.A192CBC_HS384.getJwaName(), 48); + AES_CEK_SIZE_MAP.put(ContentAlgorithm.A256CBC_HS512.getJwaName(), 64); + } + public AesCbcHmacJweEncryption(String cekAlgo, + KeyEncryptionProvider keyEncryptionAlgorithm) { + this(ContentAlgorithm.getAlgorithm(cekAlgo), keyEncryptionAlgorithm); + } + public AesCbcHmacJweEncryption(ContentAlgorithm cekAlgoJwt, + KeyEncryptionProvider keyEncryptionAlgorithm) { + this(cekAlgoJwt, null, null, keyEncryptionAlgorithm); + } + public AesCbcHmacJweEncryption(ContentAlgorithm cekAlgoJwt, byte[] cek, + byte[] iv, KeyEncryptionProvider keyEncryptionAlgorithm) { + super(keyEncryptionAlgorithm, + new AesCbcContentEncryptionAlgorithm(cek, iv, + validateCekAlgorithm(cekAlgoJwt))); + + } + @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 byte[] getActualCipher(byte[] cipher) { + return cipher; + } + protected byte[] getAuthenticationTag(JweEncryptionInternal state, byte[] cipher) { + final MacState macState = getInitializedMacState(state); + macState.mac.update(cipher); + return signAndGetTag(macState); + } + + 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) { + return getInitializedMacState(state.secretKey, state.theIv, state.aad, + state.theHeaders, state.protectedHeadersJson); + } + protected static MacState getInitializedMacState(byte[] secretKey, + byte[] theIv, + byte[] extraAad, + JweHeaders theHeaders, + String protectedHeadersJson) { + String algoJwt = theHeaders.getContentEncryptionAlgorithm().getJwaName(); + 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 = JweUtils.getAdditionalAuthenticationData(protectedHeadersJson, extraAad); + 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; + 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); + } + }; + } + @Override + protected byte[] getEncryptedContentEncryptionKey(JweHeaders headers, byte[] theCek) { + return getKeyEncryptionAlgo().getEncryptedContentEncryptionKey(headers, theCek); + } + + private static class AesCbcContentEncryptionAlgorithm extends AbstractContentEncryptionAlgorithm { + AesCbcContentEncryptionAlgorithm(byte[] cek, byte[] iv, ContentAlgorithm algo) { + super(cek, iv, algo); + } + @Override + public AlgorithmParameterSpec getAlgorithmParameterSpec(byte[] theIv) { + return new IvParameterSpec(theIv); + } + @Override + public byte[] getAdditionalAuthenticationData(String headersJson, byte[] aad) { + return null; + } + } + + protected static class MacState { + protected Mac mac; + private byte[] al; + } + + private static ContentAlgorithm validateCekAlgorithm(ContentAlgorithm cekAlgo) { + if (!AlgorithmUtils.isAesCbcHmac(cekAlgo.getJwaName())) { + LOG.warning("Invalid content encryption algorithm"); + throw new JweException(JweException.Error.INVALID_CONTENT_ALGORITHM); + } + return cekAlgo; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmContentDecryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmContentDecryptionAlgorithm.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmContentDecryptionAlgorithm.java new file mode 100644 index 0000000..64206b7 --- /dev/null +++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmContentDecryptionAlgorithm.java @@ -0,0 +1,41 @@ +/** + * 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 org.apache.cxf.rs.security.jose.jwa.AlgorithmUtils; +import org.apache.cxf.rs.security.jose.jwa.ContentAlgorithm; + + + +public class AesGcmContentDecryptionAlgorithm extends AbstractContentEncryptionCipherProperties + implements ContentDecryptionProvider { + public AesGcmContentDecryptionAlgorithm(ContentAlgorithm supportedAlgo) { + super(supportedAlgo); + } + + @Override + public byte[] getEncryptedSequence(JweHeaders headers, byte[] cipher, byte[] authTag) { + String algo = headers.getContentEncryptionAlgorithm().getJwaName(); + if (!AlgorithmUtils.isAesGcm(algo) || !getAlgorithm().getJwaName().equals(algo)) { + LOG.warning("Invalid content encryption algorithm"); + throw new JweException(JweException.Error.INVALID_CONTENT_ALGORITHM); + } + return JweCompactConsumer.getCipherWithAuthTag(cipher, authTag); + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmContentEncryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmContentEncryptionAlgorithm.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmContentEncryptionAlgorithm.java new file mode 100644 index 0000000..4f87829 --- /dev/null +++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmContentEncryptionAlgorithm.java @@ -0,0 +1,55 @@ +/** + * 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.AlgorithmUtils; +import org.apache.cxf.rs.security.jose.jwa.ContentAlgorithm; +import org.apache.cxf.rt.security.crypto.CryptoUtils; + + +public class AesGcmContentEncryptionAlgorithm extends AbstractContentEncryptionAlgorithm { + private static final int DEFAULT_IV_SIZE = 96; + public AesGcmContentEncryptionAlgorithm(ContentAlgorithm algo) { + this((byte[])null, null, algo); + } + public AesGcmContentEncryptionAlgorithm(String encodedCek, String encodedIv, ContentAlgorithm algo) { + this((byte[])CryptoUtils.decodeSequence(encodedCek), CryptoUtils.decodeSequence(encodedIv), algo); + } + public AesGcmContentEncryptionAlgorithm(String encodedCek, ContentAlgorithm algo) { + this((byte[])CryptoUtils.decodeSequence(encodedCek), null, algo); + } + public AesGcmContentEncryptionAlgorithm(SecretKey key, byte[] iv, ContentAlgorithm algo) { + this(key.getEncoded(), iv, algo); + } + public AesGcmContentEncryptionAlgorithm(byte[] cek, byte[] iv, ContentAlgorithm algo) { + super(cek, iv, checkAlgorithm(algo)); + } + protected int getIvSize() { + return DEFAULT_IV_SIZE; + } + private static ContentAlgorithm checkAlgorithm(ContentAlgorithm algo) { + if (AlgorithmUtils.isAesGcm(algo.getJwaName())) { + return algo; + } + LOG.warning("Invalid content encryption algorithm"); + throw new JweException(JweException.Error.INVALID_CONTENT_ALGORITHM); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmWrapKeyDecryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmWrapKeyDecryptionAlgorithm.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmWrapKeyDecryptionAlgorithm.java new file mode 100644 index 0000000..dda527e --- /dev/null +++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmWrapKeyDecryptionAlgorithm.java @@ -0,0 +1,78 @@ +/** + * 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.logging.Logger; + +import javax.crypto.SecretKey; + +import org.apache.cxf.common.logging.LogUtils; +import org.apache.cxf.common.util.Base64UrlUtility; +import org.apache.cxf.rs.security.jose.JoseException; +import org.apache.cxf.rs.security.jose.jwa.AlgorithmUtils; +import org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm; +import org.apache.cxf.rt.security.crypto.CryptoUtils; + +public class AesGcmWrapKeyDecryptionAlgorithm extends WrappedKeyDecryptionAlgorithm { + protected static final Logger LOG = LogUtils.getL7dLogger(AesGcmWrapKeyDecryptionAlgorithm.class); + public AesGcmWrapKeyDecryptionAlgorithm(String encodedKey) { + this(encodedKey, null); + } + public AesGcmWrapKeyDecryptionAlgorithm(String encodedKey, KeyAlgorithm supportedAlgo) { + this(CryptoUtils.decodeSequence(encodedKey), supportedAlgo); + } + public AesGcmWrapKeyDecryptionAlgorithm(byte[] secretKey) { + this(secretKey, KeyAlgorithm.A128GCMKW); + } + public AesGcmWrapKeyDecryptionAlgorithm(byte[] secretKey, KeyAlgorithm supportedAlgo) { + this(CryptoUtils.createSecretKeySpec(secretKey, AlgorithmUtils.AES), supportedAlgo); + } + public AesGcmWrapKeyDecryptionAlgorithm(SecretKey secretKey) { + this(secretKey, null); + } + public AesGcmWrapKeyDecryptionAlgorithm(SecretKey secretKey, KeyAlgorithm supportedAlgo) { + super(secretKey, supportedAlgo); + } + @Override + protected byte[] getEncryptedContentEncryptionKey(JweDecryptionInput jweDecryptionInput) { + byte[] encryptedCekKey = super.getEncryptedContentEncryptionKey(jweDecryptionInput); + byte[] tag = getDecodedBytes(jweDecryptionInput, "tag"); + return JweCompactConsumer.getCipherWithAuthTag(encryptedCekKey, tag); + } + protected AlgorithmParameterSpec getAlgorithmParameterSpec(JweDecryptionInput jweDecryptionInput) { + byte[] iv = getDecodedBytes(jweDecryptionInput, "iv"); + return CryptoUtils.getContentEncryptionCipherSpec(128, iv); + } + private byte[] getDecodedBytes(JweDecryptionInput jweDecryptionInput, String headerName) { + try { + Object ivHeader = jweDecryptionInput.getJweHeaders().getHeader(headerName); + return Base64UrlUtility.decode(ivHeader.toString()); + } catch (Exception ex) { + throw new JoseException(ex); + } + } + protected void validateKeyEncryptionAlgorithm(String keyAlgo) { + super.validateKeyEncryptionAlgorithm(keyAlgo); + if (!AlgorithmUtils.isAesGcmKeyWrap(keyAlgo)) { + LOG.warning("Invalid key encryption algorithm"); + throw new JweException(JweException.Error.INVALID_KEY_ALGORITHM); + } + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmWrapKeyEncryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmWrapKeyEncryptionAlgorithm.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmWrapKeyEncryptionAlgorithm.java new file mode 100644 index 0000000..6349b7d --- /dev/null +++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesGcmWrapKeyEncryptionAlgorithm.java @@ -0,0 +1,65 @@ +/** + * 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.common.util.Base64UrlUtility; +import org.apache.cxf.rs.security.jose.jwa.AlgorithmUtils; +import org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm; +import org.apache.cxf.rt.security.crypto.CryptoUtils; + +public class AesGcmWrapKeyEncryptionAlgorithm extends AbstractWrapKeyEncryptionAlgorithm { + private static final Set<String> SUPPORTED_ALGORITHMS = new HashSet<String>( + Arrays.asList(KeyAlgorithm.A128GCMKW.getJwaName(), + KeyAlgorithm.A192GCMKW.getJwaName(), + KeyAlgorithm.A256GCMKW.getJwaName())); + public AesGcmWrapKeyEncryptionAlgorithm(String encodedKey, KeyAlgorithm keyAlgoJwt) { + this(CryptoUtils.decodeSequence(encodedKey), keyAlgoJwt); + } + public AesGcmWrapKeyEncryptionAlgorithm(byte[] keyBytes, KeyAlgorithm keyAlgoJwt) { + this(CryptoUtils.createSecretKeySpec(keyBytes, AlgorithmUtils.AES), + keyAlgoJwt); + } + public AesGcmWrapKeyEncryptionAlgorithm(SecretKey key, KeyAlgorithm 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/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesWrapKeyDecryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesWrapKeyDecryptionAlgorithm.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesWrapKeyDecryptionAlgorithm.java new file mode 100644 index 0000000..11350a2 --- /dev/null +++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesWrapKeyDecryptionAlgorithm.java @@ -0,0 +1,59 @@ +/** + * 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.AlgorithmUtils; +import org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm; +import org.apache.cxf.rt.security.crypto.CryptoUtils; + +public class AesWrapKeyDecryptionAlgorithm extends WrappedKeyDecryptionAlgorithm { + public AesWrapKeyDecryptionAlgorithm(String encodedKey) { + this(encodedKey, KeyAlgorithm.A128KW); + } + public AesWrapKeyDecryptionAlgorithm(String encodedKey, KeyAlgorithm supportedAlgo) { + this(CryptoUtils.decodeSequence(encodedKey), supportedAlgo); + } + public AesWrapKeyDecryptionAlgorithm(byte[] secretKey) { + this(secretKey, KeyAlgorithm.A128KW); + } + public AesWrapKeyDecryptionAlgorithm(byte[] secretKey, KeyAlgorithm supportedAlgo) { + this(CryptoUtils.createSecretKeySpec(secretKey, AlgorithmUtils.AES_WRAP_ALGO_JAVA), + supportedAlgo); + } + public AesWrapKeyDecryptionAlgorithm(SecretKey secretKey) { + this(secretKey, null); + } + public AesWrapKeyDecryptionAlgorithm(SecretKey secretKey, KeyAlgorithm supportedAlgo) { + super(secretKey, supportedAlgo); + } + @Override + protected void validateKeyEncryptionAlgorithm(String keyAlgo) { + super.validateKeyEncryptionAlgorithm(keyAlgo); + if (!isValidAlgorithmFamily(keyAlgo)) { + reportInvalidKeyAlgorithm(keyAlgo); + } + } + + protected boolean isValidAlgorithmFamily(String keyAlgo) { + return AlgorithmUtils.isAesKeyWrap(keyAlgo); + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesWrapKeyEncryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesWrapKeyEncryptionAlgorithm.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AesWrapKeyEncryptionAlgorithm.java new file mode 100644 index 0000000..3fe85e3 --- /dev/null +++ b/rt/rs/security/jose/jose-core/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.KeyAlgorithm; +import org.apache.cxf.rt.security.crypto.CryptoUtils; + +public class AesWrapKeyEncryptionAlgorithm extends AbstractWrapKeyEncryptionAlgorithm { + private static final Set<String> SUPPORTED_ALGORITHMS = new HashSet<String>( + Arrays.asList(KeyAlgorithm.A128KW.getJwaName(), + KeyAlgorithm.A192KW.getJwaName(), + KeyAlgorithm.A256KW.getJwaName())); + public AesWrapKeyEncryptionAlgorithm(String encodedKey, KeyAlgorithm keyAlgoJwt) { + this(CryptoUtils.decodeSequence(encodedKey), keyAlgoJwt); + } + public AesWrapKeyEncryptionAlgorithm(byte[] keyBytes, KeyAlgorithm keyAlgoJwt) { + this(CryptoUtils.createSecretKeySpec(keyBytes, keyAlgoJwt.getJavaName()), + keyAlgoJwt); + } + public AesWrapKeyEncryptionAlgorithm(SecretKey key, KeyAlgorithm keyAlgoJwt) { + super(key, keyAlgoJwt, SUPPORTED_ALGORITHMS); + } + + + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AuthenticationTagProducer.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/AuthenticationTagProducer.java b/rt/rs/security/jose/jose-core/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/jose/jose-core/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/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentDecryptionProvider.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentDecryptionProvider.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentDecryptionProvider.java new file mode 100644 index 0000000..6c79019 --- /dev/null +++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentDecryptionProvider.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 ContentDecryptionProvider extends ContentEncryptionCipherProperties { + byte[] getEncryptedSequence(JweHeaders headers, byte[] cipher, byte[] authTag); +} http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentEncryptionCipherProperties.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentEncryptionCipherProperties.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentEncryptionCipherProperties.java new file mode 100644 index 0000000..055d602 --- /dev/null +++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentEncryptionCipherProperties.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; + +import java.security.spec.AlgorithmParameterSpec; + +import org.apache.cxf.rs.security.jose.jwa.ContentAlgorithm; + + +public interface ContentEncryptionCipherProperties { + ContentAlgorithm getAlgorithm(); + byte[] getAdditionalAuthenticationData(String headersJson, byte[] aad); + AlgorithmParameterSpec getAlgorithmParameterSpec(byte[] iv); +} http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentEncryptionProvider.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentEncryptionProvider.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentEncryptionProvider.java new file mode 100644 index 0000000..940455a --- /dev/null +++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentEncryptionProvider.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 ContentEncryptionProvider extends ContentEncryptionCipherProperties { + byte[] getInitVector(); + byte[] getContentEncryptionKey(JweHeaders headers); +} http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyDecryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyDecryptionAlgorithm.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyDecryptionAlgorithm.java new file mode 100644 index 0000000..3883dcd --- /dev/null +++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyDecryptionAlgorithm.java @@ -0,0 +1,56 @@ +/** + * 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.util.logging.Logger; + +import org.apache.cxf.common.logging.LogUtils; +import org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm; +import org.apache.cxf.rt.security.crypto.CryptoUtils; + +public class DirectKeyDecryptionAlgorithm implements KeyDecryptionProvider { + private static final Logger LOG = LogUtils.getL7dLogger(DirectKeyDecryptionAlgorithm.class); + private byte[] contentDecryptionKey; + public DirectKeyDecryptionAlgorithm(Key contentDecryptionKey) { + this(contentDecryptionKey.getEncoded()); + } + public DirectKeyDecryptionAlgorithm(String encodedContentDecryptionKey) { + this(CryptoUtils.decodeSequence(encodedContentDecryptionKey)); + } + public DirectKeyDecryptionAlgorithm(byte[] contentDecryptionKey) { + this.contentDecryptionKey = contentDecryptionKey; + } + @Override + public byte[] getDecryptedContentEncryptionKey(JweDecryptionInput jweDecryptionInput) { + validateKeyEncryptionKey(jweDecryptionInput); + return contentDecryptionKey; + } + @Override + public KeyAlgorithm getAlgorithm() { + return null; + } + protected void validateKeyEncryptionKey(JweDecryptionInput jweDecryptionInput) { + byte[] encryptedCEK = jweDecryptionInput.getEncryptedCEK(); + if (encryptedCEK != null && encryptedCEK.length > 0) { + LOG.warning("Unexpected content encryption key"); + throw new JweException(JweException.Error.INVALID_KEY_ALGORITHM); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyEncryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyEncryptionAlgorithm.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyEncryptionAlgorithm.java new file mode 100644 index 0000000..2f038a9 --- /dev/null +++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyEncryptionAlgorithm.java @@ -0,0 +1,42 @@ +/** + * 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.logging.Logger; + +import org.apache.cxf.common.logging.LogUtils; +import org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm; + +public class DirectKeyEncryptionAlgorithm implements KeyEncryptionProvider { + private static final Logger LOG = LogUtils.getL7dLogger(DirectKeyEncryptionAlgorithm.class); + public byte[] getEncryptedContentEncryptionKey(JweHeaders headers, byte[] theCek) { + checkKeyEncryptionAlgorithm(headers); + return new byte[0]; + } + protected void checkKeyEncryptionAlgorithm(JweHeaders headers) { + if (headers.getKeyEncryptionAlgorithm() != null) { + LOG.warning("Key encryption algorithm header is set"); + throw new JweException(JweException.Error.INVALID_KEY_ALGORITHM); + } + } + @Override + public KeyAlgorithm getAlgorithm() { + return null; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyJweDecryption.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyJweDecryption.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyJweDecryption.java new file mode 100644 index 0000000..7434acf --- /dev/null +++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyJweDecryption.java @@ -0,0 +1,32 @@ +/** + * 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 DirectKeyJweDecryption extends JweDecryption { + public DirectKeyJweDecryption(String encodedKey, ContentDecryptionProvider ctAlgo) { + super(new DirectKeyDecryptionAlgorithm(encodedKey), + ctAlgo); + } + public DirectKeyJweDecryption(byte[] key, ContentDecryptionProvider ctAlgo) { + super(new DirectKeyDecryptionAlgorithm(key), + ctAlgo); + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyJweEncryption.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyJweEncryption.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyJweEncryption.java new file mode 100644 index 0000000..3c83466 --- /dev/null +++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyJweEncryption.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; + + + +public class DirectKeyJweEncryption extends JweEncryption { + public DirectKeyJweEncryption(ContentEncryptionProvider contentEncryptionAlgo) { + super(new DirectKeyEncryptionAlgorithm(), contentEncryptionAlgo); + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/EcdhAesWrapKeyDecryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/EcdhAesWrapKeyDecryptionAlgorithm.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/EcdhAesWrapKeyDecryptionAlgorithm.java new file mode 100644 index 0000000..4860904 --- /dev/null +++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/EcdhAesWrapKeyDecryptionAlgorithm.java @@ -0,0 +1,54 @@ +/** + * 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.interfaces.ECPrivateKey; + +import org.apache.cxf.rs.security.jose.jwa.AlgorithmUtils; +import org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm; + +public class EcdhAesWrapKeyDecryptionAlgorithm implements KeyDecryptionProvider { + private ECPrivateKey key; + private KeyAlgorithm algo; + public EcdhAesWrapKeyDecryptionAlgorithm(ECPrivateKey key) { + this(key, KeyAlgorithm.ECDH_ES_A128KW); + } + public EcdhAesWrapKeyDecryptionAlgorithm(ECPrivateKey key, KeyAlgorithm algo) { + this.key = key; + this.algo = algo; + } + @Override + public byte[] getDecryptedContentEncryptionKey(JweDecryptionInput jweDecryptionInput) { + byte[] derivedKey = + EcdhDirectKeyJweDecryption.getDecryptedContentEncryptionKeyFromHeaders( + jweDecryptionInput.getJweHeaders(), key); + KeyDecryptionProvider aesWrap = new AesWrapKeyDecryptionAlgorithm(derivedKey) { + protected boolean isValidAlgorithmFamily(String wrapAlgo) { + return AlgorithmUtils.isEcdhEsWrap(wrapAlgo); + } + }; + return aesWrap.getDecryptedContentEncryptionKey(jweDecryptionInput); + } + + @Override + public KeyAlgorithm getAlgorithm() { + return algo; + } + +}
