cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cohei...@apache.org
Subject [15/18] cxf git commit: Renaming jose module
Date Wed, 21 Oct 2015 13:27:55 GMT
http://git-wip-us.apache.org/repos/asf/cxf/blob/b33b7d7a/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/b33b7d7a/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/b33b7d7a/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/b33b7d7a/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/b33b7d7a/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/b33b7d7a/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/b33b7d7a/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/b33b7d7a/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/b33b7d7a/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/b33b7d7a/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/b33b7d7a/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/b33b7d7a/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/b33b7d7a/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/b33b7d7a/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/b33b7d7a/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..7896ee5
--- /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 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/b33b7d7a/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/b33b7d7a/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/b33b7d7a/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/b33b7d7a/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/b33b7d7a/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/b33b7d7a/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/b33b7d7a/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();
+}


Mime
View raw message