diff --git a/openid-connect-common/pom.xml b/openid-connect-common/pom.xml index 494c0225c..75fe644f5 100644 --- a/openid-connect-common/pom.xml +++ b/openid-connect-common/pom.xml @@ -20,6 +20,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs 1.0.0.BUILD-SNAPSHOT spring-security-oauth2 + + + 1.6 diff --git a/openid-connect-common/src/main/java/org/mitre/jwe/model/Jwe.java b/openid-connect-common/src/main/java/org/mitre/jwe/model/Jwe.java index c95d53fa5..0421c32c1 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwe/model/Jwe.java +++ b/openid-connect-common/src/main/java/org/mitre/jwe/model/Jwe.java @@ -66,6 +66,11 @@ public class Jwe extends Jwt { this.signature = signature; } + + /** + * Return the canonical encoded string of this JWE, the header in Base64, a period ".", the encrypted key in Base64, a period ".", + * the ciphertext in Base64, a period ".", and the signature, or integrity value, in Base64. + */ @Override public String toString() { return getSignatureBase() + "." + Strings.nullToEmpty(this.signature); @@ -105,6 +110,7 @@ public class Jwe extends Jwt { String i64 = parts.get(3); Jwe jwe = new Jwe(new JweHeader(h64), e64.getBytes(), c64.getBytes(), i64); + //Jwe jwe = new Jwe(new JweHeader(h64), e64.getBytes(), new ClaimSet(c64), i64); return jwe; 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 c79a198ff..dd887420d 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 @@ -1,29 +1,111 @@ package org.mitre.jwt.encryption; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; + import org.mitre.jwe.model.Jwe; -import org.mitre.jwt.encryption.impl.RsaDecrypter; public abstract class AbstractJweDecrypter implements JwtDecrypter { + + private Jwe jwe; + + private PrivateKey privateKey; + + private PublicKey publicKey; + + public Jwe getJwe() { + return jwe; + } + + public void setJwe(Jwe jwe) { + this.jwe = jwe; + } + + public PrivateKey getPrivateKey() { + return privateKey; + } + + public void setPrivateKey(PrivateKey privateKey) { + this.privateKey = privateKey; + } + + public PublicKey getPublicKey() { + return publicKey; + } + + public void setPublicKey(PublicKey publicKey) { + this.publicKey = publicKey; + } + @Override - public Jwe decrypt(Jwe jwe) { - String alg = jwe.getHeader().getAlgorithm(); - if(alg.equals("RS256") || alg.equals("RS384") || alg.equals("RS512")) { + public String decryptCipherText(Jwe jwe) { + Cipher cipher; + String clearTextString = null; + try { - RsaDecrypter decrypter = new RsaDecrypter(jwe); - jwe.setCiphertext(decrypter.decryptCipherText(jwe).getBytes()); //TODO: When decrypting, should it return a jwe or jwt? - jwe.setEncryptedKey(decrypter.decryptEncryptionKey(jwe)); + cipher = Cipher.getInstance("RSA"); + cipher.init(Cipher.DECRYPT_MODE, privateKey); + byte[] clearText = cipher.doFinal(jwe.getCiphertext()); + clearTextString = new String(clearText); - } else if(alg.equals("HS256") || alg.equals("HS384") || alg.equals("HS512")){ - - throw new IllegalArgumentException("Cannot use Hmac for decryption"); - - } else { - throw new IllegalArgumentException("Not a valid decrypting algorithm"); + } 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 jwe; + return clearTextString; + } + + @Override + public byte[] decryptEncryptionKey(Jwe jwe) { + Cipher cipher; + byte[] unencryptedKey = 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()); + + } 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 unencryptedKey; + } } 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 e0fe293c9..8a736e858 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,31 +11,19 @@ import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import org.mitre.jwe.model.Jwe; -import org.mitre.jwe.model.JweHeader; -import org.mitre.jwt.model.JwtClaims; public abstract class AbstractJweEncrypter implements JwtEncrypter { - private Jwe jwe; - - private JweHeader header; - - private JwtClaims claims; - - private String signature; - private byte[] encryptedKey; private byte[] cipherText; - public Jwe getJwe() { - return jwe; - } + private RSAPublicKey publicKey; + + private RSAPrivateKey privateKey; + - public void setJwe(Jwe jwe) { - this.jwe = jwe; - } public byte[] getEncryptecKey() { return encryptedKey; @@ -44,31 +32,7 @@ public abstract class AbstractJweEncrypter implements JwtEncrypter { public void setEncryptedKey(byte[] encryptedKey) { this.encryptedKey = encryptedKey; } - - public JweHeader getHeader() { - return header; - } - public void setHeader(JweHeader header) { - this.header = header; - } - - public JwtClaims getClaims() { - return claims; - } - - public void setClaims(JwtClaims claims) { - this.claims = claims; - } - - public String getSignature() { - return signature; - } - - public void setSignature(String signature) { - this.signature = signature; - } - public byte[] getCipherText() { return cipherText; } @@ -79,10 +43,9 @@ public abstract class AbstractJweEncrypter implements JwtEncrypter { public byte[] encryptKey(Jwe jwe){ - - RSAPublicKey publicKey = null; // TODO: placeholder - RSAPrivateKey privateKey = null; + + //TODO:Get keys from keystore, currently null Cipher cipher; try { cipher = Cipher.getInstance("RSA"); @@ -112,13 +75,13 @@ public abstract class AbstractJweEncrypter implements JwtEncrypter { public byte[] encryptClaims(Jwe jwe) { - RSAPublicKey publicKey = null; // TODO: placeholder - + + //TODO:Get keys from keystore, currently null Cipher cipher; try { cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); - cipherText = cipher.doFinal(claims.toString().getBytes()); + cipherText = cipher.doFinal(jwe.getClaims().toString().getBytes()); } catch (NoSuchAlgorithmException e) { // TODO Auto-generated catch block @@ -140,6 +103,8 @@ public abstract class AbstractJweEncrypter implements JwtEncrypter { return cipherText; } + + public abstract Jwe encryptAndSign(Jwe jwe); } diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/encryption/JwtDecrypter.java b/openid-connect-common/src/main/java/org/mitre/jwt/encryption/JwtDecrypter.java index 2038f9a97..6f6c9bd93 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/encryption/JwtDecrypter.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/encryption/JwtDecrypter.java @@ -4,7 +4,7 @@ import org.mitre.jwe.model.Jwe; public interface JwtDecrypter { - public Jwe decrypt(Jwe jwe); + public Jwe decrypt(String encryptedJwe); public String decryptCipherText(Jwe jwe); 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 360572066..d350c251e 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 @@ -1,115 +1,41 @@ package org.mitre.jwt.encryption.impl; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.PublicKey; - -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; - +import org.apache.commons.codec.binary.Base64; import org.mitre.jwe.model.Jwe; import org.mitre.jwt.encryption.AbstractJweDecrypter; +import org.mitre.jwt.model.JwtHeader; public class RsaDecrypter extends AbstractJweDecrypter { - private Jwe jwe; - - private PrivateKey privateKey; - - private PublicKey publicKey; - public RsaDecrypter(Jwe jwe) { setJwe(jwe); } - - public Jwe getJwe() { - return jwe; - } - - public void setJwe(Jwe jwe) { - this.jwe = jwe; - } - - public PrivateKey getPrivateKey() { - return privateKey; - } - - public void setPrivateKey(PrivateKey privateKey) { - this.privateKey = privateKey; - } - - public PublicKey getPublicKey() { - return publicKey; - } - - public void setPublicKey(PublicKey publicKey) { - this.publicKey = publicKey; - } @Override - public String decryptCipherText(Jwe jwe) { - Cipher cipher; - String clearTextString = null; - try { - - cipher = Cipher.getInstance("RSA"); - cipher.init(Cipher.DECRYPT_MODE, privateKey); - byte[] clearText = cipher.doFinal(jwe.getCiphertext()); - clearTextString = new String(clearText); - - } 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 Jwe decrypt(String encryptedJwe) { - return clearTextString; + Jwe jwe = Jwe.parse(encryptedJwe); - } - - @Override - public byte[] decryptEncryptionKey(Jwe jwe) { - Cipher cipher; - byte[] unencryptedKey = null; - - try { + String alg = jwe.getHeader().getAlgorithm(); + if(alg.equals("RS256") || alg.equals("RS384") || alg.equals("RS512")) { + + String decodedHeader = new String(Base64.decodeBase64(jwe.getHeader().toString())); + JwtHeader unencryptedHeader = new JwtHeader(decodedHeader); + String decodedSig = new String(Base64.decodeBase64(jwe.getSignature())); + + jwe.setHeader(unencryptedHeader); + jwe.setCiphertext(decryptCipherText(jwe).getBytes()); + jwe.setEncryptedKey(decryptEncryptionKey(jwe)); + jwe.setSignature(decodedSig); - cipher = Cipher.getInstance("RSA"); - cipher.init(Cipher.DECRYPT_MODE, privateKey); - unencryptedKey = cipher.doFinal(jwe.getEncryptedKey()); + } else if(alg.equals("HS256") || alg.equals("HS384") || alg.equals("HS512")){ - } 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(); + throw new IllegalArgumentException("Cannot use Hmac for decryption"); + + } else { + throw new IllegalArgumentException("Not a valid decrypting algorithm"); } - - return unencryptedKey; + return jwe; } } 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 5b49b6b3b..85fcd3335 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 @@ -3,17 +3,60 @@ package org.mitre.jwt.encryption.impl; import java.security.NoSuchAlgorithmException; import org.mitre.jwe.model.Jwe; +import org.mitre.jwe.model.JweHeader; import org.mitre.jwt.encryption.AbstractJweEncrypter; +import org.mitre.jwt.model.JwtClaims; import org.mitre.jwt.signer.impl.RsaSigner; public class RsaEncrypter extends AbstractJweEncrypter { + private Jwe jwe; + + private JweHeader header; + + private JwtClaims claims; + + private String signature; + public RsaEncrypter(Jwe jwe) { setJwe(jwe); setHeader(jwe.getHeader()); setClaims(jwe.getClaims()); setSignature(jwe.getSignature()); } + + public Jwe getJwe() { + return jwe; + } + + public void setJwe(Jwe jwe) { + this.jwe = jwe; + } + + + public JweHeader getHeader() { + return header; + } + + public void setHeader(JweHeader header) { + this.header = header; + } + + public JwtClaims getClaims() { + return claims; + } + + public void setClaims(JwtClaims claims) { + this.claims = claims; + } + + public String getSignature() { + return signature; + } + + public void setSignature(String signature) { + this.signature = signature; + } @Override public Jwe encryptAndSign(Jwe jwe) {