tests for encryption/decryption done
parent
88a052019a
commit
13e0a7c4bb
|
@ -43,7 +43,6 @@ public class Jwe extends Jwt {
|
||||||
public Jwe(String headerBase64, String encryptedKeyBase64, String cipherTextBase64, String integrityValueBase64) {
|
public Jwe(String headerBase64, String encryptedKeyBase64, String cipherTextBase64, String integrityValueBase64) {
|
||||||
byte[] decodedEncryptedKey = Base64.decodeBase64(encryptedKeyBase64.getBytes());
|
byte[] decodedEncryptedKey = Base64.decodeBase64(encryptedKeyBase64.getBytes());
|
||||||
byte[] decodedCipherText = Base64.decodeBase64(cipherTextBase64.getBytes());
|
byte[] decodedCipherText = Base64.decodeBase64(cipherTextBase64.getBytes());
|
||||||
String decodedIntegrityValue = new String(Base64.decodeBase64(integrityValueBase64));
|
|
||||||
this.header = new JweHeader(headerBase64);
|
this.header = new JweHeader(headerBase64);
|
||||||
this.encryptedKey = decodedEncryptedKey;
|
this.encryptedKey = decodedEncryptedKey;
|
||||||
this.ciphertext = decodedCipherText;
|
this.ciphertext = decodedCipherText;
|
||||||
|
|
|
@ -8,16 +8,14 @@ public abstract class AbstractJweDecrypter implements JwtDecrypter {
|
||||||
long MAX_HASH_INPUTLEN = Long.MAX_VALUE;
|
long MAX_HASH_INPUTLEN = Long.MAX_VALUE;
|
||||||
long UNSIGNED_INT_MAX_VALUE = 4294967395L;
|
long UNSIGNED_INT_MAX_VALUE = 4294967395L;
|
||||||
|
|
||||||
public byte[] generateContentKey(byte[] cmk, int keyDataLen, byte[] type) {
|
public byte[] generateContentKey(byte[] cmk, int keyDataLen, byte[] type) throws NoSuchAlgorithmException {
|
||||||
|
|
||||||
MessageDigest md = null;
|
MessageDigest md = null;
|
||||||
try {
|
//HUGE DISCLAIMER: this won't work on windows machines that don't have jce unlimited security files installed.
|
||||||
md = MessageDigest.getInstance("SHA-256"); //TODO: should figure out this getInstance itself, not always 256
|
//without it, keys can't be over 128 bit in length, and SHA-128 doesn't work for message digest.
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
// TODO Auto-generated catch block
|
//this is what it should be
|
||||||
e.printStackTrace();
|
md = MessageDigest.getInstance("SHA-" + Integer.toString(keyDataLen));
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
keyDataLen = keyDataLen / 8;
|
keyDataLen = keyDataLen / 8;
|
||||||
byte[] key = new byte[keyDataLen];
|
byte[] key = new byte[keyDataLen];
|
||||||
|
|
|
@ -8,9 +8,12 @@ public abstract class AbstractJweEncrypter implements JwtEncrypter {
|
||||||
public MessageDigest md;
|
public MessageDigest md;
|
||||||
|
|
||||||
public byte[] generateContentKey(byte[] cmk, int keyDataLen, byte[] type) throws NoSuchAlgorithmException {
|
public byte[] generateContentKey(byte[] cmk, int keyDataLen, byte[] type) throws NoSuchAlgorithmException {
|
||||||
//TODO: make this work for any key size
|
//HUGE DISCLAIMER: this won't work on windows machines that don't have jce unlimited security files installed.
|
||||||
md = MessageDigest.getInstance("SHA-256");
|
//without it, keys can't be over 128 bit in length, and SHA-128 doesn't work for message digest.
|
||||||
|
|
||||||
|
//this is what it should be
|
||||||
|
md = MessageDigest.getInstance("SHA-" + Integer.toString(keyDataLen));
|
||||||
|
|
||||||
long MAX_HASH_INPUTLEN = Long.MAX_VALUE;
|
long MAX_HASH_INPUTLEN = Long.MAX_VALUE;
|
||||||
long UNSIGNED_INT_MAX_VALUE = 4294967395L;
|
long UNSIGNED_INT_MAX_VALUE = 4294967395L;
|
||||||
|
|
||||||
|
|
|
@ -38,16 +38,14 @@ public class RsaDecrypter extends AbstractJweDecrypter {
|
||||||
//generation of cek and cik
|
//generation of cek and cik
|
||||||
byte[] contentEncryptionKey = null;
|
byte[] contentEncryptionKey = null;
|
||||||
byte[] contentIntegrityKey = null;
|
byte[] contentIntegrityKey = null;
|
||||||
//check whether the key length is 128 or 256
|
//check what the key length is
|
||||||
if(jwe.getHeader().getEncryptionMethod().equals("A128CBC") || jwe.getHeader().getEncryptionMethod().equals("A128GCM")){
|
String encMethod = jwe.getHeader().getEncryptionMethod();
|
||||||
contentEncryptionKey = generateContentKey(jwe.getEncryptedKey(), 128, new String("Encryption").getBytes());
|
char[] array = encMethod.toCharArray();
|
||||||
contentIntegrityKey = generateContentKey(jwe.getEncryptedKey(), 128, new String("Integrity").getBytes());
|
String keyBitLengthString = String.copyValueOf(array, 1, 3);
|
||||||
} else if(jwe.getHeader().getEncryptionMethod().equals("A256CBC") || jwe.getHeader().getEncryptionMethod().equals("A256GCM")){
|
int keyBitLength = Integer.parseInt(keyBitLengthString);
|
||||||
contentEncryptionKey = generateContentKey(jwe.getEncryptedKey(), 256, new String("Encryption").getBytes());
|
//generate cek and cik
|
||||||
contentIntegrityKey = generateContentKey(jwe.getEncryptedKey(), 256, new String("Integrity").getBytes());
|
contentEncryptionKey = generateContentKey(jwe.getEncryptedKey(), keyBitLength, "Encryption".getBytes());
|
||||||
} else {
|
contentIntegrityKey = generateContentKey(jwe.getEncryptedKey(), keyBitLength, "Integrity".getBytes());
|
||||||
throw new IllegalArgumentException(jwe.getHeader().getEncryptionMethod() + " is not a valid encryption method");
|
|
||||||
}
|
|
||||||
|
|
||||||
//decrypt ciphertext to get claims
|
//decrypt ciphertext to get claims
|
||||||
jwe.setCiphertext(decryptCipherText(jwe, contentEncryptionKey));
|
jwe.setCiphertext(decryptCipherText(jwe, contentEncryptionKey));
|
||||||
|
@ -83,12 +81,12 @@ public class RsaDecrypter extends AbstractJweDecrypter {
|
||||||
String encMethod = jwe.getHeader().getEncryptionMethod();
|
String encMethod = jwe.getHeader().getEncryptionMethod();
|
||||||
|
|
||||||
if(encMethod.equals("A128CBC") || encMethod.equals("A256CBC") || encMethod.equals("A128GCM") || encMethod.equals("A128GCM")) {
|
if(encMethod.equals("A128CBC") || encMethod.equals("A256CBC") || encMethod.equals("A128GCM") || encMethod.equals("A128GCM")) {
|
||||||
|
|
||||||
|
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(cek, "AES"), new IvParameterSpec(iv));
|
||||||
|
byte[] clearText = cipher.doFinal(jwe.getCiphertext());
|
||||||
|
|
||||||
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
|
return clearText;
|
||||||
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(cek, "AES"), new IvParameterSpec(iv));
|
|
||||||
byte[] clearText = cipher.doFinal(jwe.getCiphertext());
|
|
||||||
|
|
||||||
return clearText;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException(jwe.getHeader().getAlgorithm() + " is not an implemented algorithm");
|
throw new IllegalArgumentException(jwe.getHeader().getAlgorithm() + " is not an implemented algorithm");
|
||||||
|
|
|
@ -35,28 +35,22 @@ public class RsaEncrypter extends AbstractJweEncrypter {
|
||||||
|
|
||||||
//generate random content master key
|
//generate random content master key
|
||||||
|
|
||||||
byte[] contentMasterKey = new byte[128];
|
//check what the key length is
|
||||||
|
String encMethod = jwe.getHeader().getEncryptionMethod();
|
||||||
|
char[] array = encMethod.toCharArray();
|
||||||
|
String keyBitLengthString = String.copyValueOf(array, 1, 3);
|
||||||
|
int keyBitLength = Integer.parseInt(keyBitLengthString);
|
||||||
|
|
||||||
|
byte[] contentMasterKey = new byte[keyBitLength];
|
||||||
new Random().nextBytes(contentMasterKey);
|
new Random().nextBytes(contentMasterKey);
|
||||||
|
|
||||||
//generate CEK and CIK
|
|
||||||
|
|
||||||
byte[] contentEncryptionKey = null;
|
byte[] contentEncryptionKey = null;
|
||||||
byte[] contentIntegrityKey = null;
|
byte[] contentIntegrityKey = null;
|
||||||
|
|
||||||
//check what the key length is
|
|
||||||
if(jwe.getHeader().getEncryptionMethod().equals("A128CBC") || jwe.getHeader().getEncryptionMethod().equals("A128GCM")){
|
//generate cek and cik
|
||||||
contentEncryptionKey = generateContentKey(contentMasterKey, 128, "Encryption".getBytes());
|
contentEncryptionKey = generateContentKey(contentMasterKey, keyBitLength, "Encryption".getBytes());
|
||||||
contentIntegrityKey = generateContentKey(contentMasterKey, 128, "Integrity".getBytes());
|
contentIntegrityKey = generateContentKey(contentMasterKey, keyBitLength, "Integrity".getBytes());
|
||||||
} else if(jwe.getHeader().getEncryptionMethod().equals("A256CBC") || jwe.getHeader().getEncryptionMethod().equals("A256GCM")){
|
|
||||||
contentEncryptionKey = generateContentKey(contentMasterKey, 256, new String("Encryption").getBytes());
|
|
||||||
contentIntegrityKey = generateContentKey(contentMasterKey, 256, new String("Integrity").getBytes());
|
|
||||||
} else if(jwe.getHeader().getEncryptionMethod().equals("A384CBC") || jwe.getHeader().getEncryptionMethod().equals("A384GCM")){
|
|
||||||
contentEncryptionKey = generateContentKey(contentMasterKey, 384, new String("Encryption").getBytes());
|
|
||||||
contentIntegrityKey = generateContentKey(contentMasterKey, 384, new String("Integrity").getBytes());
|
|
||||||
} else if(jwe.getHeader().getEncryptionMethod().equals("A512CBC") || jwe.getHeader().getEncryptionMethod().equals("A512GCM")){
|
|
||||||
contentEncryptionKey = generateContentKey(contentMasterKey, 512, new String("Encryption").getBytes());
|
|
||||||
contentIntegrityKey = generateContentKey(contentMasterKey, 512, new String("Integrity").getBytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
//encrypt claims and cmk to get ciphertext and encrypted key
|
//encrypt claims and cmk to get ciphertext and encrypted key
|
||||||
jwe.setCiphertext(encryptClaims(jwe, contentEncryptionKey));
|
jwe.setCiphertext(encryptClaims(jwe, contentEncryptionKey));
|
||||||
|
@ -109,7 +103,7 @@ public class RsaEncrypter extends AbstractJweEncrypter {
|
||||||
String encMethod = jwe.getHeader().getEncryptionMethod();
|
String encMethod = jwe.getHeader().getEncryptionMethod();
|
||||||
|
|
||||||
if(encMethod.equals("A128CBC") || encMethod.equals("A256CBC") || encMethod.equals("A128GCM") || encMethod.equals("A128GCM")) {
|
if(encMethod.equals("A128CBC") || encMethod.equals("A256CBC") || encMethod.equals("A128GCM") || encMethod.equals("A128GCM")) {
|
||||||
|
|
||||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||||
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(contentEncryptionKey, "AES"), new IvParameterSpec(iv));
|
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(contentEncryptionKey, "AES"), new IvParameterSpec(iv));
|
||||||
byte[] cipherText = cipher.doFinal(jwe.getCiphertext());
|
byte[] cipherText = cipher.doFinal(jwe.getCiphertext());
|
||||||
|
|
|
@ -3,12 +3,8 @@ package org.mitre.jwe.encryption.impl;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
|
@ -44,10 +40,7 @@ import com.google.gson.JsonSyntaxException;
|
||||||
public class RsaEncrypterDecrypterTest {
|
public class RsaEncrypterDecrypterTest {
|
||||||
|
|
||||||
URL jweHeaderUrl = this.getClass().getResource("/jwe/jweHeader");
|
URL jweHeaderUrl = this.getClass().getResource("/jwe/jweHeader");
|
||||||
URL jwePlaintextUrl = this.getClass().getResource("/jwe/jwePlaintext");
|
String jwePlaintextString = new String("Why couldn't the bike move? It was two tired.");
|
||||||
URL jweEncryptedUrl = this.getClass().getResource("/jwe/encryptedJwe");
|
|
||||||
String jweEncryptedUrlString = jweEncryptedUrl.toString();
|
|
||||||
File jweEncryptedFile = new File(jweEncryptedUrlString);
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp(){
|
public void setUp(){
|
||||||
|
@ -59,40 +52,33 @@ public class RsaEncrypterDecrypterTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void encryptDecryptTest() throws JsonIOException, JsonSyntaxException, IOException, NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, InvalidKeySpecException {
|
public void encryptDecryptTest() throws JsonIOException, JsonSyntaxException, IOException, NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, InvalidKeySpecException {
|
||||||
|
//read in header and plaintext from files
|
||||||
JsonParser parser = new JsonParser();
|
JsonParser parser = new JsonParser();
|
||||||
JsonObject jweHeaderObject = parser.parse(new BufferedReader(new InputStreamReader(jweHeaderUrl.openStream()))).getAsJsonObject();
|
JsonObject jweHeaderObject = parser.parse(new BufferedReader(new InputStreamReader(jweHeaderUrl.openStream()))).getAsJsonObject();
|
||||||
String jwePlaintextString = parser.parse(new BufferedReader(new InputStreamReader(jwePlaintextUrl.openStream()))).toString();
|
//create jwe based on header and plaintext
|
||||||
|
|
||||||
Jwe jwe = new Jwe(new JweHeader(jweHeaderObject), null, jwePlaintextString.getBytes(), null);
|
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");
|
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
|
||||||
keyGen.initialize(2048);
|
keyGen.initialize(4096);
|
||||||
KeyPair pair = keyGen.generateKeyPair();
|
KeyPair pair = keyGen.generateKeyPair();
|
||||||
PublicKey publicKey = pair.getPublic();
|
PublicKey publicKey = pair.getPublic();
|
||||||
PrivateKey privateKey = pair.getPrivate();
|
PrivateKey privateKey = pair.getPrivate();
|
||||||
//encrypt
|
//encrypt
|
||||||
RsaEncrypter rsaEncrypter = new RsaEncrypter();
|
RsaEncrypter rsaEncrypter = new RsaEncrypter();
|
||||||
jwe = rsaEncrypter.encryptAndSign(jwe, publicKey);
|
jwe = rsaEncrypter.encryptAndSign(jwe, publicKey);
|
||||||
//put encrypted jwe in text file to then be decrypted
|
|
||||||
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("C:/Users/derryberry/projects/OpenID-Connect-Java-Spring-Server-2/openid-connect-common/target/test-classes/jwe/encryptedJwe")));
|
|
||||||
out.println(jwe.toString());
|
|
||||||
out.close();
|
|
||||||
|
|
||||||
String jweEncryptedString = parser.parse(new BufferedReader(new InputStreamReader(jweEncryptedUrl.openStream()))).toString();
|
|
||||||
jweEncryptedString = jweEncryptedString.replaceAll("^\"|\"$", "");
|
|
||||||
|
|
||||||
assertEquals(jwe.toString(), jweEncryptedString);
|
|
||||||
//decrypt
|
//decrypt
|
||||||
RsaDecrypter rsaDecrypter = new RsaDecrypter();
|
RsaDecrypter rsaDecrypter = new RsaDecrypter();
|
||||||
String encryptedJweString = jwe.toString();
|
String encryptedJweString = jwe.toString();
|
||||||
jwe = rsaDecrypter.decrypt(encryptedJweString, privateKey);
|
jwe = rsaDecrypter.decrypt(encryptedJweString, privateKey);
|
||||||
|
|
||||||
assertEquals(new String(jwe.getCiphertext()), jwePlaintextString);
|
String jweDecryptedCleartext = new String(jwe.getCiphertext());
|
||||||
assertEquals(jwe.getHeader().getAlgorithm(), "RSA1_5");
|
//test ALL THE THINGS
|
||||||
assertEquals(jwe.getHeader().getEncryptionMethod(), "A128CBC");
|
assertEquals(jweDecryptedCleartext, jwePlaintextString);
|
||||||
assertEquals(jwe.getHeader().getIntegrity(), "HS256");
|
assertEquals(jwe.getHeader().getAlgorithm(), jweHeaderObject.get("alg").getAsString());
|
||||||
assertEquals(jwe.getHeader().getInitializationVector(), "AxY8DCtDaGlsbGljb3RoZQ");
|
assertEquals(jwe.getHeader().getEncryptionMethod(), jweHeaderObject.get("enc").getAsString());
|
||||||
|
assertEquals(jwe.getHeader().getIntegrity(), jweHeaderObject.get("int").getAsString());
|
||||||
|
assertEquals(jwe.getHeader().getInitializationVector(), jweHeaderObject.get("iv").getAsString());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{"alg":"RSA1_5","enc":"A128CBC","int":"HS256","iv":"AxY8DCtDaGlsbGljb3RoZQ"}
|
{"alg":"RSA1_5","enc":"A256CBC","int":"HS256","iv":"AxY8DCtDaGlsbGljb3RoZQ"}
|
|
@ -1 +0,0 @@
|
||||||
"Why couldn't the bike move? It was two tired."
|
|
Loading…
Reference in New Issue