http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/EcdhAesWrapKeyDecryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/EcdhAesWrapKeyDecryptionAlgorithm.java b/rt/rs/security/jose-parent/jose/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-parent/jose/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; + } + +}
http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/EcdhAesWrapKeyEncryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/EcdhAesWrapKeyEncryptionAlgorithm.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/EcdhAesWrapKeyEncryptionAlgorithm.java new file mode 100644 index 0000000..6ebf791 --- /dev/null +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/EcdhAesWrapKeyEncryptionAlgorithm.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.interfaces.ECPublicKey; +import java.util.HashMap; +import java.util.Map; + +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.jwe.EcdhDirectKeyJweEncryption.EcdhHelper; +import org.apache.cxf.rs.security.jose.jwk.JsonWebKey; + +public class EcdhAesWrapKeyEncryptionAlgorithm implements KeyEncryptionProvider { + + private static final Map<String, String> ECDH_AES_MAP; + static { + ECDH_AES_MAP = new HashMap<String, String>(); + ECDH_AES_MAP.put(KeyAlgorithm.ECDH_ES_A128KW.getJwaName(), KeyAlgorithm.A128KW.getJwaName()); + ECDH_AES_MAP.put(KeyAlgorithm.ECDH_ES_A192KW.getJwaName(), KeyAlgorithm.A192KW.getJwaName()); + ECDH_AES_MAP.put(KeyAlgorithm.ECDH_ES_A256KW.getJwaName(), KeyAlgorithm.A256KW.getJwaName()); + } + private KeyAlgorithm keyAlgo; + private EcdhHelper helper; + + public EcdhAesWrapKeyEncryptionAlgorithm(ECPublicKey peerPublicKey, + KeyAlgorithm keyAlgo) { + this(peerPublicKey, JsonWebKey.EC_CURVE_P256, keyAlgo); + } + public EcdhAesWrapKeyEncryptionAlgorithm(ECPublicKey peerPublicKey, + String curve, + KeyAlgorithm keyAlgo) { + + this(peerPublicKey, curve, null, null, keyAlgo, ContentAlgorithm.A128GCM); + } + public EcdhAesWrapKeyEncryptionAlgorithm(ECPublicKey peerPublicKey, + String curve, + KeyAlgorithm keyAlgo, + ContentAlgorithm ctAlgo) { + + this(peerPublicKey, curve, null, null, keyAlgo, ctAlgo); + } + public EcdhAesWrapKeyEncryptionAlgorithm(ECPublicKey peerPublicKey, + String curve, + String apuString, + String apvString, + KeyAlgorithm keyAlgo, + ContentAlgorithm ctAlgo) { + + this.keyAlgo = keyAlgo; + helper = new EcdhHelper(peerPublicKey, curve, apuString, apvString, + ctAlgo.getJwaName()); + } + + @Override + public byte[] getEncryptedContentEncryptionKey(JweHeaders headers, byte[] cek) { + final byte[] derivedKey = helper.getDerivedKey(headers); + KeyEncryptionProvider aesWrap = new AesWrapKeyEncryptionAlgorithm(derivedKey, + keyAlgo) { + protected void checkAlgorithms(JweHeaders headers) { + // complete + } + protected String getKeyEncryptionAlgoJava(JweHeaders headers) { + return AlgorithmUtils.AES_WRAP_ALGO_JAVA; + } + }; + return aesWrap.getEncryptedContentEncryptionKey(headers, cek); + } + + @Override + public KeyAlgorithm getAlgorithm() { + return keyAlgo; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/EcdhDirectKeyJweDecryption.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/EcdhDirectKeyJweDecryption.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/EcdhDirectKeyJweDecryption.java new file mode 100644 index 0000000..85485e0 --- /dev/null +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/EcdhDirectKeyJweDecryption.java @@ -0,0 +1,58 @@ +/** + * 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.common.JoseUtils; +import org.apache.cxf.rs.security.jose.jwa.ContentAlgorithm; +import org.apache.cxf.rs.security.jose.jwk.JsonWebKey; +import org.apache.cxf.rs.security.jose.jwk.JwkUtils; + + +public class EcdhDirectKeyJweDecryption extends JweDecryption { + public EcdhDirectKeyJweDecryption(ECPrivateKey privateKey, ContentAlgorithm supportedCtAlgo) { + super(new EcdhDirectKeyDecryptionAlgorithm(privateKey), + new AesGcmContentDecryptionAlgorithm(supportedCtAlgo)); + } + protected static byte[] getDecryptedContentEncryptionKeyFromHeaders(JweHeaders headers, + ECPrivateKey privateKey) { + ContentAlgorithm jwtAlgo = headers.getContentEncryptionAlgorithm(); + JsonWebKey publicJwk = headers.getJsonWebKey("epv"); + String apuHeader = (String)headers.getHeader("apu"); + byte[] apuBytes = apuHeader == null ? null : JoseUtils.decode(apuHeader); + String apvHeader = (String)headers.getHeader("apv"); + byte[] apvBytes = apvHeader == null ? null : JoseUtils.decode(apvHeader); + return JweUtils.getECDHKey(privateKey, JwkUtils.toECPublicKey(publicJwk), + apuBytes, apvBytes, jwtAlgo.getJwaName(), jwtAlgo.getKeySizeBits()); + } + protected static class EcdhDirectKeyDecryptionAlgorithm extends DirectKeyDecryptionAlgorithm { + private ECPrivateKey privateKey; + public EcdhDirectKeyDecryptionAlgorithm(ECPrivateKey privateKey) { + super((byte[])null); + this.privateKey = privateKey; + } + @Override + public byte[] getDecryptedContentEncryptionKey(JweDecryptionInput jweDecryptionInput) { + super.validateKeyEncryptionKey(jweDecryptionInput); + + return getDecryptedContentEncryptionKeyFromHeaders(jweDecryptionInput.getJweHeaders(), privateKey); + } + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/EcdhDirectKeyJweEncryption.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/EcdhDirectKeyJweEncryption.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/EcdhDirectKeyJweEncryption.java new file mode 100644 index 0000000..39b6928 --- /dev/null +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/EcdhDirectKeyJweEncryption.java @@ -0,0 +1,118 @@ +/** + * 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.KeyPair; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; + +import org.apache.cxf.common.util.Base64UrlUtility; +import org.apache.cxf.common.util.StringUtils; +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.jwk.JwkUtils; +import org.apache.cxf.rt.security.crypto.CryptoUtils; + + +public class EcdhDirectKeyJweEncryption extends JweEncryption { + public EcdhDirectKeyJweEncryption(ECPublicKey peerPublicKey, + String curve, + ContentAlgorithm ctAlgo) { + this(peerPublicKey, curve, null, null, ctAlgo); + } + public EcdhDirectKeyJweEncryption(ECPublicKey peerPublicKey, + String curve, + String apuString, + String apvString, + ContentAlgorithm ctAlgo) { + super(new EcdhDirectKeyEncryptionAlgorithm(), + new EcdhAesGcmContentEncryptionAlgorithm(peerPublicKey, + curve, + apuString, + apvString, + ctAlgo)); + } + protected static class EcdhDirectKeyEncryptionAlgorithm extends DirectKeyEncryptionAlgorithm { + protected void checkKeyEncryptionAlgorithm(JweHeaders headers) { + headers.setKeyEncryptionAlgorithm(KeyAlgorithm.ECDH_ES_DIRECT); + } + } + protected static class EcdhAesGcmContentEncryptionAlgorithm extends AesGcmContentEncryptionAlgorithm { + private EcdhHelper helper; + public EcdhAesGcmContentEncryptionAlgorithm(ECPublicKey peerPublicKey, + String curve, + String apuString, + String apvString, + ContentAlgorithm ctAlgo) { + super(ctAlgo); + helper = new EcdhHelper(peerPublicKey, curve, apuString, apvString, ctAlgo.getJwaName()); + } + public byte[] getContentEncryptionKey(JweHeaders headers) { + return helper.getDerivedKey(headers); + } + } + + protected static class EcdhHelper { + private ECPublicKey peerPublicKey; + private String ecurve; + private byte[] apuBytes; + private byte[] apvBytes; + private String ctAlgo; + public EcdhHelper(ECPublicKey peerPublicKey, + String curve, + String apuString, + String apvString, + String ctAlgo) { + this.ctAlgo = ctAlgo; + this.peerPublicKey = peerPublicKey; + this.ecurve = curve; + // JWA spec suggests the "apu" field MAY either be omitted or + // represent a random 512-bit value (...) and the "apv" field SHOULD NOT be present." + this.apuBytes = toApuBytes(apuString); + this.apvBytes = toBytes(apvString); + } + public byte[] getDerivedKey(JweHeaders headers) { + KeyPair pair = CryptoUtils.generateECKeyPair(ecurve); + ECPublicKey publicKey = (ECPublicKey)pair.getPublic(); + ECPrivateKey privateKey = (ECPrivateKey)pair.getPrivate(); + ContentAlgorithm jwtAlgo = ContentAlgorithm.valueOf(ctAlgo); + + headers.setHeader("apu", Base64UrlUtility.encode(apuBytes)); + headers.setHeader("apv", Base64UrlUtility.encode(apvBytes)); + headers.setJsonWebKey("epv", JwkUtils.fromECPublicKey(publicKey, ecurve)); + + return JweUtils.getECDHKey(privateKey, peerPublicKey, apuBytes, apvBytes, + jwtAlgo.getJwaName(), jwtAlgo.getKeySizeBits()); + + } + private byte[] toApuBytes(String apuString) { + if (apuString != null) { + return toBytes(apuString); + } else { + return CryptoUtils.generateSecureRandomBytes(512 / 8); + } + + } + private byte[] toBytes(String str) { + return str == null ? null : StringUtils.toBytesUTF8(str); + } + + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCompactConsumer.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCompactConsumer.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCompactConsumer.java new file mode 100644 index 0000000..eb0c2a7 --- /dev/null +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCompactConsumer.java @@ -0,0 +1,125 @@ +/** + * 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 java.util.logging.Logger; + +import org.apache.cxf.common.logging.LogUtils; +import org.apache.cxf.common.util.Base64Exception; +import org.apache.cxf.common.util.Base64UrlUtility; +import org.apache.cxf.jaxrs.json.basic.JsonMapObject; +import org.apache.cxf.jaxrs.json.basic.JsonMapObjectReaderWriter; +import org.apache.cxf.rs.security.jose.common.JoseException; +import org.apache.cxf.rs.security.jose.common.JoseUtils; + + +public class JweCompactConsumer { + protected static final Logger LOG = LogUtils.getL7dLogger(JweCompactConsumer.class); + private JweDecryptionInput jweDecryptionInput; + public JweCompactConsumer(String jweContent) { + String[] parts = JoseUtils.getCompactParts(jweContent); + if (parts.length != 5) { + LOG.warning("5 JWE parts are expected"); + throw new JweException(JweException.Error.INVALID_COMPACT_JWE); + } + try { + String headersJson = new String(Base64UrlUtility.decode(parts[0])); + byte[] encryptedCEK = Base64UrlUtility.decode(parts[1]); + byte[] initVector = Base64UrlUtility.decode(parts[2]); + byte[] encryptedContent = Base64UrlUtility.decode(parts[3]); + byte[] authTag = Base64UrlUtility.decode(parts[4]); + JsonMapObjectReaderWriter reader = new JsonMapObjectReaderWriter(); + JsonMapObject joseHeaders = reader.fromJsonToJsonObject(headersJson); + if (joseHeaders.getUpdateCount() != null) { + LOG.warning("Duplicate headers have been detected"); + throw new JweException(JweException.Error.INVALID_COMPACT_JWE); + } + JweHeaders jweHeaders = new JweHeaders(joseHeaders.asMap()); + jweDecryptionInput = new JweDecryptionInput(encryptedCEK, + initVector, + encryptedContent, + authTag, + null, + headersJson, + jweHeaders); + + } catch (Base64Exception ex) { + LOG.warning("Incorrect Base64 URL encoding"); + throw new JweException(JweException.Error.INVALID_COMPACT_JWE); + } + } + + public String getDecodedJsonHeaders() { + return jweDecryptionInput.getDecodedJsonHeaders(); + } + + public JweHeaders getJweHeaders() { + return jweDecryptionInput.getJweHeaders(); + } + + public byte[] getEncryptedContentEncryptionKey() { + return jweDecryptionInput.getEncryptedCEK(); + } + + public byte[] getContentDecryptionCipherInitVector() { + return jweDecryptionInput.getInitVector(); + } + + public byte[] getContentEncryptionCipherAAD() { + return JweHeaders.toCipherAdditionalAuthData(jweDecryptionInput.getDecodedJsonHeaders()); + } + + public byte[] getEncryptionAuthenticationTag() { + return jweDecryptionInput.getAuthTag(); + } + + public byte[] getEncryptedContent() { + return jweDecryptionInput.getEncryptedContent(); + } + + public byte[] getEncryptedContentWithAuthTag() { + return getCipherWithAuthTag(getEncryptedContent(), getEncryptionAuthenticationTag()); + } + public JweDecryptionInput getJweDecryptionInput() { + return jweDecryptionInput; + } + 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) { + // temp workaround + return decryption.decrypt(jweDecryptionInput); + } + public String getDecryptedContentText(JweDecryptionProvider decryption) { + try { + return new String(getDecryptedContent(decryption), "UTF-8"); + } catch (UnsupportedEncodingException ex) { + throw new JoseException(ex); + } + } + public boolean validateCriticalHeaders() { + return JweUtils.validateCriticalHeaders(getJweHeaders()); + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCompactProducer.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCompactProducer.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCompactProducer.java new file mode 100644 index 0000000..b7d8e2c --- /dev/null +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCompactProducer.java @@ -0,0 +1,129 @@ +/** + * 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.common.util.Base64UrlUtility; +import org.apache.cxf.common.util.StringUtils; +import org.apache.cxf.jaxrs.json.basic.JsonMapObjectReaderWriter; + + +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(getHeadersJson(headers), 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) { + jweContentBuilder = startJweContent(new StringBuilder(), headers, + 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, + byte[] encryptedContentEncryptionKey, + byte[] cipherInitVector) { + return startJweContent(new StringBuilder(), + headers, encryptedContentEncryptionKey, cipherInitVector).toString(); + } + public static StringBuilder startJweContent(StringBuilder sb, + JweHeaders headers, + byte[] encryptedContentEncryptionKey, + byte[] cipherInitVector) { + return startJweContent(sb, + getHeadersJson(headers), + encryptedContentEncryptionKey, + cipherInitVector); + } + private static String getHeadersJson(JweHeaders headers) { + return new JsonMapObjectReaderWriter().toJson(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, + byte[] encryptedContentEncryptionKey, + byte[] cipherInitVector) throws IOException { + byte[] jsonBytes = StringUtils.toBytesUTF8(getHeadersJson(headers)); + 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); + os.flush(); + } + + public String getJweContent() { + return jweContentBuilder.append(encodedEncryptedContent) + .append('.') + .append(encodedAuthTag) + .toString(); + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryption.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryption.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryption.java new file mode 100644 index 0000000..4b5b4bf --- /dev/null +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryption.java @@ -0,0 +1,28 @@ +/** + * 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 JweDecryption extends AbstractJweDecryption { + + public JweDecryption(KeyDecryptionProvider keyDecryptionAlgo, + ContentDecryptionProvider cipherProps) { + super(keyDecryptionAlgo, cipherProps); + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionInput.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionInput.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionInput.java new file mode 100644 index 0000000..8d7f00f --- /dev/null +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionInput.java @@ -0,0 +1,68 @@ +/** + * 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 JweDecryptionInput { + private String headersJson; + private byte[] encryptedCEK; + private byte[] initVector; + private byte[] encryptedContent; + private byte[] authTag; + private byte[] aad; + private JweHeaders jweHeaders; + + public JweDecryptionInput(byte[] encryptedCEK, + byte[] initVector, + byte[] encryptedContent, + byte[] authTag, + byte[] aad, + String headersJson, + JweHeaders jweHeaders) { + this.encryptedCEK = encryptedCEK; + this.initVector = initVector; + this.encryptedContent = encryptedContent; + this.aad = aad; + this.authTag = authTag; + this.headersJson = headersJson; + this.jweHeaders = jweHeaders; + } + + public byte[] getEncryptedCEK() { + return encryptedCEK; + } + public byte[] getInitVector() { + return initVector; + } + public byte[] getEncryptedContent() { + return encryptedContent; + } + public byte[] getAuthTag() { + return authTag; + } + public byte[] getAad() { + return aad; + } + public String getDecodedJsonHeaders() { + return headersJson; + } + public JweHeaders getJweHeaders() { + return jweHeaders; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionOutput.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionOutput.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionOutput.java new file mode 100644 index 0000000..3432236 --- /dev/null +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionOutput.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.io.UnsupportedEncodingException; + +import org.apache.cxf.rs.security.jose.common.JoseException; + +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 JoseException(ex); + } + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionProvider.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionProvider.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionProvider.java new file mode 100644 index 0000000..1f4861a --- /dev/null +++ b/rt/rs/security/jose-parent/jose/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 extends JweKeyProperties { + JweDecryptionOutput decrypt(String jweContent); + byte[] decrypt(JweDecryptionInput jweInput); +} http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryption.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryption.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryption.java new file mode 100644 index 0000000..e314515 --- /dev/null +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryption.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 JweEncryption extends AbstractJweEncryption { + public JweEncryption(KeyEncryptionProvider keyEncryptionAlgorithm, + ContentEncryptionProvider contentEncryptionAlgo) { + super(contentEncryptionAlgo, keyEncryptionAlgorithm); + } + + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionInput.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionInput.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionInput.java new file mode 100644 index 0000000..a1336ca --- /dev/null +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionInput.java @@ -0,0 +1,90 @@ +/** + * 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 JweEncryptionInput { + private JweHeaders jweHeaders; + private byte[] cek; + private byte[] iv; + private byte[] aad; + private byte[] content; + public JweEncryptionInput() { + + } + public JweEncryptionInput(JweHeaders jweHeaders) { + this(jweHeaders, null); + } + public JweEncryptionInput(JweHeaders jweHeaders, + byte[] content) { + this(jweHeaders, content, null); + } + public JweEncryptionInput(JweHeaders jweHeaders, + byte[] content, + byte[] aad) { + this(jweHeaders, content, aad, null, null); + + } + public JweEncryptionInput(JweHeaders jweHeaders, + byte[] content, + byte[] cek, + byte[] iv) { + this(jweHeaders, content, null, cek, iv); + } + public JweEncryptionInput(JweHeaders jweHeaders, + byte[] content, + byte[] aad, + byte[] cek, + byte[] iv) { + this.jweHeaders = jweHeaders; + this.content = content; + this.cek = cek; + this.iv = iv; + this.aad = aad; + } + public JweHeaders getJweHeaders() { + return jweHeaders; + } + public void setJweHeaders(JweHeaders jweHeaders) { + this.jweHeaders = jweHeaders; + } + public byte[] getCek() { + return cek; + } + public void setCek(byte[] cek) { + this.cek = cek; + } + public byte[] getIv() { + return iv; + } + public void setIv(byte[] iv) { + this.iv = iv; + } + public byte[] getAad() { + return aad; + } + public void setAad(byte[] aad) { + this.aad = aad; + } + public byte[] getContent() { + return content; + } + public void setContent(byte[] content) { + this.content = content; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionOutput.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionOutput.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionOutput.java new file mode 100644 index 0000000..5036887 --- /dev/null +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionOutput.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 javax.crypto.Cipher; + +import org.apache.cxf.rt.security.crypto.KeyProperties; + +public class JweEncryptionOutput { + private Cipher cipher; + private JweHeaders headers; + private byte[] contentEncryptionKey; + private byte[] iv; + private AuthenticationTagProducer authTagProducer; + private byte[] encryptedContent; + private byte[] authTag; + private KeyProperties keyProps; + + //CHECKSTYLE:OFF + public JweEncryptionOutput(Cipher cipher, + JweHeaders headers, + byte[] contentEncryptionKey, + byte[] iv, + AuthenticationTagProducer authTagProducer, + KeyProperties keyProps, + byte[] encryptedContent, + byte[] authTag) { + //CHECKSTYLE:ON + this.cipher = cipher; + this.headers = headers; + this.contentEncryptionKey = contentEncryptionKey; + this.iv = iv; + this.authTagProducer = authTagProducer; + this.keyProps = keyProps; + this.encryptedContent = encryptedContent; + this.authTag = authTag; + } + public Cipher getCipher() { + return cipher; + } + public JweHeaders getHeaders() { + return headers; + } + public byte[] getContentEncryptionKey() { + return contentEncryptionKey; + } + public byte[] getIv() { + return iv; + } + public boolean isCompressionSupported() { + return keyProps.isCompressionSupported(); + } + public AuthenticationTagProducer getAuthTagProducer() { + return authTagProducer; + } + public byte[] getEncryptedContent() { + return encryptedContent; + } + public byte[] getAuthTag() { + return authTag; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionProvider.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionProvider.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionProvider.java new file mode 100644 index 0000000..615212b --- /dev/null +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionProvider.java @@ -0,0 +1,33 @@ +/** + * 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 extends JweKeyProperties { + /** + * JWE compact encryption + */ + String encrypt(byte[] jweContent, JweHeaders jweHeaders); + /** + * Prepare JWE state for completing either + * JWE compact or JSON encryption + */ + JweEncryptionOutput getEncryptionOutput(JweEncryptionInput jweInput); +} http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweException.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweException.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweException.java new file mode 100644 index 0000000..b67b1e2 --- /dev/null +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweException.java @@ -0,0 +1,53 @@ +/** + * 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.common.JoseException; + +public class JweException extends JoseException { + + private static final long serialVersionUID = 4118589816228511524L; + private Error status; + public JweException(Error status) { + this(status, null); + } + public JweException(Error status, Throwable cause) { + super(cause); + this.status = status; + } + public Error getError() { + return status; + } + public static enum Error { + NO_ENCRYPTOR, + NO_DECRYPTOR, + NO_INIT_PROPERTIES, + KEY_ALGORITHM_NOT_SET, + CUSTOM_IV_REUSED, + INVALID_KEY_ALGORITHM, + INVALID_CONTENT_ALGORITHM, + INVALID_CONTENT_KEY, + KEY_ENCRYPTION_FAILURE, + CONTENT_ENCRYPTION_FAILURE, + KEY_DECRYPTION_FAILURE, + CONTENT_DECRYPTION_FAILURE, + INVALID_COMPACT_JWE, + INVALID_JSON_JWE + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweHeaders.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweHeaders.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweHeaders.java new file mode 100644 index 0000000..d632777 --- /dev/null +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweHeaders.java @@ -0,0 +1,118 @@ +/** + * 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.Map; + +import org.apache.cxf.common.util.Base64UrlUtility; +import org.apache.cxf.common.util.StringUtils; +import org.apache.cxf.jaxrs.json.basic.JsonMapObjectReaderWriter; +import org.apache.cxf.rs.security.jose.common.JoseConstants; +import org.apache.cxf.rs.security.jose.common.JoseHeaders; +import org.apache.cxf.rs.security.jose.common.JoseType; +import org.apache.cxf.rs.security.jose.jwa.ContentAlgorithm; +import org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm; + + + + +public class JweHeaders extends JoseHeaders { + private JweHeaders protectedHeaders; + public JweHeaders() { + } + public JweHeaders(JoseType type) { + super(type); + } + public JweHeaders(JoseHeaders headers) { + super(headers.asMap()); + } + + public JweHeaders(Map<String, Object> values) { + super(values); + } + public JweHeaders(KeyAlgorithm keyEncAlgo, ContentAlgorithm ctEncAlgo) { + this(keyEncAlgo, ctEncAlgo, false); + } + public JweHeaders(ContentAlgorithm ctEncAlgo) { + this(null, ctEncAlgo, false); + } + public JweHeaders(ContentAlgorithm ctEncAlgo, boolean deflate) { + this(null, ctEncAlgo, deflate); + } + public JweHeaders(KeyAlgorithm keyEncAlgo, ContentAlgorithm ctEncAlgo, boolean deflate) { + init(keyEncAlgo, ctEncAlgo, deflate); + } + private void init(KeyAlgorithm keyEncAlgo, ContentAlgorithm ctEncAlgo, boolean deflate) { + if (keyEncAlgo != null) { + setKeyEncryptionAlgorithm(keyEncAlgo); + } + setContentEncryptionAlgorithm(ctEncAlgo); + if (deflate) { + setZipAlgorithm(JoseConstants.JWE_DEFLATE_ZIP_ALGORITHM); + } + } + + public void setKeyEncryptionAlgorithm(KeyAlgorithm algo) { + super.setAlgorithm(algo.getJwaName()); + } + + public KeyAlgorithm getKeyEncryptionAlgorithm() { + String algo = super.getAlgorithm(); + return algo == null ? null : KeyAlgorithm.getAlgorithm(algo); + } + + public void setContentEncryptionAlgorithm(ContentAlgorithm algo) { + setHeader(JoseConstants.JWE_HEADER_CONTENT_ENC_ALGORITHM, algo.getJwaName()); + } + + public ContentAlgorithm getContentEncryptionAlgorithm() { + Object prop = getHeader(JoseConstants.JWE_HEADER_CONTENT_ENC_ALGORITHM); + return prop == null ? null : ContentAlgorithm.getAlgorithm(prop.toString()); + } + + public void setZipAlgorithm(String type) { + setHeader(JoseConstants.JWE_HEADER_ZIP_ALGORITHM, type); + } + + public String getZipAlgorithm() { + return (String)getHeader(JoseConstants.JWE_HEADER_ZIP_ALGORITHM); + } + + @Override + public JoseHeaders setHeader(String name, Object value) { + return (JoseHeaders)super.setHeader(name, value); + } + public byte[] toCipherAdditionalAuthData() { + return toCipherAdditionalAuthData(new JsonMapObjectReaderWriter().toJson(this)); + } + public static byte[] toCipherAdditionalAuthData(String headersJson) { + byte[] headerBytes = StringUtils.toBytesUTF8(headersJson); + String base64UrlHeadersInJson = Base64UrlUtility.encode(headerBytes); + return StringUtils.toBytesASCII(base64UrlHeadersInJson); + } + + public JweHeaders getProtectedHeaders() { + return protectedHeaders; + } + + public void setProtectedHeaders(JweHeaders protectedHeaders) { + this.protectedHeaders = protectedHeaders; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJsonConsumer.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJsonConsumer.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJsonConsumer.java new file mode 100644 index 0000000..3535208 --- /dev/null +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJsonConsumer.java @@ -0,0 +1,191 @@ +/** + * 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 java.util.Collections; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +import org.apache.cxf.common.logging.LogUtils; +import org.apache.cxf.helpers.CastUtils; +import org.apache.cxf.jaxrs.json.basic.JsonMapObjectReaderWriter; +import org.apache.cxf.rs.security.jose.common.JoseException; +import org.apache.cxf.rs.security.jose.common.JoseUtils; +import org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm; + +public class JweJsonConsumer { + protected static final Logger LOG = LogUtils.getL7dLogger(JweJsonConsumer.class); + private String protectedHeaderJson; + private JweHeaders protectedHeaderJwe; + private JweHeaders sharedUnprotectedHeader; + private List<JweJsonEncryptionEntry> recipients = new LinkedList<JweJsonEncryptionEntry>(); + private Map<JweJsonEncryptionEntry, JweHeaders> recipientsMap = + new LinkedHashMap<JweJsonEncryptionEntry, JweHeaders>(); + private byte[] aad; + private byte[] iv; + private byte[] cipherBytes; + private byte[] authTag; + + private JsonMapObjectReaderWriter reader = new JsonMapObjectReaderWriter(); + + public JweJsonConsumer(String payload) { + prepare(payload); + } + + public JweDecryptionOutput decryptWith(JweDecryptionProvider jwe) { + JweJsonEncryptionEntry entry = getJweDecryptionEntry(jwe); + return decryptWith(jwe, entry); + } + public JweDecryptionOutput decryptWith(JweDecryptionProvider jwe, JweJsonEncryptionEntry entry) { + JweDecryptionInput jweDecryptionInput = getJweDecryptionInput(jwe, entry); + byte[] content = jwe.decrypt(jweDecryptionInput); + return new JweDecryptionOutput(jweDecryptionInput.getJweHeaders(), content); + } + + private JweDecryptionInput getJweDecryptionInput(JweDecryptionProvider jwe, JweJsonEncryptionEntry entry) { + if (entry == null) { + LOG.warning("JWE JSON Entry is not available"); + throw new JweException(JweException.Error.INVALID_JSON_JWE); + } + JweHeaders unionHeaders = recipientsMap.get(entry); + if (unionHeaders == null) { + LOG.warning("JWE JSON Entry union headers are not available"); + throw new JweException(JweException.Error.INVALID_JSON_JWE); + } + JweDecryptionInput input = new JweDecryptionInput(entry.getEncryptedKey(), + iv, + cipherBytes, + authTag, + aad, + protectedHeaderJson, + unionHeaders); + return input; + } + + private JweJsonEncryptionEntry getJweDecryptionEntry(JweDecryptionProvider jwe) { + for (Map.Entry<JweJsonEncryptionEntry, JweHeaders> entry : recipientsMap.entrySet()) { + KeyAlgorithm keyAlgo = entry.getValue().getKeyEncryptionAlgorithm(); + if (keyAlgo != null && keyAlgo.equals(jwe.getKeyAlgorithm()) + || keyAlgo == null && jwe.getKeyAlgorithm() == null) { + return entry.getKey(); + } + } + return null; + } + + private void prepare(String payload) { + Map<String, Object> jsonObjectMap = reader.fromJson(payload); + String encodedProtectedHeader = (String)jsonObjectMap.get("protected"); + if (encodedProtectedHeader != null) { + protectedHeaderJson = JoseUtils.decodeToString(encodedProtectedHeader); + protectedHeaderJwe = + new JweHeaders(reader.fromJson(protectedHeaderJson)); + } + Map<String, Object> unprotectedHeader = CastUtils.cast((Map<?, ?>)jsonObjectMap.get("unprotected")); + sharedUnprotectedHeader = unprotectedHeader == null ? null : new JweHeaders(unprotectedHeader); + List<Map<String, Object>> encryptionArray = CastUtils.cast((List<?>)jsonObjectMap.get("recipients")); + if (encryptionArray != null) { + if (jsonObjectMap.containsKey("encryption_key")) { + LOG.warning("JWE JSON encryption_key is missing"); + throw new JweException(JweException.Error.INVALID_JSON_JWE); + } + for (Map<String, Object> encryptionEntry : encryptionArray) { + this.recipients.add(getEncryptionObject(encryptionEntry)); + } + } else { + this.recipients.add(getEncryptionObject(jsonObjectMap)); + } + aad = getDecodedBytes(jsonObjectMap, "aad"); + cipherBytes = getDecodedBytes(jsonObjectMap, "ciphertext"); + iv = getDecodedBytes(jsonObjectMap, "iv"); + authTag = getDecodedBytes(jsonObjectMap, "tag"); + } + protected JweJsonEncryptionEntry getEncryptionObject(Map<String, Object> encryptionEntry) { + Map<String, Object> header = CastUtils.cast((Map<?, ?>)encryptionEntry.get("header")); + JweHeaders recipientUnprotected = header == null ? null : new JweHeaders(header); + String encodedKey = (String)encryptionEntry.get("encrypted_key"); + JweJsonEncryptionEntry entry = new JweJsonEncryptionEntry(recipientUnprotected, encodedKey); + + JweHeaders unionHeaders = new JweHeaders(); + if (protectedHeaderJwe != null) { + unionHeaders.asMap().putAll(protectedHeaderJwe.asMap()); + unionHeaders.setProtectedHeaders(protectedHeaderJwe); + } + if (sharedUnprotectedHeader != null) { + if (!Collections.disjoint(unionHeaders.asMap().keySet(), + sharedUnprotectedHeader.asMap().keySet())) { + LOG.warning("Protected and unprotected headers have duplicate values"); + throw new JweException(JweException.Error.INVALID_JSON_JWE); + } + unionHeaders.asMap().putAll(sharedUnprotectedHeader.asMap()); + } + if (recipientUnprotected != null) { + if (!Collections.disjoint(unionHeaders.asMap().keySet(), + recipientUnprotected.asMap().keySet())) { + LOG.warning("Union and recipient unprotected headers have duplicate values"); + throw new JweException(JweException.Error.INVALID_JSON_JWE); + } + unionHeaders.asMap().putAll(recipientUnprotected.asMap()); + } + + recipientsMap.put(entry, unionHeaders); + return entry; + + } + protected byte[] getDecodedBytes(Map<String, Object> map, String name) { + String value = (String)map.get(name); + if (value != null) { + return JoseUtils.decode(value); + } + return null; + } + + public JweHeaders getProtectedHeader() { + return protectedHeaderJwe; + } + + public JweHeaders getSharedUnprotectedHeader() { + return sharedUnprotectedHeader; + } + + public byte[] getAad() { + return aad; + } + public String getAadText() { + if (aad == null) { + return null; + } + try { + return new String(aad, "UTF-8"); + } catch (UnsupportedEncodingException ex) { + throw new JoseException(ex); + } + } + public List<JweJsonEncryptionEntry> getRecipients() { + return recipients; + } + + public Map<JweJsonEncryptionEntry, JweHeaders> getRecipientsMap() { + return recipientsMap; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJsonEncryptionEntry.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJsonEncryptionEntry.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJsonEncryptionEntry.java new file mode 100644 index 0000000..d744892 --- /dev/null +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJsonEncryptionEntry.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.LinkedHashMap; +import java.util.Map; + +import org.apache.cxf.jaxrs.json.basic.JsonMapObjectReaderWriter; +import org.apache.cxf.rs.security.jose.common.JoseUtils; + +public class JweJsonEncryptionEntry { + private JweHeaders unprotectedHeader; + private String encodedEncryptedKey; + public JweJsonEncryptionEntry(String encodedEncryptedKey) { + this(null, encodedEncryptedKey); + } + public JweJsonEncryptionEntry(JweHeaders unprotectedHeader, String encodedEncryptedKey) { + this.unprotectedHeader = unprotectedHeader; + this.encodedEncryptedKey = encodedEncryptedKey; + } + public JweHeaders getUnprotectedHeader() { + return unprotectedHeader; + } + public String getEncodedEncryptedKey() { + return encodedEncryptedKey; + } + public byte[] getEncryptedKey() { + return encodedEncryptedKey == null ? null : JoseUtils.decode(encodedEncryptedKey); + } + public String toJson() { + JsonMapObjectReaderWriter jsonWriter = new JsonMapObjectReaderWriter(); + Map<String, Object> recipientsEntry = new LinkedHashMap<String, Object>(); + if (unprotectedHeader != null) { + recipientsEntry.put("header", this.unprotectedHeader); + } + if (encodedEncryptedKey != null) { + recipientsEntry.put("encrypted_key", this.encodedEncryptedKey); + } + return jsonWriter.toJson(recipientsEntry); + } + public String toString() { + return toJson(); + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJsonProducer.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJsonProducer.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJsonProducer.java new file mode 100644 index 0000000..661a537 --- /dev/null +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJsonProducer.java @@ -0,0 +1,192 @@ +/** + * 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.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.logging.Logger; + +import org.apache.cxf.common.logging.LogUtils; +import org.apache.cxf.common.util.Base64UrlUtility; +import org.apache.cxf.jaxrs.json.basic.JsonMapObjectReaderWriter; +import org.apache.cxf.rs.security.jose.common.JoseConstants; + +public class JweJsonProducer { + protected static final Logger LOG = LogUtils.getL7dLogger(JweJsonProducer.class); + private JsonMapObjectReaderWriter writer = new JsonMapObjectReaderWriter(); + private JweHeaders protectedHeader; + private JweHeaders unprotectedHeader; + private byte[] content; + private byte[] aad; + private boolean canBeFlat; + public JweJsonProducer(JweHeaders protectedHeader, byte[] content) { + this(protectedHeader, content, false); + } + public JweJsonProducer(JweHeaders protectedHeader, byte[] content, boolean canBeFlat) { + this(protectedHeader, content, null, canBeFlat); + } + public JweJsonProducer(JweHeaders protectedHeader, byte[] content, byte[] aad, boolean canBeFlat) { + this.protectedHeader = protectedHeader; + this.content = content; + this.aad = aad; + this.canBeFlat = canBeFlat; + } + public JweJsonProducer(JweHeaders protectedHeader, + JweHeaders unprotectedHeader, + byte[] content, + byte[] aad, + boolean canBeFlat) { + this(protectedHeader, content, aad, canBeFlat); + this.unprotectedHeader = unprotectedHeader; + } + public String encryptWith(JweEncryptionProvider encryptor) { + return encryptWith(Collections.singletonList(encryptor), null); + } + public String encryptWith(JweEncryptionProvider encryptor, JweHeaders recipientUnprotected) { + return encryptWith(Collections.singletonList(encryptor), + Collections.singletonList(recipientUnprotected)); + } + public String encryptWith(List<JweEncryptionProvider> encryptors) { + return encryptWith(encryptors, null); + } + public String encryptWith(List<JweEncryptionProvider> encryptors, + List<JweHeaders> recipientUnprotected) { + checkAndGetContentAlgorithm(encryptors); + if (recipientUnprotected != null + && recipientUnprotected.size() != encryptors.size()) { + throw new IllegalArgumentException(); + } + JweHeaders unionHeaders = new JweHeaders(); + if (protectedHeader != null) { + unionHeaders.asMap().putAll(protectedHeader.asMap()); + } + if (unprotectedHeader != null) { + if (!Collections.disjoint(unionHeaders.asMap().keySet(), + unprotectedHeader.asMap().keySet())) { + LOG.warning("Protected and unprotected headers have duplicate values"); + throw new JweException(JweException.Error.INVALID_JSON_JWE); + } + checkCriticalHeaders(unprotectedHeader); + unionHeaders.asMap().putAll(unprotectedHeader.asMap()); + } + + List<JweJsonEncryptionEntry> entries = new ArrayList<JweJsonEncryptionEntry>(encryptors.size()); + Map<String, Object> jweJsonMap = new LinkedHashMap<String, Object>(); + byte[] cipherText = null; + byte[] authTag = null; + byte[] iv = null; + for (int i = 0; i < encryptors.size(); i++) { + JweEncryptionProvider encryptor = encryptors.get(i); + JweHeaders perRecipientUnprotected = + recipientUnprotected == null ? null : recipientUnprotected.get(i); + JweHeaders jsonHeaders = null; + if (perRecipientUnprotected != null) { + checkCriticalHeaders(perRecipientUnprotected); + if (!Collections.disjoint(unionHeaders.asMap().keySet(), + perRecipientUnprotected.asMap().keySet())) { + LOG.warning("union and recipient unprotected headers have duplicate values"); + throw new JweException(JweException.Error.INVALID_JSON_JWE); + } + jsonHeaders = new JweHeaders(unionHeaders.asMap()); + jsonHeaders.asMap().putAll(perRecipientUnprotected.asMap()); + } else { + jsonHeaders = unionHeaders; + } + jsonHeaders.setProtectedHeaders(protectedHeader); + + JweEncryptionInput input = createEncryptionInput(jsonHeaders); + if (i > 0) { + input.setContent(null); + } + JweEncryptionOutput state = encryptor.getEncryptionOutput(input); + byte[] currentCipherText = state.getEncryptedContent(); + byte[] currentAuthTag = state.getAuthTag(); + byte[] currentIv = state.getIv(); + if (cipherText == null) { + cipherText = currentCipherText; + } + if (authTag == null) { + authTag = currentAuthTag; + } + if (iv == null) { + iv = currentIv; + } + + byte[] encryptedCek = state.getContentEncryptionKey(); + if (encryptedCek.length == 0 && encryptor.getKeyAlgorithm() != null) { + LOG.warning("Unexpected key encryption algorithm"); + throw new JweException(JweException.Error.INVALID_JSON_JWE); + } + String encodedCek = encryptedCek.length == 0 ? null : Base64UrlUtility.encode(encryptedCek); + entries.add(new JweJsonEncryptionEntry(perRecipientUnprotected, encodedCek)); + + } + if (protectedHeader != null) { + jweJsonMap.put("protected", + Base64UrlUtility.encode(writer.toJson(protectedHeader))); + } + if (unprotectedHeader != null) { + jweJsonMap.put("unprotected", unprotectedHeader); + } + if (entries.size() == 1 && canBeFlat) { + JweHeaders unprotectedEntryHeader = entries.get(0).getUnprotectedHeader(); + if (unprotectedEntryHeader != null) { + jweJsonMap.put("header", unprotectedEntryHeader); + } + String encryptedKey = entries.get(0).getEncodedEncryptedKey(); + if (encryptedKey != null) { + jweJsonMap.put("encrypted_key", encryptedKey); + } + } else { + jweJsonMap.put("recipients", entries); + } + if (aad != null) { + jweJsonMap.put("aad", Base64UrlUtility.encode(aad)); + } + jweJsonMap.put("iv", Base64UrlUtility.encode(iv)); + jweJsonMap.put("ciphertext", Base64UrlUtility.encode(cipherText)); + jweJsonMap.put("tag", Base64UrlUtility.encode(authTag)); + return writer.toJson(jweJsonMap); + } + protected JweEncryptionInput createEncryptionInput(JweHeaders jsonHeaders) { + return new JweEncryptionInput(jsonHeaders, content, aad); + } + private String checkAndGetContentAlgorithm(List<JweEncryptionProvider> encryptors) { + Set<String> set = new HashSet<String>(); + for (JweEncryptionProvider encryptor : encryptors) { + set.add(encryptor.getContentAlgorithm().getJwaName()); + } + if (set.size() != 1) { + LOG.warning("Invalid content encryption algorithm"); + throw new JweException(JweException.Error.INVALID_CONTENT_ALGORITHM); + } + return set.iterator().next(); + } + private static void checkCriticalHeaders(JweHeaders unprotected) { + if (unprotected.asMap().containsKey(JoseConstants.HEADER_CRITICAL)) { + LOG.warning("Unprotected headers contain critical headers"); + throw new JweException(JweException.Error.INVALID_JSON_JWE); + } + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJwtCompactConsumer.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJwtCompactConsumer.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJwtCompactConsumer.java new file mode 100644 index 0000000..d7a76b9 --- /dev/null +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJwtCompactConsumer.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 java.security.interfaces.RSAPrivateKey; + +import javax.crypto.SecretKey; + +import org.apache.cxf.rs.security.jose.jwk.JsonWebKey; +import org.apache.cxf.rs.security.jose.jwt.JwtClaims; +import org.apache.cxf.rs.security.jose.jwt.JwtToken; +import org.apache.cxf.rs.security.jose.jwt.JwtTokenReaderWriter; + + +public class JweJwtCompactConsumer { + private JweCompactConsumer jweConsumer; + private JweHeaders headers; + public JweJwtCompactConsumer(String content) { + jweConsumer = new JweCompactConsumer(content); + headers = jweConsumer.getJweHeaders(); + } + public JwtToken decryptWith(JsonWebKey key) { + return decryptWith(JweUtils.createJweDecryptionProvider(key, + headers.getContentEncryptionAlgorithm())); + } + public JwtToken decryptWith(RSAPrivateKey key) { + return decryptWith(JweUtils.createJweDecryptionProvider(key, + headers.getKeyEncryptionAlgorithm(), + headers.getContentEncryptionAlgorithm())); + } + public JwtToken decryptWith(SecretKey key) { + return decryptWith(JweUtils.createJweDecryptionProvider(key, + headers.getKeyEncryptionAlgorithm(), + headers.getContentEncryptionAlgorithm())); + } + public JwtToken decryptWith(JweDecryptionProvider jwe) { + byte[] bytes = jwe.decrypt(jweConsumer.getJweDecryptionInput()); + JwtClaims claims = new JwtTokenReaderWriter().fromJsonClaims(toString(bytes)); + return new JwtToken(headers, claims); + } + private static String toString(byte[] bytes) { + try { + return new String(bytes, "UTF-8"); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJwtCompactProducer.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJwtCompactProducer.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJwtCompactProducer.java new file mode 100644 index 0000000..5b65790 --- /dev/null +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJwtCompactProducer.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.security.PublicKey; + +import javax.crypto.SecretKey; + +import org.apache.cxf.common.util.StringUtils; +import org.apache.cxf.rs.security.jose.jwk.JsonWebKey; +import org.apache.cxf.rs.security.jose.jwt.JwtClaims; +import org.apache.cxf.rs.security.jose.jwt.JwtToken; +import org.apache.cxf.rs.security.jose.jwt.JwtUtils; + + +public class JweJwtCompactProducer { + private JweHeaders headers; + private String claimsJson; + public JweJwtCompactProducer(JwtToken token) { + this(new JweHeaders(token.getHeaders()), token.getClaims()); + } + public JweJwtCompactProducer(JwtClaims claims) { + this(new JweHeaders(), claims); + } + public JweJwtCompactProducer(JweHeaders joseHeaders, JwtClaims claims) { + headers = new JweHeaders(joseHeaders); + claimsJson = JwtUtils.claimsToJson(claims); + } + + public String encryptWith(JsonWebKey key) { + JweEncryptionProvider jwe = JweUtils.createJweEncryptionProvider(key, headers); + return encryptWith(jwe); + } + public String encryptWith(PublicKey key) { + JweEncryptionProvider jwe = JweUtils.createJweEncryptionProvider(key, headers); + return encryptWith(jwe); + } + public String encryptWith(SecretKey key) { + JweEncryptionProvider jwe = JweUtils.createJweEncryptionProvider(key, headers); + return encryptWith(jwe); + } + public String encryptWith(JweEncryptionProvider jwe) { + return jwe.encrypt(StringUtils.toBytesUTF8(claimsJson), headers); + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweKeyProperties.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweKeyProperties.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweKeyProperties.java new file mode 100644 index 0000000..49d274c --- /dev/null +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweKeyProperties.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; + +import org.apache.cxf.rs.security.jose.jwa.ContentAlgorithm; +import org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm; + + + +public interface JweKeyProperties { + KeyAlgorithm getKeyAlgorithm(); + ContentAlgorithm getContentAlgorithm(); +}
