Repository: cxf Updated Branches: refs/heads/3.0.x-fixes d0b86402f -> 97251de37
[CXF-6202] Adding more JWS tests, another patch from Daniel Torkian applied Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/97251de3 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/97251de3 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/97251de3 Branch: refs/heads/3.0.x-fixes Commit: 97251de37cbc9e0035af3c90eb2b2d248211e052 Parents: d0b8640 Author: Sergey Beryozkin <[email protected]> Authored: Thu Jan 22 11:09:07 2015 +0000 Committer: Sergey Beryozkin <[email protected]> Committed: Thu Jan 22 11:10:31 2015 +0000 ---------------------------------------------------------------------- .../security/jose/jws/JwsCompactConsumer.java | 2 +- .../security/jose/jws/JwsCompactProducer.java | 10 +- .../jose/cookbook/JwsJoseCookBookTest.java | 128 +++++++++++++++++++ 3 files changed, 132 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/97251de3/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java index 5589f56..97f49c8 100644 --- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java @@ -57,7 +57,7 @@ public class JwsCompactConsumer { } String encodedJwsPayload = parts[1]; if (encodedDetachedPayload != null) { - if (StringUtils.isEmpty(encodedJwsPayload)) { + if (!StringUtils.isEmpty(encodedJwsPayload)) { throw new SecurityException("Invalid JWS Compact sequence"); } encodedJwsPayload = encodedDetachedPayload; http://git-wip-us.apache.org/repos/asf/cxf/blob/97251de3/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java index 0bed1c4..b8f192b 100644 --- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java @@ -32,7 +32,6 @@ public class JwsCompactProducer { private JoseHeaders headers; private String plainJwsPayload; private String signature; - private String plainRep; public JwsCompactProducer(String plainJwsPayload) { this(null, null, plainJwsPayload); } @@ -57,12 +56,9 @@ public class JwsCompactProducer { } private String getUnsignedEncodedJws(boolean detached) { checkAlgorithm(); - if (plainRep == null) { - plainRep = Base64UrlUtility.encode(writer.headersToJson(getJoseHeaders())) - + "." - + (detached ? "" : Base64UrlUtility.encode(plainJwsPayload)); - } - return plainRep; + return Base64UrlUtility.encode(writer.headersToJson(getJoseHeaders())) + + "." + + (detached ? "" : Base64UrlUtility.encode(plainJwsPayload)); } public String getEncodedSignature() { return signature; http://git-wip-us.apache.org/repos/asf/cxf/blob/97251de3/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/cookbook/JwsJoseCookBookTest.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/cookbook/JwsJoseCookBookTest.java b/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/cookbook/JwsJoseCookBookTest.java index 2598963..e27e6a7 100644 --- a/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/cookbook/JwsJoseCookBookTest.java +++ b/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/cookbook/JwsJoseCookBookTest.java @@ -164,6 +164,61 @@ public class JwsJoseCookBookTest { private static final String ECSDA_SIGNATURE_PROTECTED_HEADER = "eyJhbGciOiJFUzUxMiIsImtpZCI6ImJpbGJvLmJhZ2dpbnNAaG9iYml0b24uZX" + "hhbXBsZSJ9"; + private static final String HMAC_KID_VALUE = "018c0ae5-4d9b-471b-bfd6-eef314bc7037"; + private static final String HMAC_SIGNATURE_PROTECTED_HEADER_JSON = ("{" + + "\"alg\": \"HS256\"," + + "\"kid\": \"018c0ae5-4d9b-471b-bfd6-eef314bc7037\"" + + "}").replaceAll(" ", ""); + private static final String HMAC_SIGNATURE_PROTECTED_HEADER = + "eyJhbGciOiJIUzI1NiIsImtpZCI6IjAxOGMwYWU1LTRkOWItNDcxYi1iZmQ2LW" + + "VlZjMxNGJjNzAzNyJ9"; + private static final String HMAC_SIGNATURE_VALUE = "s0h6KThzkfBBBkLspW1h84VsJZFTsPPqMDA7g1Md7p0"; + private static final String HMAC_JSON_GENERAL_SERIALIZATION = ("{" + + "\"payload\": \"SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywg" + + "Z29pbmcgb3V0IHlvdXIgZG9vci4gWW91IHN0ZXAgb250byB0aGUgcm9h" + + "ZCwgYW5kIGlmIHlvdSBkb24ndCBrZWVwIHlvdXIgZmVldCwgdGhlcmXi" + + "gJlzIG5vIGtub3dpbmcgd2hlcmUgeW91IG1pZ2h0IGJlIHN3ZXB0IG9m" + + "ZiB0by4\"," + + "\"signatures\": [" + + "{" + + "\"protected\": \"eyJhbGciOiJIUzI1NiIsImtpZCI6IjAxOGMwYWU1LT" + + "RkOWItNDcxYi1iZmQ2LWVlZjMxNGJjNzAzNyJ9\"," + + "\"signature\": \"s0h6KThzkfBBBkLspW1h84VsJZFTsPPqMDA7g1Md7p" + + "0\"" + + "}" + + "]" + + "}").replaceAll(" ", ""); + private static final String HMAC_JSON_FLATTENED_SERIALIZATION = ("{" + + "\"payload\": \"SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywg" + + "Z29pbmcgb3V0IHlvdXIgZG9vci4gWW91IHN0ZXAgb250byB0aGUgcm9h" + + "ZCwgYW5kIGlmIHlvdSBkb24ndCBrZWVwIHlvdXIgZmVldCwgdGhlcmXi" + + "gJlzIG5vIGtub3dpbmcgd2hlcmUgeW91IG1pZ2h0IGJlIHN3ZXB0IG9m" + + "ZiB0by4\"," + + "\"protected\": \"eyJhbGciOiJIUzI1NiIsImtpZCI6IjAxOGMwYWU1LTRkOW" + + "ItNDcxYi1iZmQ2LWVlZjMxNGJjNzAzNyJ9\"," + + "\"signature\": \"s0h6KThzkfBBBkLspW1h84VsJZFTsPPqMDA7g1Md7p0\"" + + "}").replaceAll(" ", ""); + private static final String DETACHED_HMAC_JWS = + ("eyJhbGciOiJIUzI1NiIsImtpZCI6IjAxOGMwYWU1LTRkOWItNDcxYi1iZmQ2LW" + + "VlZjMxNGJjNzAzNyJ9" + + "." + + "." + + "s0h6KThzkfBBBkLspW1h84VsJZFTsPPqMDA7g1Md7p0").replaceAll(" ", ""); + private static final String HMAC_DETACHED_JSON_GENERAL_SERIALIZATION = ("{" + + "\"signatures\": [" + + "{" + + "\"protected\": \"eyJhbGciOiJIUzI1NiIsImtpZCI6IjAxOGMwYWU1LT" + + "RkOWItNDcxYi1iZmQ2LWVlZjMxNGJjNzAzNyJ9\"," + + "\"signature\": \"s0h6KThzkfBBBkLspW1h84VsJZFTsPPqMDA7g1Md7p" + + "0\"" + + "}" + + "]" + + "}").replaceAll(" ", ""); + private static final String HMAC_DETACHED_JSON_FLATTENED_SERIALIZATION = ("{" + + "\"protected\": \"eyJhbGciOiJIUzI1NiIsImtpZCI6IjAxOGMwYWU1LTRkOW" + + "ItNDcxYi1iZmQ2LWVlZjMxNGJjNzAzNyJ9\"," + + "\"signature\": \"s0h6KThzkfBBBkLspW1h84VsJZFTsPPqMDA7g1Md7p0\"" + + "}").replaceAll(" ", ""); @Test public void testEncodedPayload() throws Exception { @@ -290,6 +345,79 @@ public class JwsJoseCookBookTest { Security.removeProvider(BouncyCastleProvider.class.getName()); } } + @Test + public void testHMACSignature() throws Exception { + JwsCompactProducer compactProducer = new JwsCompactProducer(PAYLOAD); + compactProducer.getJoseHeaders().setAlgorithm(JoseConstants.HMAC_SHA_256_ALGO); + compactProducer.getJoseHeaders().setKeyId(HMAC_KID_VALUE); + JsonMapObjectReaderWriter reader = new JsonMapObjectReaderWriter(); + assertEquals(reader.toJson(compactProducer.getJoseHeaders().asMap()), HMAC_SIGNATURE_PROTECTED_HEADER_JSON); + assertEquals(compactProducer.getUnsignedEncodedJws(), + HMAC_SIGNATURE_PROTECTED_HEADER + "." + ENCODED_PAYLOAD); + JsonWebKeys jwks = readKeySet("cookbookSecretSet.txt"); + List<JsonWebKey> keys = jwks.getKeys(); + JsonWebKey key = keys.get(0); + compactProducer.signWith(key); + assertEquals(compactProducer.getSignedEncodedJws(), + HMAC_SIGNATURE_PROTECTED_HEADER + "." + ENCODED_PAYLOAD + "." + HMAC_SIGNATURE_VALUE); + JwsCompactConsumer compactConsumer = new JwsCompactConsumer(compactProducer.getSignedEncodedJws()); + assertTrue(compactConsumer.verifySignatureWith(key, JoseConstants.HMAC_SHA_256_ALGO)); + + JwsJsonProducer jsonProducer = new JwsJsonProducer(PAYLOAD); + assertEquals(jsonProducer.getPlainPayload(), PAYLOAD); + assertEquals(jsonProducer.getUnsignedEncodedPayload(), ENCODED_PAYLOAD); + JoseHeaders joseHeaders = new JoseHeaders(); + joseHeaders.setAlgorithm(JoseConstants.HMAC_SHA_256_ALGO); + joseHeaders.setKeyId(HMAC_KID_VALUE); + JwsJsonProtectedHeader protectedHeader = new JwsJsonProtectedHeader(joseHeaders); + jsonProducer.signWith(JwsUtils.getSignatureProvider(key, JoseConstants.HMAC_SHA_256_ALGO), protectedHeader); + assertEquals(jsonProducer.getJwsJsonSignedDocument(), HMAC_JSON_GENERAL_SERIALIZATION); + JwsJsonConsumer jsonConsumer = new JwsJsonConsumer(jsonProducer.getJwsJsonSignedDocument()); + assertTrue(jsonConsumer.verifySignatureWith(key, JoseConstants.HMAC_SHA_256_ALGO)); + + jsonProducer = new JwsJsonProducer(PAYLOAD, true); + jsonProducer.signWith(JwsUtils.getSignatureProvider(key, JoseConstants.HMAC_SHA_256_ALGO), protectedHeader); + assertEquals(jsonProducer.getJwsJsonSignedDocument(), HMAC_JSON_FLATTENED_SERIALIZATION); + jsonConsumer = new JwsJsonConsumer(jsonProducer.getJwsJsonSignedDocument()); + assertTrue(jsonConsumer.verifySignatureWith(key, JoseConstants.HMAC_SHA_256_ALGO)); + } + @Test + public void testDetachedHMACSignature() throws Exception { + JwsCompactProducer compactProducer = new JwsCompactProducer(PAYLOAD); + compactProducer.getJoseHeaders().setAlgorithm(JoseConstants.HMAC_SHA_256_ALGO); + compactProducer.getJoseHeaders().setKeyId(HMAC_KID_VALUE); + JsonMapObjectReaderWriter reader = new JsonMapObjectReaderWriter(); + assertEquals(reader.toJson(compactProducer.getJoseHeaders().asMap()), HMAC_SIGNATURE_PROTECTED_HEADER_JSON); + assertEquals(compactProducer.getUnsignedEncodedJws(), + HMAC_SIGNATURE_PROTECTED_HEADER + "." + ENCODED_PAYLOAD); + JsonWebKeys jwks = readKeySet("cookbookSecretSet.txt"); + List<JsonWebKey> keys = jwks.getKeys(); + JsonWebKey key = keys.get(0); + compactProducer.signWith(key); + assertEquals(compactProducer.getSignedEncodedJws(true), DETACHED_HMAC_JWS); + JwsCompactConsumer compactConsumer = + new JwsCompactConsumer(compactProducer.getSignedEncodedJws(true), ENCODED_PAYLOAD); + assertTrue(compactConsumer.verifySignatureWith(key, JoseConstants.HMAC_SHA_256_ALGO)); + + JwsJsonProducer jsonProducer = new JwsJsonProducer(PAYLOAD); + assertEquals(jsonProducer.getPlainPayload(), PAYLOAD); + assertEquals(jsonProducer.getUnsignedEncodedPayload(), ENCODED_PAYLOAD); + JoseHeaders joseHeaders = new JoseHeaders(); + joseHeaders.setAlgorithm(JoseConstants.HMAC_SHA_256_ALGO); + joseHeaders.setKeyId(HMAC_KID_VALUE); + JwsJsonProtectedHeader protectedHeader = new JwsJsonProtectedHeader(joseHeaders); + jsonProducer.signWith(JwsUtils.getSignatureProvider(key, JoseConstants.HMAC_SHA_256_ALGO), protectedHeader); + assertEquals(jsonProducer.getJwsJsonSignedDocument(true), HMAC_DETACHED_JSON_GENERAL_SERIALIZATION); + JwsJsonConsumer jsonConsumer = + new JwsJsonConsumer(jsonProducer.getJwsJsonSignedDocument(true), ENCODED_PAYLOAD); + assertTrue(jsonConsumer.verifySignatureWith(key, JoseConstants.HMAC_SHA_256_ALGO)); + + jsonProducer = new JwsJsonProducer(PAYLOAD, true); + jsonProducer.signWith(JwsUtils.getSignatureProvider(key, JoseConstants.HMAC_SHA_256_ALGO), protectedHeader); + assertEquals(jsonProducer.getJwsJsonSignedDocument(true), HMAC_DETACHED_JSON_FLATTENED_SERIALIZATION); + jsonConsumer = new JwsJsonConsumer(jsonProducer.getJwsJsonSignedDocument(true), ENCODED_PAYLOAD); + assertTrue(jsonConsumer.verifySignatureWith(key, JoseConstants.HMAC_SHA_256_ALGO)); + } public JsonWebKeys readKeySet(String fileName) throws Exception { InputStream is = JwsJoseCookBookTest.class.getResourceAsStream(fileName); String s = IOUtils.readStringFromStream(is);
