From e380d85ad7ac35a650e9d8bed7c1ccad1fc55d7a Mon Sep 17 00:00:00 2001 From: Mike Derryberry Date: Mon, 16 Jul 2012 15:46:31 -0400 Subject: [PATCH] updated encryption/decryption to dynamically get mode for cipher. also made the keyDataLen come from the kdf parameter rather than enc --- openid-connect-common/encryptedJwe.txt | 1 - .../jwt/encryption/AbstractJweDecrypter.java | 10 ++-------- .../jwt/encryption/AbstractJweEncrypter.java | 9 +-------- .../mitre/jwt/encryption/impl/RsaDecrypter.java | 13 ++++++++----- .../mitre/jwt/encryption/impl/RsaEncrypter.java | 15 +++++++++------ .../org/mitre/jwt/signer/AbstractJwtSigner.java | 7 ++++--- .../src/test/resources/jwe/jweHeader | 2 +- 7 files changed, 25 insertions(+), 32 deletions(-) delete mode 100644 openid-connect-common/encryptedJwe.txt diff --git a/openid-connect-common/encryptedJwe.txt b/openid-connect-common/encryptedJwe.txt deleted file mode 100644 index a35dd21b3..000000000 --- a/openid-connect-common/encryptedJwe.txt +++ /dev/null @@ -1 +0,0 @@ -eyJpbnQiOiJIUzI1NiIsIml2IjoiQXhZOERDdERhR2xzYkdsamIzUm9aUSIsImFsZyI6IkhTMjU2IiwiZW5jIjoiQTEyOENCQyJ9.1TWc1U58WUtz6HnRVfFcCFt04dWJivMZmTG3ZeIUKbfWbG6UHsYRNnj1a9LvYpb7DA97j57whfXxxwT9P3ZnCMaeqm_JCmyasocu7ftefELw4BSYcBuIGeiOzZO7mffS4lj5s7N76kV-LXkVIMwjzKom1z1doBqnmV7M5yUCTnxQJ3ao7LYLJI0QiCY5Pcqd.CS8GW8JLnDAF4SEvw2kras0yp50-eIX90Mbn1qKF1cePqG3VWcItEJoPa0FbFbmj.0uQ48_WFcQR-q6IBcs8IG-DquLi17kbeXjqKRANr0Hw diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/encryption/AbstractJweDecrypter.java b/openid-connect-common/src/main/java/org/mitre/jwt/encryption/AbstractJweDecrypter.java index 658004c3c..145768e3e 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/encryption/AbstractJweDecrypter.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/encryption/AbstractJweDecrypter.java @@ -13,15 +13,9 @@ public abstract class AbstractJweDecrypter implements JwtDecrypter { MessageDigest md = null; //HUGE DISCLAIMER: this won't work on windows machines that don't have jce unlimited security files installed. //without it, keys can't be over 128 bit in length, and SHA-128 doesn't work for message digest. - - //SHA-128 is not a valid instance, therefore change to 256 - if(keyDataLen == 128){ - md = MessageDigest.getInstance("SHA-256"); - } + //use keyDataLen to determine instance - else { - md = MessageDigest.getInstance("SHA-" + Integer.toString(keyDataLen)); - } + md = MessageDigest.getInstance("SHA-" + Integer.toString(keyDataLen)); keyDataLen = keyDataLen / 8; byte[] key = new byte[keyDataLen]; diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/encryption/AbstractJweEncrypter.java b/openid-connect-common/src/main/java/org/mitre/jwt/encryption/AbstractJweEncrypter.java index ad83bc662..a71a4a9e0 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/encryption/AbstractJweEncrypter.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/encryption/AbstractJweEncrypter.java @@ -11,14 +11,8 @@ public abstract class AbstractJweEncrypter implements JwtEncrypter { //HUGE DISCLAIMER: this won't work on windows machines that don't have jce unlimited security files installed. //without it, keys can't be over 128 bit in length, and SHA-128 doesn't work for message digest. - //SHA-128 is not a valid instance, therefore change to 256 - if(keyDataLen == 128){ - md = MessageDigest.getInstance("SHA-256"); - } //Use keyDataLen to determine instance - else { - md = MessageDigest.getInstance("SHA-" + Integer.toString(keyDataLen)); - } + md = MessageDigest.getInstance("SHA-" + Integer.toString(keyDataLen)); long MAX_HASH_INPUTLEN = Long.MAX_VALUE; long UNSIGNED_INT_MAX_VALUE = 4294967395L; @@ -60,5 +54,4 @@ public abstract class AbstractJweEncrypter implements JwtEncrypter { return res; } - } diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/encryption/impl/RsaDecrypter.java b/openid-connect-common/src/main/java/org/mitre/jwt/encryption/impl/RsaDecrypter.java index 516b58ba2..7057758ec 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/encryption/impl/RsaDecrypter.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/encryption/impl/RsaDecrypter.java @@ -39,9 +39,9 @@ public class RsaDecrypter extends AbstractJweDecrypter { byte[] contentEncryptionKey = null; byte[] contentIntegrityKey = null; //check what the key length is - String encMethod = jwe.getHeader().getEncryptionMethod(); + String encMethod = jwe.getHeader().getKeyDerivationFunction(); char[] array = encMethod.toCharArray(); - String keyBitLengthString = String.copyValueOf(array, 1, 3); + String keyBitLengthString = new String("" + array[2] + array[3] + array[4]); int keyBitLength = Integer.parseInt(keyBitLengthString); //generate cek and cik contentEncryptionKey = generateContentKey(jwe.getEncryptedKey(), keyBitLength, "Encryption".getBytes()); @@ -79,10 +79,13 @@ public class RsaDecrypter extends AbstractJweDecrypter { iv = Base64.decodeBase64(jwe.getHeader().getInitializationVector()); String encMethod = jwe.getHeader().getEncryptionMethod(); - - if(encMethod.equals("A128CBC") || encMethod.equals("A256CBC") || encMethod.equals("A128GCM") || encMethod.equals("A256GCM")) { + //TODO: should also check for A128GCM and A256GCM, but Cipher.getInstance() does not support the GCM mode. For now, don't use them + if(encMethod.equals("A128CBC") || encMethod.equals("A256CBC")) { - Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + String delims = "[8,6]+"; + String[] mode = encMethod.split(delims); + + Cipher cipher = Cipher.getInstance("AES/" + mode[1] + "/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(contentEncryptionKey, "AES"), new IvParameterSpec(iv)); byte[] clearText = cipher.doFinal(jwe.getCiphertext()); diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/encryption/impl/RsaEncrypter.java b/openid-connect-common/src/main/java/org/mitre/jwt/encryption/impl/RsaEncrypter.java index a4bcda866..fbc09ee55 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/encryption/impl/RsaEncrypter.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/encryption/impl/RsaEncrypter.java @@ -36,9 +36,9 @@ public class RsaEncrypter extends AbstractJweEncrypter { //generate random content master key //check what the key length is - String encMethod = jwe.getHeader().getEncryptionMethod(); + String encMethod = jwe.getHeader().getKeyDerivationFunction(); char[] array = encMethod.toCharArray(); - String keyBitLengthString = String.copyValueOf(array, 1, 3); + String keyBitLengthString = new String("" + array[2] + array[3] + array[4]); int keyBitLength = Integer.parseInt(keyBitLengthString); byte[] contentMasterKey = new byte[keyBitLength]; @@ -99,10 +99,13 @@ public class RsaEncrypter extends AbstractJweEncrypter { } String encMethod = jwe.getHeader().getEncryptionMethod(); - - if(encMethod.equals("A128CBC") || encMethod.equals("A256CBC") || encMethod.equals("A128GCM") || encMethod.equals("A256GCM")) { - - Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + //TODO: should also check for A128GCM and A256GCM, but Cipher.getInstance() does not support the GCM mode. For now, don't use them + if(encMethod.equals("A128CBC") || encMethod.equals("A256CBC")) { + + String delims = "[8,6]+"; + String[] mode = encMethod.split(delims); + + Cipher cipher = Cipher.getInstance("AES/" + mode[1] + "/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(contentEncryptionKey, "AES"), new IvParameterSpec(iv)); byte[] cipherText = cipher.doFinal(jwe.getCiphertext()); return cipherText; diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/AbstractJwtSigner.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/AbstractJwtSigner.java index 6d889d3a2..ec8deaa9b 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/AbstractJwtSigner.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/AbstractJwtSigner.java @@ -57,14 +57,15 @@ public abstract class AbstractJwtSigner implements JwtSigner { */ @Override public Jwt sign(Jwt jwt) throws NoSuchAlgorithmException { - //TODO: this check changes the algorithm param of a jwe to the int param. not sure why? + + //TODO: need a seperate check for Jwe. As is, it will change the alg param to be the enc param /*if (!Objects.equal(algorithm, jwt.getHeader().getAlgorithm())) { // algorithm type doesn't match // TODO: should this be an error or should we just fix it in the incoming jwt? // for now, we fix the Jwt jwt.getHeader().setAlgorithm(algorithm); - }*/ - + }*/ + String sig = generateSignature(jwt.getSignatureBase()); jwt.setSignature(sig); diff --git a/openid-connect-common/src/test/resources/jwe/jweHeader b/openid-connect-common/src/test/resources/jwe/jweHeader index c8566eae5..6a06d9b14 100644 --- a/openid-connect-common/src/test/resources/jwe/jweHeader +++ b/openid-connect-common/src/test/resources/jwe/jweHeader @@ -1 +1 @@ -{"alg":"RSA1_5","enc":"A128CBC","int":"HS384","iv":"AxY8DCtDaGlsbGljb3RoZQ"} \ No newline at end of file +{"alg":"RSA1_5","enc":"A256CBC","int":"HS384","iv":"AxY8DCtDaGlsbGljb3RoZQ","kdf":"CS256"} \ No newline at end of file