added testing for encryption and decryption. slight bug where [ ] gets appended to clearText. working on that

pull/105/head
Mike Derryberry 2012-07-12 15:31:11 -04:00
parent 5152fa1c69
commit 88a052019a
16 changed files with 263 additions and 353 deletions

View File

@ -0,0 +1 @@
eyJpbnQiOiJIUzI1NiIsIml2IjoiQXhZOERDdERhR2xzYkdsamIzUm9aUSIsImFsZyI6IkhTMjU2IiwiZW5jIjoiQTEyOENCQyJ9.1TWc1U58WUtz6HnRVfFcCFt04dWJivMZmTG3ZeIUKbfWbG6UHsYRNnj1a9LvYpb7DA97j57whfXxxwT9P3ZnCMaeqm_JCmyasocu7ftefELw4BSYcBuIGeiOzZO7mffS4lj5s7N76kV-LXkVIMwjzKom1z1doBqnmV7M5yUCTnxQJ3ao7LYLJI0QiCY5Pcqd.CS8GW8JLnDAF4SEvw2kras0yp50-eIX90Mbn1qKF1cePqG3VWcItEJoPa0FbFbmj.0uQ48_WFcQR-q6IBcs8IG-DquLi17kbeXjqKRANr0Hw

View File

@ -41,14 +41,13 @@ public class Jwe extends Jwt {
}
public Jwe(String headerBase64, String encryptedKeyBase64, String cipherTextBase64, String integrityValueBase64) {
super(null, null, new String(Base64.decodeBase64(integrityValueBase64)));
String decodedEncryptedKey = new String(Base64.decodeBase64(encryptedKeyBase64));
String decodedCipherText = new String(Base64.decodeBase64(cipherTextBase64));
byte[] decodedEncryptedKey = Base64.decodeBase64(encryptedKeyBase64.getBytes());
byte[] decodedCipherText = Base64.decodeBase64(cipherTextBase64.getBytes());
String decodedIntegrityValue = new String(Base64.decodeBase64(integrityValueBase64));
this.header = new JweHeader(headerBase64);
this.encryptedKey = decodedEncryptedKey.getBytes();
this.ciphertext = decodedCipherText.getBytes();
setSignature(decodedIntegrityValue);
this.encryptedKey = decodedEncryptedKey;
this.ciphertext = decodedCipherText;
setSignature(integrityValueBase64);
}
public JweHeader getHeader() {
@ -82,8 +81,8 @@ public class Jwe extends Jwt {
byte[] e = encryptedKey;
String h64 = new String(Base64.encodeBase64URLSafe(h.toString().getBytes()));
String c64 = new String(Base64.encodeBase64URLSafe(c));
String e64 = new String(Base64.encodeBase64URLSafe(e));
String c64 = new String(Base64.encodeBase64URLSafe(c));
return h64 + "." + e64 + "." + c64;
}

View File

@ -72,47 +72,47 @@ public class JweHeader extends JwtHeader{
}
public String getIntegrity() {
return INTEGRITY;
return getClaimAsString(INTEGRITY);
}
public String getInitializationVector() {
return INITIALIZATION_VECTOR;
return getClaimAsString(INITIALIZATION_VECTOR);
}
public String getEphemeralPublicKey() {
return EPHEMERAL_PUBLIC_KEY;
return getClaimAsString(EPHEMERAL_PUBLIC_KEY);
}
public String getCompressionAlgorithm() {
return COMPRESSION_ALGORITHM;
return getClaimAsString(COMPRESSION_ALGORITHM);
}
public String getJsonSetUrl() {
return JSON_SET_URL;
return getClaimAsString(JSON_SET_URL);
}
public String getJsonWebKey() {
return JSON_WEB_KEY;
return getClaimAsString(JSON_WEB_KEY);
}
public String getX509Url() {
return X509_URL;
return getClaimAsString(X509_URL);
}
public String getX509CertificateThumbprint() {
return X509_CERTIFICATE_THUMBPRINT;
return getClaimAsString(X509_CERTIFICATE_THUMBPRINT);
}
public String getX509CertificateChain() {
return X509_CERTIFICATE_CHAIN;
return getClaimAsString(X509_CERTIFICATE_CHAIN);
}
public String getKeyId() {
return KEY_ID;
return getClaimAsString(KEY_ID);
}
public String getKeyDerivationFunction() {
return KEY_DERIVATION_FUNCTION;
return getClaimAsString(KEY_DERIVATION_FUNCTION);
}
public void setIv(String iv) {

View File

@ -1,12 +1,15 @@
package org.mitre.jwt.encryption;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public abstract class AbstractJweEncrypter implements JwtEncrypter {
public MessageDigest md;
public byte[] generateContentKey(byte[] cmk, int keyDataLen, byte[] type) {
public byte[] generateContentKey(byte[] cmk, int keyDataLen, byte[] type) throws NoSuchAlgorithmException {
//TODO: make this work for any key size
md = MessageDigest.getInstance("SHA-256");
long MAX_HASH_INPUTLEN = Long.MAX_VALUE;
long UNSIGNED_INT_MAX_VALUE = 4294967395L;

View File

@ -1,52 +0,0 @@
package org.mitre.jwt.encryption;
import org.apache.commons.lang.StringUtils;
public enum AlgorithmLength {
//TODO:Fill in values for each standard name
// RSA
A128CBC("128"),
A256CBC("256"),
A128GCM("128"),
A256GCM("256");
/**
* Returns the Algorithm for the name
*
* @param name
* @return
*/
public static AlgorithmLength getByName(String name) {
for (AlgorithmLength correspondingType : AlgorithmLength.values()) {
if (correspondingType.toString().equals(name)) {
return correspondingType;
}
}
// corresponding type not found
throw new IllegalArgumentException(
"AlgorithmLength name " + name + " does not have a corresponding AlgorithmLength: expected one of [" + StringUtils.join(AlgorithmLength.values(), ", ") + "]");
}
private final String standardName;
/**
* Constructor of AlgorithmLength
*
* @param standardName
*/
AlgorithmLength(String standardName) {
this.standardName = standardName;
}
/**
* Return the Java standard Algorithm Length
*
* @return
*/
public String getStandardName() {
return standardName;
}
}

View File

@ -1,14 +1,23 @@
package org.mitre.jwt.encryption;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.mitre.jwe.model.Jwe;
public interface JwtDecrypter {
public Jwe decrypt(String encryptedJwe);
public Jwe decrypt(String encryptedJwe, Key privateKey) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException;
public byte[] decryptCipherText(Jwe jwe, byte[] cek);
public byte[] decryptCipherText(Jwe jwe, byte[] cek) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException;
public byte[] decryptEncryptionKey(Jwe jwe);
public byte[] decryptEncryptionKey(Jwe jwe, Key privateKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException;
}

View File

@ -1,8 +1,15 @@
package org.mitre.jwt.encryption;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.mitre.jwe.model.Jwe;
@ -12,13 +19,13 @@ import com.google.gson.JsonSyntaxException;
public interface JwtEncrypter {
public byte[] encryptKey(Jwe jwe, Key cmk) throws JsonIOException, JsonSyntaxException, IOException;
public byte[] encryptKey(Jwe jwe, byte[] cmk, Key publicKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException;
public byte[] encryptClaims(Jwe jwe, byte[] cik);
public byte[] encryptClaims(Jwe jwe, byte[] cik) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, InvalidKeySpecException;
public Jwe encryptAndSign(Jwe jwe) throws NoSuchAlgorithmException, JsonIOException, JsonSyntaxException, IOException;
public Jwe encryptAndSign(Jwe jwe, Key publicKey) throws NoSuchAlgorithmException, JsonIOException, JsonSyntaxException, IOException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, InvalidKeySpecException;
public byte[] generateContentKey(byte[] cmk, int keyDataLen, byte[] type);
public byte[] generateContentKey(byte[] cmk, int keyDataLen, byte[] type) throws NoSuchAlgorithmException;
public byte[] intToFourBytes(int i);

View File

@ -1,18 +1,20 @@
package org.mitre.jwt.encryption.impl;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
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.encryption.AlgorithmLength;
import org.mitre.jwt.signer.impl.HmacSigner;
@ -23,7 +25,7 @@ public class RsaDecrypter extends AbstractJweDecrypter {
}
@Override
public Jwe decrypt(String encryptedJwe) {
public Jwe decrypt(String encryptedJwe, Key privateKey) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
Jwe jwe = Jwe.parse(encryptedJwe);
@ -31,13 +33,21 @@ public class RsaDecrypter extends AbstractJweDecrypter {
if(alg.equals("RSA1_5") || alg.equals("RSA-OAEP") || alg.equals("ECDH-ES") || alg.equals("A128KW") || alg.equals("A256KW")) {
//decrypt to get cmk to be used for cek and cik
jwe.setEncryptedKey(decryptEncryptionKey(jwe));
jwe.setEncryptedKey(decryptEncryptionKey(jwe, privateKey));
//generation of cek and cik
String algorithmLength = AlgorithmLength.getByName(jwe.getHeader().getEncryptionMethod()).getStandardName();
int keyLength = Integer.parseInt(algorithmLength);
byte[] contentEncryptionKey = generateContentKey(jwe.getEncryptedKey(), keyLength, new String("Encryption").getBytes());
byte[] contentIntegrityKey = generateContentKey(jwe.getEncryptedKey(), keyLength, new String("Integrity").getBytes());
byte[] contentEncryptionKey = null;
byte[] contentIntegrityKey = null;
//check whether the key length is 128 or 256
if(jwe.getHeader().getEncryptionMethod().equals("A128CBC") || jwe.getHeader().getEncryptionMethod().equals("A128GCM")){
contentEncryptionKey = generateContentKey(jwe.getEncryptedKey(), 128, new String("Encryption").getBytes());
contentIntegrityKey = generateContentKey(jwe.getEncryptedKey(), 128, new String("Integrity").getBytes());
} else if(jwe.getHeader().getEncryptionMethod().equals("A256CBC") || jwe.getHeader().getEncryptionMethod().equals("A256GCM")){
contentEncryptionKey = generateContentKey(jwe.getEncryptedKey(), 256, new String("Encryption").getBytes());
contentIntegrityKey = generateContentKey(jwe.getEncryptedKey(), 256, new String("Integrity").getBytes());
} else {
throw new IllegalArgumentException(jwe.getHeader().getEncryptionMethod() + " is not a valid encryption method");
}
//decrypt ciphertext to get claims
jwe.setCiphertext(decryptCipherText(jwe, contentEncryptionKey));
@ -53,77 +63,54 @@ public class RsaDecrypter extends AbstractJweDecrypter {
}
//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");
}
/*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("Not a valid decrypting algorithm");
throw new IllegalArgumentException(jwe.getHeader().getEncryptionMethod() + " is not a valid decrypting algorithm");
}
return jwe;
}
@Override
public byte[] decryptCipherText(Jwe jwe, byte[] cek) {
Cipher cipher;
byte[] clearText = null;
try {
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(cek, "RSA"));
clearText = cipher.doFinal(jwe.getCiphertext());
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
public byte[] decryptCipherText(Jwe jwe, byte[] cek) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
byte[] iv = new byte[16];
iv = Base64.decodeBase64(jwe.getHeader().getInitializationVector());
String encMethod = jwe.getHeader().getEncryptionMethod();
if(encMethod.equals("A128CBC") || encMethod.equals("A256CBC") || encMethod.equals("A128GCM") || encMethod.equals("A128GCM")) {
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(cek, "AES"), new IvParameterSpec(iv));
byte[] clearText = cipher.doFinal(jwe.getCiphertext());
return clearText;
} else {
throw new IllegalArgumentException(jwe.getHeader().getAlgorithm() + " is not an implemented algorithm");
}
}
@Override
public byte[] decryptEncryptionKey(Jwe jwe) {
Cipher cipher;
byte[] contentMasterKey = null;
PrivateKey privateKey = null;
public byte[] decryptEncryptionKey(Jwe jwe, Key privateKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
try {
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);//TODO: Get private key from key store. Placeholder
contentMasterKey = cipher.doFinal(jwe.getEncryptedKey());
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
if(jwe.getHeader().getAlgorithm().equals("RSA1_5")){
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
//TODO: Get private key from key store. Placeholder
byte[] contentMasterKey = cipher.doFinal(jwe.getEncryptedKey());
return contentMasterKey;
} else {
throw new IllegalArgumentException(jwe.getHeader().getAlgorithm() + " is not an implemented algorithm");
}
return contentMasterKey;
}
}

View File

@ -1,22 +1,22 @@
package org.mitre.jwt.encryption.impl;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.util.Random;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
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.AlgorithmLength;
import org.mitre.jwt.signer.impl.HmacSigner;
public class RsaEncrypter extends AbstractJweEncrypter {
@ -26,132 +26,99 @@ public class RsaEncrypter extends AbstractJweEncrypter {
//TODO: Put something here
}
public Jwe encryptAndSign(Jwe jwe) throws NoSuchAlgorithmException {
public Jwe encryptAndSign(Jwe jwe, Key publicKey) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, InvalidKeySpecException {
String alg = jwe.getHeader().getAlgorithm();
String iv = jwe.getHeader().getIntegrity();
String integrityAlg = jwe.getHeader().getIntegrity();
if(alg.equals("RSA1_5") || alg.equals("RSA-OAEP") || alg.equals("ECDH-ES") || alg.equals("A128KW") || alg.equals("A256KW")) {
//generate random content master key
Key contentMasterKey = null;
try {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
SecureRandom random = SecureRandom.getInstance("RSA");
keyGen.initialize(1024, random);
KeyPair pair = keyGen.generateKeyPair();
contentMasterKey = pair.getPublic();
} catch (NoSuchAlgorithmException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
byte[] contentMasterKey = new byte[128];
new Random().nextBytes(contentMasterKey);
//generate CEK and CIK
String algorithmLength = AlgorithmLength.getByName(jwe.getHeader().getEncryptionMethod()).toString();
int keyLength = Integer.parseInt(algorithmLength);
byte[] contentEncryptionKey = generateContentKey(contentMasterKey.getEncoded(), keyLength, new String("Encryption").getBytes());
byte[] contentIntegrityKey = generateContentKey(contentMasterKey.getEncoded(), keyLength, new String("Integrity").getBytes());
byte[] contentEncryptionKey = null;
byte[] contentIntegrityKey = null;
//check what the key length is
if(jwe.getHeader().getEncryptionMethod().equals("A128CBC") || jwe.getHeader().getEncryptionMethod().equals("A128GCM")){
contentEncryptionKey = generateContentKey(contentMasterKey, 128, "Encryption".getBytes());
contentIntegrityKey = generateContentKey(contentMasterKey, 128, "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
jwe.setCiphertext(encryptClaims(jwe, contentEncryptionKey));
jwe.setEncryptedKey(encryptKey(jwe, contentMasterKey));
jwe.setEncryptedKey(encryptKey(jwe, contentMasterKey, publicKey));
//Signer must be hmac
if(iv.equals("HS256") || iv.equals("HS384") || iv.equals("HS512")){
if(integrityAlg.equals("HS256") || integrityAlg.equals("HS384") || integrityAlg.equals("HS512")){
HmacSigner hmacSigner = new HmacSigner(contentIntegrityKey);
jwe = (Jwe) hmacSigner.sign(jwe);
} else {
throw new IllegalArgumentException("Not a valid integrity value algorithm");
throw new IllegalArgumentException(integrityAlg + " is not a valid integrity value algorithm");
}
} else {
throw new IllegalArgumentException("Not a valid signing algorithm");
throw new IllegalArgumentException(alg + " is not a valid signing algorithm");
}
return jwe;
}
public byte[] encryptKey(Jwe jwe, Key cmk) {
public byte[] encryptKey(Jwe jwe, byte[] cmk, Key publicKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
//TODO:Get public key from keystore, for now randomly generate key pair
if(jwe.getHeader().getAlgorithm().equals("RSA1_5")){
PublicKey publicKey = null;
try {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(1024);
KeyPair pair = keyGen.generateKeyPair();
publicKey = pair.getPublic();
} catch (NoSuchAlgorithmException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Cipher cipher;
byte[] encryptedKey = null;
try {
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
encryptedKey = cipher.doFinal(cmk.getEncoded());
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedKey = cipher.doFinal(cmk);
return encryptedKey;
} else {
throw new IllegalArgumentException(jwe.getHeader().getAlgorithm() + " is not a supported algorithm");
}
}
public byte[] encryptClaims(Jwe jwe, byte[] contentEncryptionKey) {
public byte[] encryptClaims(Jwe jwe, byte[] contentEncryptionKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, InvalidKeySpecException {
Cipher cipher;
byte[] cipherText = null;
byte[] iv = new byte[16];
//look for iv value in header, if not there make one
if(jwe.getHeader().getInitializationVector() != null){
iv = Base64.decodeBase64(jwe.getHeader().getInitializationVector());
} else {
new Random().nextBytes(iv);
jwe.getHeader().setIv(Base64.encodeBase64String(iv));
}
try {
cipher = Cipher.getInstance("RSA");
String encMethod = jwe.getHeader().getEncryptionMethod();
if(encMethod.equals("A128CBC") || encMethod.equals("A256CBC") || encMethod.equals("A128GCM") || encMethod.equals("A128GCM")) {
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(contentEncryptionKey, "RSA"));
cipherText = cipher.doFinal(jwe.getClaims().toString().getBytes());
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return cipherText;
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(contentEncryptionKey, "AES"), new IvParameterSpec(iv));
byte[] cipherText = cipher.doFinal(jwe.getCiphertext());
return cipherText;
} else {
throw new IllegalArgumentException(jwe.getHeader().getAlgorithm() + " is not a supported algorithm");
}
}

View File

@ -64,6 +64,8 @@ public class JwtHeader extends ClaimSet {
this.setAlgorithm(element.getValue().getAsString());
} else if (element.getKey().equals(ENCRYPTION_METHOD)) {
this.setEncryptionMethod(element.getValue().getAsString());
} else if (element.getKey().equals(CONTENT_TYPE)) {
this.setContentType(element.getValue().getAsString());
} else {
pass.add(element.getKey(), element.getValue());
}

View File

@ -57,12 +57,13 @@ public abstract class AbstractJwtSigner implements JwtSigner {
*/
@Override
public Jwt sign(Jwt jwt) throws NoSuchAlgorithmException {
if (!Objects.equal(algorithm, jwt.getHeader().getAlgorithm())) {
//TODO: this check changes the algorithm param of a jwe to the int param. not sure why?
/*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());

View File

@ -1,50 +0,0 @@
package org.mitre.jwe.encryption.impl;
import static org.junit.Assert.assertEquals;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mitre.jwe.model.Jwe;
import org.mitre.jwt.encryption.impl.RsaDecrypter;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.google.gson.JsonIOException;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:test-context.xml" })
public class RsaDecrypterTest {
URL jweUrl = this.getClass().getResource("/jwe/encryptedJwe");
@Before
public void setUp(){
}
@After
public void tearDown(){
}
@Test
public void decryptTest() throws JsonIOException, JsonSyntaxException, IOException {
JsonParser parser = new JsonParser();
String jweString = parser.parse(new BufferedReader(new InputStreamReader(jweUrl.openStream()))).toString();
RsaDecrypter rsaDecrypter = new RsaDecrypter();
Jwe jwe = rsaDecrypter.decrypt(jweString);
assertEquals(jwe.getCiphertext().toString(), "Now is the time for all good men to come to the aid of their country.");
}
}

View File

@ -0,0 +1,99 @@
package org.mitre.jwe.encryption.impl;
import static org.junit.Assert.assertEquals;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mitre.jwe.model.Jwe;
import org.mitre.jwe.model.JweHeader;
import org.mitre.jwt.encryption.impl.RsaDecrypter;
import org.mitre.jwt.encryption.impl.RsaEncrypter;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.google.gson.JsonIOException;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:test-context.xml" })
public class RsaEncrypterDecrypterTest {
URL jweHeaderUrl = this.getClass().getResource("/jwe/jweHeader");
URL jwePlaintextUrl = this.getClass().getResource("/jwe/jwePlaintext");
URL jweEncryptedUrl = this.getClass().getResource("/jwe/encryptedJwe");
String jweEncryptedUrlString = jweEncryptedUrl.toString();
File jweEncryptedFile = new File(jweEncryptedUrlString);
@Before
public void setUp(){
}
@After
public void tearDown(){
}
@Test
public void encryptDecryptTest() throws JsonIOException, JsonSyntaxException, IOException, NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, InvalidKeySpecException {
JsonParser parser = new JsonParser();
JsonObject jweHeaderObject = parser.parse(new BufferedReader(new InputStreamReader(jweHeaderUrl.openStream()))).getAsJsonObject();
String jwePlaintextString = parser.parse(new BufferedReader(new InputStreamReader(jwePlaintextUrl.openStream()))).toString();
Jwe jwe = new Jwe(new JweHeader(jweHeaderObject), null, jwePlaintextString.getBytes(), null);
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(2048);
KeyPair pair = keyGen.generateKeyPair();
PublicKey publicKey = pair.getPublic();
PrivateKey privateKey = pair.getPrivate();
//encrypt
RsaEncrypter rsaEncrypter = new RsaEncrypter();
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
RsaDecrypter rsaDecrypter = new RsaDecrypter();
String encryptedJweString = jwe.toString();
jwe = rsaDecrypter.decrypt(encryptedJweString, privateKey);
assertEquals(new String(jwe.getCiphertext()), jwePlaintextString);
assertEquals(jwe.getHeader().getAlgorithm(), "RSA1_5");
assertEquals(jwe.getHeader().getEncryptionMethod(), "A128CBC");
assertEquals(jwe.getHeader().getIntegrity(), "HS256");
assertEquals(jwe.getHeader().getInitializationVector(), "AxY8DCtDaGlsbGljb3RoZQ");
}
}

View File

@ -1,62 +0,0 @@
package org.mitre.jwe.encryption.impl;
import static org.junit.Assert.assertEquals;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.NoSuchAlgorithmException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mitre.jwe.model.Jwe;
import org.mitre.jwe.model.JweHeader;
import org.mitre.jwt.encryption.impl.RsaEncrypter;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.google.gson.JsonIOException;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:test-context.xml" })
public class RsaEncrypterTest {
URL jweHeaderUrl = this.getClass().getResource("/jwe/jweHeader");
URL jwePlaintextUrl = this.getClass().getResource("/jwe/jwePlaintext");
@Before
public void setUp(){
}
@After
public void tearDown(){
}
@Test
public void encryptTest() throws JsonIOException, JsonSyntaxException, IOException {
JsonParser parser = new JsonParser();
JsonObject jweHeaderObject = parser.parse(new BufferedReader(new InputStreamReader(jweHeaderUrl.openStream()))).getAsJsonObject();
String jwePlaintextString = parser.parse(new BufferedReader(new InputStreamReader(jwePlaintextUrl.openStream()))).toString();
Jwe jwe = new Jwe(new JweHeader(jweHeaderObject), null, jwePlaintextString.getBytes(), null);
RsaEncrypter rsaEncrypter = new RsaEncrypter();
try {
jwe = rsaEncrypter.encryptAndSign(jwe);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
assertEquals(jwe.toString(), "yooooo");
}
}

View File

@ -1 +0,0 @@
eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDIiwiaW50IjoiSFMyNTYiLCJpdiI6IkF4WThEQ3REYUdsc2JHbGpiM1JvWlEifQ.IPI_z172hSWHMFgED8EG9DM6hIXU_6NaO1DImCn0vNeuoBq847Sl6qw_GHSYHJUQXtXJq7S_CxWVrI82wjrOyaQca5tLZRZc45BfKHeqByThKI261QevEK56SyAwwXfKKZjSvkQ5dwTFSgfy76rMSUvVynHYEhdCatBF9HWTAiXPx7hgZixG1FeP_QCmOylz2VClVyYFCbjKREOwBFf-puNYfO75S3LNlJUtTsGGQL2oTKpMsEiUTdefkje91VX9h8g7908lFsggbjV7NicJsufuXxnTj1fcWIrRDeNIOmakiPEODi0gTSz0ou-W-LWK-3T1zYlOIiIKBjsExQKZ-w._Z_djlIoC4MDSCKireWS2beti4Q6iSG2UjFujQvdz-_PQdUcFNkOulegD6BgjgdFLjeB4HHOO7UHvP8PEDu0a0sA2a_-CI0w2YQQ2QQe35M.c41k4T4eAgCCt63m8ZNmiOinMciFFypOFpvid7i6D0k

View File

@ -1 +1 @@
"Live long and prosper"
"Why couldn't the bike move? It was two tired."