http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweHeaders.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweHeaders.java
 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweHeaders.java
new file mode 100644
index 0000000..7fe91d6
--- /dev/null
+++ 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweHeaders.java
@@ -0,0 +1,102 @@
+/**
+ * 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.Map;
+
+import org.apache.cxf.rs.security.jose.jwt.JwtConstants;
+import org.apache.cxf.rs.security.jose.jwt.JwtHeaders;
+import org.apache.cxf.rs.security.jose.jwt.JwtHeadersWriter;
+import org.apache.cxf.rs.security.oauth2.utils.Base64UrlUtility;
+
+
+
+
+public class JweHeaders extends JwtHeaders {
+    
+    public JweHeaders() {
+    }
+    
+    public JweHeaders(Map<String, Object> values) {
+        super(values);
+    }
+    public JweHeaders(String keyEncAlgo, String ctEncAlgo) {
+        this(keyEncAlgo, ctEncAlgo, false);
+    }
+    public JweHeaders(String ctEncAlgo) {
+        this(null, ctEncAlgo, false);
+    }
+    public JweHeaders(String ctEncAlgo, boolean deflate) {
+        this(null, ctEncAlgo, deflate);
+    }
+    public JweHeaders(String keyEncAlgo, String ctEncAlgo, boolean deflate) {
+        init(keyEncAlgo, ctEncAlgo, deflate);
+    }
+    private void init(String keyEncAlgo, String ctEncAlgo, boolean deflate) {
+        if (keyEncAlgo != null) {
+            setKeyEncryptionAlgorithm(keyEncAlgo);    
+        }
+        setContentEncryptionAlgorithm(ctEncAlgo);
+        if (deflate) {
+            setZipAlgorithm(JwtConstants.DEFLATE_ZIP_ALGORITHM);
+        }
+    }
+    
+    public void setKeyEncryptionAlgorithm(String type) {
+        super.setAlgorithm(type);
+    }
+    
+    public String getKeyEncryptionAlgorithm() {
+        return super.getAlgorithm();
+    }
+    
+    public void setContentEncryptionAlgorithm(String type) {
+        setHeader(JwtConstants.JWE_HEADER_CONTENT_ENC_ALGORITHM, type);
+    }
+    
+    public String getContentEncryptionAlgorithm() {
+        return 
(String)getHeader(JwtConstants.JWE_HEADER_CONTENT_ENC_ALGORITHM);
+    }
+    
+    public void setZipAlgorithm(String type) {
+        setHeader(JwtConstants.JWE_HEADER_ZIP_ALGORITHM, type);
+    }
+    
+    public String getZipAlgorithm() {
+        return (String)getHeader(JwtConstants.JWE_HEADER_ZIP_ALGORITHM);
+    }
+    
+    @Override
+    public JwtHeaders setHeader(String name, Object value) {
+        return (JwtHeaders)super.setHeader(name, value);
+    }
+    public byte[] toCipherAdditionalAuthData(JwtHeadersWriter writer) { 
+        return toCipherAdditionalAuthData(writer.headersToJson(this));
+    }
+    public static byte[] toCipherAdditionalAuthData(String headersJson) { 
+        try {
+            String base64UrlHeadersInJson = 
Base64UrlUtility.encode(headersJson.getBytes("UTF-8"));
+            return base64UrlHeadersInJson.getBytes("US-ASCII");
+        } catch (UnsupportedEncodingException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweOutputStream.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweOutputStream.java
 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweOutputStream.java
new file mode 100644
index 0000000..5abe38c
--- /dev/null
+++ 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweOutputStream.java
@@ -0,0 +1,145 @@
+/**
+ * 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 javax.crypto.Cipher;
+
+import org.apache.cxf.rs.security.oauth2.utils.Base64UrlUtility;
+
+public class JweOutputStream extends FilterOutputStream {
+    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);
+        
+        if (rem > 0) {
+            lastEncryptedDataChunk = newArray(theChunk, lenToEncode - rem, 
rem);
+        } else {
+            lastEncryptedDataChunk = null;
+        }
+    }
+    
+    @Override
+    public void flush() 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) {
+            throw new SecurityException();
+        }
+        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/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/KeyDecryptionAlgorithm.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/KeyDecryptionAlgorithm.java
 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/KeyDecryptionAlgorithm.java
new file mode 100644
index 0000000..9932ab2
--- /dev/null
+++ 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/KeyDecryptionAlgorithm.java
@@ -0,0 +1,24 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.jose.jwe;
+
+
+public interface KeyDecryptionAlgorithm {
+    byte[] getDecryptedContentEncryptionKey(JweCompactConsumer consumer);
+}

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

http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyDecryptionAlgorithm.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyDecryptionAlgorithm.java
 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyDecryptionAlgorithm.java
new file mode 100644
index 0000000..ac66535
--- /dev/null
+++ 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyDecryptionAlgorithm.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 org.apache.cxf.rs.security.oauth2.utils.Base64UrlUtility;
+
+public class PbesHmacAesWrapKeyDecryptionAlgorithm implements 
KeyDecryptionAlgorithm {
+    private byte[] password;
+    public PbesHmacAesWrapKeyDecryptionAlgorithm(String password) {    
+        this(PbesHmacAesWrapKeyEncryptionAlgorithm.stringToBytes(password));
+    }
+    public PbesHmacAesWrapKeyDecryptionAlgorithm(char[] password) {    
+        this(PbesHmacAesWrapKeyEncryptionAlgorithm.charsToBytes(password));
+    }
+    public PbesHmacAesWrapKeyDecryptionAlgorithm(byte[] password) {    
+        this.password = password;
+    }
+    @Override
+    public byte[] getDecryptedContentEncryptionKey(JweCompactConsumer 
consumer) {
+        byte[] saltInput = getDecodedBytes(consumer, "p2s");
+        int pbesCount = consumer.getJweHeaders().getIntegerHeader("p2c");
+        String keyAlgoJwt = consumer.getJweHeaders().getAlgorithm();
+        int keySize = 
PbesHmacAesWrapKeyEncryptionAlgorithm.getKeySize(keyAlgoJwt);
+        byte[] derivedKey = PbesHmacAesWrapKeyEncryptionAlgorithm
+            .createDerivedKey(keyAlgoJwt, keySize, password, saltInput, 
pbesCount);
+        KeyDecryptionAlgorithm aesWrap = new 
AesWrapKeyDecryptionAlgorithm(derivedKey);
+        return aesWrap.getDecryptedContentEncryptionKey(consumer);
+    }    
+    private byte[] getDecodedBytes(JweCompactConsumer consumer, String 
headerName) {
+        try {
+            Object headerValue = 
consumer.getJweHeaders().getHeader(headerName);
+            return Base64UrlUtility.decode(headerValue.toString());
+        } catch (Exception ex) {
+            throw new SecurityException(ex);
+        }
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyEncryptionAlgorithm.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyEncryptionAlgorithm.java
 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyEncryptionAlgorithm.java
new file mode 100644
index 0000000..b67332d
--- /dev/null
+++ 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyEncryptionAlgorithm.java
@@ -0,0 +1,169 @@
+/**
+ * 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.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.cxf.rs.security.jose.jwa.Algorithm;
+import org.apache.cxf.rs.security.oauth2.utils.Base64UrlUtility;
+import org.apache.cxf.rs.security.oauth2.utils.crypto.CryptoUtils;
+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 
KeyEncryptionAlgorithm {
+    private static final Set<String> SUPPORTED_ALGORITHMS = new 
HashSet<String>(
+        Arrays.asList(Algorithm.PBES2_HS256_A128KW.getJwtName(),
+                      Algorithm.PBES2_HS384_A192KW.getJwtName(),
+                      Algorithm.PBES2_HS512_A256KW.getJwtName()));
+    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(Algorithm.PBES2_HS256_A128KW.getJwtName(), 256);
+        PBES_HMAC_MAP.put(Algorithm.PBES2_HS384_A192KW.getJwtName(), 384);
+        PBES_HMAC_MAP.put(Algorithm.PBES2_HS512_A256KW.getJwtName(), 512);
+        
+        PBES_AES_MAP = new HashMap<String, String>();
+        PBES_AES_MAP.put(Algorithm.PBES2_HS256_A128KW.getJwtName(), 
Algorithm.A128KW.getJwtName());
+        PBES_AES_MAP.put(Algorithm.PBES2_HS384_A192KW.getJwtName(), 
Algorithm.A192KW.getJwtName());
+        PBES_AES_MAP.put(Algorithm.PBES2_HS512_A256KW.getJwtName(), 
Algorithm.A256KW.getJwtName());
+        
+        DERIVED_KEY_SIZE_MAP = new HashMap<String, Integer>();
+        DERIVED_KEY_SIZE_MAP.put(Algorithm.PBES2_HS256_A128KW.getJwtName(), 
16);
+        DERIVED_KEY_SIZE_MAP.put(Algorithm.PBES2_HS384_A192KW.getJwtName(), 
24);
+        DERIVED_KEY_SIZE_MAP.put(Algorithm.PBES2_HS512_A256KW.getJwtName(), 
32);
+    }
+    
+    
+    private byte[] password;
+    private int pbesCount;
+    private String keyAlgoJwt;
+    public PbesHmacAesWrapKeyEncryptionAlgorithm(String password, String 
keyAlgoJwt) {
+        this(stringToBytes(password), keyAlgoJwt);
+    }
+    public PbesHmacAesWrapKeyEncryptionAlgorithm(String password, int 
pbesCount, String keyAlgoJwt) {
+        this(stringToBytes(password), pbesCount, keyAlgoJwt);
+    }
+    public PbesHmacAesWrapKeyEncryptionAlgorithm(char[] password, String 
keyAlgoJwt) {
+        this(password, 4096, keyAlgoJwt);
+    }
+    public PbesHmacAesWrapKeyEncryptionAlgorithm(char[] password, int 
pbesCount, String keyAlgoJwt) {
+        this(charsToBytes(password), pbesCount, keyAlgoJwt);
+    }
+    public PbesHmacAesWrapKeyEncryptionAlgorithm(byte[] password, String 
keyAlgoJwt) {
+        this(password, 4096, keyAlgoJwt);
+    }
+    public PbesHmacAesWrapKeyEncryptionAlgorithm(byte[] password, int 
pbesCount, String keyAlgoJwt) {
+        this.password = password;
+        this.keyAlgoJwt = validateKeyAlgorithm(keyAlgoJwt);
+        this.pbesCount = validatePbesCount(pbesCount);
+    }
+    
+    @Override
+    public byte[] getEncryptedContentEncryptionKey(JweHeaders headers, byte[] 
cek) {
+        int keySize = getKeySize(keyAlgoJwt);
+        byte[] saltInput = CryptoUtils.generateSecureRandomBytes(keySize);
+        byte[] derivedKey = createDerivedKey(keyAlgoJwt, keySize, password, 
saltInput, pbesCount);
+        
+        headers.setHeader("p2s", Base64UrlUtility.encode(saltInput));
+        headers.setIntegerHeader("p2c", pbesCount);
+        
+        final String aesAlgoJwt = PBES_AES_MAP.get(keyAlgoJwt);
+        KeyEncryptionAlgorithm aesWrap = new 
AesWrapKeyEncryptionAlgorithm(derivedKey, aesAlgoJwt) {
+            protected void checkAlgorithms(JweHeaders headers, String 
defaultAlgo) {
+                // complete
+            }
+            protected String getKeyEncryptionAlgoJava(JweHeaders headers) {
+                return Algorithm.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 String validateKeyAlgorithm(String algo) {
+        if (!SUPPORTED_ALGORITHMS.contains(algo)) {
+            throw new SecurityException();
+        }
+        return algo;
+    }
+    static int validatePbesCount(int count) {
+        if (count < 1000) {
+            throw new SecurityException();
+        }
+        return count;
+    }    
+    
+    static byte[] stringToBytes(String str) {
+        try {
+            return str.getBytes("UTF-8");
+        } catch (UnsupportedEncodingException ex) {
+            throw new SecurityException(ex);
+        }
+    }
+    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;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/RSAOaepKeyDecryptionAlgorithm.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/RSAOaepKeyDecryptionAlgorithm.java
 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/RSAOaepKeyDecryptionAlgorithm.java
new file mode 100644
index 0000000..c0e2f28
--- /dev/null
+++ 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/RSAOaepKeyDecryptionAlgorithm.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;
+
+import java.security.interfaces.RSAPrivateKey;
+
+public class RSAOaepKeyDecryptionAlgorithm extends 
WrappedKeyDecryptionAlgorithm {
+    public RSAOaepKeyDecryptionAlgorithm(RSAPrivateKey privateKey) {    
+        this(privateKey, true);
+    }
+    public RSAOaepKeyDecryptionAlgorithm(RSAPrivateKey privateKey, boolean 
unwrap) {    
+        super(privateKey, unwrap);
+    }
+    protected int getKeyCipherBlockSize() {
+        return 
((RSAPrivateKey)getCekDecryptionKey()).getModulus().toByteArray().length;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/RSAOaepKeyEncryptionAlgorithm.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/RSAOaepKeyEncryptionAlgorithm.java
 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/RSAOaepKeyEncryptionAlgorithm.java
new file mode 100644
index 0000000..b658e36
--- /dev/null
+++ 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/RSAOaepKeyEncryptionAlgorithm.java
@@ -0,0 +1,39 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.jose.jwe;
+
+import java.security.interfaces.RSAPublicKey;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.cxf.rs.security.jose.jwa.Algorithm;
+
+public class RSAOaepKeyEncryptionAlgorithm extends 
AbstractWrapKeyEncryptionAlgorithm {
+    private static final Set<String> SUPPORTED_ALGORITHMS = new 
HashSet<String>(
+        Arrays.asList(Algorithm.RSA_OAEP.getJwtName(),
+                      Algorithm.RSA_OAEP_256.getJwtName()));
+    public RSAOaepKeyEncryptionAlgorithm(RSAPublicKey publicKey, String 
jweAlgo) {
+        this(publicKey, jweAlgo, true);
+    }
+    public RSAOaepKeyEncryptionAlgorithm(RSAPublicKey publicKey, String 
jweAlgo, boolean wrap) {
+        super(publicKey, jweAlgo, wrap, SUPPORTED_ALGORITHMS);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/WrappedKeyDecryptionAlgorithm.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/WrappedKeyDecryptionAlgorithm.java
 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/WrappedKeyDecryptionAlgorithm.java
new file mode 100644
index 0000000..789e8cd
--- /dev/null
+++ 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/WrappedKeyDecryptionAlgorithm.java
@@ -0,0 +1,74 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.jose.jwe;
+
+import java.security.Key;
+import java.security.spec.AlgorithmParameterSpec;
+
+import org.apache.cxf.rs.security.jose.jwa.Algorithm;
+import org.apache.cxf.rs.security.oauth2.utils.crypto.CryptoUtils;
+import org.apache.cxf.rs.security.oauth2.utils.crypto.KeyProperties;
+
+public class WrappedKeyDecryptionAlgorithm implements KeyDecryptionAlgorithm {
+    private Key cekDecryptionKey;
+    private boolean unwrap;
+    public WrappedKeyDecryptionAlgorithm(Key cekDecryptionKey) {    
+        this(cekDecryptionKey, true);
+    }
+    public WrappedKeyDecryptionAlgorithm(Key cekDecryptionKey, boolean unwrap) 
{    
+        this.cekDecryptionKey = cekDecryptionKey;
+        this.unwrap = unwrap;
+    }
+    public byte[] getDecryptedContentEncryptionKey(JweCompactConsumer 
consumer) {
+        KeyProperties keyProps = new 
KeyProperties(getKeyEncryptionAlgorithm(consumer));
+        AlgorithmParameterSpec spec = getAlgorithmParameterSpec(consumer); 
+        if (spec != null) {
+            keyProps.setAlgoSpec(spec);
+        }
+        if (!unwrap) {
+            keyProps.setBlockSize(getKeyCipherBlockSize());
+            return 
CryptoUtils.decryptBytes(getEncryptedContentEncryptionKey(consumer), 
+                                            getCekDecryptionKey(), keyProps);
+        } else {
+            return 
CryptoUtils.unwrapSecretKey(getEncryptedContentEncryptionKey(consumer), 
+                                               
getContentEncryptionAlgorithm(consumer), 
+                                               getCekDecryptionKey(), 
+                                               keyProps).getEncoded();
+        }
+    }
+    
+    protected Key getCekDecryptionKey() {
+        return cekDecryptionKey;
+    }
+    protected int getKeyCipherBlockSize() {
+        return -1;
+    }
+    protected String getKeyEncryptionAlgorithm(JweCompactConsumer consumer) {
+        return 
Algorithm.toJavaName(consumer.getJweHeaders().getKeyEncryptionAlgorithm());
+    }
+    protected String getContentEncryptionAlgorithm(JweCompactConsumer 
consumer) {
+        return 
Algorithm.toJavaName(consumer.getJweHeaders().getContentEncryptionAlgorithm());
+    }
+    protected AlgorithmParameterSpec 
getAlgorithmParameterSpec(JweCompactConsumer consumer) {
+        return null;
+    }
+    protected byte[] getEncryptedContentEncryptionKey(JweCompactConsumer 
consumer) {
+        return consumer.getEncryptedContentEncryptionKey();
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/WrappedKeyJweDecryption.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/WrappedKeyJweDecryption.java
 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/WrappedKeyJweDecryption.java
new file mode 100644
index 0000000..b14effc
--- /dev/null
+++ 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwe/WrappedKeyJweDecryption.java
@@ -0,0 +1,56 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.jose.jwe;
+
+import java.security.Key;
+
+import org.apache.cxf.rs.security.jose.jwt.JwtHeadersReader;
+
+public class WrappedKeyJweDecryption extends AbstractJweDecryption {
+    public WrappedKeyJweDecryption(Key cekDecryptionKey) {    
+        this(cekDecryptionKey, true);
+    }
+    public WrappedKeyJweDecryption(Key cekDecryptionKey, boolean unwrap) {    
+        this(cekDecryptionKey, unwrap, null);
+    }
+    public WrappedKeyJweDecryption(Key cekDecryptionKey, JweCryptoProperties 
props) {
+        this(cekDecryptionKey, true, props);
+    }
+    public WrappedKeyJweDecryption(Key cekDecryptionKey, boolean unwrap,
+                                  JweCryptoProperties props) {    
+        this(cekDecryptionKey, unwrap, props, null);
+    }
+    public WrappedKeyJweDecryption(Key cekDecryptionKey, boolean unwrap,
+                                   JweCryptoProperties props, JwtHeadersReader 
reader) {    
+        this(new WrappedKeyDecryptionAlgorithm(cekDecryptionKey, unwrap),
+             props, reader);
+    }
+    public WrappedKeyJweDecryption(KeyDecryptionAlgorithm keyDecryptionAlgo) { 
   
+        this(keyDecryptionAlgo, null, null);
+    }
+    public WrappedKeyJweDecryption(KeyDecryptionAlgorithm keyDecryptionAlgo,
+                                   JweCryptoProperties props, JwtHeadersReader 
reader) {    
+        this(keyDecryptionAlgo, props, reader, new 
AesGcmContentDecryptionAlgorithm());
+    }
+    public WrappedKeyJweDecryption(KeyDecryptionAlgorithm keyDecryptionAlgo,
+                                   JweCryptoProperties props, JwtHeadersReader 
reader,
+                                   ContentDecryptionAlgorithm cipherProps) {   
 
+        super(props, reader, keyDecryptionAlgo, cipherProps);
+    }
+}

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

http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwk/DefaultJwkReaderWriter.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwk/DefaultJwkReaderWriter.java
 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwk/DefaultJwkReaderWriter.java
new file mode 100644
index 0000000..be300f4
--- /dev/null
+++ 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwk/DefaultJwkReaderWriter.java
@@ -0,0 +1,48 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.jose.jwk;
+
+import org.apache.cxf.rs.security.jose.jwt.AbstractJwtObjectReaderWriter;
+
+
+
+
+public class DefaultJwkReaderWriter extends AbstractJwtObjectReaderWriter
+    implements JwkReaderWriter {
+    @Override
+    public String jwkSetToJson(JsonWebKeys jwks) {
+        return toJson(jwks);
+    }
+    @Override
+    public JsonWebKeys jsonToJwkSet(String jwksJson) {
+        JsonWebKeys jwks = new JsonWebKeys();
+        fromJsonInternal(jwks, jwksJson);
+        return jwks;
+    }
+    @Override
+    public String jwkToJson(JsonWebKey jwk) {
+        return toJson(jwk);
+    }
+    @Override
+    public JsonWebKey jsonToJwk(String jwkJson) {
+        JsonWebKey jwk = new JsonWebKey();
+        fromJsonInternal(jwk, jwkJson);
+        return jwk;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKey.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKey.java
 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKey.java
new file mode 100644
index 0000000..510e7a7
--- /dev/null
+++ 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKey.java
@@ -0,0 +1,213 @@
+/**
+ * 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.security.interfaces.ECPrivateKey;
+import java.security.interfaces.ECPublicKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.util.List;
+import java.util.Map;
+
+import javax.crypto.SecretKey;
+
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.rs.security.jose.jwa.Algorithm;
+import org.apache.cxf.rs.security.jose.jwt.AbstractJwtObject;
+import org.apache.cxf.rs.security.jose.jwt.JwtConstants;
+import org.apache.cxf.rs.security.oauth2.utils.crypto.CryptoUtils;
+
+
+public class JsonWebKey extends AbstractJwtObject {
+    
+    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 = JwtConstants.HEADER_ALGORITHM;
+    public static final String KEY_ID = JwtConstants.HEADER_KEY_ID;
+    public static final String X509_URL = JwtConstants.HEADER_X509_URL;
+    public static final String X509_CHAIN = JwtConstants.HEADER_X509_CHAIN;
+    public static final String X509_THUMBPRINT = 
JwtConstants.HEADER_X509_THUMBPRINT;
+    public static final String X509_THUMBPRINT_SHA256 = 
JwtConstants.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_P512 = "P-512";
+    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 JsonWebKey() {
+        
+    }
+    
+    public JsonWebKey(Map<String, Object> values) {
+        super(values);
+    }
+    
+    public void setKeyType(String keyType) {
+        super.setValue(KEY_TYPE, keyType);
+    }
+
+    public String getKeyType() {
+        return (String)super.getValue(KEY_TYPE);
+    }
+
+    public void setPublicKeyUse(String use) {
+        super.setValue(PUBLIC_KEY_USE, use);
+    }
+    
+    public String getPublicKeyUse() {
+        return (String)super.getValue(PUBLIC_KEY_USE);
+    }
+
+    public void setKeyOperation(List<String> keyOperation) {
+        super.setValue(KEY_OPERATIONS, keyOperation);
+    }
+
+    public List<String> getKeyOperation() {
+        return CastUtils.cast((List<?>)super.getValue(KEY_OPERATIONS));
+    }
+    
+    public void setAlgorithm(String algorithm) {
+        super.setValue(KEY_ALGO, algorithm);
+    }
+
+    public String getAlgorithm() {
+        return (String)super.getValue(KEY_ALGO);
+    }
+    
+    public void setKid(String kid) {
+        super.setValue(KEY_ID, kid);
+    }
+
+    public String getKid() {
+        return (String)super.getValue(KEY_ID);
+    }
+    
+    public void setX509Url(String x509Url) {
+        super.setValue(X509_URL, x509Url);
+    }
+    
+    public String getX509Url() {
+        return (String)super.getValue(X509_URL);
+    }
+
+    public void setX509Chain(String x509Chain) {
+        super.setValue(X509_CHAIN, x509Chain);
+    }
+
+    public String getX509Chain() {
+        return (String)super.getValue(X509_CHAIN);
+    }
+    
+    public void setX509Thumbprint(String x509Thumbprint) {
+        super.setValue(X509_THUMBPRINT, x509Thumbprint);
+    }
+    
+    public String getX509Thumbprint() {
+        return (String)super.getValue(X509_THUMBPRINT);
+    }
+    
+    public void setX509ThumbprintSHA256(String x509Thumbprint) {
+        super.setValue(X509_THUMBPRINT_SHA256, x509Thumbprint);
+    }
+    
+    public String getX509ThumbprintSHA256() {
+        return (String)super.getValue(X509_THUMBPRINT_SHA256);
+    }
+    
+    public JsonWebKey setProperty(String name, Object value) {
+        super.setValue(name, value);
+        return this;
+    }
+    
+    public Object getProperty(String name) {
+        return super.getValue(name);
+    }
+    
+    public RSAPublicKey toRSAPublicKey() {
+        String encodedModulus = (String)super.getValue(RSA_MODULUS);
+        String encodedPublicExponent = (String)super.getValue(RSA_PUBLIC_EXP);
+        return CryptoUtils.getRSAPublicKey(encodedModulus, 
encodedPublicExponent);
+    }
+    public RSAPrivateKey toRSAPrivateKey() {
+        String encodedModulus = (String)super.getValue(RSA_MODULUS);
+        String encodedPrivateExponent = 
(String)super.getValue(RSA_PRIVATE_EXP);
+        String encodedPrimeP = (String)super.getValue(RSA_FIRST_PRIME_FACTOR);
+        if (encodedPrimeP == null) {
+            return CryptoUtils.getRSAPrivateKey(encodedModulus, 
encodedPrivateExponent);
+        } else {
+            String encodedPublicExponent = 
(String)super.getValue(RSA_PUBLIC_EXP);
+            String encodedPrimeQ = 
(String)super.getValue(RSA_SECOND_PRIME_FACTOR);
+            String encodedPrimeExpP = 
(String)super.getValue(RSA_FIRST_PRIME_CRT);
+            String encodedPrimeExpQ = 
(String)super.getValue(RSA_SECOND_PRIME_CRT);
+            String encodedCrtCoefficient = 
(String)super.getValue(RSA_FIRST_CRT_COEFFICIENT);
+            return CryptoUtils.getRSAPrivateKey(encodedModulus, 
+                                                encodedPublicExponent,
+                                                encodedPrivateExponent,
+                                                encodedPrimeP,
+                                                encodedPrimeQ,
+                                                encodedPrimeExpP,
+                                                encodedPrimeExpQ,
+                                                encodedCrtCoefficient);
+        }
+    }
+    public ECPublicKey toECPublicKey() {
+        String eCurve = (String)super.getValue(EC_CURVE);
+        String encodedXCoord = (String)super.getValue(EC_X_COORDINATE);
+        String encodedYCoord = (String)super.getValue(EC_Y_COORDINATE);
+        return CryptoUtils.getECPublicKey(eCurve, encodedXCoord, 
encodedYCoord);
+    }
+    public ECPrivateKey toECPrivateKey() {
+        String eCurve = (String)super.getValue(EC_CURVE);
+        String encodedPrivateKey = (String)super.getValue(EC_PRIVATE_KEY);
+        return CryptoUtils.getECPrivateKey(eCurve, encodedPrivateKey);
+    }
+    
+    public SecretKey toSecretKey() {
+        return 
CryptoUtils.createSecretKeySpec((String)getProperty(OCTET_KEY_VALUE), 
+                                               
Algorithm.toJavaName(getAlgorithm()));
+    }
+    
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKeys.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKeys.java
 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKeys.java
new file mode 100644
index 0000000..3c79454
--- /dev/null
+++ 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKeys.java
@@ -0,0 +1,131 @@
+/**
+ * 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.rs.security.jose.jwt.AbstractJwtObject;
+
+public class JsonWebKeys extends AbstractJwtObject {
+    public static final String KEYS_PROPERTY = "keys";
+    public List<JsonWebKey> getKeys() {
+        List<?> list = (List<?>)super.getValue(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.getValue(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.setValue(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.getKid();
+            if (kid != null) {
+                map.put(kid, key);
+            }
+        }
+        return map;
+    }
+    public JsonWebKey getKey(String kid) {
+        return getKeyIdMap().get(kid);
+    }
+    public Map<String, List<JsonWebKey>> getKeyTypeMap() {
+        return getKeyPropertyMap(JsonWebKey.KEY_TYPE);
+    }
+    public Map<String, List<JsonWebKey>> getKeyUseMap() {
+        return getKeyPropertyMap(JsonWebKey.PUBLIC_KEY_USE);
+    }
+    private Map<String, List<JsonWebKey>> getKeyPropertyMap(String 
propertyName) {
+        List<JsonWebKey> keys = getKeys();
+        if (keys == null) {
+            return Collections.emptyMap();
+        }
+        Map<String, List<JsonWebKey>> map = new LinkedHashMap<String, 
List<JsonWebKey>>();
+        for (JsonWebKey key : keys) {
+            String propValue = (String)key.getProperty(propertyName);
+            if (propValue != null) {
+                List<JsonWebKey> list = map.get(propValue);
+                if (list == null) {
+                    list = new LinkedList<JsonWebKey>();
+                    map.put(propValue, list);
+                }
+                list.add(key);
+            }
+        }
+        return map;
+    }
+    public Map<String, List<JsonWebKey>> getKeyOperationMap() {
+        List<JsonWebKey> keys = getKeys();
+        if (keys == null) {
+            return Collections.emptyMap();
+        }
+        Map<String, List<JsonWebKey>> map = new LinkedHashMap<String, 
List<JsonWebKey>>();
+        for (JsonWebKey key : keys) {
+            List<String> ops = key.getKeyOperation();
+            if (ops != null) {
+                for (String 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) {
+        return getKeyTypeMap().get(keyType);
+    }
+    public List<JsonWebKey> getRsaKeys() {
+        return getKeyTypeMap().get(JsonWebKey.KEY_TYPE_RSA);
+    }
+    public List<JsonWebKey> getEllipticKeys() {
+        return getKeyTypeMap().get(JsonWebKey.KEY_TYPE_ELLIPTIC);
+    }
+    public List<JsonWebKey> getSecretKeys() {
+        return getKeyTypeMap().get(JsonWebKey.KEY_TYPE_OCTET);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkReaderWriter.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkReaderWriter.java
 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkReaderWriter.java
new file mode 100644
index 0000000..679b7aa
--- /dev/null
+++ 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkReaderWriter.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.jwk;
+
+
+public interface JwkReaderWriter {
+    String jwkToJson(JsonWebKey jwk);
+    JsonWebKey jsonToJwk(String jwkJson);
+    String jwkSetToJson(JsonWebKeys jwkSet);
+    JsonWebKeys jsonToJwkSet(String jwkSetJson);
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkUtils.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkUtils.java
 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkUtils.java
new file mode 100644
index 0000000..9661bdb
--- /dev/null
+++ 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkUtils.java
@@ -0,0 +1,190 @@
+/**
+ * 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.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.helpers.IOUtils;
+import org.apache.cxf.jaxrs.utils.ResourceUtils;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.rs.security.jose.jwa.Algorithm;
+import org.apache.cxf.rs.security.jose.jwe.AesCbcHmacJweDecryption;
+import org.apache.cxf.rs.security.jose.jwe.AesCbcHmacJweEncryption;
+import org.apache.cxf.rs.security.jose.jwe.JweDecryptionProvider;
+import org.apache.cxf.rs.security.jose.jwe.JweEncryptionProvider;
+import org.apache.cxf.rs.security.jose.jwe.KeyDecryptionAlgorithm;
+import org.apache.cxf.rs.security.jose.jwe.KeyEncryptionAlgorithm;
+import 
org.apache.cxf.rs.security.jose.jwe.PbesHmacAesWrapKeyDecryptionAlgorithm;
+import 
org.apache.cxf.rs.security.jose.jwe.PbesHmacAesWrapKeyEncryptionAlgorithm;
+import org.apache.cxf.rs.security.oauth2.utils.crypto.CryptoUtils;
+import 
org.apache.cxf.rs.security.oauth2.utils.crypto.PrivateKeyPasswordProvider;
+
+public final class JwkUtils {
+    public static final String JWK_KEY_STORE_TYPE = "jwk";
+    public static final String RSSEC_KEY_STORE_JWKSET = 
"rs.security.keystore.jwkset";
+    public static final String RSSEC_KEY_STORE_JWKKEY = 
"rs.security.keystore.jwkkey";
+    private JwkUtils() {
+        
+    }
+    public static String encryptJwkSet(JsonWebKeys jwkSet, char[] password) {
+        return encryptJwkSet(jwkSet, password, new DefaultJwkReaderWriter());
+    }
+    public static String encryptJwkSet(JsonWebKeys jwkSet, char[] password, 
JwkReaderWriter writer) {
+        return encryptJwkSet(jwkSet, createDefaultEncryption(password), 
writer);
+    }
+    public static String encryptJwkSet(JsonWebKeys jwkSet, 
JweEncryptionProvider jwe, JwkReaderWriter writer) {
+        return jwe.encrypt(stringToBytes(writer.jwkSetToJson(jwkSet)), 
"jwk-set+json");
+    }
+    public static JsonWebKeys decryptJwkSet(String jsonJwkSet, char[] 
password) {
+        return decryptJwkSet(jsonJwkSet, password, new 
DefaultJwkReaderWriter());
+    }
+    public static JsonWebKeys decryptJwkSet(String jsonJwkSet, char[] 
password, JwkReaderWriter reader) {
+        return decryptJwkSet(jsonJwkSet, createDefaultDecryption(password), 
reader);
+    }
+    public static JsonWebKeys decryptJwkSet(String jsonJwkSet, 
JweDecryptionProvider jwe, JwkReaderWriter reader) {
+        return reader.jsonToJwkSet(jwe.decrypt(jsonJwkSet).getContentText());
+    }
+    public static String encryptJwkKey(JsonWebKey jwk, char[] password) {
+        return encryptJwkKey(jwk, password, new DefaultJwkReaderWriter());
+    }
+    public static String encryptJwkKey(JsonWebKey jwkKey, char[] password, 
JwkReaderWriter writer) {
+        return encryptJwkKey(jwkKey, createDefaultEncryption(password), 
writer);
+    }
+    public static String encryptJwkKey(JsonWebKey jwkKey, 
JweEncryptionProvider jwe, JwkReaderWriter writer) {
+        return jwe.encrypt(stringToBytes(writer.jwkToJson(jwkKey)), 
"jwk+json");
+    }
+    public static JsonWebKey decryptJwkKey(String jsonJwkKey, char[] password) 
{
+        return decryptJwkKey(jsonJwkKey, password, new 
DefaultJwkReaderWriter());
+    }
+    public static JsonWebKey decryptJwkKey(String jsonJwkKey, char[] password, 
JwkReaderWriter reader) {
+        return decryptJwkKey(jsonJwkKey, createDefaultDecryption(password), 
reader);
+    }
+    public static JsonWebKey decryptJwkKey(String jsonJwkKey, 
JweDecryptionProvider jwe, JwkReaderWriter reader) {
+        return reader.jsonToJwk(jwe.decrypt(jsonJwkKey).getContentText());
+    }
+    private static JweEncryptionProvider createDefaultEncryption(char[] 
password) {
+        KeyEncryptionAlgorithm keyEncryption = 
+            new PbesHmacAesWrapKeyEncryptionAlgorithm(password, 
Algorithm.PBES2_HS256_A128KW.getJwtName());
+        return new 
AesCbcHmacJweEncryption(Algorithm.PBES2_HS256_A128KW.getJwtName(),
+                                           
Algorithm.A128CBC_HS256.getJwtName(),
+                                           keyEncryption);
+    }
+    private static JweDecryptionProvider createDefaultDecryption(char[] 
password) {
+        KeyDecryptionAlgorithm keyDecryption = new 
PbesHmacAesWrapKeyDecryptionAlgorithm(password);
+        return new AesCbcHmacJweDecryption(keyDecryption);
+    }
+    public static JsonWebKeys loadJwkSet(Message m, Properties props, 
PrivateKeyPasswordProvider cb) {
+        return loadJwkSet(m, props, cb, new DefaultJwkReaderWriter());
+    }
+    public static JsonWebKeys loadJwkSet(Message m, Properties props, 
PrivateKeyPasswordProvider cb, 
+                                         JwkReaderWriter reader) {
+        JsonWebKeys jwkSet = 
(JsonWebKeys)m.getExchange().get(props.get(CryptoUtils.RSSEC_KEY_STORE_FILE));
+        if (jwkSet == null) {
+            jwkSet = loadJwkSet(props, m.getExchange().getBus(), cb, reader);
+            
m.getExchange().put((String)props.get(CryptoUtils.RSSEC_KEY_STORE_FILE), 
jwkSet);
+        }
+        return jwkSet;
+    }
+    public static JsonWebKeys loadJwkSet(Properties props, Bus bus, 
PrivateKeyPasswordProvider cb) {
+        return loadJwkSet(props, bus, cb, new DefaultJwkReaderWriter());
+    }
+    public static JsonWebKeys loadJwkSet(Properties props, Bus bus, 
PrivateKeyPasswordProvider cb, 
+                                         JwkReaderWriter reader) {
+        JweDecryptionProvider decryption = cb != null
+            ? new AesCbcHmacJweDecryption(new 
PbesHmacAesWrapKeyDecryptionAlgorithm(cb.getPassword(props))) : null;
+        return loadJwkSet(props, bus, decryption, reader);
+    }
+    public static JsonWebKeys loadJwkSet(Properties props, Bus bus, 
JweDecryptionProvider jwe, JwkReaderWriter reader) {
+        String keyContent = null;
+        String keyStoreLoc = 
props.getProperty(CryptoUtils.RSSEC_KEY_STORE_FILE);
+        if (keyStoreLoc != null) {
+            try {
+                InputStream is = ResourceUtils.getResourceStream(keyStoreLoc, 
bus);
+                keyContent = IOUtils.readStringFromStream(is);
+            } catch (Exception ex) {
+                throw new SecurityException(ex);
+            }
+        } else {
+            keyContent = props.getProperty(RSSEC_KEY_STORE_JWKSET);
+            if (keyContent == null) {
+                keyContent = props.getProperty(RSSEC_KEY_STORE_JWKKEY);
+            }
+        }
+        if (jwe != null) {
+            keyContent = jwe.decrypt(keyContent).getContentText();
+        }
+        if (props.getProperty(RSSEC_KEY_STORE_JWKKEY) == null) {
+            return reader.jsonToJwkSet(keyContent);
+        } else {
+            JsonWebKey key = reader.jsonToJwk(keyContent);
+            JsonWebKeys keys = new JsonWebKeys();
+            keys.setKeys(Collections.singletonList(key));
+            return keys;
+        }
+    }
+    public static JsonWebKey loadJsonWebKey(Message m, Properties props, 
String keyOper) {
+        return loadJsonWebKey(m, props, keyOper, new DefaultJwkReaderWriter());
+    }
+    public static JsonWebKey loadJsonWebKey(Message m, Properties props, 
String keyOper, JwkReaderWriter reader) {
+        PrivateKeyPasswordProvider cb = 
+            
(PrivateKeyPasswordProvider)m.getContextualProperty(CryptoUtils.RSSEC_KEY_PSWD_PROVIDER);
+        if (cb == null && keyOper != null) {
+            String propName = keyOper.equals(JsonWebKey.KEY_OPER_SIGN) ? 
CryptoUtils.RSSEC_SIG_KEY_PSWD_PROVIDER
+                : keyOper.equals(JsonWebKey.KEY_OPER_ENCRYPT) ? 
CryptoUtils.RSSEC_DECRYPT_KEY_PSWD_PROVIDER : null;
+            if (propName != null) {
+                cb = 
(PrivateKeyPasswordProvider)m.getContextualProperty(propName);
+            }
+        }
+        JsonWebKeys jwkSet = loadJwkSet(m, props, cb, reader);
+        String kid = props.getProperty(CryptoUtils.RSSEC_KEY_STORE_ALIAS);
+        if (kid == null && keyOper != null) {
+            String keyIdProp = null;
+            if (keyOper.equals(JsonWebKey.KEY_OPER_ENCRYPT)) {
+                keyIdProp = CryptoUtils.RSSEC_KEY_STORE_ALIAS + ".jwe";
+            } else if (keyOper.equals(JsonWebKey.KEY_OPER_SIGN)
+                       || keyOper.equals(JsonWebKey.KEY_OPER_VERIFY)) {
+                keyIdProp = CryptoUtils.RSSEC_KEY_STORE_ALIAS + ".jws";
+            }
+            if (keyIdProp != null) {
+                kid = props.getProperty(keyIdProp);
+            }
+        }
+        if (kid != null) {
+            return jwkSet.getKey(kid);
+        } else if (keyOper != null) {
+            List<JsonWebKey> keys = jwkSet.getKeyUseMap().get(keyOper);
+            if (keys != null && keys.size() == 1) {
+                return keys.get(0);
+            }
+        }
+        return null;
+    }
+    private static byte[] stringToBytes(String str) {
+        try {
+            return str.getBytes("UTF-8");
+        } catch (UnsupportedEncodingException ex) {
+            throw new SecurityException(ex);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jws/AbstractJwsSignatureProvider.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jws/AbstractJwsSignatureProvider.java
 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jws/AbstractJwsSignatureProvider.java
new file mode 100644
index 0000000..04516a3
--- /dev/null
+++ 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jws/AbstractJwsSignatureProvider.java
@@ -0,0 +1,62 @@
+/**
+ * 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.jws;
+
+import java.util.Set;
+
+import org.apache.cxf.rs.security.jose.jwt.JwtHeaders;
+
+public abstract class AbstractJwsSignatureProvider implements 
JwsSignatureProvider {
+    private Set<String> supportedAlgorithms;
+    private String defaultJwtAlgorithm;
+    
+    protected AbstractJwsSignatureProvider(Set<String> supportedAlgorithms) {
+        this.supportedAlgorithms = supportedAlgorithms;
+    }
+    
+    protected JwtHeaders prepareHeaders(JwtHeaders headers) {
+        if (headers == null) {
+            headers = new JwtHeaders();
+        }
+        String algo = headers.getAlgorithm();
+        if (algo != null) {
+            checkAlgorithm(algo);
+        } else {
+            headers.setAlgorithm(defaultJwtAlgorithm);
+        }
+        return headers;
+    }
+    
+    @Override
+    public JwsSignature createJwsSignature(JwtHeaders headers) {
+        return doCreateJwsSignature(prepareHeaders(headers));
+    }
+    
+    protected abstract JwsSignature doCreateJwsSignature(JwtHeaders headers);
+    
+    public void setDefaultJwtAlgorithm(String algo) {
+        this.defaultJwtAlgorithm = algo;
+    }
+    protected void checkAlgorithm(String algo) {
+        if (algo == null || !supportedAlgorithms.contains(algo)) {
+            throw new SecurityException();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureProvider.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureProvider.java
 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureProvider.java
new file mode 100644
index 0000000..f1547b5
--- /dev/null
+++ 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureProvider.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.jws;
+
+import java.security.SecureRandom;
+import java.security.interfaces.ECPrivateKey;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.cxf.rs.security.jose.jwa.Algorithm;
+
+public class EcDsaJwsSignatureProvider extends PrivateKeyJwsSignatureProvider {
+    private static final Set<String> SUPPORTED_ALGORITHMS = new 
HashSet<String>(
+        Arrays.asList(Algorithm.SHA256withECDSA.getJwtName(),
+                      Algorithm.SHA384withECDSA.getJwtName(),
+                      Algorithm.SHA512withECDSA.getJwtName())); 
+    
+    public EcDsaJwsSignatureProvider(ECPrivateKey key) {
+        this(key, null);
+    }
+    public EcDsaJwsSignatureProvider(ECPrivateKey key, AlgorithmParameterSpec 
spec) {
+        this(key, null, spec);
+    }
+    public EcDsaJwsSignatureProvider(ECPrivateKey key, SecureRandom random, 
AlgorithmParameterSpec spec) {
+        super(key, random, spec, SUPPORTED_ALGORITHMS);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jws/HmacJwsSignatureProvider.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jws/HmacJwsSignatureProvider.java
 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jws/HmacJwsSignatureProvider.java
new file mode 100644
index 0000000..38ed06a
--- /dev/null
+++ 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jws/HmacJwsSignatureProvider.java
@@ -0,0 +1,89 @@
+/**
+ * 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.jws;
+
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.crypto.Mac;
+
+import org.apache.cxf.common.util.Base64Exception;
+import org.apache.cxf.rs.security.jose.jwa.Algorithm;
+import org.apache.cxf.rs.security.jose.jwt.JwtHeaders;
+import org.apache.cxf.rs.security.oauth2.utils.Base64UrlUtility;
+import org.apache.cxf.rs.security.oauth2.utils.crypto.HmacUtils;
+
+public class HmacJwsSignatureProvider extends AbstractJwsSignatureProvider 
implements JwsSignatureVerifier {
+    private static final Set<String> SUPPORTED_ALGORITHMS = new 
HashSet<String>(
+        Arrays.asList(Algorithm.HmacSHA256.getJwtName(),
+                      Algorithm.HmacSHA384.getJwtName(),
+                      Algorithm.HmacSHA512.getJwtName())); 
+    private byte[] key;
+    private AlgorithmParameterSpec hmacSpec;
+    
+    public HmacJwsSignatureProvider(byte[] key) {
+        this(key, null);
+    }
+    public HmacJwsSignatureProvider(byte[] key, AlgorithmParameterSpec spec) {
+        super(SUPPORTED_ALGORITHMS);
+        this.key = key;
+        this.hmacSpec = spec;
+    }
+    public HmacJwsSignatureProvider(String encodedKey) {
+        super(SUPPORTED_ALGORITHMS);
+        try {
+            this.key = Base64UrlUtility.decode(encodedKey);
+        } catch (Base64Exception ex) {
+            throw new SecurityException();
+        }
+    }
+    
+    @Override
+    public boolean verify(JwtHeaders headers, String unsignedText, byte[] 
signature) {
+        byte[] expected = computeMac(headers, unsignedText);
+        return Arrays.equals(expected, signature);
+    }
+    
+    private byte[] computeMac(JwtHeaders headers, String text) {
+        return HmacUtils.computeHmac(key, 
+                                     
Algorithm.toJavaName(headers.getAlgorithm()),
+                                     hmacSpec,
+                                     text);
+    }
+    protected JwsSignature doCreateJwsSignature(JwtHeaders headers) {
+        final Mac mac = HmacUtils.getInitializedMac(key, 
Algorithm.toJavaName(headers.getAlgorithm()),
+                                                    hmacSpec);
+        return new JwsSignature() {
+
+            @Override
+            public void update(byte[] src, int off, int len) {
+                mac.update(src, off, len);
+            }
+
+            @Override
+            public byte[] sign() {
+                return mac.doFinal();
+            }
+            
+        };
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java
 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java
new file mode 100644
index 0000000..422473f
--- /dev/null
+++ 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java
@@ -0,0 +1,122 @@
+/**
+ * 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.jws;
+
+import java.io.UnsupportedEncodingException;
+
+import org.apache.cxf.common.util.Base64Exception;
+import org.apache.cxf.rs.security.jose.jwt.JwtHeaders;
+import org.apache.cxf.rs.security.jose.jwt.JwtHeadersReader;
+import org.apache.cxf.rs.security.jose.jwt.JwtTokenReader;
+import org.apache.cxf.rs.security.jose.jwt.JwtTokenReaderWriter;
+import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
+import org.apache.cxf.rs.security.oauth2.utils.Base64UrlUtility;
+
+public class JwsCompactConsumer {
+    private JwtHeadersReader reader = new JwtTokenReaderWriter();
+    private String encodedSequence;
+    private String encodedSignature;
+    private String headersJson;
+    private String jwsPayload;
+    private JwsSignatureProperties props;
+    public JwsCompactConsumer(String encodedJws) {
+        this(encodedJws, null, null);
+    }
+    public JwsCompactConsumer(String encodedJws, JwsSignatureProperties props) 
{
+        this(encodedJws, props, null);
+    }
+    public JwsCompactConsumer(String encodedJws, JwtTokenReader r) {
+        this(encodedJws, null, r);
+    }
+    public JwsCompactConsumer(String encodedJws, JwsSignatureProperties props, 
JwtHeadersReader r) {
+        if (r != null) {
+            this.reader = r;
+        }
+        this.props = props;
+        String[] parts = encodedJws.split("\\.");
+        if (parts.length != 3) {
+            if (parts.length == 2 && encodedJws.endsWith(".")) {
+                encodedSignature = "";
+            } else {
+                throw new OAuthServiceException("Invalid JWS Compact 
sequence");
+            }
+        } else {
+            encodedSignature = parts[2];
+        }
+        headersJson = decodeToString(parts[0]);
+        jwsPayload = decodeToString(parts[1]);
+        encodedSequence = parts[0] + "." + parts[1];
+        
+    }
+    public String getUnsignedEncodedPayload() {
+        return encodedSequence;
+    }
+    public String getEncodedSignature() {
+        return encodedSignature;
+    }
+    public String getDecodedJsonHeaders() {
+        return headersJson;
+    }
+    public String getDecodedJwsPayload() {
+        return jwsPayload;
+    }
+    public byte[] getDecodedJwsPayloadBytes() {
+        try {
+            return jwsPayload.getBytes("UTF-8");
+        } catch (UnsupportedEncodingException ex) {
+            throw new SecurityException(ex);
+        }
+    }
+    public byte[] getDecodedSignature() {
+        return encodedSignature.isEmpty() ? new byte[]{} : 
decode(encodedSignature);
+    }
+    public JwtHeaders getJwtHeaders() {
+        return getReader().fromJsonHeaders(headersJson);
+    }
+    public boolean verifySignatureWith(JwsSignatureVerifier validator) {
+        enforceJweSignatureProperties();
+        if (!validator.verify(getJwtHeaders(), getUnsignedEncodedPayload(), 
getDecodedSignature())) {
+            throw new SecurityException();
+        }
+        return true;
+    }
+    private void enforceJweSignatureProperties() {
+        if (props != null) {
+            //TODO:
+        }
+    }
+    private static String decodeToString(String encoded) {
+        try {
+            return new String(decode(encoded), "UTF-8");
+        } catch (UnsupportedEncodingException ex) {
+            throw new SecurityException(ex);
+        }
+        
+    }
+    protected JwtHeadersReader getReader() {
+        return reader;
+    }
+    private static byte[] decode(String encoded) {
+        try {
+            return Base64UrlUtility.decode(encoded);
+        } catch (Base64Exception ex) {
+            throw new SecurityException(ex);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/30dec871/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java
 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java
new file mode 100644
index 0000000..ef4dd52
--- /dev/null
+++ 
b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java
@@ -0,0 +1,109 @@
+/**
+ * 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.jws;
+
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.rs.security.jose.jwt.JwtConstants;
+import org.apache.cxf.rs.security.jose.jwt.JwtHeaders;
+import org.apache.cxf.rs.security.jose.jwt.JwtHeadersWriter;
+import org.apache.cxf.rs.security.jose.jwt.JwtTokenReaderWriter;
+import org.apache.cxf.rs.security.oauth2.utils.Base64UrlUtility;
+
+public class JwsCompactProducer {
+    private JwtHeadersWriter writer = new JwtTokenReaderWriter();
+    private JwtHeaders headers;
+    private String plainJwsPayload;
+    private String signature;
+    private String plainRep;
+    
+    public JwsCompactProducer(String plainJwsPayload) {
+        this(null, null, plainJwsPayload);
+    }
+    public JwsCompactProducer(JwtHeaders headers, String plainJwsPayload) {
+        this(headers, null, plainJwsPayload);
+    }
+    public JwsCompactProducer(JwtHeaders headers, JwtHeadersWriter w, String 
plainJwsPayload) {
+        this.headers = headers;
+        if (w != null) {
+            this.writer = w;
+        }
+        this.plainJwsPayload = plainJwsPayload;
+    }
+    public JwtHeaders getHeaders() {
+        if (headers == null) {
+            headers = new JwtHeaders();
+        }
+        return headers;
+    }
+    public String getUnsignedEncodedJws() {
+        checkAlgorithm();
+        if (plainRep == null) {
+            plainRep = 
Base64UrlUtility.encode(writer.headersToJson(getHeaders())) 
+                + "." 
+                + Base64UrlUtility.encode(plainJwsPayload);
+        }
+        return plainRep;
+    }
+    
+    public String getSignedEncodedJws() {
+        checkAlgorithm();
+        boolean noSignature = StringUtils.isEmpty(signature);
+        if (noSignature && !isPlainText()) {
+            throw new IllegalStateException("Signature is not available");
+        }
+        return getUnsignedEncodedJws() + "." + (noSignature ? "" : signature);
+    }
+    
+    public String signWith(JwsSignatureProvider signer) { 
+        JwsSignature worker = signer.createJwsSignature(getHeaders());
+        try {
+            byte[] bytes = getUnsignedEncodedJws().getBytes("UTF-8");
+            worker.update(bytes, 0, bytes.length);
+            signWith(worker.sign());
+            return getSignedEncodedJws();
+        } catch (Exception ex) {
+            throw new SecurityException();
+        }
+    }
+    
+    public String signWith(String signatureText) {
+        setEncodedSignature(Base64UrlUtility.encode(signatureText));
+        return getSignedEncodedJws();
+    }
+    
+    public String signWith(byte[] signatureOctets) {
+        setEncodedSignature(Base64UrlUtility.encode(signatureOctets));
+        return getSignedEncodedJws();
+    }
+    
+    private void setEncodedSignature(String sig) {
+        this.signature = sig;
+    }
+    private boolean isPlainText() {
+        return JwtConstants.PLAIN_TEXT_ALGO.equals(getAlgorithm());
+    }
+    private String getAlgorithm() {
+        return getHeaders().getAlgorithm();
+    }
+    private void checkAlgorithm() {
+        if (getAlgorithm() == null) {
+            throw new IllegalStateException("Algorithm header is not set");
+        }
+    }
+}

Reply via email to