cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cohei...@apache.org
Subject [15/22] cxf git commit: Splitting current jose module into jose-core + jose-jaxrs
Date Tue, 13 Oct 2015 10:35:08 GMT
http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweOutputStream.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweOutputStream.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweOutputStream.java
new file mode 100644
index 0000000..1a0447d
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweOutputStream.java
@@ -0,0 +1,148 @@
+/**
+ * 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.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.util.logging.Logger;
+
+import javax.crypto.Cipher;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.Base64UrlUtility;
+
+public class JweOutputStream extends FilterOutputStream {
+    protected static final Logger LOG = LogUtils.getL7dLogger(JweOutputStream.class);
+    private Cipher encryptingCipher;
+    private int blockSize;
+    private AuthenticationTagProducer authTagProducer;
+    private byte[] lastRawDataChunk;
+    private byte[] lastEncryptedDataChunk;
+    private boolean flushed;
+    public JweOutputStream(OutputStream out, 
+                           Cipher encryptingCipher, 
+                           AuthenticationTagProducer authTagProducer) {
+        super(out);
+        this.encryptingCipher = encryptingCipher;
+        this.blockSize = encryptingCipher.getBlockSize(); 
+        this.authTagProducer = authTagProducer;
+    }
+
+    @Override
+    public void write(int value) throws IOException {
+        byte[] bytes = ByteBuffer.allocate(Integer.SIZE / 8).putInt(value).array();
+        write(bytes, 0, bytes.length);
+    }
+    
+    @Override
+    public void write(byte b[], int off, int len) throws IOException {
+        if (lastRawDataChunk != null) {
+            int remaining = blockSize - lastRawDataChunk.length;
+            int lenToCopy = remaining < len ? remaining : len;
+            lastRawDataChunk = newArray(lastRawDataChunk, 0, lastRawDataChunk.length, b, off, lenToCopy);
+            off = off + lenToCopy;
+            len -= lenToCopy;
+            if (lastRawDataChunk.length < blockSize) {
+                return;
+            } else {
+                encryptAndWrite(lastRawDataChunk, 0, lastRawDataChunk.length);
+                lastRawDataChunk = null;
+            }
+        } 
+        int offset = 0;
+        int chunkSize = blockSize > len ? blockSize : blockSize * (len / blockSize);
+        for (; offset + chunkSize <= len; offset += chunkSize, off += chunkSize) {
+            encryptAndWrite(b, off, chunkSize);
+        }
+        if (offset < len) {
+            lastRawDataChunk = newArray(b, off, len - offset);
+        }
+        
+    }
+    
+    private void encryptAndWrite(byte[] chunk, int off, int len) throws IOException {
+        byte[] encrypted = encryptingCipher.update(chunk, off, len);
+        if (authTagProducer != null) {
+            authTagProducer.update(encrypted, 0, encrypted.length);
+        }
+        encodeAndWrite(encrypted, 0, encrypted.length, false);
+    }
+    private void encodeAndWrite(byte[] encryptedChunk, int off, int len, boolean finalWrite) throws IOException {
+        byte[] theChunk = lastEncryptedDataChunk;
+        int lenToEncode = len;
+        if (theChunk != null) {
+            theChunk = newArray(theChunk, 0, theChunk.length, encryptedChunk, off, len);
+            lenToEncode = theChunk.length;
+            off = 0;
+        } else {
+            theChunk = encryptedChunk;
+        }
+        int rem = finalWrite ? 0 : lenToEncode % 3; 
+        Base64UrlUtility.encodeAndStream(theChunk, off, lenToEncode - rem, out);
+        out.flush();
+        if (rem > 0) {
+            lastEncryptedDataChunk = newArray(theChunk, lenToEncode - rem, rem);
+        } else {
+            lastEncryptedDataChunk = null;
+        }
+    }
+    
+    public void finalFlush() throws IOException {
+        if (flushed) {
+            return;
+        }
+        try {
+            byte[] finalBytes = lastRawDataChunk == null 
+                ? encryptingCipher.doFinal()
+                : encryptingCipher.doFinal(lastRawDataChunk, 0, lastRawDataChunk.length);
+            final int authTagLengthBits = 128;
+            if (authTagProducer != null) {
+                authTagProducer.update(finalBytes, 0, finalBytes.length);
+                encodeAndWrite(finalBytes, 0, finalBytes.length, true);
+            } else {
+                encodeAndWrite(finalBytes, 0, finalBytes.length - authTagLengthBits / 8, true);
+            }
+            out.write(new byte[]{'.'});
+            
+            if (authTagProducer == null) {
+                encodeAndWrite(finalBytes, finalBytes.length - authTagLengthBits / 8, authTagLengthBits / 8, true);
+            } else {
+                byte[] authTag = authTagProducer.getTag();
+                encodeAndWrite(authTag, 0, authTagLengthBits / 8, true);
+            }
+        } catch (Exception ex) {
+            LOG.warning("Content encryption failure");
+            throw new JweException(JweException.Error.CONTENT_ENCRYPTION_FAILURE, ex);
+        }
+        flushed = true;
+    }
+    private byte[] newArray(byte[] src, int srcPos, int srcLen) {
+        byte[] buf = new byte[srcLen];
+        System.arraycopy(src, srcPos, buf, 0, srcLen);
+        return buf;
+    }
+    private byte[] newArray(byte[] src, int srcPos, int srcLen, byte[] src2, int srcPos2, int srcLen2) {
+        byte[] buf = new byte[srcLen + srcLen2];
+        System.arraycopy(src, srcPos, buf, 0, srcLen);
+        System.arraycopy(src2, srcPos2, buf, srcLen, srcLen2);
+        return buf;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java
new file mode 100644
index 0000000..3f71aca
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java
@@ -0,0 +1,633 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.jose.jwe;
+
+import java.nio.ByteBuffer;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.security.interfaces.ECPrivateKey;
+import java.security.interfaces.ECPublicKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+import java.util.logging.Logger;
+
+import javax.crypto.KeyAgreement;
+import javax.crypto.SecretKey;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageUtils;
+import org.apache.cxf.phase.PhaseInterceptorChain;
+import org.apache.cxf.rs.security.jose.JoseConstants;
+import org.apache.cxf.rs.security.jose.JoseHeaders;
+import org.apache.cxf.rs.security.jose.JoseUtils;
+import org.apache.cxf.rs.security.jose.common.KeyManagementUtils;
+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.jwk.JsonWebKey;
+import org.apache.cxf.rs.security.jose.jwk.JwkUtils;
+import org.apache.cxf.rs.security.jose.jwk.KeyOperation;
+import org.apache.cxf.rs.security.jose.jwk.KeyType;
+import org.apache.cxf.rt.security.crypto.MessageDigestUtils;
+
+public final class JweUtils {
+    private static final Logger LOG = LogUtils.getL7dLogger(JweUtils.class);
+    private static final String JSON_WEB_ENCRYPTION_CEK_ALGO_PROP = "rs.security.jwe.content.encryption.algorithm";
+    private static final String JSON_WEB_ENCRYPTION_KEY_ALGO_PROP = "rs.security.jwe.key.encryption.algorithm";
+    private static final String JSON_WEB_ENCRYPTION_ZIP_ALGO_PROP = "rs.security.jwe.zip.algorithm";
+    private static final String RSSEC_ENCRYPTION_OUT_PROPS = "rs.security.encryption.out.properties";
+    private static final String RSSEC_ENCRYPTION_IN_PROPS = "rs.security.encryption.in.properties";
+    private static final String RSSEC_ENCRYPTION_PROPS = "rs.security.encryption.properties";
+    private static final String RSSEC_ENCRYPTION_REPORT_KEY_PROP = "rs.security.jwe.report.public.key";
+    private static final String RSSEC_ENCRYPTION_REPORT_KEY_ID_PROP = "rs.security.jwe.report.public.key.id";
+    
+    private JweUtils() {
+        
+    }
+    public static String encrypt(PublicKey key, KeyAlgorithm keyAlgo, ContentAlgorithm contentAlgo, 
+                                 byte[] content) {
+        return encrypt(key, keyAlgo, contentAlgo, content, null);
+    }
+    public static String encrypt(PublicKey key, KeyAlgorithm keyAlgo, 
+                                 ContentAlgorithm contentAlgo, byte[] content, String ct) {
+        KeyEncryptionProvider keyEncryptionProvider = getPublicKeyEncryptionProvider(key, keyAlgo);
+        return encrypt(keyEncryptionProvider, contentAlgo, content, ct);
+    }
+    public static String encrypt(SecretKey key, KeyAlgorithm keyAlgo, ContentAlgorithm contentAlgo, 
+                                 byte[] content) {
+        return encrypt(key, keyAlgo, contentAlgo, content, null);
+    }
+    public static String encrypt(SecretKey key, KeyAlgorithm keyAlgo, ContentAlgorithm contentAlgo, 
+                                 byte[] content, String ct) {
+        if (keyAlgo != null) {
+            KeyEncryptionProvider keyEncryptionProvider = getSecretKeyEncryptionAlgorithm(key, keyAlgo);
+            return encrypt(keyEncryptionProvider, contentAlgo, content, ct);
+        } else {
+            return encryptDirect(key, contentAlgo, content, ct);
+        }
+    }
+    public static String encrypt(JsonWebKey key, ContentAlgorithm contentAlgo, byte[] content, String ct) {
+        KeyEncryptionProvider keyEncryptionProvider = getKeyEncryptionProvider(key);
+        return encrypt(keyEncryptionProvider, contentAlgo, content, ct);
+    }
+    public static String encryptDirect(SecretKey key, ContentAlgorithm contentAlgo, byte[] content) {
+        return encryptDirect(key, contentAlgo, content, null);
+    }
+    public static String encryptDirect(SecretKey key, ContentAlgorithm contentAlgo, byte[] content, String ct) {
+        JweEncryptionProvider jwe = getDirectKeyJweEncryption(key, contentAlgo);
+        return jwe.encrypt(content, toJweHeaders(ct));
+    }
+    public static String encryptDirect(JsonWebKey key, byte[] content, String ct) {
+        JweEncryptionProvider jwe = getDirectKeyJweEncryption(key);
+        return jwe.encrypt(content, toJweHeaders(ct));
+    }
+    public static byte[] decrypt(PrivateKey key, KeyAlgorithm keyAlgo, ContentAlgorithm contentAlgo, String content) {
+        KeyDecryptionProvider keyDecryptionProvider = getPrivateKeyDecryptionProvider(key, keyAlgo);
+        return decrypt(keyDecryptionProvider, contentAlgo, content);
+    }
+    public static byte[] decrypt(SecretKey key, KeyAlgorithm keyAlgo, ContentAlgorithm contentAlgo, String content) {
+        if (keyAlgo != null) {
+            KeyDecryptionProvider keyDecryptionProvider = getSecretKeyDecryptionProvider(key, keyAlgo);
+            return decrypt(keyDecryptionProvider, contentAlgo, content);
+        } else {
+            return decryptDirect(key, contentAlgo, content);
+        }
+    }
+    public static byte[] decrypt(JsonWebKey key, ContentAlgorithm contentAlgo, String content) {
+        KeyDecryptionProvider keyDecryptionProvider = getKeyDecryptionProvider(key);
+        return decrypt(keyDecryptionProvider, contentAlgo, content);
+    }
+    public static byte[] decryptDirect(SecretKey key, ContentAlgorithm contentAlgo, String content) {
+        JweDecryptionProvider jwe = getDirectKeyJweDecryption(key, contentAlgo);
+        return jwe.decrypt(content).getContent();
+    }
+    public static byte[] decryptDirect(JsonWebKey key, String content) {
+        JweDecryptionProvider jwe = getDirectKeyJweDecryption(key);
+        return jwe.decrypt(content).getContent();
+    }
+    public static KeyEncryptionProvider getKeyEncryptionProvider(JsonWebKey jwk) {
+        return getKeyEncryptionProvider(jwk, null);
+    }
+    public static KeyEncryptionProvider getKeyEncryptionProvider(JsonWebKey jwk, KeyAlgorithm defaultAlgorithm) {
+        KeyAlgorithm keyAlgo = jwk.getAlgorithm() == null ? defaultAlgorithm 
+            : KeyAlgorithm.getAlgorithm(jwk.getAlgorithm());
+        KeyEncryptionProvider keyEncryptionProvider = null;
+        KeyType keyType = jwk.getKeyType();
+        if (KeyType.RSA == keyType) {
+            keyEncryptionProvider = getPublicKeyEncryptionProvider(JwkUtils.toRSAPublicKey(jwk, true), 
+                                                                 keyAlgo);
+        } else if (KeyType.OCTET == keyType) {
+            keyEncryptionProvider = getSecretKeyEncryptionAlgorithm(JwkUtils.toSecretKey(jwk), 
+                                                                    keyAlgo);
+        } else {
+            keyEncryptionProvider = new EcdhAesWrapKeyEncryptionAlgorithm(JwkUtils.toECPublicKey(jwk),
+                                        jwk.getStringProperty(JsonWebKey.EC_CURVE),
+                                        keyAlgo);
+        }
+        return keyEncryptionProvider;
+    }
+    public static KeyEncryptionProvider getPublicKeyEncryptionProvider(PublicKey key, KeyAlgorithm algo) {
+        if (key instanceof PublicKey) {
+            return new RSAKeyEncryptionAlgorithm((RSAPublicKey)key, algo);
+        } else {
+            return new EcdhAesWrapKeyEncryptionAlgorithm((ECPublicKey)key, algo);
+        }
+    }
+    public static KeyEncryptionProvider getSecretKeyEncryptionAlgorithm(SecretKey key, KeyAlgorithm algo) {
+        if (AlgorithmUtils.isAesKeyWrap(algo.getJwaName())) {
+            return new AesWrapKeyEncryptionAlgorithm(key, algo);
+        } else if (AlgorithmUtils.isAesGcmKeyWrap(algo.getJwaName())) {
+            return new AesGcmWrapKeyEncryptionAlgorithm(key, algo);
+        }
+        return null;
+    }
+    public static KeyDecryptionProvider getKeyDecryptionProvider(JsonWebKey jwk) {
+        return getKeyDecryptionProvider(jwk, null);
+    }
+    
+    public static KeyDecryptionProvider getKeyDecryptionProvider(JsonWebKey jwk, KeyAlgorithm defaultAlgorithm) {
+        KeyAlgorithm keyAlgo = jwk.getAlgorithm() == null ? defaultAlgorithm 
+            : KeyAlgorithm.getAlgorithm(jwk.getAlgorithm());
+        KeyDecryptionProvider keyDecryptionProvider = null;
+        KeyType keyType = jwk.getKeyType();
+        if (KeyType.RSA == keyType) {
+            keyDecryptionProvider = getPrivateKeyDecryptionProvider(JwkUtils.toRSAPrivateKey(jwk), 
+                                                                 keyAlgo);
+        } else if (KeyType.OCTET == keyType) {
+            keyDecryptionProvider = getSecretKeyDecryptionProvider(JwkUtils.toSecretKey(jwk),
+                                            keyAlgo);
+        } else {
+            keyDecryptionProvider = getPrivateKeyDecryptionProvider(JwkUtils.toECPrivateKey(jwk), 
+                                                                     keyAlgo);
+        }
+        return keyDecryptionProvider;
+    }
+    public static KeyDecryptionProvider getPrivateKeyDecryptionProvider(PrivateKey key, KeyAlgorithm algo) {
+        if (key instanceof RSAPrivateKey) {
+            return new RSAKeyDecryptionAlgorithm((RSAPrivateKey)key, algo);
+        } else {
+            return new EcdhAesWrapKeyDecryptionAlgorithm((ECPrivateKey)key, algo);
+        }
+    }
+    public static KeyDecryptionProvider getSecretKeyDecryptionProvider(SecretKey key, KeyAlgorithm algo) {
+        if (AlgorithmUtils.isAesKeyWrap(algo.getJwaName())) {
+            return new AesWrapKeyDecryptionAlgorithm(key, algo);
+        } else if (AlgorithmUtils.isAesGcmKeyWrap(algo.getJwaName())) {
+            return new AesGcmWrapKeyDecryptionAlgorithm(key, algo);
+        }
+        return null;
+    }
+    public static ContentEncryptionProvider getContentEncryptionAlgorithm(JsonWebKey jwk) {
+        return getContentEncryptionAlgorithm(jwk, null);
+    }
+    public static ContentEncryptionProvider getContentEncryptionAlgorithm(JsonWebKey jwk, String defaultAlgorithm) {
+        String ctEncryptionAlgo = jwk.getAlgorithm() == null ? defaultAlgorithm : jwk.getAlgorithm();
+        ContentEncryptionProvider contentEncryptionProvider = null;
+        KeyType keyType = jwk.getKeyType();
+        if (KeyType.OCTET == keyType) {
+            return getContentEncryptionAlgorithm(JwkUtils.toSecretKey(jwk),
+                                                 getContentAlgo(ctEncryptionAlgo));
+        }
+        return contentEncryptionProvider;
+    }
+    public static ContentEncryptionProvider getContentEncryptionAlgorithm(SecretKey key, 
+                                                                          ContentAlgorithm algorithm) {
+        if (AlgorithmUtils.isAesGcm(algorithm.getJwaName())) {
+            return new AesGcmContentEncryptionAlgorithm(key, null, algorithm);
+        }
+        return null;
+    }
+    public static ContentEncryptionProvider getContentEncryptionAlgorithm(String algorithm) {
+        if (AlgorithmUtils.isAesGcm(algorithm)) {
+            return new AesGcmContentEncryptionAlgorithm(getContentAlgo(algorithm));
+        }
+        return null;
+    }
+    public static ContentDecryptionProvider getContentDecryptionProvider(ContentAlgorithm algorithm) {
+        if (AlgorithmUtils.isAesGcm(algorithm.getJwaName())) {
+            return new AesGcmContentDecryptionAlgorithm(algorithm);
+        }
+        return null;
+    }
+    public static SecretKey getContentDecryptionSecretKey(JsonWebKey jwk) {
+        return getContentDecryptionSecretKey(jwk, null);
+    }
+    public static SecretKey getContentDecryptionSecretKey(JsonWebKey jwk, String defaultAlgorithm) {
+        String ctEncryptionAlgo = jwk.getAlgorithm() == null ? defaultAlgorithm : jwk.getAlgorithm();
+        KeyType keyType = jwk.getKeyType();
+        if (KeyType.OCTET == keyType && AlgorithmUtils.isAesGcm(ctEncryptionAlgo)) {
+            return JwkUtils.toSecretKey(jwk);
+        }
+        return null;
+    }
+    private static ContentAlgorithm getContentAlgo(String algo) {
+        return ContentAlgorithm.getAlgorithm(algo);
+    }
+    public static JweEncryption getDirectKeyJweEncryption(JsonWebKey key) {
+        return getDirectKeyJweEncryption(JwkUtils.toSecretKey(key), 
+                                         getContentAlgo(key.getAlgorithm()));
+    }
+    public static JweEncryption getDirectKeyJweEncryption(SecretKey key, ContentAlgorithm algo) {
+        if (AlgorithmUtils.isAesCbcHmac(algo.getJwaName())) {
+            return new AesCbcHmacJweEncryption(algo, key.getEncoded(), 
+                                               null, new DirectKeyEncryptionAlgorithm());
+        } else {
+            return new JweEncryption(new DirectKeyEncryptionAlgorithm(), 
+                                 getContentEncryptionAlgorithm(key, algo));
+        }
+    }
+    public static JweDecryption getDirectKeyJweDecryption(JsonWebKey key) {
+        return getDirectKeyJweDecryption(JwkUtils.toSecretKey(key), getContentAlgo(key.getAlgorithm()));
+    }
+    public static JweDecryption getDirectKeyJweDecryption(SecretKey key, ContentAlgorithm algorithm) {
+        if (AlgorithmUtils.isAesCbcHmac(algorithm.getJwaName())) { 
+            return new AesCbcHmacJweDecryption(new DirectKeyDecryptionAlgorithm(key), algorithm);
+        } else {
+            return new JweDecryption(new DirectKeyDecryptionAlgorithm(key), 
+                                 getContentDecryptionProvider(algorithm));
+        }
+    }
+    public static JweEncryptionProvider loadEncryptionProvider(boolean required) {
+        return loadEncryptionProvider(null, required);
+    }
+    public static JweEncryptionProvider loadEncryptionProvider(JweHeaders headers, boolean required) {
+        Message m = PhaseInterceptorChain.getCurrentMessage();
+        Properties props = KeyManagementUtils.loadStoreProperties(m, required, 
+                                                                  RSSEC_ENCRYPTION_OUT_PROPS, RSSEC_ENCRYPTION_PROPS);
+        if (props == null) {
+            return null;
+        }
+        
+        boolean reportPublicKey = 
+            headers != null && MessageUtils.isTrue(
+                MessageUtils.getContextualProperty(m, RSSEC_ENCRYPTION_REPORT_KEY_PROP, 
+                                                   KeyManagementUtils.RSSEC_REPORT_KEY_PROP));
+        boolean reportPublicKeyId = 
+            headers != null && MessageUtils.isTrue(
+                MessageUtils.getContextualProperty(m, RSSEC_ENCRYPTION_REPORT_KEY_ID_PROP, 
+                                                   KeyManagementUtils.RSSEC_REPORT_KEY_ID_PROP));
+        
+        KeyEncryptionProvider keyEncryptionProvider = null;
+        String keyEncryptionAlgo = getKeyEncryptionAlgo(m, props, null, null);
+        KeyAlgorithm keyAlgo = KeyAlgorithm.getAlgorithm(keyEncryptionAlgo); 
+        String contentEncryptionAlgo = getContentEncryptionAlgo(m, props, null);
+        ContentEncryptionProvider ctEncryptionProvider = null;
+        if (JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(KeyManagementUtils.RSSEC_KEY_STORE_TYPE))) {
+            JsonWebKey jwk = JwkUtils.loadJsonWebKey(m, props, KeyOperation.ENCRYPT);
+            if ("direct".equals(keyEncryptionAlgo)) {
+                contentEncryptionAlgo = getContentEncryptionAlgo(m, props, jwk.getAlgorithm());
+                ctEncryptionProvider = getContentEncryptionAlgorithm(jwk, contentEncryptionAlgo);
+            } else {
+                keyEncryptionAlgo = getKeyEncryptionAlgo(m, props, jwk.getAlgorithm(), 
+                                                         getDefaultKeyAlgo(jwk));
+                keyEncryptionProvider = getKeyEncryptionProvider(jwk, keyAlgo);
+                if (reportPublicKey || reportPublicKeyId) {
+                    JwkUtils.setPublicKeyInfo(jwk, headers, keyEncryptionAlgo, 
+                                              reportPublicKey, reportPublicKeyId);
+                }
+            }
+        } else {
+            keyEncryptionProvider = getPublicKeyEncryptionProvider(
+                KeyManagementUtils.loadPublicKey(m, props), 
+                keyAlgo);
+            if (reportPublicKey) {
+                headers.setX509Chain(KeyManagementUtils.loadAndEncodeX509CertificateOrChain(m, props));
+            }
+            
+        }
+        return createJweEncryptionProvider(keyEncryptionProvider, 
+                                    ctEncryptionProvider, 
+                                    contentEncryptionAlgo,
+                                    props.getProperty(JSON_WEB_ENCRYPTION_ZIP_ALGO_PROP));
+    }
+    public static JweDecryptionProvider loadDecryptionProvider(boolean required) {
+        return loadDecryptionProvider(null, required);
+    }
+    public static JweDecryptionProvider loadDecryptionProvider(JweHeaders inHeaders, boolean required) {
+        Message m = PhaseInterceptorChain.getCurrentMessage();
+        Properties props = KeyManagementUtils.loadStoreProperties(m, required, 
+                                                                  RSSEC_ENCRYPTION_IN_PROPS, RSSEC_ENCRYPTION_PROPS);
+        if (props == null) {
+            return null;
+        }    
+        
+        KeyDecryptionProvider keyDecryptionProvider = null;
+        String contentEncryptionAlgo = getContentEncryptionAlgo(m, props, null);
+        SecretKey ctDecryptionKey = null;
+        String keyEncryptionAlgo = getKeyEncryptionAlgo(m, props, null, null);
+        if (inHeaders != null && inHeaders.getHeader(JoseConstants.HEADER_X509_CHAIN) != null) {
+            //TODO: validate incoming public keys or certificates  
+            //TODO: optionally validate inHeaders.getAlgorithm against a property in props
+            // Supporting loading a private key via a certificate for now
+            List<X509Certificate> chain = KeyManagementUtils.toX509CertificateChain(inHeaders.getX509Chain());
+            KeyManagementUtils.validateCertificateChain(props, chain);
+            PrivateKey privateKey = 
+                KeyManagementUtils.loadPrivateKey(m, props, chain, KeyOperation.DECRYPT);
+            contentEncryptionAlgo = inHeaders.getContentEncryptionAlgorithm().getJwaName();
+            keyDecryptionProvider = getPrivateKeyDecryptionProvider(privateKey, 
+                                                                 inHeaders.getKeyEncryptionAlgorithm());
+        } else {
+            if (JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(KeyManagementUtils.RSSEC_KEY_STORE_TYPE))) {
+                JsonWebKey jwk = JwkUtils.loadJsonWebKey(m, props, KeyOperation.DECRYPT);
+                if ("direct".equals(keyEncryptionAlgo)) {
+                    contentEncryptionAlgo = getContentEncryptionAlgo(m, props, jwk.getAlgorithm());
+                    ctDecryptionKey = getContentDecryptionSecretKey(jwk, contentEncryptionAlgo);
+                } else {
+                    keyEncryptionAlgo = getKeyEncryptionAlgo(m, props, jwk.getAlgorithm(),
+                                                             getDefaultKeyAlgo(jwk));
+                    keyDecryptionProvider = getKeyDecryptionProvider(jwk, 
+                                                                      KeyAlgorithm.getAlgorithm(keyEncryptionAlgo));
+                }
+            } else {
+                keyDecryptionProvider = getPrivateKeyDecryptionProvider(
+                    KeyManagementUtils.loadPrivateKey(m, props, KeyOperation.DECRYPT), 
+                    KeyAlgorithm.getAlgorithm(keyEncryptionAlgo));
+            }
+        }
+        return createJweDecryptionProvider(keyDecryptionProvider, ctDecryptionKey, 
+                                           getContentAlgo(contentEncryptionAlgo));
+    }
+    public static JweEncryptionProvider createJweEncryptionProvider(PublicKey key,
+                                                                    KeyAlgorithm keyAlgo,
+                                                                    ContentAlgorithm contentEncryptionAlgo,
+                                                                    String compression) {
+        KeyEncryptionProvider keyEncryptionProvider = getPublicKeyEncryptionProvider(key, keyAlgo);
+        return createJweEncryptionProvider(keyEncryptionProvider, contentEncryptionAlgo, compression);
+    }
+    public static JweEncryptionProvider createJweEncryptionProvider(PublicKey key, JweHeaders headers) {
+        KeyEncryptionProvider keyEncryptionProvider = getPublicKeyEncryptionProvider(key, 
+                                                           headers.getKeyEncryptionAlgorithm());
+        return createJweEncryptionProvider(keyEncryptionProvider, headers);
+    }
+    public static JweEncryptionProvider createJweEncryptionProvider(SecretKey key,
+                                                                    KeyAlgorithm keyAlgo,
+                                                                    ContentAlgorithm contentEncryptionAlgo,
+                                                                    String compression) {
+        KeyEncryptionProvider keyEncryptionProvider = getSecretKeyEncryptionAlgorithm(key, keyAlgo);
+        return createJweEncryptionProvider(keyEncryptionProvider, contentEncryptionAlgo, compression);
+    }
+    public static JweEncryptionProvider createJweEncryptionProvider(SecretKey key, JweHeaders headers) {
+        KeyEncryptionProvider keyEncryptionProvider = getSecretKeyEncryptionAlgorithm(key, 
+                                                           headers.getKeyEncryptionAlgorithm());
+        return createJweEncryptionProvider(keyEncryptionProvider, headers);
+    }
+    public static JweEncryptionProvider createJweEncryptionProvider(JsonWebKey key,
+                                                                    ContentAlgorithm contentEncryptionAlgo,
+                                                                    String compression) {
+        KeyEncryptionProvider keyEncryptionProvider = getKeyEncryptionProvider(key);
+        return createJweEncryptionProvider(keyEncryptionProvider, contentEncryptionAlgo, compression);
+    }
+    public static JweEncryptionProvider createJweEncryptionProvider(JsonWebKey key, JweHeaders headers) {
+        KeyEncryptionProvider keyEncryptionProvider = getKeyEncryptionProvider(key);
+        return createJweEncryptionProvider(keyEncryptionProvider, headers);
+    }
+    public static JweEncryptionProvider createJweEncryptionProvider(KeyEncryptionProvider keyEncryptionProvider,
+                                                                    ContentAlgorithm contentEncryptionAlgo,
+                                                                    String compression) {
+        JweHeaders headers = 
+            prepareJweHeaders(keyEncryptionProvider != null ? keyEncryptionProvider.getAlgorithm().getJwaName() : null,
+                contentEncryptionAlgo.getJwaName(), compression);
+        return createJweEncryptionProvider(keyEncryptionProvider, headers);
+    }
+    public static JweEncryptionProvider createJweEncryptionProvider(KeyEncryptionProvider keyEncryptionProvider,
+                                                                    JweHeaders headers) {
+        String contentEncryptionAlgo = headers.getContentEncryptionAlgorithm().getJwaName();
+        if (AlgorithmUtils.isAesCbcHmac(contentEncryptionAlgo)) { 
+            return new AesCbcHmacJweEncryption(getContentAlgo(contentEncryptionAlgo), keyEncryptionProvider);
+        } else {
+            return new JweEncryption(keyEncryptionProvider,
+                                     getContentEncryptionAlgorithm(contentEncryptionAlgo));
+        }
+    }
+    public static JweDecryptionProvider createJweDecryptionProvider(PrivateKey key,
+                                                                    KeyAlgorithm keyAlgo,
+                                                                    ContentAlgorithm contentDecryptionAlgo) {
+        return createJweDecryptionProvider(getPrivateKeyDecryptionProvider(key, keyAlgo), contentDecryptionAlgo);
+    }
+    public static JweDecryptionProvider createJweDecryptionProvider(SecretKey key,
+                                                                    KeyAlgorithm keyAlgo,
+                                                                    ContentAlgorithm contentDecryptionAlgo) {
+        return createJweDecryptionProvider(getSecretKeyDecryptionProvider(key, keyAlgo), contentDecryptionAlgo);
+    }
+    public static JweDecryptionProvider createJweDecryptionProvider(JsonWebKey key,
+                                                                    ContentAlgorithm contentDecryptionAlgo) {
+        return createJweDecryptionProvider(getKeyDecryptionProvider(key), contentDecryptionAlgo);
+    }
+    public static JweDecryptionProvider createJweDecryptionProvider(KeyDecryptionProvider keyDecryptionProvider,
+                                                                    ContentAlgorithm contentDecryptionAlgo) {
+        if (AlgorithmUtils.isAesCbcHmac(contentDecryptionAlgo.getJwaName())) { 
+            return new AesCbcHmacJweDecryption(keyDecryptionProvider, contentDecryptionAlgo);
+        } else {
+            return new JweDecryption(keyDecryptionProvider, 
+                                     getContentDecryptionProvider(contentDecryptionAlgo));
+        }
+    }
+    public static boolean validateCriticalHeaders(JoseHeaders headers) {
+        //TODO: Validate JWE specific constraints
+        return JoseUtils.validateCriticalHeaders(headers);
+    }
+    public static byte[] getECDHKey(JsonWebKey privateKey, 
+                                    JsonWebKey peerPublicKey,
+                                    byte[] partyUInfo,
+                                    byte[] partyVInfo,
+                                    String algoName,
+                                    int algoKeyBitLen) { 
+        return getECDHKey(JwkUtils.toECPrivateKey(privateKey),
+                          JwkUtils.toECPublicKey(peerPublicKey),
+                          partyUInfo, partyVInfo, algoName, algoKeyBitLen);
+    }
+    public static byte[] getECDHKey(ECPrivateKey privateKey, 
+                                    ECPublicKey peerPublicKey,
+                                    byte[] partyUInfo,
+                                    byte[] partyVInfo,
+                                    String algoName,
+                                    int algoKeyBitLen) { 
+        byte[] keyZ = generateKeyZ(privateKey, peerPublicKey);
+        return calculateDerivedKey(keyZ, algoName, partyUInfo, partyVInfo, algoKeyBitLen);
+    }
+    public static byte[] getAdditionalAuthenticationData(String headersJson, byte[] aad) {
+        byte[] headersAAD = JweHeaders.toCipherAdditionalAuthData(headersJson);
+        if (aad != null) {
+            // JWE JSON can provide the extra aad
+            byte[] newAAD = Arrays.copyOf(headersAAD, headersAAD.length + 1 + aad.length);
+            newAAD[headersAAD.length] = '.';
+            System.arraycopy(aad, 0, newAAD, headersAAD.length + 1, aad.length);
+            return newAAD;
+        } else {
+            return headersAAD;
+        }
+    }
+    private static byte[] calculateDerivedKey(byte[] keyZ, 
+                                              String algoName,
+                                              byte[] apuBytes, 
+                                              byte[] apvBytes,
+                                              int algoKeyBitLen) {
+        final byte[] emptyPartyInfo = new byte[4];
+       
+        if (apuBytes != null && apvBytes != null && Arrays.equals(apuBytes, apvBytes)) {
+            LOG.warning("Derived key calculation problem: apu equals to apv");
+            throw new JweException(JweException.Error.KEY_ENCRYPTION_FAILURE);
+        }
+        byte[] algorithmId = concatenateDatalenAndData(StringUtils.toBytesASCII(algoName));
+        byte[] partyUInfo = apuBytes == null ? emptyPartyInfo : concatenateDatalenAndData(apuBytes);
+        byte[] partyVInfo = apvBytes == null ? emptyPartyInfo : concatenateDatalenAndData(apvBytes);
+        byte[] suppPubInfo = datalenToBytes(algoKeyBitLen);
+       
+        byte[] otherInfo = new byte[algorithmId.length 
+                                   + partyUInfo.length
+                                   + partyVInfo.length
+                                   + suppPubInfo.length];
+        System.arraycopy(algorithmId, 0, otherInfo, 0, algorithmId.length);
+        System.arraycopy(partyUInfo, 0, otherInfo, algorithmId.length, partyUInfo.length);
+        System.arraycopy(partyVInfo, 0, otherInfo, algorithmId.length + partyUInfo.length, partyVInfo.length);
+        System.arraycopy(suppPubInfo, 0, otherInfo, algorithmId.length + partyUInfo.length + partyVInfo.length,
+                         suppPubInfo.length);
+       
+       
+        byte[] concatKDF = new byte[36 + otherInfo.length];
+        concatKDF[3] = 1;
+        System.arraycopy(keyZ, 0, concatKDF, 4, keyZ.length);
+        System.arraycopy(otherInfo, 0, concatKDF, 36, otherInfo.length);
+        try {
+            byte[] round1Hash = MessageDigestUtils.createDigest(concatKDF, MessageDigestUtils.ALGO_SHA_256);
+            return Arrays.copyOf(round1Hash, algoKeyBitLen / 8);
+        } catch (Exception ex) {
+            LOG.warning("Derived key calculation problem: round hash1 error");
+            throw new JweException(JweException.Error.KEY_ENCRYPTION_FAILURE);
+        }
+    }
+    private static byte[] generateKeyZ(ECPrivateKey privateKey, ECPublicKey publicKey) {
+        try {
+            KeyAgreement ka = KeyAgreement.getInstance("ECDH");
+            ka.init(privateKey);
+            ka.doPhase(publicKey, true);
+            return ka.generateSecret();
+        } catch (Exception ex) {
+            LOG.warning("Derived key calculation problem");
+            throw new JweException(JweException.Error.KEY_ENCRYPTION_FAILURE);
+        }
+    }
+    private static byte[] concatenateDatalenAndData(byte[] bytesASCII) {
+        final byte[] datalen = datalenToBytes(bytesASCII.length);
+        byte[] all = new byte[4 + bytesASCII.length];
+        System.arraycopy(datalen, 0, all, 0, 4);
+        System.arraycopy(bytesASCII, 0, all, 4, bytesASCII.length);
+        return all;
+    }
+    private static byte[] datalenToBytes(int len) {
+        ByteBuffer buf = ByteBuffer.allocate(4);
+        return buf.putInt(len).array();
+    }
+    private static JweHeaders prepareJweHeaders(String keyEncryptionAlgo,
+                                                String contentEncryptionAlgo,
+                                                String compression) {
+        JweHeaders headers = new JweHeaders();
+        if (keyEncryptionAlgo != null) {
+            headers.setKeyEncryptionAlgorithm(KeyAlgorithm.getAlgorithm(keyEncryptionAlgo));
+        }
+        headers.setContentEncryptionAlgorithm(ContentAlgorithm.getAlgorithm(contentEncryptionAlgo));
+        if (compression != null) {
+            headers.setZipAlgorithm(compression);
+        }
+        return headers;
+    }
+    private static JweEncryptionProvider createJweEncryptionProvider(KeyEncryptionProvider keyEncryptionProvider,
+                                                                     ContentEncryptionProvider ctEncryptionProvider,
+                                                                     String contentEncryptionAlgo,
+                                                                     String compression) {
+        if (keyEncryptionProvider == null && ctEncryptionProvider == null) {
+            LOG.warning("Key or content encryptor is not available");
+            throw new JweException(JweException.Error.NO_ENCRYPTOR);
+        }
+        JweHeaders headers = 
+            prepareJweHeaders(keyEncryptionProvider != null ? keyEncryptionProvider.getAlgorithm().getJwaName() : null,
+                contentEncryptionAlgo, compression);
+        if (keyEncryptionProvider != null) {
+            return createJweEncryptionProvider(keyEncryptionProvider, headers);
+        } else {
+            return new JweEncryption(new DirectKeyEncryptionAlgorithm(), ctEncryptionProvider);
+        }
+    }
+    private static JweDecryptionProvider createJweDecryptionProvider(KeyDecryptionProvider keyDecryptionProvider,
+                                                                    SecretKey ctDecryptionKey,
+                                                                    ContentAlgorithm contentDecryptionAlgo) {
+        if (keyDecryptionProvider == null && ctDecryptionKey == null) {
+            LOG.warning("Key or content encryptor is not available");
+            throw new JweException(JweException.Error.NO_ENCRYPTOR);
+        }
+        if (keyDecryptionProvider != null) {
+            return createJweDecryptionProvider(keyDecryptionProvider, contentDecryptionAlgo);
+        } else {
+            return getDirectKeyJweDecryption(ctDecryptionKey, contentDecryptionAlgo);
+        }
+    }
+    private static String getKeyEncryptionAlgo(Message m, Properties props, 
+                                               String algo, String defaultAlgo) {
+        if (algo == null) {
+            if (defaultAlgo == null) {
+                defaultAlgo = AlgorithmUtils.RSA_OAEP_ALGO;
+            }
+            return KeyManagementUtils.getKeyAlgorithm(m, props, 
+                JSON_WEB_ENCRYPTION_KEY_ALGO_PROP, defaultAlgo);
+        }
+        return algo;
+    }
+    private static String getDefaultKeyAlgo(JsonWebKey jwk) {
+        KeyType keyType = jwk.getKeyType();
+        if (KeyType.OCTET == keyType) {
+            return AlgorithmUtils.A128GCMKW_ALGO;
+        } else {
+            return AlgorithmUtils.RSA_OAEP_ALGO;
+        }
+    }
+    private static String getContentEncryptionAlgo(Message m, Properties props, String algo) {
+        if (algo == null) {
+            return KeyManagementUtils.getKeyAlgorithm(m, props, 
+                JSON_WEB_ENCRYPTION_CEK_ALGO_PROP, AlgorithmUtils.A128GCM_ALGO);
+        }
+        return algo;
+    }
+    private static String encrypt(KeyEncryptionProvider keyEncryptionProvider, 
+                                  ContentAlgorithm contentAlgo, byte[] content, String ct) {
+        JweEncryptionProvider jwe = createJweEncryptionProvider(keyEncryptionProvider, contentAlgo, null);
+        return jwe.encrypt(content, toJweHeaders(ct));
+    }
+    private static byte[] decrypt(KeyDecryptionProvider keyDecryptionProvider, ContentAlgorithm contentAlgo, 
+                                  String content) {
+        JweDecryptionProvider jwe = createJweDecryptionProvider(keyDecryptionProvider, contentAlgo);
+        return jwe.decrypt(content).getContent();
+    }
+    private static JweHeaders toJweHeaders(String ct) {
+        return new JweHeaders(Collections.<String, Object>singletonMap(JoseConstants.HEADER_CONTENT_TYPE, ct));
+    }
+    public static void validateJweCertificateChain(List<X509Certificate> certs) {
+        Message m = PhaseInterceptorChain.getCurrentMessage();
+        Properties props = KeyManagementUtils.loadStoreProperties(m, true, 
+                                                                  RSSEC_ENCRYPTION_IN_PROPS, RSSEC_ENCRYPTION_PROPS);
+        KeyManagementUtils.validateCertificateChain(props, certs);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/KeyDecryptionProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/KeyDecryptionProvider.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/KeyDecryptionProvider.java
new file mode 100644
index 0000000..1924e78
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/KeyDecryptionProvider.java
@@ -0,0 +1,27 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.jose.jwe;
+
+import org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm;
+
+
+public interface KeyDecryptionProvider {
+    KeyAlgorithm getAlgorithm();
+    byte[] getDecryptedContentEncryptionKey(JweDecryptionInput jweDecryptionInput);
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/KeyEncryptionProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/KeyEncryptionProvider.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/KeyEncryptionProvider.java
new file mode 100644
index 0000000..2f5c8db
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/KeyEncryptionProvider.java
@@ -0,0 +1,27 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.jose.jwe;
+
+import org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm;
+
+
+public interface KeyEncryptionProvider {
+    KeyAlgorithm getAlgorithm();
+    byte[] getEncryptedContentEncryptionKey(JweHeaders headers, byte[] cek);
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyDecryptionAlgorithm.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyDecryptionAlgorithm.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyDecryptionAlgorithm.java
new file mode 100644
index 0000000..1ee6eea
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyDecryptionAlgorithm.java
@@ -0,0 +1,77 @@
+/**
+ * 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.common.util.Base64UrlUtility;
+import org.apache.cxf.rs.security.jose.JoseException;
+import org.apache.cxf.rs.security.jose.jwa.AlgorithmUtils;
+import org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm;
+
+public class PbesHmacAesWrapKeyDecryptionAlgorithm implements KeyDecryptionProvider {
+    private byte[] password;
+    private KeyAlgorithm algo;
+    public PbesHmacAesWrapKeyDecryptionAlgorithm(String password) {    
+        this(password, KeyAlgorithm.PBES2_HS256_A128KW, false);
+    }
+    public PbesHmacAesWrapKeyDecryptionAlgorithm(String password, KeyAlgorithm algo, boolean hashLargePasswords) {    
+        this(PbesHmacAesWrapKeyEncryptionAlgorithm.stringToBytes(password), algo, hashLargePasswords);
+    }
+    public PbesHmacAesWrapKeyDecryptionAlgorithm(char[] password) {    
+        this(password, KeyAlgorithm.PBES2_HS256_A128KW, false);
+    }
+    public PbesHmacAesWrapKeyDecryptionAlgorithm(char[] password, KeyAlgorithm algo, boolean hashLargePasswords) {    
+        this(PbesHmacAesWrapKeyEncryptionAlgorithm.charsToBytes(password), algo, hashLargePasswords);
+    }
+    public PbesHmacAesWrapKeyDecryptionAlgorithm(byte[] password) {    
+        this(password, KeyAlgorithm.PBES2_HS256_A128KW, false);
+    }
+    public PbesHmacAesWrapKeyDecryptionAlgorithm(byte[] password, KeyAlgorithm algo, boolean hashLargePasswords) {    
+        this.password = 
+            PbesHmacAesWrapKeyEncryptionAlgorithm.validatePassword(password, algo.getJwaName(), hashLargePasswords);
+        this.algo = algo;
+    }
+    @Override
+    public byte[] getDecryptedContentEncryptionKey(JweDecryptionInput jweDecryptionInput) {
+        JweHeaders jweHeaders = jweDecryptionInput.getJweHeaders();
+        byte[] saltInput = getDecodedBytes(jweHeaders.getHeader("p2s"));
+        int pbesCount = jweHeaders.getIntegerHeader("p2c");
+        String keyAlgoJwt = jweHeaders.getKeyEncryptionAlgorithm().getJwaName();
+        int keySize = PbesHmacAesWrapKeyEncryptionAlgorithm.getKeySize(keyAlgoJwt);
+        byte[] derivedKey = PbesHmacAesWrapKeyEncryptionAlgorithm
+            .createDerivedKey(keyAlgoJwt, keySize, password, saltInput, pbesCount);
+        KeyDecryptionProvider aesWrap = new AesWrapKeyDecryptionAlgorithm(derivedKey, algo) {
+            protected boolean isValidAlgorithmFamily(String wrapAlgo) {
+                return AlgorithmUtils.isPbesHsWrap(wrapAlgo);
+            }    
+        };
+        return aesWrap.getDecryptedContentEncryptionKey(jweDecryptionInput);
+    }    
+    private byte[] getDecodedBytes(Object p2sHeader) {
+        try {
+            return Base64UrlUtility.decode(p2sHeader.toString());
+        } catch (Exception ex) {
+            throw new JoseException(ex);
+        }
+    }
+    @Override
+    public KeyAlgorithm getAlgorithm() {
+        return algo;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyEncryptionAlgorithm.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyEncryptionAlgorithm.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyEncryptionAlgorithm.java
new file mode 100644
index 0000000..0a17be5
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyEncryptionAlgorithm.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.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.Base64UrlUtility;
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.rs.security.jose.jwa.AlgorithmUtils;
+import org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm;
+import org.apache.cxf.rt.security.crypto.CryptoUtils;
+import org.apache.cxf.rt.security.crypto.MessageDigestUtils;
+import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.crypto.digests.SHA256Digest;
+import org.bouncycastle.crypto.digests.SHA384Digest;
+import org.bouncycastle.crypto.digests.SHA512Digest;
+import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;
+import org.bouncycastle.crypto.params.KeyParameter;
+
+public class PbesHmacAesWrapKeyEncryptionAlgorithm implements KeyEncryptionProvider {
+    protected static final Logger LOG = LogUtils.getL7dLogger(PbesHmacAesWrapKeyEncryptionAlgorithm.class);
+    private static final Map<String, Integer> PBES_HMAC_MAP;
+    private static final Map<String, String> PBES_AES_MAP;
+    private static final Map<String, Integer> DERIVED_KEY_SIZE_MAP;
+    static {
+        PBES_HMAC_MAP = new HashMap<String, Integer>();
+        PBES_HMAC_MAP.put(KeyAlgorithm.PBES2_HS256_A128KW.getJwaName(), 256);
+        PBES_HMAC_MAP.put(KeyAlgorithm.PBES2_HS384_A192KW.getJwaName(), 384);
+        PBES_HMAC_MAP.put(KeyAlgorithm.PBES2_HS512_A256KW.getJwaName(), 512);
+        
+        PBES_AES_MAP = new HashMap<String, String>();
+        PBES_AES_MAP.put(KeyAlgorithm.PBES2_HS256_A128KW.getJwaName(), KeyAlgorithm.A128KW.getJwaName());
+        PBES_AES_MAP.put(KeyAlgorithm.PBES2_HS384_A192KW.getJwaName(), KeyAlgorithm.A192KW.getJwaName());
+        PBES_AES_MAP.put(KeyAlgorithm.PBES2_HS512_A256KW.getJwaName(), KeyAlgorithm.A256KW.getJwaName());
+        
+        DERIVED_KEY_SIZE_MAP = new HashMap<String, Integer>();
+        DERIVED_KEY_SIZE_MAP.put(KeyAlgorithm.PBES2_HS256_A128KW.getJwaName(), 16);
+        DERIVED_KEY_SIZE_MAP.put(KeyAlgorithm.PBES2_HS384_A192KW.getJwaName(), 24);
+        DERIVED_KEY_SIZE_MAP.put(KeyAlgorithm.PBES2_HS512_A256KW.getJwaName(), 32);
+    }
+    
+    
+    private byte[] password;
+    private int pbesCount;
+    private KeyAlgorithm keyAlgoJwt;
+    public PbesHmacAesWrapKeyEncryptionAlgorithm(String password, KeyAlgorithm keyAlgoJwt) {
+        this(stringToBytes(password), keyAlgoJwt);
+    }
+    public PbesHmacAesWrapKeyEncryptionAlgorithm(String password, int pbesCount, 
+                                                 KeyAlgorithm keyAlgoJwt, 
+                                                 boolean hashLargePasswords) {
+        this(stringToBytes(password), pbesCount, keyAlgoJwt, hashLargePasswords);
+    }
+    public PbesHmacAesWrapKeyEncryptionAlgorithm(char[] password, KeyAlgorithm keyAlgoJwt) {
+        this(password, 4096, keyAlgoJwt, false);
+    }
+    public PbesHmacAesWrapKeyEncryptionAlgorithm(char[] password, int pbesCount, 
+                                                 KeyAlgorithm keyAlgoJwt, 
+                                                 boolean hashLargePasswords) {
+        this(charsToBytes(password), pbesCount, keyAlgoJwt, hashLargePasswords);
+    }
+    public PbesHmacAesWrapKeyEncryptionAlgorithm(byte[] password, KeyAlgorithm keyAlgoJwt) {
+        this(password, 4096, keyAlgoJwt, false);
+    }
+    public PbesHmacAesWrapKeyEncryptionAlgorithm(byte[] password, int pbesCount, 
+                                                 KeyAlgorithm keyAlgoJwt, 
+                                                 boolean hashLargePasswords) {
+        this.keyAlgoJwt = validateKeyAlgorithm(keyAlgoJwt);
+        this.password = validatePassword(password, keyAlgoJwt.getJwaName(), hashLargePasswords);
+        this.pbesCount = validatePbesCount(pbesCount);
+    }
+    
+    static byte[] validatePassword(byte[] p, String keyAlgoJwt, boolean hashLargePasswords) {
+        int minLen = DERIVED_KEY_SIZE_MAP.get(keyAlgoJwt);
+        if (p.length < minLen || p.length > 128) {
+            LOG.warning("Invalid password length: " + p.length);
+            throw new JweException(JweException.Error.KEY_ENCRYPTION_FAILURE);
+        }
+        if (p.length > minLen && hashLargePasswords) {
+            try {
+                return MessageDigestUtils.createDigest(p, MessageDigestUtils.ALGO_SHA_256);
+            } catch (Exception ex) {
+                LOG.warning("Password hash calculation error");
+                throw new JweException(JweException.Error.KEY_ENCRYPTION_FAILURE, ex);
+            }
+        } else {
+            return p;
+        }
+    }
+    @Override
+    public byte[] getEncryptedContentEncryptionKey(JweHeaders headers, byte[] cek) {
+        int keySize = getKeySize(keyAlgoJwt.getJwaName());
+        byte[] saltInput = CryptoUtils.generateSecureRandomBytes(keySize);
+        byte[] derivedKey = createDerivedKey(keyAlgoJwt.getJwaName(), 
+                                             keySize, password, saltInput, pbesCount);
+        
+        headers.setHeader("p2s", Base64UrlUtility.encode(saltInput));
+        headers.setIntegerHeader("p2c", pbesCount);
+        
+        KeyEncryptionProvider aesWrap = new AesWrapKeyEncryptionAlgorithm(derivedKey, keyAlgoJwt) {
+            protected void checkAlgorithms(JweHeaders headers) {
+                // complete
+            }
+            protected String getKeyEncryptionAlgoJava(JweHeaders headers) {
+                return AlgorithmUtils.AES_WRAP_ALGO_JAVA;
+            }
+        };
+        return aesWrap.getEncryptedContentEncryptionKey(headers, cek);
+        
+        
+    }
+    static int getKeySize(String keyAlgoJwt) {
+        return DERIVED_KEY_SIZE_MAP.get(keyAlgoJwt);
+    }
+    static byte[] createDerivedKey(String keyAlgoJwt, int keySize,
+                                   byte[] password, byte[] saltInput, int pbesCount) {
+        byte[] saltValue = createSaltValue(keyAlgoJwt, saltInput);
+        Digest digest = null;
+        int macSigSize = PBES_HMAC_MAP.get(keyAlgoJwt);
+        if (macSigSize == 256) { 
+            digest = new SHA256Digest();
+        } else if (macSigSize == 384) {
+            digest = new SHA384Digest();
+        } else {
+            digest = new SHA512Digest();
+        }
+        PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(digest);
+        gen.init(password, saltValue, pbesCount);
+        return ((KeyParameter) gen.generateDerivedParameters(keySize * 8)).getKey();
+    }
+    
+    
+    private static byte[] createSaltValue(String keyAlgoJwt, byte[] saltInput) {
+        byte[] algoBytes = stringToBytes(keyAlgoJwt);
+        byte[] saltValue = new byte[algoBytes.length + 1 + saltInput.length];
+        System.arraycopy(algoBytes, 0, saltValue, 0, algoBytes.length);
+        saltValue[algoBytes.length] = 0;
+        System.arraycopy(saltInput, 0, saltValue, algoBytes.length + 1, saltInput.length);
+        return saltValue;
+    }
+    static KeyAlgorithm validateKeyAlgorithm(KeyAlgorithm algo) {
+        if (!AlgorithmUtils.isPbesHsWrap(algo.getJwaName())) {
+            LOG.warning("Invalid key encryption algorithm");
+            throw new JweException(JweException.Error.INVALID_KEY_ALGORITHM);
+        }
+        return algo;
+    }
+    static int validatePbesCount(int count) {
+        if (count < 1000) {
+            LOG.warning("Iteration count is too low");
+            throw new JweException(JweException.Error.KEY_ENCRYPTION_FAILURE);
+        }
+        return count;
+    }    
+    
+    static byte[] stringToBytes(String str) {
+        return StringUtils.toBytesUTF8(str);
+    }
+    static byte[] charsToBytes(char[] chars) {
+        ByteBuffer bb = Charset.forName("UTF-8").encode(CharBuffer.wrap(chars));
+        byte[] b = new byte[bb.remaining()];
+        bb.get(b);
+        return b;
+    }
+    @Override
+    public KeyAlgorithm getAlgorithm() {
+        return keyAlgoJwt;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/RSAKeyDecryptionAlgorithm.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/RSAKeyDecryptionAlgorithm.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/RSAKeyDecryptionAlgorithm.java
new file mode 100644
index 0000000..d29b442
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/RSAKeyDecryptionAlgorithm.java
@@ -0,0 +1,46 @@
+/**
+ * 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 org.apache.cxf.rs.security.jose.jwa.AlgorithmUtils;
+import org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm;
+
+public class RSAKeyDecryptionAlgorithm extends WrappedKeyDecryptionAlgorithm {
+    public RSAKeyDecryptionAlgorithm(RSAPrivateKey privateKey) {    
+        this(privateKey, KeyAlgorithm.RSA_OAEP);
+    }
+    public RSAKeyDecryptionAlgorithm(RSAPrivateKey privateKey, KeyAlgorithm supportedAlgo) {    
+        this(privateKey, supportedAlgo, true);
+    }
+    public RSAKeyDecryptionAlgorithm(RSAPrivateKey privateKey, KeyAlgorithm supportedAlgo, boolean unwrap) {    
+        super(privateKey, supportedAlgo, unwrap);
+    }
+    protected int getKeyCipherBlockSize() {
+        return ((RSAPrivateKey)getCekDecryptionKey()).getModulus().toByteArray().length;
+    }
+    @Override
+    protected void validateKeyEncryptionAlgorithm(String keyAlgo) {
+        super.validateKeyEncryptionAlgorithm(keyAlgo);
+        if (!AlgorithmUtils.isRsaKeyWrap(keyAlgo)) {
+            reportInvalidKeyAlgorithm(keyAlgo);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/RSAKeyEncryptionAlgorithm.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/RSAKeyEncryptionAlgorithm.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/RSAKeyEncryptionAlgorithm.java
new file mode 100644
index 0000000..b820cdd
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/RSAKeyEncryptionAlgorithm.java
@@ -0,0 +1,34 @@
+/**
+ * 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.RSAPublicKey;
+
+import org.apache.cxf.rs.security.jose.jwa.AlgorithmUtils;
+import org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm;
+
+public class RSAKeyEncryptionAlgorithm extends AbstractWrapKeyEncryptionAlgorithm {
+    public RSAKeyEncryptionAlgorithm(RSAPublicKey publicKey, KeyAlgorithm jweAlgo) {
+        this(publicKey, jweAlgo, true);
+    }
+    public RSAKeyEncryptionAlgorithm(RSAPublicKey publicKey, KeyAlgorithm jweAlgo, boolean wrap) {
+        super(publicKey, jweAlgo, wrap, AlgorithmUtils.RSA_CEK_SET);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/WrappedKeyDecryptionAlgorithm.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/WrappedKeyDecryptionAlgorithm.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/WrappedKeyDecryptionAlgorithm.java
new file mode 100644
index 0000000..0787886
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwe/WrappedKeyDecryptionAlgorithm.java
@@ -0,0 +1,97 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.jose.jwe;
+
+import java.security.Key;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.logging.Logger;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.rs.security.jose.jwa.AlgorithmUtils;
+import org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm;
+import org.apache.cxf.rt.security.crypto.CryptoUtils;
+import org.apache.cxf.rt.security.crypto.KeyProperties;
+
+public class WrappedKeyDecryptionAlgorithm implements KeyDecryptionProvider {
+    protected static final Logger LOG = LogUtils.getL7dLogger(WrappedKeyDecryptionAlgorithm.class);
+    private Key cekDecryptionKey;
+    private boolean unwrap;
+    private KeyAlgorithm supportedAlgo;
+    public WrappedKeyDecryptionAlgorithm(Key cekDecryptionKey, KeyAlgorithm supportedAlgo) {    
+        this(cekDecryptionKey, supportedAlgo, true);
+    }
+    public WrappedKeyDecryptionAlgorithm(Key cekDecryptionKey, KeyAlgorithm supportedAlgo, boolean unwrap) {    
+        this.cekDecryptionKey = cekDecryptionKey;
+        this.supportedAlgo = supportedAlgo;
+        this.unwrap = unwrap;
+    }
+    public byte[] getDecryptedContentEncryptionKey(JweDecryptionInput jweDecryptionInput) {
+        KeyProperties keyProps = new KeyProperties(getKeyEncryptionAlgorithm(jweDecryptionInput));
+        AlgorithmParameterSpec spec = getAlgorithmParameterSpec(jweDecryptionInput); 
+        if (spec != null) {
+            keyProps.setAlgoSpec(spec);
+        }
+        if (!unwrap) {
+            keyProps.setBlockSize(getKeyCipherBlockSize());
+            return CryptoUtils.decryptBytes(getEncryptedContentEncryptionKey(jweDecryptionInput), 
+                                            getCekDecryptionKey(), keyProps);
+        } else {
+            return CryptoUtils.unwrapSecretKey(getEncryptedContentEncryptionKey(jweDecryptionInput), 
+                                               getContentEncryptionAlgorithm(jweDecryptionInput), 
+                                               getCekDecryptionKey(), 
+                                               keyProps).getEncoded();
+        }
+    }
+    
+    protected Key getCekDecryptionKey() {
+        return cekDecryptionKey;
+    }
+    protected int getKeyCipherBlockSize() {
+        return -1;
+    }
+    protected String getKeyEncryptionAlgorithm(JweDecryptionInput jweDecryptionInput) {
+        String keyAlgo = jweDecryptionInput.getJweHeaders().getKeyEncryptionAlgorithm().getJwaName();
+        validateKeyEncryptionAlgorithm(keyAlgo);
+        return AlgorithmUtils.toJavaName(keyAlgo);
+    }
+    protected void validateKeyEncryptionAlgorithm(String keyAlgo) {
+        if (keyAlgo == null 
+            || !supportedAlgo.getJwaName().equals(keyAlgo)) {
+            reportInvalidKeyAlgorithm(keyAlgo);
+        }
+    }
+    protected void reportInvalidKeyAlgorithm(String keyAlgo) {
+        LOG.warning("Invalid key encryption algorithm: " + keyAlgo);
+        throw new JweException(JweException.Error.INVALID_KEY_ALGORITHM);
+    }
+    protected String getContentEncryptionAlgorithm(JweDecryptionInput jweDecryptionInput) {
+        return AlgorithmUtils.toJavaName(
+            jweDecryptionInput.getJweHeaders().getContentEncryptionAlgorithm().getJwaName());
+    }
+    protected AlgorithmParameterSpec getAlgorithmParameterSpec(JweDecryptionInput jweDecryptionInput) {
+        return null;
+    }
+    protected byte[] getEncryptedContentEncryptionKey(JweDecryptionInput jweDecryptionInput) {
+        return jweDecryptionInput.getEncryptedCEK();
+    }
+    @Override
+    public KeyAlgorithm getAlgorithm() {
+        return supportedAlgo;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwk/DefaultJwkReaderWriter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwk/DefaultJwkReaderWriter.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwk/DefaultJwkReaderWriter.java
new file mode 100644
index 0000000..5593e0b
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwk/DefaultJwkReaderWriter.java
@@ -0,0 +1,49 @@
+/**
+ * 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.jwk;
+
+import org.apache.cxf.jaxrs.provider.json.JsonMapObjectReaderWriter;
+
+
+
+
+
+public class DefaultJwkReaderWriter extends JsonMapObjectReaderWriter
+    implements JwkReaderWriter {
+    @Override
+    public String jwkSetToJson(JsonWebKeys jwks) {
+        return toJson(jwks);
+    }
+    @Override
+    public JsonWebKeys jsonToJwkSet(String jwksJson) {
+        JsonWebKeys jwks = new JsonWebKeys();
+        fromJson(jwks, jwksJson);
+        return jwks;
+    }
+    @Override
+    public String jwkToJson(JsonWebKey jwk) {
+        return toJson(jwk);
+    }
+    @Override
+    public JsonWebKey jsonToJwk(String jwkJson) {
+        JsonWebKey jwk = new JsonWebKey();
+        fromJson(jwk, jwkJson);
+        return jwk;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKey.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKey.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKey.java
new file mode 100644
index 0000000..a5479d0
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKey.java
@@ -0,0 +1,180 @@
+/**
+ * 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.jwk;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.jaxrs.provider.json.JsonMapObject;
+import org.apache.cxf.rs.security.jose.JoseConstants;
+
+
+public class JsonWebKey extends JsonMapObject {
+    
+    public static final String KEY_TYPE = "kty";
+    public static final String PUBLIC_KEY_USE = "use";
+    public static final String KEY_OPERATIONS = "key_ops";
+    public static final String KEY_ALGO = JoseConstants.HEADER_ALGORITHM;
+    public static final String KEY_ID = JoseConstants.HEADER_KEY_ID;
+    public static final String X509_URL = JoseConstants.HEADER_X509_URL;
+    public static final String X509_CHAIN = JoseConstants.HEADER_X509_CHAIN;
+    public static final String X509_THUMBPRINT = JoseConstants.HEADER_X509_THUMBPRINT;
+    public static final String X509_THUMBPRINT_SHA256 = JoseConstants.HEADER_X509_THUMBPRINT_SHA256;
+    
+    public static final String KEY_TYPE_RSA = "RSA";
+    public static final String RSA_MODULUS = "n";
+    public static final String RSA_PUBLIC_EXP = "e";
+    public static final String RSA_PRIVATE_EXP = "d";
+    public static final String RSA_FIRST_PRIME_FACTOR = "p";
+    public static final String RSA_SECOND_PRIME_FACTOR = "q";
+    public static final String RSA_FIRST_PRIME_CRT = "dp";
+    public static final String RSA_SECOND_PRIME_CRT = "dq";
+    public static final String RSA_FIRST_CRT_COEFFICIENT = "qi";
+        
+    public static final String KEY_TYPE_OCTET = "oct";
+    public static final String OCTET_KEY_VALUE = "k";
+    
+    public static final String KEY_TYPE_ELLIPTIC = "EC";
+    public static final String EC_CURVE = "crv";
+    public static final String EC_CURVE_P256 = "P-256";
+    public static final String EC_CURVE_P384 = "P-384";
+    public static final String EC_CURVE_P521 = "P-521";
+    public static final String EC_X_COORDINATE = "x";
+    public static final String EC_Y_COORDINATE = "y";
+    public static final String EC_PRIVATE_KEY = "d";
+    
+    public static final String PUBLIC_KEY_USE_SIGN = "sig";
+    public static final String PUBLIC_KEY_USE_ENCRYPT = "enc";
+    
+    public static final String KEY_OPER_SIGN = "sign";
+    public static final String KEY_OPER_VERIFY = "verify";
+    public static final String KEY_OPER_ENCRYPT = "encrypt";
+    public static final String KEY_OPER_DECRYPT = "decrypt";
+    public static final String KEY_OPER_WRAP_KEY = "wrapKey";
+    public static final String KEY_OPER_UNWRAP_KEY = "unwrapKey";
+    public static final String KEY_OPER_DERIVE_KEY = "deriveKey";
+    public static final String KEY_OPER_DERIVE_BITS = "deriveBits";
+    
+    public JsonWebKey() {
+        
+    }
+    
+    public JsonWebKey(Map<String, Object> values) {
+        super(values);
+    }
+    
+    public void setKeyType(KeyType keyType) {
+        setProperty(KEY_TYPE, keyType.toString());
+    }
+    
+    public KeyType getKeyType() {
+        Object prop = getProperty(KEY_TYPE);
+        return prop == null ? null : KeyType.getKeyType(prop.toString());
+    }
+
+    public void setPublicKeyUse(PublicKeyUse use) {
+        setProperty(PUBLIC_KEY_USE, use.toString());
+    }
+    
+    public PublicKeyUse getPublicKeyUse() {
+        Object prop = getProperty(PUBLIC_KEY_USE);
+        return prop == null ? null : PublicKeyUse.getPublicKeyUse(prop.toString());
+    }
+
+    public void setKeyOperation(List<KeyOperation> keyOperation) {
+        List<String> ops = new ArrayList<String>(keyOperation.size());
+        for (KeyOperation op : keyOperation) {
+            ops.add(op.toString());
+        }
+        setProperty(KEY_OPERATIONS, ops);
+    }
+
+    public List<KeyOperation> getKeyOperation() {
+        List<Object> ops = CastUtils.cast((List<?>)getProperty(KEY_OPERATIONS));
+        if (ops == null) {
+            return null;
+        }
+        List<KeyOperation> keyOps = new ArrayList<KeyOperation>(ops.size());
+        for (Object op : ops) {
+            keyOps.add(KeyOperation.getKeyOperation(op.toString()));
+        }
+        return keyOps;
+    }
+    
+    public void setAlgorithm(String algorithm) {
+        setProperty(KEY_ALGO, algorithm);
+    }
+
+    public String getAlgorithm() {
+        return (String)getProperty(KEY_ALGO);
+    }
+    
+    public void setKeyId(String kid) {
+        setProperty(KEY_ID, kid);
+    }
+
+    public String getKeyId() {
+        return (String)getProperty(KEY_ID);
+    }
+    
+    public void setX509Url(String x509Url) {
+        setProperty(X509_URL, x509Url);
+    }
+    
+    public String getX509Url() {
+        return (String)getProperty(X509_URL);
+    }
+
+    public void setX509Chain(List<String> x509Chain) {
+        setProperty(X509_CHAIN, x509Chain);
+    }
+
+    public List<String> getX509Chain() {
+        return CastUtils.cast((List<?>)getProperty(X509_CHAIN));
+    }
+    
+    public void setX509Thumbprint(String x509Thumbprint) {
+        setProperty(X509_THUMBPRINT, x509Thumbprint);
+    }
+    
+    public String getX509Thumbprint() {
+        return (String)getProperty(X509_THUMBPRINT);
+    }
+    
+    public void setX509ThumbprintSHA256(String x509Thumbprint) {
+        setProperty(X509_THUMBPRINT_SHA256, x509Thumbprint);
+    }
+    
+    public String getX509ThumbprintSHA256() {
+        return (String)getProperty(X509_THUMBPRINT_SHA256);
+    }
+    
+    public JsonWebKey setKeyProperty(String name, Object value) {
+        setProperty(name, value);
+        return this;
+    }
+    public Object getKeyProperty(String name) {
+        return getProperty(name);
+    }
+    
+    
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKeys.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKeys.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKeys.java
new file mode 100644
index 0000000..55a19f6
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKeys.java
@@ -0,0 +1,130 @@
+/**
+ * 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.jwk;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.jaxrs.provider.json.JsonMapObject;
+
+public class JsonWebKeys extends JsonMapObject {
+    public static final String KEYS_PROPERTY = "keys";
+    public List<JsonWebKey> getKeys() {
+        List<?> list = (List<?>)super.getProperty(KEYS_PROPERTY);
+        if (list != null && !list.isEmpty()) {
+            Object first = list.get(0);
+            if (first instanceof JsonWebKey) {
+                return CastUtils.cast(list);
+            } else {
+                List<JsonWebKey> keys = new LinkedList<JsonWebKey>();
+                List<Map<String, Object>> listOfMaps = 
+                    CastUtils.cast((List<?>)super.getProperty(KEYS_PROPERTY));
+                for (Map<String, Object> map : listOfMaps) {
+                    keys.add(new JsonWebKey(map));
+                }
+                return keys;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    public void setKeys(List<JsonWebKey> keys) {
+        super.setProperty(KEYS_PROPERTY, keys);
+    }
+    
+    public Map<String, JsonWebKey> getKeyIdMap() {
+        List<JsonWebKey> keys = getKeys();
+        if (keys == null) {
+            return Collections.emptyMap();
+        }
+        Map<String, JsonWebKey> map = new LinkedHashMap<String, JsonWebKey>();
+        for (JsonWebKey key : keys) {
+            String kid = key.getKeyId();
+            if (kid != null) {
+                map.put(kid, key);
+            }
+        }
+        return map;
+    }
+    public JsonWebKey getKey(String kid) {
+        return getKeyIdMap().get(kid);
+    }
+    public Map<KeyType, List<JsonWebKey>> getKeyTypeMap() {
+        List<JsonWebKey> keys = getKeys();
+        if (keys == null) {
+            return Collections.emptyMap();
+        }
+        Map<KeyType, List<JsonWebKey>> map = new LinkedHashMap<KeyType, List<JsonWebKey>>();
+        for (JsonWebKey key : keys) {
+            KeyType type = key.getKeyType();
+            if (type != null) {
+                List<JsonWebKey> list = map.get(type);
+                if (list == null) {
+                    list = new LinkedList<JsonWebKey>();
+                    map.put(type, list);
+                }
+                list.add(key);
+            }
+        }
+        return map;
+    }
+    
+    public Map<KeyOperation, List<JsonWebKey>> getKeyOperationMap() {
+        List<JsonWebKey> keys = getKeys();
+        if (keys == null) {
+            return Collections.emptyMap();
+        }
+        Map<KeyOperation, List<JsonWebKey>> map = new LinkedHashMap<KeyOperation, List<JsonWebKey>>();
+        for (JsonWebKey key : keys) {
+            List<KeyOperation> ops = key.getKeyOperation();
+            if (ops != null) {
+                for (KeyOperation op : ops) {
+                    List<JsonWebKey> list = map.get(op);
+                    if (list == null) {
+                        list = new LinkedList<JsonWebKey>();
+                        map.put(op, list);
+                    }
+                    list.add(key);
+                }
+            }
+        }
+        return map;
+    }
+    public List<JsonWebKey> getKeys(String keyType) {
+        KeyType kt = KeyType.getKeyType(keyType);
+        if (kt == null) {
+            return null;
+        }
+        return getKeyTypeMap().get(kt);
+    }
+    public List<JsonWebKey> getRsaKeys() {
+        return getKeyTypeMap().get(KeyType.RSA);
+    }
+    public List<JsonWebKey> getEllipticKeys() {
+        return getKeyTypeMap().get(KeyType.EC);
+    }
+    public List<JsonWebKey> getSecretKeys() {
+        return getKeyTypeMap().get(KeyType.OCTET);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/66a81773/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkException.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkException.java b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkException.java
new file mode 100644
index 0000000..44e9535
--- /dev/null
+++ b/rt/rs/security/jose/jose-core/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkException.java
@@ -0,0 +1,35 @@
+/**
+ * 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.jwk;
+
+import org.apache.cxf.rs.security.jose.JoseException;
+
+public class JwkException extends JoseException {
+
+    private static final long serialVersionUID = 4118589816228511524L;
+    public JwkException() {
+
+    }
+    public JwkException(String error) {
+        super(error);
+    }
+    public JwkException(Throwable cause) {
+        super(cause);
+    }
+}


Mime
View raw message