cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From serg...@apache.org
Subject cxf git commit: Making the way the elliptic key signature is prepared JWS compliant
Date Mon, 24 Nov 2014 16:48:31 GMT
Repository: cxf
Updated Branches:
  refs/heads/master a4caf9383 -> 710bf9a1e


Making the way the elliptic key signature is prepared JWS compliant


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/710bf9a1
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/710bf9a1
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/710bf9a1

Branch: refs/heads/master
Commit: 710bf9a1e87b6ade87dcd8f80a2626f2939e96a9
Parents: a4caf93
Author: Sergey Beryozkin <sberyozkin@talend.com>
Authored: Mon Nov 24 16:48:15 2014 +0000
Committer: Sergey Beryozkin <sberyozkin@talend.com>
Committed: Mon Nov 24 16:48:15 2014 +0000

----------------------------------------------------------------------
 .../jose/jws/EcDsaJwsSignatureProvider.java     | 41 ++++++++++++++++
 .../jose/jws/EcDsaJwsSignatureVerifier.java     | 37 +++++++++++++++
 .../jws/PrivateKeyJwsSignatureProvider.java     | 49 +++++++++++---------
 .../security/jose/jws/JwsJsonConsumerTest.java  |  2 +-
 4 files changed, 107 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/710bf9a1/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureProvider.java
b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureProvider.java
index b6da904..3e4fcda 100644
--- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureProvider.java
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureProvider.java
@@ -19,6 +19,7 @@
 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;
 
