update to encryption/decryption. added cmk, cek, and cik use

pull/105/head
Mike Derryberry 2012-07-09 11:49:05 -04:00
parent bc1ff0d964
commit 7e7cd4f480
7 changed files with 121 additions and 45 deletions

View File

@ -20,7 +20,6 @@ public class JweHeader extends JwtHeader{
public static final String X509_CERTIFICATE_CHAIN = "x5c";
public static final String KEY_ID = "kid";
public static final String KEY_DERIVATION_FUNCTION = "kdf";
public static final String CONTENT_TYPE = "cty";
public JweHeader(){
super();
@ -112,14 +111,10 @@ public class JweHeader extends JwtHeader{
return KEY_ID;
}
public static String getKeyDerivationFunction() {
public String getKeyDerivationFunction() {
return KEY_DERIVATION_FUNCTION;
}
public static String getContentType() {
return CONTENT_TYPE;
}
public void setIv(String iv) {
setClaim(INITIALIZATION_VECTOR, iv);
}
@ -163,8 +158,4 @@ public class JweHeader extends JwtHeader{
public void setKeyDerivationFunction(String kdf) {
setClaim(KEY_DERIVATION_FUNCTION, kdf);
}
public void setContentType(String cty) {
setClaim(CONTENT_TYPE, cty);
}
}

View File

@ -1,6 +1,7 @@
package org.mitre.jwt.encryption;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
@ -39,13 +40,13 @@ public abstract class AbstractJweDecrypter implements JwtDecrypter {
@Override
public String decryptCipherText(Jwe jwe) {
public String decryptCipherText(Jwe jwe, Key cek) {
Cipher cipher;
String clearTextString = null;
try {
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
cipher.init(Cipher.DECRYPT_MODE, cek);
byte[] clearText = cipher.doFinal(jwe.getCiphertext());
clearTextString = new String(clearText);
@ -73,13 +74,13 @@ public abstract class AbstractJweDecrypter implements JwtDecrypter {
@Override
public byte[] decryptEncryptionKey(Jwe jwe) {
Cipher cipher;
byte[] unencryptedKey = null;
byte[] contentMasterKey = null;
try {
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);//TODO: Keys are null, get them from keystore. Placeholder
unencryptedKey = cipher.doFinal(jwe.getEncryptedKey());
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
@ -98,6 +99,6 @@ public abstract class AbstractJweDecrypter implements JwtDecrypter {
e.printStackTrace();
}
return unencryptedKey;
return contentMasterKey;
}
}

View File

@ -1,16 +1,23 @@
package org.mitre.jwt.encryption;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidParameterSpecException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import org.mitre.jwe.model.Jwe;
import org.springframework.security.crypto.codec.Base64;
public abstract class AbstractJweEncrypter implements JwtEncrypter {
@ -21,10 +28,6 @@ public abstract class AbstractJweEncrypter implements JwtEncrypter {
private RSAPublicKey publicKey;
private RSAPrivateKey privateKey;
public byte[] getEncryptecKey() {
return encryptedKey;
}
@ -44,13 +47,29 @@ public abstract class AbstractJweEncrypter implements JwtEncrypter {
public byte[] encryptKey(Jwe jwe){
//generate random content master key
PublicKey contentMasterKey = null;
//TODO:Get keys from keystore, currently null
try {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance(jwe.getHeader().getAlgorithm());
SecureRandom random = SecureRandom.getInstance(jwe.getHeader().getAlgorithm());
keyGen.initialize(1024, random);
KeyPair pair = keyGen.generateKeyPair();
contentMasterKey = pair.getPublic();
} catch (NoSuchAlgorithmException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
//TODO:Get public key from keystore, currently null
Cipher cipher;
try {
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
encryptedKey = cipher.doFinal(privateKey.getEncoded());
encryptedKey = cipher.doFinal(contentMasterKey.getEncoded());
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
@ -73,14 +92,17 @@ public abstract class AbstractJweEncrypter implements JwtEncrypter {
}
public byte[] encryptClaims(Jwe jwe) {
public byte[] encryptClaims(Jwe jwe, Key cek) {
//TODO:Get keys from keystore, currently null
Cipher cipher;
try {
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
//TODO: generated the iv, but not sure how to use it to encrypt?
IvParameterSpec spec = cipher.getParameters().getParameterSpec(IvParameterSpec.class);
byte[] iv = spec.getIV();
cipher.init(Cipher.ENCRYPT_MODE, cek);
cipherText = cipher.doFinal(jwe.getClaims().toString().getBytes());
} catch (NoSuchAlgorithmException e) {
@ -98,13 +120,16 @@ public abstract class AbstractJweEncrypter implements JwtEncrypter {
} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidParameterSpecException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return cipherText;
}
public abstract Jwe encryptAndSign(Jwe jwe);
public abstract Jwe encryptAndSign(Jwe jwe) throws NoSuchAlgorithmException;
}

View File

@ -1,12 +1,14 @@
package org.mitre.jwt.encryption;
import java.security.Key;
import org.mitre.jwe.model.Jwe;
public interface JwtDecrypter {
public Jwe decrypt(String encryptedJwe);
public String decryptCipherText(Jwe jwe);
public String decryptCipherText(Jwe jwe, Key cek);
public byte[] decryptEncryptionKey(Jwe jwe);

View File

@ -1,5 +1,8 @@
package org.mitre.jwt.encryption;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import org.mitre.jwe.model.Jwe;
@ -7,8 +10,8 @@ public interface JwtEncrypter {
public byte[] encryptKey(Jwe jwe);
public byte[] encryptClaims(Jwe jwe);
public byte[] encryptClaims(Jwe jwe, Key cik);
public Jwe encryptAndSign(Jwe jwe);
public Jwe encryptAndSign(Jwe jwe) throws NoSuchAlgorithmException;
}

View File

@ -1,9 +1,16 @@
package org.mitre.jwt.encryption.impl;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import org.apache.commons.codec.binary.Base64;
import org.mitre.jwe.model.Jwe;
import org.mitre.jwe.model.JweHeader;
import org.mitre.jwt.encryption.AbstractJweDecrypter;
import org.mitre.jwt.signer.impl.HmacSigner;
public class Decrypter extends AbstractJweDecrypter {
@ -33,6 +40,7 @@ public class Decrypter extends AbstractJweDecrypter {
//Base 64 decode each part of the jwe
String decodedHeader = new String(Base64.decodeBase64(jwe.getHeader().toString()));
JweHeader unencryptedHeader = new JweHeader(decodedHeader);
jwe.setHeader(unencryptedHeader);
String decodedEncryptionKey = new String(Base64.decodeBase64(jwe.getEncryptedKey().toString()));
//sets decoded key on jwe so that it can be decrypted
@ -42,12 +50,43 @@ public class Decrypter extends AbstractJweDecrypter {
//sets decoded ciphertext on jwe so that it can be decrypted
jwe.setCiphertext(decodedCiphertext.getBytes());
//decode signature, but don't set it on jwe yet. first has to be verified (see below)
String decodedSig = new String(Base64.decodeBase64(jwe.getSignature()));
//create new jwe using the decoded header and signature, and decrypt the ciphertext and key
jwe.setHeader(unencryptedHeader);
jwe.setCiphertext(decryptCipherText(jwe).getBytes());
PrivateKey contentEncryptionKey = null;
PublicKey contentIntegrityKey = null;
try {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance(jwe.getHeader().getKeyDerivationFunction());
KeyPair keyPair = keyGen.genKeyPair();
contentEncryptionKey = keyPair.getPrivate();
contentIntegrityKey = keyPair.getPublic();
} catch (NoSuchAlgorithmException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
jwe.setCiphertext(decryptCipherText(jwe, contentEncryptionKey).getBytes());
jwe.setEncryptedKey(decryptEncryptionKey(jwe));
//generate signature for decrypted signature base in order to verify that decryption worked
String signature = null;
try {
HmacSigner hmacSigner = new HmacSigner(contentIntegrityKey.getEncoded());
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 != decodedSig){
throw new IllegalArgumentException("Didn't decrypt correctly. Decoded Sig and generated Sig do not match");
}
jwe.setSignature(decodedSig);
} else if(alg.equals("HS256") || alg.equals("HS384") || alg.equals("HS512")){

View File

@ -1,6 +1,10 @@
package org.mitre.jwt.encryption.impl;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import org.mitre.jwe.model.Jwe;
import org.mitre.jwe.model.JweHeader;
@ -59,25 +63,38 @@ public class Encrypter extends AbstractJweEncrypter {
}
@Override
public Jwe encryptAndSign(Jwe jwe) {
public Jwe encryptAndSign(Jwe jwe) throws NoSuchAlgorithmException {
String alg = jwe.getHeader().getAlgorithm();
String iv = jwe.getHeader().getIntegrity();
if(alg.equals("RS256") || alg.equals("RS384") || alg.equals("RS512")) {
jwe.setCiphertext(encryptClaims(jwe));
//generate CEK and CIK
PrivateKey contentEncryptionKey = null;
PublicKey contentIntegrityKey = null;
try {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance(jwe.getHeader().getKeyDerivationFunction());
KeyPair keyPair = keyGen.genKeyPair();
contentEncryptionKey = keyPair.getPrivate();
contentIntegrityKey = keyPair.getPublic();
} catch (NoSuchAlgorithmException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
jwe.setCiphertext(encryptClaims(jwe, contentEncryptionKey));
jwe.setEncryptedKey(encryptKey(jwe));
if(iv.equals("HS256") || iv.equals("HS384") || iv.equals("HS512")){
HmacSigner hmacSigner = new HmacSigner(); //TODO: Add parameters to RsaSigner. ie: keys from keystore (null at the moment)
try {
HmacSigner hmacSigner = new HmacSigner(contentIntegrityKey.getEncoded());
jwe = (Jwe) hmacSigner.sign(jwe);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else if(iv.equals("RS256") || iv.equals("RS384") || iv.equals("RS512")) {
throw new IllegalArgumentException("Integrity Value must use Hmac signing");
} else {
@ -85,9 +102,7 @@ public class Encrypter extends AbstractJweEncrypter {
}
} else if(alg.equals("HS256") || alg.equals("HS384") || alg.equals("HS512")){
throw new IllegalArgumentException("Cannot use Hmac for encryption");
} else {
throw new IllegalArgumentException("Not a valid signing algorithm");
}