Return-Path: X-Original-To: apmail-cxf-commits-archive@www.apache.org Delivered-To: apmail-cxf-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id D5EB811225 for ; Thu, 24 Jul 2014 13:33:34 +0000 (UTC) Received: (qmail 93799 invoked by uid 500); 24 Jul 2014 13:33:34 -0000 Delivered-To: apmail-cxf-commits-archive@cxf.apache.org Received: (qmail 93742 invoked by uid 500); 24 Jul 2014 13:33:34 -0000 Mailing-List: contact commits-help@cxf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cxf.apache.org Delivered-To: mailing list commits@cxf.apache.org Received: (qmail 93733 invoked by uid 99); 24 Jul 2014 13:33:34 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 24 Jul 2014 13:33:34 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 428E89B2A9A; Thu, 24 Jul 2014 13:33:34 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: sergeyb@apache.org To: commits@cxf.apache.org Message-Id: <771596193732495e9a1f9294a5cfefcd@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: git commit: [CXF-5902] Initial test code, to be optimized later Date: Thu, 24 Jul 2014 13:33:34 +0000 (UTC) Repository: cxf Updated Branches: refs/heads/3.0.x-fixes adf6a5b70 -> d607ef353 [CXF-5902] Initial test code, to be optimized later Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/d607ef35 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/d607ef35 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/d607ef35 Branch: refs/heads/3.0.x-fixes Commit: d607ef3537456f2aea1b661f6c5906743e5786b7 Parents: adf6a5b Author: Sergey Beryozkin Authored: Thu Jul 24 16:26:35 2014 +0300 Committer: Sergey Beryozkin Committed: Thu Jul 24 16:32:52 2014 +0300 ---------------------------------------------------------------------- .../cxf/rs/security/oauth2/jwt/Algorithm.java | 21 +++++- .../rs/security/oauth2/jwt/JwtConstants.java | 9 +++ .../oauth2/jwe/JweCompactReaderWriterTest.java | 73 ++++++++++++++++++++ 3 files changed, 102 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/d607ef35/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/Algorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/Algorithm.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/Algorithm.java index 19382db..4f115a7 100644 --- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/Algorithm.java +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/Algorithm.java @@ -41,10 +41,18 @@ public enum Algorithm { // Key Encryption RSA_OAEP(JwtConstants.RSA_OAEP_ALGO, "RSA/ECB/OAEPWithSHA-1AndMGF1Padding", -1), + RSA_OAEP_256(JwtConstants.RSA_OAEP_256_ALGO, "RSA/ECB/OAEPWithSHA-256AndMGF1Padding", -1), + RSA_1_5(JwtConstants.RSA_1_5_ALGO, "RSA/ECB/PKCS1Padding", -1), + A128KW(JwtConstants.A128KW_ALGO, "AESWrap", 128), + A192KW(JwtConstants.A192KW_ALGO, "AESWrap", 192), + A256KW(JwtConstants.A256KW_ALGO, "AESWrap", 256), // Content Encryption A128GCM(JwtConstants.A128GCM_ALGO, "AES/GCM/NoPadding", 128), A192GCM(JwtConstants.A192GCM_ALGO, "AES/GCM/NoPadding", 192), - A256GCM(JwtConstants.A256GCM_ALGO, "AES/GCM/NoPadding", 256); + A256GCM(JwtConstants.A256GCM_ALGO, "AES/GCM/NoPadding", 256), + A128CBC_HS256(JwtConstants.A128CBC_HS256_ALGO, "AES/CBC/PKCS7Padding", 128), + A192CBC_HS354(JwtConstants.A192CBC_HS354_ALGO, "AES/CBC/PKCS7Padding", 192), + A256CBC_HS512(JwtConstants.A256CBC_HS512_ALGO, "AES/CBC/PKCS7Padding", 256); public static final String HMAC_SHA_256_JAVA = "HmacSHA256"; public static final String HMAC_SHA_384_JAVA = "HmacSHA384"; @@ -59,7 +67,9 @@ public enum Algorithm { public static final String RSA_OAEP_256_ALGO_JAVA = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding"; public static final String RSA_1_5_ALGO_JAVA = "RSA/ECB/PKCS1Padding"; public static final String AES_ALGO_JAVA = "AES"; + public static final String AES_WRAP_ALGO_JAVA = "AESWrap"; public static final String AES_GCM_ALGO_JAVA = "AES/GCM/NoPadding"; + public static final String AES_CBC_ALGO_JAVA = "AES/CBC/PKCS7Padding"; private static final Map JAVA_TO_JWT_NAMES; private static final Map JWT_TO_JAVA_NAMES; @@ -77,6 +87,12 @@ public enum Algorithm { JAVA_TO_JWT_NAMES.put(RSA_OAEP_ALGO_JAVA, JwtConstants.RSA_OAEP_ALGO); JAVA_TO_JWT_NAMES.put(RSA_OAEP_256_ALGO_JAVA, JwtConstants.RSA_OAEP_256_ALGO); JAVA_TO_JWT_NAMES.put(RSA_1_5_ALGO_JAVA, JwtConstants.RSA_1_5_ALGO); + JAVA_TO_JWT_NAMES.put(AES_GCM_ALGO_JAVA, JwtConstants.A256GCM_ALGO); + JAVA_TO_JWT_NAMES.put(AES_GCM_ALGO_JAVA, JwtConstants.A192GCM_ALGO); + JAVA_TO_JWT_NAMES.put(AES_GCM_ALGO_JAVA, JwtConstants.A128GCM_ALGO); + JAVA_TO_JWT_NAMES.put(AES_CBC_ALGO_JAVA, JwtConstants.A128CBC_HS256_ALGO); + JAVA_TO_JWT_NAMES.put(AES_CBC_ALGO_JAVA, JwtConstants.A192CBC_HS354_ALGO); + JAVA_TO_JWT_NAMES.put(AES_CBC_ALGO_JAVA, JwtConstants.A256CBC_HS512_ALGO); JWT_TO_JAVA_NAMES = new HashMap(); JWT_TO_JAVA_NAMES.put(JwtConstants.HMAC_SHA_256_ALGO, HMAC_SHA_256_JAVA); JWT_TO_JAVA_NAMES.put(JwtConstants.HMAC_SHA_384_ALGO, HMAC_SHA_384_JAVA); @@ -93,6 +109,9 @@ public enum Algorithm { JWT_TO_JAVA_NAMES.put(JwtConstants.A256GCM_ALGO, AES_GCM_ALGO_JAVA); JWT_TO_JAVA_NAMES.put(JwtConstants.A192GCM_ALGO, AES_GCM_ALGO_JAVA); JWT_TO_JAVA_NAMES.put(JwtConstants.A128GCM_ALGO, AES_GCM_ALGO_JAVA); + JWT_TO_JAVA_NAMES.put(JwtConstants.A128CBC_HS256_ALGO, AES_CBC_ALGO_JAVA); + JWT_TO_JAVA_NAMES.put(JwtConstants.A192CBC_HS354_ALGO, AES_CBC_ALGO_JAVA); + JWT_TO_JAVA_NAMES.put(JwtConstants.A256CBC_HS512_ALGO, AES_CBC_ALGO_JAVA); } private final String jwtName; private final String javaName; http://git-wip-us.apache.org/repos/asf/cxf/blob/d607ef35/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/JwtConstants.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/JwtConstants.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/JwtConstants.java index e6eee3d..0356fab 100644 --- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/JwtConstants.java +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwt/JwtConstants.java @@ -60,10 +60,19 @@ public final class JwtConstants { public static final String ES_SHA_256_ALGO = "ES256"; public static final String ES_SHA_384_ALGO = "ES384"; public static final String ES_SHA_512_ALGO = "ES512"; + + // Key Encryption public static final String RSA_OAEP_ALGO = "RSA-OAEP"; public static final String RSA_OAEP_256_ALGO = "RSA-OAEP-256"; public static final String RSA_1_5_ALGO = "RSA1_5"; + public static final String A128KW_ALGO = "A128KW"; + public static final String A192KW_ALGO = "A192KW"; + public static final String A256KW_ALGO = "A256KW"; + // Content Encryption + public static final String A128CBC_HS256_ALGO = "A128CBC-HS256"; + public static final String A192CBC_HS354_ALGO = "A192CBC-HS354"; + public static final String A256CBC_HS512_ALGO = "A256CBC-HS512"; public static final String A128GCM_ALGO = "A128GCM"; public static final String A192GCM_ALGO = "A192GCM"; public static final String A256GCM_ALGO = "A256GCM"; http://git-wip-us.apache.org/repos/asf/cxf/blob/d607ef35/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jwe/JweCompactReaderWriterTest.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jwe/JweCompactReaderWriterTest.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jwe/JweCompactReaderWriterTest.java index ec7506b..5ec0115 100644 --- a/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jwe/JweCompactReaderWriterTest.java +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/test/java/org/apache/cxf/rs/security/oauth2/jwe/JweCompactReaderWriterTest.java @@ -18,16 +18,24 @@ */ package org.apache.cxf.rs.security.oauth2.jwe; +import java.math.BigInteger; +import java.nio.ByteBuffer; import java.security.Security; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import javax.crypto.Cipher; +import javax.crypto.Mac; import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; import org.apache.cxf.rs.security.oauth2.jws.JwsCompactReaderWriterTest; import org.apache.cxf.rs.security.oauth2.jwt.Algorithm; +import org.apache.cxf.rs.security.oauth2.jwt.JwtTokenReaderWriter; +import org.apache.cxf.rs.security.oauth2.utils.Base64UrlUtility; import org.apache.cxf.rs.security.oauth2.utils.crypto.CryptoUtils; +import org.apache.cxf.rs.security.oauth2.utils.crypto.HmacUtils; +import org.apache.cxf.rs.security.oauth2.utils.crypto.KeyProperties; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.junit.AfterClass; @@ -41,6 +49,21 @@ public class JweCompactReaderWriterTest extends Assert { 115, 63, (byte)180, 3, (byte)255, 107, (byte)154, (byte)212, (byte)246, (byte)138, 7, 110, 91, 112, 46, 34, 105, 47, (byte)130, (byte)203, 46, 122, (byte)234, 64, (byte)252}; + + private static final byte[] CONTENT_ENCRYPTION_KEY_A3 = { + 4, (byte)211, 31, (byte)197, 84, (byte)157, (byte)252, (byte)254, 11, 100, + (byte)157, (byte)250, 63, (byte)170, 106, (byte)206, 107, 124, (byte)212, + 45, 111, 107, 9, (byte)219, (byte)200, (byte)177, 0, (byte)240, (byte)143, + (byte)156, 44, (byte)207}; + private static final byte[] INIT_VECTOR_A3 = { + 3, 22, 60, 12, 43, 67, 104, 105, 108, 108, 105, 99, 111, 116, 104, 101}; + private static final String KEY_ENCRYPTION_KEY_A3 = "GawgguFyGrWKav7AX4VKUg"; + private static final String JWE_OUTPUT_A3 = + "eyJhbGciOiJBMTI4S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0" + + ".6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ" + + ".AxY8DCtDaGlsbGljb3RoZQ" + + ".KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY" + + ".U0m_YmjN04DJvceFICbCVQ"; private static final String RSA_MODULUS_ENCODED = "oahUIoWw0K0usKNuOR6H4wkf4oBUXHTxRvgb48E-BVvxkeDNjbC4he8rUW" + "cJoZmds2h7M70imEVhRU5djINXtqllXI4DFqcI1DgjT9LewND8MW2Krf3S" + "psk_ZkoFnilakGygTwpZ3uesH-PFABNIUYpOiN15dsQRkgr0vEhxN92i2a" @@ -73,7 +96,56 @@ public class JweCompactReaderWriterTest extends Assert { public static void unregisterBouncyCastleIfNeeded() throws Exception { Security.removeProvider(BouncyCastleProvider.class.getName()); } + + @Test + public void testEncryptDecryptA128CBCHS256() throws Exception { + final String specPlainText = "Live long and prosper."; + byte[] macKey = new byte[16]; + System.arraycopy(CONTENT_ENCRYPTION_KEY_A3, 0, macKey, 0, 16); + byte[] encKey = new byte[16]; + System.arraycopy(CONTENT_ENCRYPTION_KEY_A3, 16, encKey, 0, 16); + SecretKey secretEncKey = + CryptoUtils.createSecretKeySpec(encKey, Algorithm.A128CBC_HS256.getJavaAlgoName()); + KeyProperties keyProps = new KeyProperties(Algorithm.AES_CBC_ALGO_JAVA); + keyProps.setAlgoSpec(new IvParameterSpec(INIT_VECTOR_A3)); + byte[] cipher = CryptoUtils.encryptBytes(specPlainText.getBytes("UTF-8"), secretEncKey, keyProps); + + JweHeaders headers = new JweHeaders(); + headers.setAlgorithm(Algorithm.A128KW.getJwtName()); + headers.setContentEncryptionAlgorithm(Algorithm.A128CBC_HS256.getJwtName()); + + SecretKey secretCompleteCek = CryptoUtils.createSecretKeySpec(CONTENT_ENCRYPTION_KEY_A3, + Algorithm.A128CBC_HS256.getJavaAlgoName()); + byte[] wrapperKeyBytes = Base64UrlUtility.decode(KEY_ENCRYPTION_KEY_A3); + SecretKey secretWrapperKey = + CryptoUtils.createSecretKeySpec(wrapperKeyBytes, Algorithm.A128KW.getJavaAlgoName()); + byte[] defaultAesWrapIv = new BigInteger("A6A6A6A6A6A6A6A6", 16).toByteArray(); + KeyProperties wrapperkeyProps = new KeyProperties(Algorithm.A128KW.getJavaName()); + keyProps.setAlgoSpec(new IvParameterSpec(defaultAesWrapIv)); + byte[] encryptedCek = CryptoUtils.wrapSecretKey(secretCompleteCek, secretWrapperKey, wrapperkeyProps); + byte[] aad = headers.toCipherAdditionalAuthData(new JwtTokenReaderWriter()); + ByteBuffer buf = ByteBuffer.allocate(8); + byte[] al = buf.putInt(0).putInt(aad.length * 8).array(); + + Mac mac = HmacUtils.getInitializedMac(macKey, Algorithm.HMAC_SHA_256_JAVA, null); + mac.update(aad); + mac.update(INIT_VECTOR_A3); + mac.update(cipher); + mac.update(al); + byte[] sig = mac.doFinal(); + assertEquals(32, sig.length); + byte[] authTag = new byte[16]; + System.arraycopy(sig, 0, authTag, 0, 16); + + JweCompactProducer p = new JweCompactProducer(headers, + encryptedCek, + INIT_VECTOR_A3, + cipher, + authTag); + assertEquals(JWE_OUTPUT_A3, p.getJweContent()); + } + @Test public void testEncryptDecryptSpecExample() throws Exception { final String specPlainText = "The true sign of intelligence is not knowledge but imagination."; @@ -81,6 +153,7 @@ public class JweCompactReaderWriterTest extends Assert { decrypt(jweContent, specPlainText, true); } + @Test public void testDirectKeyEncryptDecrypt() throws Exception { final String specPlainText = "The true sign of intelligence is not knowledge but imagination.";