Repository: cxf Updated Branches: refs/heads/master 50cb750c6 -> b5409a6d6
[CXF-5311] Optional support for auto-generating content-encryption key and IV Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/b5409a6d Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/b5409a6d Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/b5409a6d Branch: refs/heads/master Commit: b5409a6d64ab223097456004fe05a5cad1dd1a4e Parents: 50cb750 Author: Sergey Beryozkin <[email protected]> Authored: Fri May 23 13:54:35 2014 +0100 Committer: Sergey Beryozkin <[email protected]> Committed: Fri May 23 13:54:35 2014 +0100 ---------------------------------------------------------------------- .../rs/security/oauth2/jwe/JweEncryptor.java | 57 +++++++++++++------- .../cxf/rs/security/oauth2/jwe/JweHeaders.java | 11 +++- .../rs/security/oauth2/jwe/RSAJweEncryptor.java | 10 ++-- .../cxf/rs/security/oauth2/jwt/Algorithm.java | 30 ++++++----- .../oauth2/utils/crypto/CryptoUtils.java | 7 +++ 5 files changed, 79 insertions(+), 36 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/b5409a6d/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweEncryptor.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweEncryptor.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweEncryptor.java index cb6aabb..98a8f73 100644 --- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweEncryptor.java +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweEncryptor.java @@ -29,24 +29,36 @@ import org.apache.cxf.rs.security.oauth2.utils.crypto.CryptoUtils; import org.apache.cxf.rs.security.oauth2.utils.crypto.KeyProperties; public class JweEncryptor { + protected static final int DEFAULT_IV_SIZE = 96; + protected static final int DEFAULT_AUTH_TAG_LENGTH = 128; private Key cekEncryptionKey; private JweHeaders headers; private JwtHeadersWriter writer = new JwtTokenReaderWriter(); private byte[] cek; private byte[] iv; - private int authTagLen; + private int authTagLen = DEFAULT_AUTH_TAG_LENGTH; private boolean wrap; - public JweEncryptor(JweHeaders headers, byte[] iv, int authTagLen) { + public JweEncryptor(String contentEncryptionAlgo, byte[] cek) { + this(new JweHeaders(contentEncryptionAlgo), cek); + } + public JweEncryptor(JweHeaders headers, byte[] cek) { this.headers = headers; + this.cek = cek; + } + public JweEncryptor(JweHeaders headers, byte[] cek, byte[] iv, int authTagLen) { + this(headers, cek); this.iv = iv; this.authTagLen = authTagLen; } + public JweEncryptor(JweHeaders headers, Key cekEncryptionKey) { + this.headers = headers; + this.cekEncryptionKey = cekEncryptionKey; + } public JweEncryptor(JweHeaders headers, Key cekEncryptionKey, byte[] cek, byte[] iv, int authTagLen, boolean wrap) { - this(headers, iv, authTagLen); + this(headers, cek, iv, authTagLen); this.cekEncryptionKey = cekEncryptionKey; - this.cek = cek; this.wrap = wrap; } public JweEncryptor(JweHeaders headers, Key cekEncryptionKey, byte[] cek, byte[] iv, int authTagLen, @@ -57,28 +69,32 @@ public class JweEncryptor { } } - protected AlgorithmParameterSpec getContentEncryptionCipherSpec() { - return CryptoUtils.getContentEncryptionCipherSpec(getAuthTagLen(), getIv()); + protected AlgorithmParameterSpec getContentEncryptionCipherSpec(byte[] theIv) { + return CryptoUtils.getContentEncryptionCipherSpec(getAuthTagLen(), theIv); } - protected byte[] getIv() { - return iv; + protected byte[] getContentEncryptionCipherInitVector() { + return iv == null ? CryptoUtils.generateSecureRandomBytes(DEFAULT_IV_SIZE) : iv; } - protected byte[] cek() { - return cek; + protected byte[] getContentEncryptionKey() { + if (cek == null && cekEncryptionKey != null) { + String algo = headers.getContentEncryptionAlgorithm(); + return CryptoUtils.generateSecureRandomBytes(Algorithm.valueOf(algo).getKeySizeBits() / 8); + } else { + return cek; + } } - protected byte[] getEncryptedContentEncryptionKey() { - if (cekEncryptionKey == null) { - // direct key encryption + protected byte[] getEncryptedContentEncryptionKey(byte[] theCek) { + if (theCek == null) { return new byte[]{}; } else { KeyProperties secretKeyProperties = new KeyProperties(getContentEncryptionKeyEncryptionAlgo()); if (!wrap) { - return CryptoUtils.encryptBytes(cek, cekEncryptionKey, secretKeyProperties); + return CryptoUtils.encryptBytes(theCek, cekEncryptionKey, secretKeyProperties); } else { - return CryptoUtils.wrapSecretKey(cek, getContentEncryptionAlgo(), cekEncryptionKey, + return CryptoUtils.wrapSecretKey(theCek, getContentEncryptionAlgo(), cekEncryptionKey, secretKeyProperties.getKeyAlgo()); } } @@ -96,23 +112,26 @@ public class JweEncryptor { } public String getJweContent(byte[] content) { - byte[] jweContentEncryptionKey = getEncryptedContentEncryptionKey(); + byte[] theCek = getContentEncryptionKey(); + byte[] jweContentEncryptionKey = getEncryptedContentEncryptionKey(theCek); String contentEncryptionAlgoJavaName = Algorithm.toJavaName(headers.getContentEncryptionAlgorithm()); KeyProperties keyProps = new KeyProperties(contentEncryptionAlgoJavaName); byte[] additionalEncryptionParam = headers.toCipherAdditionalAuthData(writer); keyProps.setAdditionalData(additionalEncryptionParam); - AlgorithmParameterSpec specParams = getContentEncryptionCipherSpec(); + + byte[] theIv = getContentEncryptionCipherInitVector(); + AlgorithmParameterSpec specParams = getContentEncryptionCipherSpec(theIv); keyProps.setAlgoSpec(specParams); byte[] cipherText = CryptoUtils.encryptBytes( content, - CryptoUtils.createSecretKeySpec(cek, contentEncryptionAlgoJavaName), + CryptoUtils.createSecretKeySpec(theCek, contentEncryptionAlgoJavaName), keyProps); JweCompactProducer producer = new JweCompactProducer(headers, jweContentEncryptionKey, - iv, + theIv, cipherText, getAuthTagLen()); return producer.getJweContent(); http://git-wip-us.apache.org/repos/asf/cxf/blob/b5409a6d/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweHeaders.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweHeaders.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweHeaders.java index de4395e..d3806c8 100644 --- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweHeaders.java +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/JweHeaders.java @@ -41,12 +41,19 @@ public class JweHeaders extends JwtHeaders { public JweHeaders(String keyEncAlgo, String ctEncAlgo) { this(keyEncAlgo, ctEncAlgo, false); } + public JweHeaders(String ctEncAlgo) { + this(null, ctEncAlgo, false); + } + public JweHeaders(String ctEncAlgo, boolean deflate) { + this(null, ctEncAlgo, deflate); + } public JweHeaders(String keyEncAlgo, String ctEncAlgo, boolean deflate) { init(keyEncAlgo, ctEncAlgo, deflate); } - private void init(String keyEncAlgo, String ctEncAlgo, boolean deflate) { - setKeyEncryptionAlgorithm(keyEncAlgo); + if (keyEncAlgo != null) { + setKeyEncryptionAlgorithm(keyEncAlgo); + } setContentEncryptionAlgorithm(ctEncAlgo); if (deflate) { setZipAlgorithm(JwtConstants.DEFLATE_ZIP_ALGORITHM); http://git-wip-us.apache.org/repos/asf/cxf/blob/b5409a6d/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/RSAJweEncryptor.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/RSAJweEncryptor.java b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/RSAJweEncryptor.java index 44557b8..387a19e 100644 --- a/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/RSAJweEncryptor.java +++ b/rt/rs/security/oauth-parent/oauth2-jwt/src/main/java/org/apache/cxf/rs/security/oauth2/jwe/RSAJweEncryptor.java @@ -26,14 +26,18 @@ import org.apache.cxf.rs.security.oauth2.jwt.Algorithm; import org.apache.cxf.rs.security.oauth2.jwt.JwtHeadersWriter; public class RSAJweEncryptor extends JweEncryptor { + public RSAJweEncryptor(RSAPrivateKey privateKey, String contentEncryptionAlgo) { + super(new JweHeaders(Algorithm.RSA_OAEP_ALGO.getJwtName(), + contentEncryptionAlgo), privateKey); + } public RSAJweEncryptor(RSAPrivateKey privateKey, JweHeaders headers, byte[] cek, byte[] iv) { - this(privateKey, headers, cek, iv, 128, true); + this(privateKey, headers, cek, iv, DEFAULT_AUTH_TAG_LENGTH, true); } public RSAJweEncryptor(RSAPrivateKey privateKey, SecretKey secretKey, byte[] iv) { this(privateKey, new JweHeaders(Algorithm.RSA_OAEP_ALGO.getJwtName(), Algorithm.toJwtName(secretKey.getAlgorithm())), - secretKey.getEncoded(), iv, 128, true); + secretKey.getEncoded(), iv, DEFAULT_AUTH_TAG_LENGTH, true); } public RSAJweEncryptor(RSAPrivateKey privateKey, JweHeaders headers, byte[] cek, byte[] iv, @@ -43,7 +47,7 @@ public class RSAJweEncryptor extends JweEncryptor { public RSAJweEncryptor(RSAPrivateKey privateKey, JweHeaders headers, byte[] cek, byte[] iv, JwtHeadersWriter writer) { - this(privateKey, headers, cek, iv, 128, true, null); + this(privateKey, headers, cek, iv, DEFAULT_AUTH_TAG_LENGTH, true, null); } public RSAJweEncryptor(RSAPrivateKey privateKey, JweHeaders headers, byte[] cek, byte[] iv, int authTagLen, boolean wrap, JwtHeadersWriter writer) { http://git-wip-us.apache.org/repos/asf/cxf/blob/b5409a6d/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 3856eeb..3c08e8e 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 @@ -27,18 +27,18 @@ import java.util.Map; public enum Algorithm { // Signature - HmacSHA256(JwtConstants.HMAC_SHA_256_ALGO), - HmacSHA384(JwtConstants.HMAC_SHA_384_ALGO), - HmacSHA512(JwtConstants.HMAC_SHA_512_ALGO), + HmacSHA256(JwtConstants.HMAC_SHA_256_ALGO, 256), + HmacSHA384(JwtConstants.HMAC_SHA_384_ALGO, 384), + HmacSHA512(JwtConstants.HMAC_SHA_512_ALGO, 512), - SHA256withRSA(JwtConstants.RS_SHA_256_ALGO), - SHA384withRSA(JwtConstants.RS_SHA_384_ALGO), - SHA512withRSA(JwtConstants.RS_SHA_512_ALGO), + SHA256withRSA(JwtConstants.RS_SHA_256_ALGO, 256), + SHA384withRSA(JwtConstants.RS_SHA_384_ALGO, 384), + SHA512withRSA(JwtConstants.RS_SHA_512_ALGO, 512), // Key Encryption - RSA_OAEP_ALGO(JwtConstants.RSA_OAEP_ALGO, "RSA/ECB/OAEPWithSHA-1AndMGF1Padding"), + RSA_OAEP_ALGO(JwtConstants.RSA_OAEP_ALGO, "RSA/ECB/OAEPWithSHA-1AndMGF1Padding", -1), // Content Encryption - A256GCM_ALGO(JwtConstants.A256GCM_ALGO, "AES/GCM/NoPadding"); + A256GCM_ALGO(JwtConstants.A256GCM_ALGO, "AES/GCM/NoPadding", 256); public static final String HMAC_SHA_256_JAVA = "HmacSHA256"; public static final String HMAC_SHA_384_JAVA = "HmacSHA384"; @@ -73,13 +73,15 @@ public enum Algorithm { } private final String jwtName; private final String javaName; - - private Algorithm(String jwtName) { - this(jwtName, null); + private final int keySizeBits; + + private Algorithm(String jwtName, int keySizeBits) { + this(jwtName, null, keySizeBits); } - private Algorithm(String jwtName, String javaName) { + private Algorithm(String jwtName, String javaName, int keySizeBits) { this.jwtName = jwtName; this.javaName = javaName; + this.keySizeBits = keySizeBits; } public String getJwtName() { @@ -90,6 +92,10 @@ public enum Algorithm { return javaName == null ? name() : javaName; } + public int getKeySizeBits() { + return keySizeBits; + } + public static String toJwtName(String javaName) { return JAVA_TO_JWT_NAMES.get(javaName); } http://git-wip-us.apache.org/repos/asf/cxf/blob/b5409a6d/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/crypto/CryptoUtils.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/crypto/CryptoUtils.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/crypto/CryptoUtils.java index 1039d9e..0a408fc 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/crypto/CryptoUtils.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/crypto/CryptoUtils.java @@ -71,6 +71,13 @@ public final class CryptoUtils { return encodeBytes(encryptedBytes); } + public static byte[] generateSecureRandomBytes(int size) { + SecureRandom sr = new SecureRandom(); + byte[] bytes = new byte[size]; + sr.nextBytes(bytes); + return bytes; + } + public static RSAPublicKey getRSAPublicKey(String encodedModulus, String encodedPublicExponent) { try {
