updated encrypter and decrypter to use enum class rather than fragile parsing

pull/128/head
Mike Derryberry 2012-07-31 09:25:02 -04:00
parent 5f80ebc89a
commit 61c7231d9a
4 changed files with 31 additions and 37 deletions

View File

@ -1,5 +1,7 @@
package org.mitre.jwt.encryption;
import org.apache.commons.lang.StringUtils;
public enum JweAlgorithms {
//Key Derivation Function Values
@ -19,5 +21,19 @@ public enum JweAlgorithms {
JweAlgorithms(String value) {
this.value = value;
}
public static String getByName(String name) {
for (JweAlgorithms correspondingType : JweAlgorithms.values()) {
if (correspondingType.toString().equals(name)) {
return correspondingType.value;
}
}
throw new IllegalArgumentException(
"JweAlgorithm name " + name + " does not have a corresponding JweAlgorithm: expected one of [" + StringUtils.join(JweAlgorithms.values(), ", ") + "]");
}
public String getValue() {
return value;
}
}

View File

@ -15,7 +15,7 @@ import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.mitre.jwe.model.Jwe;
import org.mitre.jwt.encryption.AbstractJweDecrypter;
import org.mitre.jwt.signer.impl.HmacSigner;
import org.mitre.jwt.encryption.JweAlgorithms;
public class RsaDecrypter extends AbstractJweDecrypter {
@ -33,35 +33,16 @@ public class RsaDecrypter extends AbstractJweDecrypter {
//generation of cek and cik
byte[] contentEncryptionKey = null;
byte[] contentIntegrityKey = null;
//check what the key length is
String encMethod = jwe.getHeader().getKeyDerivationFunction();
char[] array = encMethod.toCharArray();
String keyBitLengthString = new String("" + array[2] + array[3] + array[4]);
int keyBitLength = Integer.parseInt(keyBitLengthString);
String kdf = jwe.getHeader().getKeyDerivationFunction();
String keyLength = JweAlgorithms.getByName(kdf);
int keyBitLength = Integer.parseInt(keyLength);
//generate cek and cik
contentEncryptionKey = generateContentKey(jwe.getEncryptedKey(), keyBitLength, "Encryption".getBytes());
contentIntegrityKey = generateContentKey(jwe.getEncryptedKey(), keyBitLength, "Integrity".getBytes());
//decrypt ciphertext to get claims
jwe.setCiphertext(decryptCipherText(jwe, contentEncryptionKey));
//generate signature for decrypted signature base in order to verify that decryption worked
/*String signature = null;
try {
HmacSigner hmacSigner = new HmacSigner(contentIntegrityKey);
signature = hmacSigner.generateSignature(jwe.getSignatureBase());
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//verifys that the signature base was decrypted correctly
if(signature != jwe.getSignature()){
throw new IllegalArgumentException("Didn't decrypt correctly. Decoded Sig and generated Sig do not match. " +
"Generated Signature is: " + signature + " while decoded sig is: " + jwe.getSignature());
}*/
} else {
throw new IllegalArgumentException(jwe.getHeader().getEncryptionMethod() + " is not a valid decrypting algorithm");
}
@ -78,10 +59,9 @@ public class RsaDecrypter extends AbstractJweDecrypter {
//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);
String mode = JweAlgorithms.getByName(encMethod);
Cipher cipher = Cipher.getInstance("AES/" + mode[1] + "/PKCS5Padding");
Cipher cipher = Cipher.getInstance("AES/" + mode + "/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(contentEncryptionKey, "AES"), new IvParameterSpec(iv));
byte[] clearText = cipher.doFinal(jwe.getCiphertext());

View File

@ -17,6 +17,7 @@ import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.mitre.jwe.model.Jwe;
import org.mitre.jwt.encryption.AbstractJweEncrypter;
import org.mitre.jwt.encryption.JweAlgorithms;
import org.mitre.jwt.signer.impl.HmacSigner;
public class RsaEncrypter extends AbstractJweEncrypter {
@ -31,10 +32,9 @@ public class RsaEncrypter extends AbstractJweEncrypter {
//generate random content master key
//check what the key length is
String encMethod = jwe.getHeader().getKeyDerivationFunction();
char[] array = encMethod.toCharArray();
String keyBitLengthString = new String("" + array[2] + array[3] + array[4]);
int keyBitLength = Integer.parseInt(keyBitLengthString);
String kdf = jwe.getHeader().getKeyDerivationFunction();
String keyLength = JweAlgorithms.getByName(kdf);
int keyBitLength = Integer.parseInt(keyLength);
byte[] contentMasterKey = new byte[keyBitLength];
new Random().nextBytes(contentMasterKey);
@ -96,11 +96,10 @@ public class RsaEncrypter extends AbstractJweEncrypter {
String encMethod = jwe.getHeader().getEncryptionMethod();
//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")) {
// FIXME: this is fragile
String delims = "[8,6]+";
String[] mode = encMethod.split(delims);
Cipher cipher = Cipher.getInstance("AES/" + mode[1] + "/PKCS5Padding");
String mode = JweAlgorithms.getByName(encMethod);
Cipher cipher = Cipher.getInstance("AES/" + mode + "/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(contentEncryptionKey, "AES"), new IvParameterSpec(iv));
byte[] cipherText = cipher.doFinal(jwe.getCiphertext());
return cipherText;

View File

@ -20,7 +20,6 @@ import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.easymock.internal.matchers.GreaterThan;
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
@ -64,14 +63,14 @@ public class RsaEncrypterDecrypterTest {
//read in header and plaintext from files
JsonParser parser = new JsonParser();
JsonObject jweHeaderObject = parser.parse(new BufferedReader(new InputStreamReader(jweHeaderUrl.openStream()))).getAsJsonObject();
//create jwe based on header and plaintext
Jwe jwe = new Jwe(new JweHeader(jweHeaderObject), null, jwePlaintextString.getBytes(), null);
//generate key pair. this will be passed in from the user
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(4096);
KeyPair pair = keyGen.generateKeyPair();
PublicKey publicKey = pair.getPublic();
PrivateKey privateKey = pair.getPrivate();
//create jwe based on header and plaintext
Jwe jwe = new Jwe(new JweHeader(jweHeaderObject), null, jwePlaintextString.getBytes(), null);
//encrypt
RsaEncrypter rsaEncrypter = new RsaEncrypter();
jwe = rsaEncrypter.encryptAndSign(jwe, publicKey);