@@ -39,4 +40,44 @@ public class EcDsaJwsSignatureProvider extends PrivateKeyJwsSignatureProvider
{
     protected boolean isValidAlgorithmFamily(String algo) {
         return Algorithm.isEcDsaSign(algo);
     }
+    @Override
+    protected JwsSignature doCreateJwsSignature(Signature s) {
+        return new EcDsaPrivateKeyJwsSignature(s);
+    }
+    
+    protected static class EcDsaPrivateKeyJwsSignature extends PrivateKeyJwsSignature {
+        public EcDsaPrivateKeyJwsSignature(Signature s) {
+            super(s);
+        }
+        @Override
+        public byte[] sign() {
+            byte[] der = super.sign();
+            return jcaOutputToJoseOutput(der);
+        }
+    }
+    
+    private static byte[] jcaOutputToJoseOutput(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 + R & S triples, where every triple is 2 
+        // (INTEGER TYPE + length + the actual integer)
+        
+        int rPartLen = jcaDer[3];
+        int rOffset = rPartLen % 8;
+        int rValueStart = 4 + rOffset;
+        int sPartStart = 4 + rPartLen;
+        int sPartLen = jcaDer[sPartStart + 1];
+        int sOffset = sPartLen % 8;
+        int sValueStart = sPartStart + 2 + sOffset;
+        
+        int partLen = rPartLen - rOffset;
+        byte[] result = new byte[partLen * 2]; 
+        System.arraycopy(jcaDer, rValueStart, result, 0, partLen);
+        System.arraycopy(jcaDer, sValueStart, result, partLen, partLen);
+        return result;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/710bf9a1/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureVerifier.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureVerifier.java
b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureVerifier.java
index 6670367..10341e5 100644
--- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureVerifier.java
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureVerifier.java
@@ -20,10 +20,20 @@ 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.JoseHeaders;
 import org.apache.cxf.rs.security.jose.jwa.Algorithm;
 
 public class EcDsaJwsSignatureVerifier extends PublicKeyJwsSignatureVerifier {
+    private static final Map<String, Integer> SIGNATURE_LENGTH_MAP;
+    static {
+        SIGNATURE_LENGTH_MAP = new HashMap<String, Integer>();
+        SIGNATURE_LENGTH_MAP.put(Algorithm.SHA256withECDSA.getJwtName(), 64);
+        SIGNATURE_LENGTH_MAP.put(Algorithm.SHA384withECDSA.getJwtName(), 96);
+        SIGNATURE_LENGTH_MAP.put(Algorithm.SHA512withECDSA.getJwtName(), 132);
+    }
     public EcDsaJwsSignatureVerifier(PublicKey key, String supportedAlgo) {
         this(key, null, supportedAlgo);
     }
@@ -31,7 +41,34 @@ public class EcDsaJwsSignatureVerifier extends PublicKeyJwsSignatureVerifier
{
         super(key, spec, supportedAlgo);
     }
     @Override
+    public boolean verify(JoseHeaders headers, String unsignedText, byte[] signature) {
+        if (SIGNATURE_LENGTH_MAP.get(super.getAlgorithm()) != signature.length) {
+            throw new SecurityException();
+        }
+        byte[] der = signatureToDer(signature);
+        return super.verify(headers, unsignedText, der);
+    }
+    @Override
     protected boolean isValidAlgorithmFamily(String algo) {
         return Algorithm.isEcDsaSign(algo);
     }
+    private static byte[] signatureToDer(byte joseSig[]) {
+        int partLen = joseSig.length / 2;
+        // 0 needs to be appended if the first byte is negative
+        int rOffset = joseSig[0] < 0 ? 1 : 0;
+        int sOffset = joseSig[partLen] < 0 ? 1 : 0;
+        
+        byte[] der = new byte[6 + joseSig.length + rOffset + sOffset];
+        der[0] = 48;
+        der[1] = (byte)(der.length - 2);
+        der[2] = 2;
+        der[3] = (byte)(partLen + rOffset);
+        int sPartStart = 4 + der[3];
+        der[sPartStart] = 2;
+        der[sPartStart + 1] = (byte)(partLen + sOffset);
+        System.arraycopy(joseSig, 0, der, 4 + rOffset, partLen);
+        System.arraycopy(joseSig, partLen, der, sPartStart + 2 + sOffset, partLen);
+        return der;
+    }
+    
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/710bf9a1/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/PrivateKeyJwsSignatureProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/PrivateKeyJwsSignatureProvider.java
b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/PrivateKeyJwsSignatureProvider.java
index 784248d..1f38972 100644
--- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/PrivateKeyJwsSignatureProvider.java
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/PrivateKeyJwsSignatureProvider.java
@@ -51,27 +51,10 @@ public class PrivateKeyJwsSignatureProvider extends AbstractJwsSignatureProvider
                                                      Algorithm.toJavaName(headers.getAlgorithm()),
                                                      random,
                                                      signatureSpec);
-        return new JwsSignature() {
-
-            @Override
-            public void update(byte[] src, int off, int len) {
-                try {
-                    s.update(src, off, len);
-                } catch (SignatureException ex) {
-                    throw new SecurityException();
-                }
-            }
-
-            @Override
-            public byte[] sign() {
-                try {
-                    return s.sign();
-                } catch (SignatureException ex) {
-                    throw new SecurityException();
-                }
-            }
-            
-        };
+        return doCreateJwsSignature(s);
+    }
+    protected JwsSignature doCreateJwsSignature(Signature s) {
+        return new PrivateKeyJwsSignature(s);
     }
     @Override
     protected void checkAlgorithm(String algo) {
@@ -85,4 +68,28 @@ public class PrivateKeyJwsSignatureProvider extends AbstractJwsSignatureProvider
         return Algorithm.isRsaShaSign(algo);
     }
 
+    protected static class PrivateKeyJwsSignature implements JwsSignature {
+        private Signature s;
+        public PrivateKeyJwsSignature(Signature s) {
+            this.s = s;
+        }
+        @Override
+        public void update(byte[] src, int off, int len) {
+            try {
+                s.update(src, off, len);
+            } catch (SignatureException ex) {
+                throw new SecurityException();
+            }
+        }
+
+        @Override
+        public byte[] sign() {
+            try {
+                return s.sign();
+            } catch (SignatureException ex) {
+                throw new SecurityException();
+            }
+        }
+        
+    }
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/710bf9a1/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumerTest.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumerTest.java
b/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumerTest.java
index e46b5cd..ce611e2 100644
--- a/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumerTest.java
+++ b/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumerTest.java
@@ -69,7 +69,7 @@ public class JwsJsonConsumerTest extends Assert {
         assertEquals(KID_OF_THE_SECOND_SIGNER, secondKid);
         JsonWebKey ecKey = jwks.getKey(secondKid);
         assertNotNull(ecKey);
-        //assertTrue(sigEntries.get(1).verifySignatureWith(ecKey));
+        assertTrue(sigEntries.get(1).verifySignatureWith(ecKey));
     }
     public JsonWebKeys readKeySet(String fileName) throws Exception {
         InputStream is = JwsJsonConsumerTest.class.getResourceAsStream(fileName);


Mime
View raw message