cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cohei...@apache.org
Subject [13/20] cxf git commit: Renaming jose module
Date Wed, 21 Oct 2015 15:13:09 GMT
http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkException.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkException.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkException.java
new file mode 100644
index 0000000..da54572
--- /dev/null
+++ b/rt/rs/security/jose-parent/jose/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.common.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);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkReaderWriter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkReaderWriter.java b/rt/rs/security/jose-parent/jose/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/jose-parent/jose/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/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkUtils.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkUtils.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkUtils.java
new file mode 100644
index 0000000..cb76567
--- /dev/null
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkUtils.java
@@ -0,0 +1,531 @@
+/**
+ * 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.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.net.URI;
+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.RSAPrivateCrtKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.crypto.SecretKey;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.common.util.Base64UrlUtility;
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.helpers.IOUtils;
+import org.apache.cxf.jaxrs.json.basic.JsonMapObjectReaderWriter;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageUtils;
+import org.apache.cxf.rs.security.jose.common.JoseConstants;
+import org.apache.cxf.rs.security.jose.common.JoseHeaders;
+import org.apache.cxf.rs.security.jose.common.JoseUtils;
+import org.apache.cxf.rs.security.jose.common.KeyManagementUtils;
+import org.apache.cxf.rs.security.jose.common.PrivateKeyPasswordProvider;
+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.jwa.SignatureAlgorithm;
+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.JweHeaders;
+import org.apache.cxf.rs.security.jose.jwe.JweUtils;
+import org.apache.cxf.rs.security.jose.jwe.KeyDecryptionProvider;
+import org.apache.cxf.rs.security.jose.jwe.KeyEncryptionProvider;
+import org.apache.cxf.rs.security.jose.jwe.PbesHmacAesWrapKeyDecryptionAlgorithm;
+import org.apache.cxf.rs.security.jose.jwe.PbesHmacAesWrapKeyEncryptionAlgorithm;
+import org.apache.cxf.rs.security.jose.jws.JwsUtils;
+import org.apache.cxf.rt.security.crypto.CryptoUtils;
+import org.apache.cxf.rt.security.crypto.MessageDigestUtils;
+
+public final class JwkUtils {
+    private static final Map<KeyType, List<String>> JWK_REQUIRED_FIELDS_MAP;
+    static {
+        JWK_REQUIRED_FIELDS_MAP = new HashMap<KeyType, List<String>>();
+        JWK_REQUIRED_FIELDS_MAP.put(KeyType.RSA, Arrays.asList(
+            JsonWebKey.RSA_PUBLIC_EXP, JsonWebKey.KEY_TYPE, JsonWebKey.RSA_MODULUS));
+        JWK_REQUIRED_FIELDS_MAP.put(KeyType.EC, Arrays.asList(
+            JsonWebKey.EC_CURVE, JsonWebKey.KEY_TYPE, JsonWebKey.EC_X_COORDINATE, JsonWebKey.EC_Y_COORDINATE));
+        JWK_REQUIRED_FIELDS_MAP.put(KeyType.OCTET, Arrays.asList(
+            JsonWebKey.OCTET_KEY_VALUE, JsonWebKey.KEY_TYPE));
+    }
+    private JwkUtils() {
+        
+    }
+    public static String getThumbprint(String keySequence) {
+        return getThumbprint(readJwkKey(keySequence));
+    }
+    public static String getThumbprint(JsonWebKey key) {
+        List<String> fields = getRequiredFields(key.getKeyType());
+        JsonWebKey thumbprintKey = new JsonWebKey();
+        for (String f : fields) {
+            thumbprintKey.setProperty(f, key.getProperty(f));
+        }
+        String json = new JsonMapObjectReaderWriter().toJson(thumbprintKey);
+        byte[] digest = MessageDigestUtils.createDigest(json, MessageDigestUtils.ALGO_SHA_256);
+        return Base64UrlUtility.encode(digest);
+    }
+    public static List<String> getRequiredFields(KeyType keyType) {
+        return JWK_REQUIRED_FIELDS_MAP.get(keyType);
+    }
+    public static JsonWebKey readJwkKey(URI uri) throws IOException {
+        return readJwkKey(uri.toURL().openStream());
+    }
+    public static JsonWebKeys readJwkSet(URI uri) throws IOException {
+        return readJwkSet(uri.toURL().openStream());
+    }
+    public static JsonWebKey readJwkKey(InputStream is) throws IOException {
+        return readJwkKey(IOUtils.readStringFromStream(is));
+    }
+    public static JsonWebKeys readJwkSet(InputStream is) throws IOException {
+        return readJwkSet(IOUtils.readStringFromStream(is));
+    }
+    public static JsonWebKey readJwkKey(String jwkJson) {
+        return new DefaultJwkReaderWriter().jsonToJwk(jwkJson);
+    }
+    public static JsonWebKeys readJwkSet(String jwksJson) {
+        return new DefaultJwkReaderWriter().jsonToJwkSet(jwksJson);
+    }
+    public static String jwkKeyToJson(JsonWebKey jwkKey) {
+        return new DefaultJwkReaderWriter().jwkToJson(jwkKey);
+    }
+    public static String jwkSetToJson(JsonWebKeys jwkSet) {
+        return new DefaultJwkReaderWriter().jwkSetToJson(jwkSet);
+    }
+    public static String encodeJwkKey(JsonWebKey jwkKey) {
+        return Base64UrlUtility.encode(jwkKeyToJson(jwkKey));
+    }
+    public static String encodeJwkSet(JsonWebKeys jwkSet) {
+        return Base64UrlUtility.encode(jwkSetToJson(jwkSet));
+    }
+    public static JsonWebKey decodeJwkKey(String jwkJson) {
+        return readJwkKey(JoseUtils.decodeToString(jwkJson));
+    }
+    public static JsonWebKeys decodeJwkSet(String jwksJson) {
+        return readJwkSet(JoseUtils.decodeToString(jwksJson));
+    }
+    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(StringUtils.toBytesUTF8(writer.jwkSetToJson(jwkSet)), 
+                           toJweHeaders("jwk-set+json"));
+    }
+    public static String encryptJwkSet(JsonWebKeys jwkSet, PublicKey key, KeyAlgorithm keyAlgo, 
+                                       ContentAlgorithm contentAlgo) {
+        return JweUtils.encrypt(key, keyAlgo, contentAlgo, StringUtils.toBytesUTF8(jwkSetToJson(jwkSet)),
+                                "jwk-set+json");
+    }
+    public static String signJwkSet(JsonWebKeys jwkSet, PrivateKey key, SignatureAlgorithm algo) {
+        return JwsUtils.sign(key, algo, jwkSetToJson(jwkSet), "jwk-set+json");
+    }
+    public static String encryptJwkSet(JsonWebKeys jwkSet, SecretKey key, KeyAlgorithm keyAlgo, 
+                                       ContentAlgorithm contentAlgo) {
+        return JweUtils.encrypt(key, keyAlgo, contentAlgo, StringUtils.toBytesUTF8(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 JsonWebKeys decryptJwkSet(PrivateKey key, KeyAlgorithm keyAlgo, ContentAlgorithm ctAlgo,
+                                            String jsonJwkSet) {
+        return readJwkSet(toString(JweUtils.decrypt(key, keyAlgo, ctAlgo, jsonJwkSet)));
+    }
+    public static JsonWebKeys verifyJwkSet(PublicKey key, SignatureAlgorithm keyAlgo, String jsonJwk) {
+        return readJwkSet(JwsUtils.verify(key, keyAlgo, jsonJwk));
+    }
+    public static JsonWebKeys decryptJwkSet(SecretKey key, KeyAlgorithm keyAlgo, ContentAlgorithm ctAlgo, 
+                                            String jsonJwkSet) {
+        return readJwkSet(toString(JweUtils.decrypt(key, keyAlgo, ctAlgo, jsonJwkSet)));
+    }
+    public static JsonWebKeys decryptJwkSet(InputStream is, char[] password) throws IOException {
+        return decryptJwkSet(is, password, new DefaultJwkReaderWriter());
+    }
+    public static JsonWebKeys decryptJwkSet(InputStream is, char[] password, JwkReaderWriter reader) 
+        throws IOException {
+        return decryptJwkSet(is, createDefaultDecryption(password), reader);
+    }
+    public static JsonWebKeys decryptJwkSet(InputStream is, JweDecryptionProvider jwe, JwkReaderWriter reader)
+        throws IOException {
+        return reader.jsonToJwkSet(jwe.decrypt(IOUtils.readStringFromStream(is)).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(StringUtils.toBytesUTF8(writer.jwkToJson(jwkKey)), 
+                           toJweHeaders("jwk+json"));
+    }
+    public static String encryptJwkKey(JsonWebKey jwkKey, PublicKey key, KeyAlgorithm keyAlgo, 
+                                       ContentAlgorithm contentAlgo) {
+        return JweUtils.encrypt(key, keyAlgo, contentAlgo, StringUtils.toBytesUTF8(jwkKeyToJson(jwkKey)),
+                                "jwk+json");
+    }
+    public static String encryptJwkKey(JsonWebKey jwkKey, SecretKey key, KeyAlgorithm keyAlgo, 
+                                       ContentAlgorithm contentAlgo) {
+        return JweUtils.encrypt(key, keyAlgo, contentAlgo, StringUtils.toBytesUTF8(jwkKeyToJson(jwkKey)),
+                                "jwk+json");
+    }
+    public static String signJwkKey(JsonWebKey jwkKey, PrivateKey key, SignatureAlgorithm algo) {
+        return JwsUtils.sign(key, algo, jwkKeyToJson(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(PrivateKey key, KeyAlgorithm keyAlgo, ContentAlgorithm ctAlgo, 
+                                           String jsonJwk) {
+        return readJwkKey(toString(JweUtils.decrypt(key, keyAlgo, ctAlgo, jsonJwk)));
+    }
+    public static JsonWebKey verifyJwkKey(PublicKey key, SignatureAlgorithm keyAlgo, String jsonJwk) {
+        return readJwkKey(JwsUtils.verify(key, keyAlgo, jsonJwk));
+    }
+    public static JsonWebKey decryptJwkKey(SecretKey key, KeyAlgorithm keyAlgo, ContentAlgorithm ctAlgo, 
+                                           String jsonJwk) {
+        return readJwkKey(toString(JweUtils.decrypt(key, keyAlgo, ctAlgo, jsonJwk)));
+    }
+    public static JsonWebKey decryptJwkKey(String jsonJwkKey, JweDecryptionProvider jwe, JwkReaderWriter reader) {
+        return reader.jsonToJwk(jwe.decrypt(jsonJwkKey).getContentText());
+    }
+    public static JsonWebKey decryptJwkKey(InputStream is, char[] password) throws IOException {
+        return decryptJwkKey(is, password, new DefaultJwkReaderWriter());
+    }
+    public static JsonWebKey decryptJwkKey(InputStream is, char[] password, JwkReaderWriter reader) 
+        throws IOException {
+        return decryptJwkKey(is, createDefaultDecryption(password), reader);
+    }
+    public static JsonWebKey decryptJwkKey(InputStream is, JweDecryptionProvider jwe, JwkReaderWriter reader) 
+        throws IOException {
+        return reader.jsonToJwk(jwe.decrypt(IOUtils.readStringFromStream(is)).getContentText());
+    }
+    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) {
+        String key = (String)props.get(JoseConstants.RSSEC_KEY_STORE_FILE);
+        JsonWebKeys jwkSet = key != null ? (JsonWebKeys)m.getExchange().get(key) : null;
+        if (jwkSet == null) {
+            jwkSet = loadJwkSet(props, m.getExchange().getBus(), cb, reader);
+            if (key != null) {
+                m.getExchange().put(key, 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(JoseConstants.RSSEC_KEY_STORE_FILE);
+        if (keyStoreLoc != null) {
+            try {
+                InputStream is = JoseUtils.getResourceStream(keyStoreLoc, bus);
+                if (is == null) {
+                    throw new JwkException("Error in loading keystore location: " + keyStoreLoc);
+                }
+                keyContent = IOUtils.readStringFromStream(is);
+            } catch (Exception ex) {
+                throw new JwkException(ex);
+            }
+        } else {
+            keyContent = props.getProperty(JoseConstants.RSSEC_KEY_STORE_JWKSET);
+            if (keyContent == null) {
+                keyContent = props.getProperty(JoseConstants.RSSEC_KEY_STORE_JWKKEY);
+            }
+        }
+        if (jwe != null) {
+            keyContent = jwe.decrypt(keyContent).getContentText();
+        }
+        if (props.getProperty(JoseConstants.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, KeyOperation keyOper) {
+        return loadJsonWebKey(m, props, keyOper, null);
+    }
+    public static JsonWebKey loadJsonWebKey(Message m, Properties props, KeyOperation keyOper, String inHeaderKid) {
+        return loadJsonWebKey(m, props, keyOper, inHeaderKid, new DefaultJwkReaderWriter());
+    }
+    public static JsonWebKey loadJsonWebKey(Message m, Properties props, KeyOperation keyOper, String inHeaderKid, 
+                                            JwkReaderWriter reader) {
+        PrivateKeyPasswordProvider cb = KeyManagementUtils.loadPasswordProvider(m, props, keyOper);
+        JsonWebKeys jwkSet = loadJwkSet(m, props, cb, reader);
+        String kid = null;
+        if (inHeaderKid != null 
+            && MessageUtils.getContextualBoolean(m, JoseConstants.RSSEC_ACCEPT_PUBLIC_KEY_PROP, true)) {
+            kid = inHeaderKid;
+        } else {
+            kid = KeyManagementUtils.getKeyId(m, props, JoseConstants.RSSEC_KEY_STORE_ALIAS, keyOper);
+        }
+        if (kid != null) {
+            return jwkSet.getKey(kid);
+        } else if (keyOper != null) {
+            List<JsonWebKey> keys = jwkSet.getKeyOperationMap().get(keyOper);
+            if (keys != null && keys.size() == 1) {
+                return keys.get(0);
+            }
+        }
+        return null;
+    }
+    public static List<JsonWebKey> loadJsonWebKeys(Message m, Properties props, KeyOperation keyOper) {
+        return loadJsonWebKeys(m, props, keyOper, new DefaultJwkReaderWriter());
+    }
+
+    public static List<JsonWebKey> loadJsonWebKeys(Message m, Properties props, 
+                                                   KeyOperation keyOper, 
+                                                   JwkReaderWriter reader) {
+        PrivateKeyPasswordProvider cb = KeyManagementUtils.loadPasswordProvider(m, props, keyOper);
+        JsonWebKeys jwkSet = loadJwkSet(m, props, cb, reader);
+        String kid = KeyManagementUtils.getKeyId(m, props, JoseConstants.RSSEC_KEY_STORE_ALIAS, keyOper);
+        if (kid != null) {
+            return Collections.singletonList(jwkSet.getKey(kid));
+        }
+        String kids = KeyManagementUtils.getKeyId(m, props, JoseConstants.RSSEC_KEY_STORE_ALIASES, keyOper);
+        if (kids != null) {
+            String[] values = kids.split(",");
+            List<JsonWebKey> keys = new ArrayList<JsonWebKey>(values.length);
+            for (String value : values) {
+                keys.add(jwkSet.getKey(value));
+            }
+            return keys;
+        }
+        if (keyOper != null) {
+            List<JsonWebKey> keys = jwkSet.getKeyOperationMap().get(keyOper);
+            if (keys != null && keys.size() == 1) {
+                return Collections.singletonList(keys.get(0));
+            }
+        }
+        return null;
+    }
+    public static RSAPublicKey toRSAPublicKey(JsonWebKey jwk) {
+        return toRSAPublicKey(jwk, false);
+    }
+    public static RSAPublicKey toRSAPublicKey(JsonWebKey jwk, boolean checkX509) {
+        String encodedModulus = (String)jwk.getProperty(JsonWebKey.RSA_MODULUS);
+        String encodedPublicExponent = (String)jwk.getProperty(JsonWebKey.RSA_PUBLIC_EXP);
+        if (encodedModulus != null) {
+            return CryptoUtils.getRSAPublicKey(encodedModulus, encodedPublicExponent);
+        } else if (checkX509) {
+            List<X509Certificate> chain = toX509CertificateChain(jwk);
+            return (RSAPublicKey)chain.get(0).getPublicKey();
+        }
+        return null;
+    }
+    public static List<X509Certificate> toX509CertificateChain(JsonWebKey jwk) {
+        List<String> base64EncodedChain = jwk.getX509Chain();
+        return KeyManagementUtils.toX509CertificateChain(base64EncodedChain);
+    }
+    public static JsonWebKey fromECPublicKey(ECPublicKey pk, String curve) {
+        JsonWebKey jwk = new JsonWebKey();
+        jwk.setKeyType(KeyType.EC);
+        jwk.setProperty(JsonWebKey.EC_CURVE, curve);
+        jwk.setProperty(JsonWebKey.EC_X_COORDINATE, 
+                        Base64UrlUtility.encode(pk.getW().getAffineX().toByteArray()));
+        jwk.setProperty(JsonWebKey.EC_Y_COORDINATE, 
+                        Base64UrlUtility.encode(pk.getW().getAffineY().toByteArray()));
+        return jwk;
+    }
+    public static JsonWebKey fromECPrivateKey(ECPrivateKey pk, String curve) {
+        JsonWebKey jwk = new JsonWebKey();
+        jwk.setKeyType(KeyType.EC);
+        jwk.setProperty(JsonWebKey.EC_CURVE, curve);
+        jwk.setProperty(JsonWebKey.EC_PRIVATE_KEY, 
+                        Base64UrlUtility.encode(pk.getS().toByteArray()));
+        return jwk;
+    }
+    public static JsonWebKey fromRSAPublicKey(RSAPublicKey pk, String algo) {
+        JsonWebKey jwk = prepareRSAJwk(pk.getModulus(), algo);
+        String encodedPublicExponent = Base64UrlUtility.encode(pk.getPublicExponent().toByteArray());
+        jwk.setProperty(JsonWebKey.RSA_PUBLIC_EXP, encodedPublicExponent);
+        return jwk;
+    }
+    public static JsonWebKey fromX509CertificateChain(List<X509Certificate> chain, String algo) {
+        JsonWebKey jwk = new JsonWebKey();
+        jwk.setAlgorithm(algo);
+        List<String> encodedChain = KeyManagementUtils.encodeX509CertificateChain(chain);
+        jwk.setX509Chain(encodedChain);
+        return jwk;
+    }
+    
+    public static RSAPrivateKey toRSAPrivateKey(JsonWebKey jwk) {
+        String encodedModulus = (String)jwk.getProperty(JsonWebKey.RSA_MODULUS);
+        String encodedPrivateExponent = (String)jwk.getProperty(JsonWebKey.RSA_PRIVATE_EXP);
+        String encodedPrimeP = (String)jwk.getProperty(JsonWebKey.RSA_FIRST_PRIME_FACTOR);
+        if (encodedPrimeP == null) {
+            return CryptoUtils.getRSAPrivateKey(encodedModulus, encodedPrivateExponent);
+        } else {
+            String encodedPublicExponent = (String)jwk.getProperty(JsonWebKey.RSA_PUBLIC_EXP);
+            String encodedPrimeQ = (String)jwk.getProperty(JsonWebKey.RSA_SECOND_PRIME_FACTOR);
+            String encodedPrimeExpP = (String)jwk.getProperty(JsonWebKey.RSA_FIRST_PRIME_CRT);
+            String encodedPrimeExpQ = (String)jwk.getProperty(JsonWebKey.RSA_SECOND_PRIME_CRT);
+            String encodedCrtCoefficient = (String)jwk.getProperty(JsonWebKey.RSA_FIRST_CRT_COEFFICIENT);
+            return CryptoUtils.getRSAPrivateKey(encodedModulus, 
+                                                encodedPublicExponent,
+                                                encodedPrivateExponent,
+                                                encodedPrimeP,
+                                                encodedPrimeQ,
+                                                encodedPrimeExpP,
+                                                encodedPrimeExpQ,
+                                                encodedCrtCoefficient);
+        }
+    }
+    public static JsonWebKey fromRSAPrivateKey(RSAPrivateKey pk, String algo) {
+        JsonWebKey jwk = prepareRSAJwk(pk.getModulus(), algo);
+        String encodedPrivateExponent = Base64UrlUtility.encode(pk.getPrivateExponent().toByteArray());
+        jwk.setProperty(JsonWebKey.RSA_PRIVATE_EXP, encodedPrivateExponent);
+        if (pk instanceof RSAPrivateCrtKey) {
+            RSAPrivateCrtKey pkCrt = (RSAPrivateCrtKey)pk;
+            jwk.setProperty(JsonWebKey.RSA_FIRST_PRIME_FACTOR, 
+                            Base64UrlUtility.encode(pkCrt.getPrimeP().toByteArray()));
+            jwk.setProperty(JsonWebKey.RSA_SECOND_PRIME_FACTOR, 
+                            Base64UrlUtility.encode(pkCrt.getPrimeQ().toByteArray()));
+            jwk.setProperty(JsonWebKey.RSA_FIRST_PRIME_CRT, 
+                            Base64UrlUtility.encode(pkCrt.getPrimeExponentP().toByteArray()));
+            jwk.setProperty(JsonWebKey.RSA_SECOND_PRIME_CRT, 
+                            Base64UrlUtility.encode(pkCrt.getPrimeExponentQ().toByteArray()));
+            jwk.setProperty(JsonWebKey.RSA_FIRST_CRT_COEFFICIENT, 
+                            Base64UrlUtility.encode(pkCrt.getCrtCoefficient().toByteArray()));
+        }
+        // "oth" can be populated too if needed
+        return jwk;
+    }
+    public static ECPublicKey toECPublicKey(JsonWebKey jwk) {
+        String eCurve = (String)jwk.getProperty(JsonWebKey.EC_CURVE);
+        String encodedXCoord = (String)jwk.getProperty(JsonWebKey.EC_X_COORDINATE);
+        String encodedYCoord = (String)jwk.getProperty(JsonWebKey.EC_Y_COORDINATE);
+        return CryptoUtils.getECPublicKey(eCurve, encodedXCoord, encodedYCoord);
+    }
+    public static ECPrivateKey toECPrivateKey(JsonWebKey jwk) {
+        String eCurve = (String)jwk.getProperty(JsonWebKey.EC_CURVE);
+        String encodedPrivateKey = (String)jwk.getProperty(JsonWebKey.EC_PRIVATE_KEY);
+        return CryptoUtils.getECPrivateKey(eCurve, encodedPrivateKey);
+    }
+    
+    public static SecretKey toSecretKey(JsonWebKey jwk) {
+        return CryptoUtils.createSecretKeySpec((String)jwk.getProperty(JsonWebKey.OCTET_KEY_VALUE), 
+                                               AlgorithmUtils.toJavaName(jwk.getAlgorithm()));
+    }
+    public static JsonWebKey fromSecretKey(SecretKey secretKey, String algo) {
+        if (!AlgorithmUtils.isOctet(algo)) {
+            throw new JwkException("Invalid algorithm");
+        }
+        JsonWebKey jwk = new JsonWebKey();
+        jwk.setKeyType(KeyType.OCTET);
+        jwk.setAlgorithm(algo);
+        String encodedSecretKey = Base64UrlUtility.encode(secretKey.getEncoded());
+        jwk.setProperty(JsonWebKey.OCTET_KEY_VALUE, encodedSecretKey);
+        return jwk;
+    }
+    
+    
+    private static JweEncryptionProvider createDefaultEncryption(char[] password) {
+        KeyEncryptionProvider keyEncryption = 
+            new PbesHmacAesWrapKeyEncryptionAlgorithm(password, KeyAlgorithm.PBES2_HS256_A128KW);
+        return new AesCbcHmacJweEncryption(ContentAlgorithm.A128CBC_HS256, keyEncryption);
+    }
+    private static JweDecryptionProvider createDefaultDecryption(char[] password) {
+        KeyDecryptionProvider keyDecryption = new PbesHmacAesWrapKeyDecryptionAlgorithm(password);
+        return new AesCbcHmacJweDecryption(keyDecryption);
+    }
+    private static JsonWebKey prepareRSAJwk(BigInteger modulus, String algo) {
+        if (!AlgorithmUtils.isRsa(algo)) {
+            throw new JwkException("Invalid algorithm");
+        }
+        JsonWebKey jwk = new JsonWebKey();
+        jwk.setKeyType(KeyType.RSA);
+        jwk.setAlgorithm(algo);
+        String encodedModulus = Base64UrlUtility.encode(modulus.toByteArray());
+        jwk.setProperty(JsonWebKey.RSA_MODULUS, encodedModulus);
+        return jwk;
+    }
+    private static String toString(byte[] bytes) {
+        try {
+            return new String(bytes, "UTF-8");
+        } catch (Exception ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+    private static JweHeaders toJweHeaders(String ct) {
+        return new JweHeaders(Collections.<String, Object>singletonMap(JoseConstants.HEADER_CONTENT_TYPE, ct));
+    }
+    public static void setPublicKeyInfo(JsonWebKey jwk, JoseHeaders headers, String algo,
+                                        boolean reportPublicKey, boolean reportPublicKeyId) {
+        if (reportPublicKey && KeyType.RSA.equals(jwk.getKeyType())) {
+            List<String> chain = CastUtils.cast((List<?>)jwk.getProperty("x5c"));
+            //TODO: if needed the chain can be reported as part of a 'jwk' property
+            if (chain != null) {
+                headers.setX509Chain(chain);
+            } else {
+                JsonWebKey jwkPublic = JwkUtils.fromRSAPublicKey(JwkUtils.toRSAPublicKey(jwk), algo);
+                if (reportPublicKeyId && jwk.getKeyId() != null) {
+                    jwkPublic.setKeyId(jwk.getKeyId());
+                }
+                headers.setJsonWebKey(jwkPublic);
+            }
+        }
+        if (reportPublicKeyId && jwk.getKeyId() != null) {
+            headers.setKeyId(jwk.getKeyId());
+        }
+        
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/KeyOperation.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/KeyOperation.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/KeyOperation.java
new file mode 100644
index 0000000..c258543
--- /dev/null
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/KeyOperation.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.jwk;
+
+
+public enum KeyOperation {
+    SIGN(JsonWebKey.KEY_OPER_SIGN),
+    VERIFY(JsonWebKey.KEY_OPER_VERIFY),
+    ENCRYPT(JsonWebKey.KEY_OPER_ENCRYPT),
+    DECRYPT(JsonWebKey.KEY_OPER_DECRYPT),
+    WRAPKEY(JsonWebKey.KEY_OPER_WRAP_KEY),
+    UNWRAPKEY(JsonWebKey.KEY_OPER_UNWRAP_KEY),
+    DERIVEKEY(JsonWebKey.KEY_OPER_DERIVE_KEY),
+    DERIVEBITS(JsonWebKey.KEY_OPER_DERIVE_BITS);
+    
+    private final String oper;
+    private KeyOperation(String oper) {
+        this.oper = oper;
+    }
+    public static KeyOperation getKeyOperation(String oper) {
+        if (oper == null) {
+            return null;
+        }
+        return valueOf(oper.toUpperCase());
+    }
+    public String toString() {
+        return oper;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/KeyType.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/KeyType.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/KeyType.java
new file mode 100644
index 0000000..b10afb8
--- /dev/null
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/KeyType.java
@@ -0,0 +1,44 @@
+/**
+ * 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 enum KeyType {
+    RSA(JsonWebKey.KEY_TYPE_RSA),
+    EC(JsonWebKey.KEY_TYPE_ELLIPTIC),
+    OCTET(JsonWebKey.KEY_TYPE_OCTET);
+    
+    private final String type;
+    private KeyType(String type) {
+        this.type = type;
+    }
+    public static KeyType getKeyType(String type) {
+        if (type == null) {
+            return null;
+        } else if (JsonWebKey.KEY_TYPE_OCTET.equals(type)) {
+            return OCTET;    
+        } else {
+            return valueOf(type);
+        }
+    }
+    public String toString() {
+        return type;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/PublicKeyUse.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/PublicKeyUse.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/PublicKeyUse.java
new file mode 100644
index 0000000..9b46b4f
--- /dev/null
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/PublicKeyUse.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.jwk;
+
+
+public enum PublicKeyUse {
+    SIGN(JsonWebKey.PUBLIC_KEY_USE_SIGN),
+    ENCRYPT(JsonWebKey.PUBLIC_KEY_USE_ENCRYPT);
+    
+    private final String use;
+    private PublicKeyUse(String use) {
+        this.use = use;
+    }
+    public static PublicKeyUse getPublicKeyUse(String use) {
+        if (use == null) {
+            return null;
+        }
+        if (JsonWebKey.PUBLIC_KEY_USE_SIGN.equals(use)) {
+            return SIGN; 
+        } else if (JsonWebKey.PUBLIC_KEY_USE_ENCRYPT.equals(use)) {
+            return ENCRYPT; 
+        } else {
+            return valueOf(use);
+        }
+    }
+    public String toString() {
+        return use;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/AbstractJwsSignatureProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/AbstractJwsSignatureProvider.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/AbstractJwsSignatureProvider.java
new file mode 100644
index 0000000..df400fa
--- /dev/null
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/AbstractJwsSignatureProvider.java
@@ -0,0 +1,76 @@
+/**
+ * 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.logging.Logger;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm;
+
+
+public abstract class AbstractJwsSignatureProvider implements JwsSignatureProvider {
+    protected static final Logger LOG = LogUtils.getL7dLogger(AbstractJwsSignatureProvider.class);
+    private SignatureAlgorithm algorithm;
+    
+    protected AbstractJwsSignatureProvider(SignatureAlgorithm algo) {
+        this.algorithm = algo;
+    }
+    
+    protected JwsHeaders prepareHeaders(JwsHeaders headers) {
+        if (headers == null) {
+            headers = new JwsHeaders();
+        }
+        SignatureAlgorithm sigAlgo = headers.getSignatureAlgorithm();
+        if (sigAlgo != null) {
+            checkAlgorithm(sigAlgo.getJwaName());
+        } else {
+            checkAlgorithm(algorithm.getJwaName());
+            headers.setSignatureAlgorithm(algorithm);
+        }
+        return headers;
+    }
+    @Override
+    public SignatureAlgorithm getAlgorithm() {
+        return algorithm;    
+    }
+    @Override
+    public byte[] sign(JwsHeaders headers, byte[] content) {
+        JwsSignature sig = createJwsSignature(headers);
+        sig.update(content, 0, content.length);
+        return sig.sign();
+    }
+    @Override
+    public JwsSignature createJwsSignature(JwsHeaders headers) {
+        return doCreateJwsSignature(prepareHeaders(headers));
+    }
+    
+    protected abstract JwsSignature doCreateJwsSignature(JwsHeaders headers);
+    
+    protected void checkAlgorithm(String algo) {
+        if (algo == null) {
+            LOG.warning("Signature algorithm is not set");
+            throw new JwsException(JwsException.Error.ALGORITHM_NOT_SET);
+        }
+        if (!isValidAlgorithmFamily(algo)) {
+            LOG.warning("Invalid signature algorithm: " + algo);
+            throw new JwsException(JwsException.Error.INVALID_ALGORITHM);
+        }
+    }
+    protected abstract boolean isValidAlgorithmFamily(String algo);
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureProvider.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureProvider.java
new file mode 100644
index 0000000..3bb92b9
--- /dev/null
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureProvider.java
@@ -0,0 +1,110 @@
+/**
+ * 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.Signature;
+import java.security.interfaces.ECPrivateKey;
+import java.security.spec.AlgorithmParameterSpec;
+
+import org.apache.cxf.rs.security.jose.jwa.AlgorithmUtils;
+import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm;
+
+public class EcDsaJwsSignatureProvider extends PrivateKeyJwsSignatureProvider {
+    public EcDsaJwsSignatureProvider(ECPrivateKey key, SignatureAlgorithm algo) {
+        this(key, null, algo);
+    }
+    public EcDsaJwsSignatureProvider(ECPrivateKey key, AlgorithmParameterSpec spec, SignatureAlgorithm algo) {
+        this(key, null, spec, algo);
+    }
+    public EcDsaJwsSignatureProvider(ECPrivateKey key, SecureRandom random, AlgorithmParameterSpec spec, 
+                                     SignatureAlgorithm algo) {
+        super(key, random, spec, algo);
+    }
+    @Override
+    protected boolean isValidAlgorithmFamily(String algo) {
+        return AlgorithmUtils.isEcDsaSign(algo);
+    }
+    @Override
+    protected JwsSignature doCreateJwsSignature(Signature s) {
+        return new EcDsaPrivateKeyJwsSignature(s, 
+            EcDsaJwsSignatureVerifier.SIGNATURE_LENGTH_MAP.get(super.getAlgorithm().getJwaName()));
+    }
+    
+    protected static class EcDsaPrivateKeyJwsSignature extends PrivateKeyJwsSignature {
+        private int outLen;
+        public EcDsaPrivateKeyJwsSignature(Signature s, int outLen) {
+            super(s);
+            this.outLen = outLen;
+        }
+        @Override
+        public byte[] sign() {
+            byte[] jcaDer = super.sign();
+            return jcaOutputToJoseOutput(outLen, jcaDer);
+        }
+    }
+    
+    private static byte[] jcaOutputToJoseOutput(int jwsSignatureLen, byte jcaDer[]) {
+        // DER uses a pattern of type-length-value triplets
+        // http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One#Example_encoded_in_DER
+        
+        // The algorithm implementation guarantees the correct DER format so no extra validation
+        
+        // ECDSA signature production: 
+        // 48 (SEQUENCE) + Total Length (1 or 2 bytes, the 1st byte is -127 if 2 bytes) 
+        // + R & S triples, where both triples are represented as 
+        // 2(INTEGER TYPE) + length + the actual sequence of a given length;
+        // The sequence might have the extra leading zeroes which need to be skipped
+        int requiredPartLen = jwsSignatureLen / 2;
+        
+        int rsDataBlockStart = jcaDer[1] == -127 ? 4 : 3;
+        int rPartLen = jcaDer[rsDataBlockStart];
+        int rDataBlockStart = rsDataBlockStart + 1;
+        int rPartLenDiff = rPartLen - requiredPartLen; 
+        int rValueStart = rDataBlockStart + getDataBlockOffset(jcaDer, rDataBlockStart, rPartLenDiff);
+        
+        int sPartStart = rDataBlockStart + rPartLen;
+        int sPartLen = jcaDer[sPartStart + 1];
+        int sPartLenDiff = sPartLen - requiredPartLen; 
+        int sDataBlockStart = sPartStart + 2;
+        int sValueStart = sDataBlockStart + getDataBlockOffset(jcaDer, sDataBlockStart, sPartLenDiff);
+                
+        byte[] result = new byte[jwsSignatureLen]; 
+        System.arraycopy(jcaDer, rValueStart, result, 
+            rPartLenDiff < 0 ? rPartLenDiff * -1 : 0, 
+            rPartLenDiff < 0 ? requiredPartLen + rPartLenDiff : requiredPartLen);
+        System.arraycopy(jcaDer, sValueStart, result, 
+            sPartLenDiff < 0 ? requiredPartLen + sPartLenDiff * -1 : requiredPartLen, 
+            sPartLenDiff < 0 ? requiredPartLen + sPartLenDiff : requiredPartLen);
+        return result;
+    }
+    private static int getDataBlockOffset(byte[] jcaDer, int blockStart, int partLenDiff) {
+        // ECDSA productions have 64, 96 or 132 output lengths. The R and S parts would be 32, 48 or 66 bytes each.
+        // If it is 32 or 48 bytes then we may have occasional extra zeroes in the JCA DER output
+        int i = 0;
+        if (partLenDiff > 0) {
+            while (i < partLenDiff && jcaDer[blockStart + i] == 0) {
+                i++;
+            }
+        }
+        return i;
+    }
+    
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureVerifier.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureVerifier.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureVerifier.java
new file mode 100644
index 0000000..025cd21
--- /dev/null
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureVerifier.java
@@ -0,0 +1,81 @@
+/**
+ * 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.PublicKey;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.cxf.rs.security.jose.jwa.AlgorithmUtils;
+import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm;
+
+public class EcDsaJwsSignatureVerifier extends PublicKeyJwsSignatureVerifier {
+    static final Map<String, Integer> SIGNATURE_LENGTH_MAP;
+    static {
+        SIGNATURE_LENGTH_MAP = new HashMap<String, Integer>();
+        SIGNATURE_LENGTH_MAP.put(SignatureAlgorithm.ES256.getJwaName(), 64);
+        SIGNATURE_LENGTH_MAP.put(SignatureAlgorithm.ES384.getJwaName(), 96);
+        SIGNATURE_LENGTH_MAP.put(SignatureAlgorithm.ES512.getJwaName(), 132);
+    }
+    public EcDsaJwsSignatureVerifier(PublicKey key, SignatureAlgorithm supportedAlgo) {
+        this(key, null, supportedAlgo);
+    }
+    public EcDsaJwsSignatureVerifier(PublicKey key, AlgorithmParameterSpec spec, SignatureAlgorithm supportedAlgo) {
+        super(key, spec, supportedAlgo);
+    }
+    @Override
+    public boolean verify(JwsHeaders headers, String unsignedText, byte[] signature) {
+        final String algoName = super.getAlgorithm().getJwaName();
+        if (SIGNATURE_LENGTH_MAP.get(algoName) != signature.length) {
+            LOG.warning("Algorithm " + algoName + " signature length is " + SIGNATURE_LENGTH_MAP.get(algoName) 
+                        + ", actual length is " + signature.length);
+            throw new JwsException(JwsException.Error.INVALID_SIGNATURE);
+        }
+        byte[] der = signatureToDer(signature);
+        return super.verify(headers, unsignedText, der);
+    }
+    @Override
+    protected boolean isValidAlgorithmFamily(String algo) {
+        return AlgorithmUtils.isEcDsaSign(algo);
+    }
+    private static byte[] signatureToDer(byte joseSig[]) {
+        int partLen = joseSig.length / 2;
+        int rOffset = joseSig[0] < 0 ? 1 : 0;
+        int sOffset = joseSig[partLen] < 0 ? 1 : 0;
+        int rPartLen = partLen + rOffset;
+        int sPartLen = partLen + sOffset;
+        int totalLenBytesCount = joseSig.length > 127 ? 2 : 1;
+        int rPartStart = 1 + totalLenBytesCount + 2;
+        byte[] der = new byte[rPartStart + 2 + rPartLen + sPartLen];
+        der[0] = 48;
+        if (totalLenBytesCount == 2) {
+            der[1] = -127;
+        }
+        der[totalLenBytesCount] = (byte)(der.length - (1 + totalLenBytesCount));
+        der[totalLenBytesCount + 1] = 2;
+        der[totalLenBytesCount + 2] = (byte)rPartLen;
+        int sPartStart = rPartStart + rPartLen;
+        der[sPartStart] = 2;
+        der[sPartStart + 1] = (byte)sPartLen;
+        System.arraycopy(joseSig, 0, der, rPartStart + rOffset, partLen);
+        System.arraycopy(joseSig, partLen, der, sPartStart + 2 + sOffset, partLen);
+        return der;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/HmacJwsSignatureProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/HmacJwsSignatureProvider.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/HmacJwsSignatureProvider.java
new file mode 100644
index 0000000..ce1db97
--- /dev/null
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/HmacJwsSignatureProvider.java
@@ -0,0 +1,76 @@
+/**
+ * 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 javax.crypto.Mac;
+
+import org.apache.cxf.common.util.Base64Exception;
+import org.apache.cxf.common.util.Base64UrlUtility;
+import org.apache.cxf.rs.security.jose.jwa.AlgorithmUtils;
+import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm;
+import org.apache.cxf.rt.security.crypto.HmacUtils;
+
+public class HmacJwsSignatureProvider extends AbstractJwsSignatureProvider {
+    private byte[] key;
+    private AlgorithmParameterSpec hmacSpec;
+    
+    public HmacJwsSignatureProvider(byte[] key, SignatureAlgorithm algo) {
+        this(key, null, algo);
+    }
+    public HmacJwsSignatureProvider(byte[] key, AlgorithmParameterSpec spec, SignatureAlgorithm algo) {
+        super(algo);
+        this.key = key;
+        this.hmacSpec = spec;
+    }
+    public HmacJwsSignatureProvider(String encodedKey, SignatureAlgorithm algo) {
+        super(algo);
+        try {
+            this.key = Base64UrlUtility.decode(encodedKey);
+        } catch (Base64Exception ex) {
+            LOG.warning("Hmac key can not be decoded");
+            throw new JwsException(JwsException.Error.INVALID_KEY, ex);
+        }
+    }
+    
+    protected JwsSignature doCreateJwsSignature(JwsHeaders headers) {
+        final String sigAlgo = headers.getSignatureAlgorithm().getJwaName();
+        final Mac mac = HmacUtils.getInitializedMac(key, 
+                                                    AlgorithmUtils.toJavaName(sigAlgo),
+                                                    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();
+            }
+            
+        };
+    }
+    @Override
+    protected boolean isValidAlgorithmFamily(String algo) {
+        return AlgorithmUtils.isHmacSign(algo);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/HmacJwsSignatureVerifier.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/HmacJwsSignatureVerifier.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/HmacJwsSignatureVerifier.java
new file mode 100644
index 0000000..7910659
--- /dev/null
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/HmacJwsSignatureVerifier.java
@@ -0,0 +1,85 @@
+/**
+ * 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.logging.Logger;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.rs.security.jose.common.JoseUtils;
+import org.apache.cxf.rs.security.jose.jwa.AlgorithmUtils;
+import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm;
+import org.apache.cxf.rt.security.crypto.HmacUtils;
+
+public class HmacJwsSignatureVerifier implements JwsSignatureVerifier {
+    protected static final Logger LOG = LogUtils.getL7dLogger(HmacJwsSignatureVerifier.class);
+    private byte[] key;
+    private AlgorithmParameterSpec hmacSpec;
+    private SignatureAlgorithm supportedAlgo;
+    
+    public HmacJwsSignatureVerifier(String encodedKey) {
+        this(JoseUtils.decode(encodedKey), SignatureAlgorithm.HS256);
+    }
+    public HmacJwsSignatureVerifier(String encodedKey, SignatureAlgorithm supportedAlgo) {
+        this(JoseUtils.decode(encodedKey), supportedAlgo);
+    }
+    public HmacJwsSignatureVerifier(byte[] key, SignatureAlgorithm supportedAlgo) {
+        this(key, null, supportedAlgo);
+    }
+    public HmacJwsSignatureVerifier(byte[] key, AlgorithmParameterSpec spec, SignatureAlgorithm supportedAlgo) {
+        this.key = key;
+        this.hmacSpec = spec;
+        this.supportedAlgo = supportedAlgo;
+    }
+    
+    
+    @Override
+    public boolean verify(JwsHeaders headers, String unsignedText, byte[] signature) {
+        byte[] expected = computeMac(headers, unsignedText);
+        return Arrays.equals(expected, signature);
+    }
+    
+    private byte[] computeMac(JwsHeaders headers, String text) {
+        final String sigAlgo = checkAlgorithm(headers.getSignatureAlgorithm());
+        return HmacUtils.computeHmac(key, 
+                                     AlgorithmUtils.toJavaName(sigAlgo),
+                                     hmacSpec,
+                                     text);
+    }
+    
+    protected String checkAlgorithm(SignatureAlgorithm sigAlgo) {
+        
+        if (sigAlgo == null) {
+            LOG.warning("Signature algorithm is not set");
+            throw new JwsException(JwsException.Error.ALGORITHM_NOT_SET);
+        }
+        String algo = sigAlgo.getJwaName();
+        if (!AlgorithmUtils.isHmacSign(algo)
+            || !algo.equals(supportedAlgo.getJwaName())) {
+            LOG.warning("Invalid signature algorithm: " + algo);
+            throw new JwsException(JwsException.Error.INVALID_ALGORITHM);
+        }
+        return algo;
+    }
+    @Override
+    public SignatureAlgorithm getAlgorithm() {
+        return supportedAlgo;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java
new file mode 100644
index 0000000..9d57222
--- /dev/null
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java
@@ -0,0 +1,149 @@
+/**
+ * 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.PublicKey;
+import java.security.cert.X509Certificate;
+import java.util.logging.Logger;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.jaxrs.json.basic.JsonMapObject;
+import org.apache.cxf.jaxrs.json.basic.JsonMapObjectReaderWriter;
+import org.apache.cxf.rs.security.jose.common.JoseUtils;
+import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm;
+import org.apache.cxf.rs.security.jose.jwk.JsonWebKey;
+
+public class JwsCompactConsumer {
+    protected static final Logger LOG = LogUtils.getL7dLogger(JwsCompactConsumer.class);
+    private JsonMapObjectReaderWriter reader = new JsonMapObjectReaderWriter();
+    private String encodedSequence;
+    private String encodedSignature;
+    private String headersJson;
+    private String jwsPayload;
+    private String decodedJwsPayload;
+    private JwsHeaders jwsHeaders;
+    private boolean detached;
+    public JwsCompactConsumer(String encodedJws) {
+        this(encodedJws, null, null);
+    }
+    public JwsCompactConsumer(String encodedJws, String detachedPayload) {
+        this(encodedJws, detachedPayload, null);
+    }
+    protected JwsCompactConsumer(String encodedJws, String detachedPayload, JsonMapObjectReaderWriter r) {
+        if (r != null) {
+            this.reader = r;
+        }
+        String[] parts = JoseUtils.getCompactParts(encodedJws);
+        if (parts.length != 3) {
+            if (parts.length == 2 && encodedJws.endsWith(".")) {
+                encodedSignature = "";
+            } else {
+                LOG.warning("Compact JWS does not have 3 parts");
+                throw new JwsException(JwsException.Error.INVALID_COMPACT_JWS);
+            }
+        } else {
+            encodedSignature = parts[2];
+        }
+        jwsPayload = parts[1];
+        if (detachedPayload != null) {
+            if (!StringUtils.isEmpty(jwsPayload)) {
+                LOG.warning("Compact JWS includes a payload expected to be detached");
+                throw new JwsException(JwsException.Error.INVALID_COMPACT_JWS);
+            }
+            detached = true;
+            jwsPayload = detachedPayload;
+        }
+        encodedSequence = parts[0] + "." + jwsPayload;
+        headersJson = JoseUtils.decodeToString(parts[0]);
+    }
+    public String getUnsignedEncodedSequence() {
+        return encodedSequence;
+    }
+    public String getEncodedSignature() {
+        return encodedSignature;
+    }
+    public String getDecodedJsonHeaders() {
+        return headersJson;
+    }
+    public String getDecodedJwsPayload() {
+        if (decodedJwsPayload == null) {
+            if (JwsUtils.isPayloadUnencoded(jwsHeaders)) {
+                decodedJwsPayload = jwsPayload;
+            } else {
+                decodedJwsPayload = JoseUtils.decodeToString(jwsPayload);
+            }
+        }
+        return decodedJwsPayload;
+    }
+    public byte[] getDecodedJwsPayloadBytes() {
+        return StringUtils.toBytesUTF8(getDecodedJwsPayload());
+    }
+    public byte[] getDecodedSignature() {
+        return encodedSignature.isEmpty() ? new byte[]{} : JoseUtils.decode(encodedSignature);
+    }
+    public JwsHeaders getJwsHeaders() {
+        if (jwsHeaders == null) {
+            JsonMapObject joseHeaders = reader.fromJsonToJsonObject(headersJson);
+            if (joseHeaders.getUpdateCount() != null) {
+                LOG.warning("Duplicate headers have been detected");
+                throw new JwsException(JwsException.Error.INVALID_COMPACT_JWS);
+            }
+            jwsHeaders = new JwsHeaders(joseHeaders.asMap());
+            if (JwsUtils.isPayloadUnencoded(jwsHeaders) && !detached) {
+                LOG.warning("Only detached payload can be unencoded");
+                throw new JwsException(JwsException.Error.INVALID_COMPACT_JWS);
+            }
+        }
+        return jwsHeaders;
+    }
+    public boolean verifySignatureWith(JwsSignatureVerifier validator) {
+        try {
+            if (validator.verify(getJwsHeaders(), getUnsignedEncodedSequence(), getDecodedSignature())) {
+                return true;
+            }
+        } catch (JwsException ex) {
+            // ignore
+        }
+        LOG.warning("Invalid Signature");
+        return false;
+    }
+    public boolean verifySignatureWith(JsonWebKey key) {
+        return verifySignatureWith(JwsUtils.getSignatureVerifier(key));
+    }
+    public boolean verifySignatureWith(JsonWebKey key, SignatureAlgorithm algo) {
+        return verifySignatureWith(JwsUtils.getSignatureVerifier(key, algo));
+    }
+    public boolean verifySignatureWith(X509Certificate cert, SignatureAlgorithm algo) {
+        return verifySignatureWith(JwsUtils.getPublicKeySignatureVerifier(cert, algo));
+    }
+    public boolean verifySignatureWith(PublicKey key, SignatureAlgorithm algo) {
+        return verifySignatureWith(JwsUtils.getPublicKeySignatureVerifier(key, algo));
+    }
+    public boolean verifySignatureWith(byte[] key, SignatureAlgorithm algo) {
+        return verifySignatureWith(JwsUtils.getHmacSignatureVerifier(key, algo));
+    }
+    public boolean validateCriticalHeaders() {
+        return JwsUtils.validateCriticalHeaders(getJwsHeaders());
+    }
+    protected JsonMapObjectReaderWriter getReader() {
+        return reader;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java
new file mode 100644
index 0000000..5b4c760
--- /dev/null
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java
@@ -0,0 +1,153 @@
+/**
+ * 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.PrivateKey;
+import java.util.Properties;
+
+import org.apache.cxf.common.util.Base64UrlUtility;
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.jaxrs.json.basic.JsonMapObjectReaderWriter;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.PhaseInterceptorChain;
+import org.apache.cxf.rs.security.jose.common.JoseConstants;
+import org.apache.cxf.rs.security.jose.common.KeyManagementUtils;
+import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm;
+import org.apache.cxf.rs.security.jose.jwk.JsonWebKey;
+
+public class JwsCompactProducer {
+    private JsonMapObjectReaderWriter writer = new JsonMapObjectReaderWriter();
+    private JwsHeaders headers;
+    private String plainJwsPayload;
+    private String signature;
+    private boolean detached;
+    public JwsCompactProducer(String plainJwsPayload) {
+        this(plainJwsPayload, false);
+    }
+    public JwsCompactProducer(String plainJwsPayload, boolean detached) {
+        this(null, null, plainJwsPayload, detached);
+    }
+    public JwsCompactProducer(JwsHeaders headers, String plainJwsPayload) {
+        this(headers, plainJwsPayload, false);
+    }
+    public JwsCompactProducer(JwsHeaders headers, String plainJwsPayload, boolean detached) {
+        this(headers, null, plainJwsPayload, detached);
+    }
+    protected JwsCompactProducer(JwsHeaders headers, JsonMapObjectReaderWriter w, String plainJwsPayload) {
+        this(headers, w, plainJwsPayload, false);
+    }    
+    protected JwsCompactProducer(JwsHeaders headers, JsonMapObjectReaderWriter w, String plainJwsPayload, 
+                                 boolean detached) {    
+        this.headers = headers;
+        if (w != null) {
+            this.writer = w;
+        }
+        this.plainJwsPayload = plainJwsPayload;
+        this.detached = detached;
+    }
+    public JwsHeaders getJwsHeaders() {
+        if (headers == null) {
+            headers = new JwsHeaders();
+        }
+        return headers;
+    }
+    public String getUnsignedEncodedJws() {
+        checkAlgorithm();
+        return Base64UrlUtility.encode(writer.toJson(getJwsHeaders())) 
+               + "." 
+               + (detached ? "" : Base64UrlUtility.encode(plainJwsPayload));
+    }
+    private String getSigningInput() {
+        checkAlgorithm();
+        boolean unencoded = JwsUtils.isPayloadUnencoded(getJwsHeaders());
+        if (unencoded && !detached) {
+            throw new JwsException(JwsException.Error.INVALID_COMPACT_JWS);
+        }
+        return Base64UrlUtility.encode(writer.toJson(getJwsHeaders())) 
+               + "." 
+               + (unencoded ? plainJwsPayload : Base64UrlUtility.encode(plainJwsPayload));
+    }
+    public String getEncodedSignature() {
+        return signature;
+    }
+    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(JsonWebKey jwk) {
+        return signWith(JwsUtils.getSignatureProvider(jwk, 
+                        headers.getSignatureAlgorithm()));
+    }
+    
+    public String signWith(PrivateKey key) {
+        return signWith(JwsUtils.getPrivateKeySignatureProvider(key, 
+                                   headers.getSignatureAlgorithm()));
+    }
+    public String signWith(byte[] key) {
+        return signWith(JwsUtils.getHmacSignatureProvider(key, 
+                   headers.getSignatureAlgorithm()));
+    }
+    
+    public String signWith(JwsSignatureProvider signer) {
+        byte[] bytes = StringUtils.toBytesUTF8(getSigningInput());
+        byte[] sig = signer.sign(getJwsHeaders(), bytes);
+        return setSignatureBytes(sig);
+    }
+    
+    public String setSignatureText(String signatureText) {
+        setEncodedSignature(Base64UrlUtility.encode(signatureText));
+        return getSignedEncodedJws();
+    }
+    
+    public boolean isPlainText() {
+        return SignatureAlgorithm.NONE == getAlgorithm();
+    }
+    
+    public String setSignatureBytes(byte[] signatureOctets) {
+        setEncodedSignature(Base64UrlUtility.encode(signatureOctets));
+        return getSignedEncodedJws();
+    }
+    
+    private void setEncodedSignature(String sig) {
+        this.signature = sig;
+    }
+    private SignatureAlgorithm getAlgorithm() {
+        return getJwsHeaders().getSignatureAlgorithm();
+    }
+    private void checkAlgorithm() {
+        if (getAlgorithm() == null) {
+            Message m = PhaseInterceptorChain.getCurrentMessage();
+            Properties props = KeyManagementUtils.loadStoreProperties(m, false, 
+                                                                      JoseConstants.RSSEC_SIGNATURE_OUT_PROPS, 
+                                                                      JoseConstants.RSSEC_SIGNATURE_PROPS);
+            String signatureAlgo = JwsUtils.getSignatureAlgo(m, props, null, null);
+            if (signatureAlgo != null) {
+                getJwsHeaders().setSignatureAlgorithm(SignatureAlgorithm.getAlgorithm(signatureAlgo));
+            }
+        }
+        
+        if (getAlgorithm() == null) {
+            throw new JwsException(JwsException.Error.INVALID_ALGORITHM);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsException.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsException.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsException.java
new file mode 100644
index 0000000..7482b8d
--- /dev/null
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsException.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.jws;
+
+import org.apache.cxf.rs.security.jose.common.JoseException;
+
+public class JwsException extends JoseException {
+
+    private static final long serialVersionUID = 4118589816228511524L;
+    private Error status;
+    public JwsException(Error status) {
+        this(status, null);
+    }
+    public JwsException(Error status, Throwable cause) {
+        super(cause);
+        this.status = status;
+    }
+    public Error getError() {
+        return status;
+    }
+    public static enum Error {
+        NO_PROVIDER,
+        NO_VERIFIER,
+        NO_INIT_PROPERTIES,
+        ALGORITHM_NOT_SET,
+        INVALID_ALGORITHM,
+        INVALID_KEY,
+        SIGNATURE_FAILURE,
+        INVALID_SIGNATURE,
+        INVALID_COMPACT_JWS,
+        INVALID_JSON_JWS
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsHeaders.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsHeaders.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsHeaders.java
new file mode 100644
index 0000000..a2d0e88
--- /dev/null
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsHeaders.java
@@ -0,0 +1,66 @@
+/**
+ * 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.Map;
+
+import org.apache.cxf.rs.security.jose.common.JoseConstants;
+import org.apache.cxf.rs.security.jose.common.JoseHeaders;
+import org.apache.cxf.rs.security.jose.common.JoseType;
+import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm;
+
+public class JwsHeaders extends JoseHeaders {
+    public JwsHeaders() {
+    }
+    public JwsHeaders(JoseType type) {
+        super(type);
+    }
+    public JwsHeaders(JoseHeaders headers) {
+        super(headers.asMap());
+    }
+    
+    public JwsHeaders(Map<String, Object> values) {
+        super(values);
+    }
+    public JwsHeaders(SignatureAlgorithm sigAlgo) {
+        init(sigAlgo);
+    }
+    public JwsHeaders(JoseType type, SignatureAlgorithm sigAlgo) {
+        super(type);
+        init(sigAlgo);
+    }
+    private void init(SignatureAlgorithm sigAlgo) {
+        setSignatureAlgorithm(sigAlgo);
+    }
+    
+    public void setSignatureAlgorithm(SignatureAlgorithm algo) {
+        super.setAlgorithm(algo.getJwaName());
+    }
+    
+    public SignatureAlgorithm getSignatureAlgorithm() {
+        String algo = super.getAlgorithm();
+        return algo == null ? null : SignatureAlgorithm.getAlgorithm(algo);
+    }
+    public void setPayloadEncodingStatus(Boolean status) {
+        super.setProperty(JoseConstants.JWS_HEADER_B64_STATUS_HEADER, status);
+    }
+    public Boolean getPayloadEncodingStatus() {
+        return super.getBooleanProperty(JoseConstants.JWS_HEADER_B64_STATUS_HEADER);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/532c52a7/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumer.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumer.java
new file mode 100644
index 0000000..3ad5b45
--- /dev/null
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumer.java
@@ -0,0 +1,189 @@
+/**
+ * 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.PublicKey;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.jaxrs.json.basic.JsonMapObject;
+import org.apache.cxf.jaxrs.json.basic.JsonMapObjectReaderWriter;
+import org.apache.cxf.rs.security.jose.common.JoseUtils;
+import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm;
+import org.apache.cxf.rs.security.jose.jwk.JsonWebKey;
+
+public class JwsJsonConsumer {
+    protected static final Logger LOG = LogUtils.getL7dLogger(JwsJsonConsumer.class);
+    private String jwsSignedDocument;
+    private String jwsPayload;
+    private List<JwsJsonSignatureEntry> signatures = new LinkedList<JwsJsonSignatureEntry>();
+    /**
+     * @param jwsSignedDocument
+     *            signed JWS Document
+     */
+    public JwsJsonConsumer(String jwsSignedDocument) {
+        this(jwsSignedDocument, null);
+    }
+    public JwsJsonConsumer(String jwsSignedDocument, String detachedPayload) {
+        this.jwsSignedDocument = jwsSignedDocument;
+        prepare(detachedPayload);
+    }
+
+    private void prepare(String detachedPayload) {
+        JsonMapObject jsonObject = new JsonMapObject();
+        new JsonMapObjectReaderWriter().fromJson(jsonObject, jwsSignedDocument);
+        
+        Map<String, Object> jsonObjectMap = jsonObject.asMap(); 
+        jwsPayload = (String)jsonObjectMap.get("payload");
+        if (jwsPayload == null) {
+            jwsPayload = detachedPayload;
+        } else if (detachedPayload != null) {
+            LOG.warning("JSON JWS includes a payload expected to be detached");
+            throw new JwsException(JwsException.Error.INVALID_JSON_JWS);
+        }
+        if (jwsPayload == null) {
+            LOG.warning("JSON JWS has no payload");
+            throw new JwsException(JwsException.Error.INVALID_JSON_JWS);
+        }
+        List<Map<String, Object>> signatureArray = CastUtils.cast((List<?>)jsonObjectMap.get("signatures"));
+        if (signatureArray != null) {
+            if (jsonObjectMap.containsKey("signature")) {
+                LOG.warning("JSON JWS has a flattened 'signature' element and a 'signatures' object");
+                throw new JwsException(JwsException.Error.INVALID_JSON_JWS);
+            }
+            for (Map<String, Object> signatureEntry : signatureArray) {
+                this.signatures.add(getSignatureObject(signatureEntry));
+            }
+        } else {
+            this.signatures.add(getSignatureObject(jsonObjectMap));
+        }
+        if (signatures.isEmpty()) {
+            LOG.warning("JSON JWS has no signatures");
+            throw new JwsException(JwsException.Error.INVALID_JSON_JWS);
+        }
+        validateB64Status();
+        
+        
+    }
+    private Boolean validateB64Status() {
+        return JwsJsonProducer.validateB64Status(signatures);    
+    }
+    protected JwsJsonSignatureEntry getSignatureObject(Map<String, Object> signatureEntry) {
+        String protectedHeader = (String)signatureEntry.get("protected");
+        Map<String, Object> header = CastUtils.cast((Map<?, ?>)signatureEntry.get("header"));
+        String signature = (String)signatureEntry.get("signature");
+        return 
+            new JwsJsonSignatureEntry(jwsPayload, 
+                                      protectedHeader, 
+                                      signature, 
+                                      header != null ? new JwsHeaders(header) : null);
+    }
+    public String getSignedDocument() {
+        return this.jwsSignedDocument;
+    }
+    public String getJwsPayload() {
+        return this.jwsPayload;
+    }
+    public String getDecodedJwsPayload() {
+        if (validateB64Status()) {
+            return JoseUtils.decodeToString(jwsPayload);
+        } else {
+            return jwsPayload;
+        }
+    }
+    public byte[] getDecodedJwsPayloadBytes() {
+        return StringUtils.toBytesUTF8(getDecodedJwsPayload());
+    }
+    public List<JwsJsonSignatureEntry> getSignatureEntries() {
+        return Collections.unmodifiableList(signatures);
+    }
+    public Map<SignatureAlgorithm, List<JwsJsonSignatureEntry>> getSignatureEntryMap() {
+        return JwsUtils.getJwsJsonSignatureMap(signatures);
+    }
+    public boolean verifySignatureWith(JwsSignatureVerifier validator) {
+        List<JwsJsonSignatureEntry> theSignatureEntries = 
+            getSignatureEntryMap().get(validator.getAlgorithm());
+        if (theSignatureEntries != null) {
+            for (JwsJsonSignatureEntry signatureEntry : theSignatureEntries) {
+                if (signatureEntry.verifySignatureWith(validator)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+    public boolean verifySignatureWith(PublicKey key, SignatureAlgorithm algo) {
+        return verifySignatureWith(JwsUtils.getPublicKeySignatureVerifier(key, algo));
+    }
+    public boolean verifySignatureWith(byte[] key, SignatureAlgorithm algo) {
+        return verifySignatureWith(JwsUtils.getHmacSignatureVerifier(key, algo));
+    }
+    public boolean verifySignatureWith(List<JwsSignatureVerifier> validators) {
+        try {
+            if (verifyAndGetNonValidated(validators).isEmpty()) {
+                return true;
+            }
+        } catch (JwsException ex) {
+            // ignore
+        }
+        LOG.warning("One of JSON JWS signatures is invalid");
+        return false;
+    }
+    public List<JwsJsonSignatureEntry> verifyAndGetNonValidated(List<JwsSignatureVerifier> validators) {
+        // TODO: more effective approach is needed
+        List<JwsJsonSignatureEntry> validatedSignatures = new LinkedList<JwsJsonSignatureEntry>();
+        for (JwsSignatureVerifier validator : validators) {
+            List<JwsJsonSignatureEntry> theSignatureEntries = 
+                getSignatureEntryMap().get(validator.getAlgorithm());
+            if (theSignatureEntries != null) {
+                for (JwsJsonSignatureEntry sigEntry : theSignatureEntries) {
+                    if (sigEntry.verifySignatureWith(validator)) {     
+                        validatedSignatures.add(sigEntry);
+                        break;
+                    }
+                }
+            }
+        }
+        List<JwsJsonSignatureEntry> nonValidatedSignatures = new LinkedList<JwsJsonSignatureEntry>();
+        for (JwsJsonSignatureEntry sigEntry : signatures) {
+            if (!validatedSignatures.contains(sigEntry)) {        
+                nonValidatedSignatures.add(sigEntry);
+            }
+        }
+        return nonValidatedSignatures;
+    }
+    
+    public boolean verifySignatureWith(JsonWebKey key) {
+        return verifySignatureWith(JwsUtils.getSignatureVerifier(key));
+    }
+    public boolean verifySignatureWith(JsonWebKey key, SignatureAlgorithm algo) {
+        return verifySignatureWith(JwsUtils.getSignatureVerifier(key, algo));
+    }
+    public JwsJsonProducer toProducer() {
+        JwsJsonProducer p = new JwsJsonProducer(getDecodedJwsPayload());
+        p.getSignatureEntries().addAll(signatures);
+        return p;
+    }
+}


Mime
View raw message