deleted local JOSE implementation classes

pull/306/merge
Justin Richer 2013-02-19 13:22:09 -05:00
parent 46f0e6f3cb
commit 6dc9020a31
25 changed files with 0 additions and 2783 deletions

View File

@ -1,120 +0,0 @@
package org.mitre.jwe.model;
import java.util.List;
import org.apache.commons.codec.binary.Base64;
import org.mitre.jwt.model.Jwt;
import org.mitre.jwt.model.JwtHeader;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.gson.JsonObject;
/**
*
*
* 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.
* @author DERRYBERRY
*
*/
public class Jwe extends Jwt {
private byte[] encryptedKey;
private byte[] ciphertext;
public Jwe() {
super();
this.encryptedKey = null;
this.ciphertext = null;
}
public Jwe(JweHeader header, byte[] encryptedKey, byte[] ciphertext, String integrityValue) {
super(header, null, integrityValue);
this.encryptedKey = encryptedKey;
this.ciphertext = ciphertext;
}
/*
public Jwe(String headerBase64, String encryptedKeyBase64, String cipherTextBase64, String integrityValueBase64) {
byte[] decodedEncryptedKey = Base64.decodeBase64(encryptedKeyBase64.getBytes());
byte[] decodedCipherText = Base64.decodeBase64(cipherTextBase64.getBytes());
this.header = new JweHeader(headerBase64);
this.encryptedKey = decodedEncryptedKey;
this.ciphertext = decodedCipherText;
setSignature(integrityValueBase64);
}
*/
public JweHeader getHeader() {
return (JweHeader) super.getHeader();
}
/**
* Set the header, wrapping it in a JweHeader if necessary
*/
public void setHeader(JwtHeader header) {
if (header instanceof JweHeader) {
super.setHeader(header);
} else {
super.setHeader(new JweHeader(header));
}
}
public byte[] getEncryptedKey() {
return encryptedKey;
}
public void setEncryptedKey(byte[] encryptedKey) {
this.encryptedKey = encryptedKey;
}
public byte[] getCiphertext() {
return ciphertext;
}
public void setCiphertext(byte[] ciphertext) {
this.ciphertext = ciphertext;
}
@Override
public String getSignatureBase() {
String h64 = new String(Base64.encodeBase64URLSafe(getHeader().toJsonString().getBytes()));
String e64 = new String(Base64.encodeBase64URLSafe(getEncryptedKey()));
String c64 = new String(Base64.encodeBase64URLSafe(getCiphertext()));
return h64 + "." + e64 + "." + c64;
}
public static Jwe parse(String s) {
// null string is a null token
if (s == null) {
return null;
}
// split on the dots
List<String> parts = Lists.newArrayList(Splitter.on(".").split(s));
if (parts.size() != 4) {
throw new IllegalArgumentException("Invalid JWE format.");
}
String h64 = parts.get(0);
String e64 = parts.get(1);
String c64 = parts.get(2);
String i64 = parts.get(3);
byte[] decodedEncryptedKey = Base64.decodeBase64(e64.getBytes());
byte[] decodedCipherText = Base64.decodeBase64(c64.getBytes());
Jwe jwe = new Jwe(new JweHeader(h64), decodedEncryptedKey, decodedCipherText, i64);
return jwe;
}
}

View File

@ -1,165 +0,0 @@
package org.mitre.jwe.model;
import java.util.Map.Entry;
import org.mitre.jwt.model.JwtHeader;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
public class JweHeader extends JwtHeader{
public static final String INTEGRITY = "int";
public static final String INITIALIZATION_VECTOR = "iv";
public static final String EPHEMERAL_PUBLIC_KEY = "epk";
public static final String COMPRESSION_ALGORITHM = "zip";
public static final String JSON_SET_URL = "jku";
public static final String JSON_WEB_KEY = "jwk";
public static final String X509_URL = "x5u";
public static final String X509_CERTIFICATE_THUMBPRINT = "x5t";
public static final String X509_CERTIFICATE_CHAIN = "x5c";
public static final String KEY_ID = "kid";
public static final String KEY_DERIVATION_FUNCTION = "kdf";
public JweHeader(){
super();
}
public JweHeader(JsonObject object){
super(object);
}
public JweHeader(String b64) {
super(b64);
}
public JweHeader(JwtHeader jwtHeader) {
super(jwtHeader);
}
/**
* Load all claims from the given json object into this object
*/
@Override
public void loadFromJsonObject(JsonObject json) {
JsonObject pass = new JsonObject();
for (Entry<String, JsonElement> element : json.entrySet()) {
if (element.getValue().isJsonNull()) {
pass.add(element.getKey(), element.getValue());
} else if (element.getKey().equals(INTEGRITY)) {
this.setIntegrity(json.get(INTEGRITY).getAsString());
} else if (element.getKey().equals(INITIALIZATION_VECTOR)) {
this.setIv(json.get(INITIALIZATION_VECTOR).getAsString());
} else if (element.getKey().equals(EPHEMERAL_PUBLIC_KEY)) {
this.setEphemeralPublicKey(json.get(EPHEMERAL_PUBLIC_KEY).getAsString());
} else if (element.getKey().equals(COMPRESSION_ALGORITHM)) {
this.setCompressionAlgorithm(json.get(COMPRESSION_ALGORITHM).getAsString());
} else if (element.getKey().equals(JSON_SET_URL)) {
this.setJku(json.get(JSON_SET_URL).getAsString());
} else if (element.getKey().equals(JSON_WEB_KEY)) {
this.setJsonWebKey(json.get(JSON_WEB_KEY).getAsString());
} else if (element.getKey().equals(X509_URL)) {
this.setX509Url(json.get(X509_URL).getAsString());
} else if (element.getKey().equals(X509_CERTIFICATE_THUMBPRINT)) {
this.setX509CertThumbprint(json.get(X509_CERTIFICATE_THUMBPRINT).getAsString());
} else if (element.getKey().equals(X509_CERTIFICATE_CHAIN)) {
this.setX509CertChain(json.get(X509_CERTIFICATE_CHAIN).getAsString());
} else if (element.getKey().equals(KEY_ID)) {
this.setKeyId(json.get(KEY_ID).getAsString());
} else {
pass.add(element.getKey(), element.getValue());
}
}
super.loadFromJsonObject(pass);
}
public String getIntegrity() {
return getClaimAsString(INTEGRITY);
}
public String getInitializationVector() {
return getClaimAsString(INITIALIZATION_VECTOR);
}
public String getEphemeralPublicKey() {
return getClaimAsString(EPHEMERAL_PUBLIC_KEY);
}
public String getCompressionAlgorithm() {
return getClaimAsString(COMPRESSION_ALGORITHM);
}
public String getJsonSetUrl() {
return getClaimAsString(JSON_SET_URL);
}
public String getJsonWebKey() {
return getClaimAsString(JSON_WEB_KEY);
}
public String getX509Url() {
return getClaimAsString(X509_URL);
}
public String getX509CertificateThumbprint() {
return getClaimAsString(X509_CERTIFICATE_THUMBPRINT);
}
public String getX509CertificateChain() {
return getClaimAsString(X509_CERTIFICATE_CHAIN);
}
public String getKeyId() {
return getClaimAsString(KEY_ID);
}
public String getKeyDerivationFunction() {
return getClaimAsString(KEY_DERIVATION_FUNCTION);
}
public void setIv(String iv) {
setClaim(INITIALIZATION_VECTOR, iv);
}
public void setJku(String jku) {
setClaim(JSON_SET_URL, jku);
}
public void setIntegrity(String integrity) {
setClaim(INTEGRITY, integrity);
}
public void setEphemeralPublicKey(String epk) {
setClaim(EPHEMERAL_PUBLIC_KEY, epk);
}
public void setCompressionAlgorithm(String zip) {
setClaim(COMPRESSION_ALGORITHM, zip);
}
public void setJsonWebKey(String jwk) {
setClaim(JSON_WEB_KEY, jwk);
}
public void setX509Url(String x5u) {
setClaim(X509_URL, x5u);
}
public void setX509CertThumbprint(String x5t) {
setClaim(X509_CERTIFICATE_THUMBPRINT, x5t);
}
public void setX509CertChain(String x5c) {
setClaim(X509_CERTIFICATE_CHAIN, x5c);
}
public void setKeyId(String kid) {
setClaim(KEY_ID, kid);
}
public void setKeyDerivationFunction(String kdf) {
setClaim(KEY_DERIVATION_FUNCTION, kdf);
}
}

View File

@ -1,74 +0,0 @@
package org.mitre.jwk.model;
import com.google.gson.JsonObject;
public abstract class AbstractJwk implements Jwk{
public static final String ALGORITHM = "alg";
public static final String USE = "use";
public static final String KEY_ID = "kid";
private String kid;
private String alg;
private String use;
public AbstractJwk(JsonObject object){
init(object);
}
/* (non-Javadoc)
* @see org.mitre.jwk.model.Jwk2#getAlg()
*/
@Override
public String getAlg() {
return alg;
}
public void setAlg(String alg) {
this.alg = alg;
}
/* (non-Javadoc)
* @see org.mitre.jwk.model.Jwk2#getKid()
*/
@Override
public String getKid() {
return kid;
}
public void setKid(String kid) {
this.kid = kid;
}
/* (non-Javadoc)
* @see org.mitre.jwk.model.Jwk2#getUse()
*/
@Override
public String getUse() {
return use;
}
public void setUse(String use) {
this.use = use;
}
public JsonObject toJsonObject() {
JsonObject export = new JsonObject();
export.addProperty(ALGORITHM, getAlg());
export.addProperty(USE, getUse());
export.addProperty(KEY_ID, getKid());
return export;
}
protected void init(JsonObject object){
if(object.get(ALGORITHM) != null){
setAlg(object.get(ALGORITHM).getAsString());
}
if(object.get(KEY_ID) != null){
setKid(object.get(KEY_ID).getAsString());
}
if(object.get(USE) != null){
setUse(object.get(USE).getAsString());
}
}
}

View File

@ -1,103 +0,0 @@
package org.mitre.jwk.model;
import java.math.BigInteger;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PublicKey;
import java.security.spec.ECFieldF2m;
import java.security.spec.EllipticCurve;
import java.security.spec.InvalidKeySpecException;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
import org.bouncycastle.math.ec.ECCurve;
import com.google.gson.JsonObject;
public class EllipticCurveJwk extends AbstractJwk {
public static final String CURVE = "crv";
public static final String X = "x";
public static final String Y = "y";
private String crv;
private String x;
private String y;
JsonObject object = new JsonObject();
public String getCrv() {
return crv;
}
public void setCrv(String crv) {
this.crv = crv;
}
public String getX() {
return x;
}
public void setX(String x) {
this.x = x;
}
public String getY() {
return y;
}
public void setY(String y) {
this.y = y;
}
public EllipticCurveJwk(JsonObject object) {
super(object);
}
@Override
public JsonObject toJsonObject() {
JsonObject obj = super.toJsonObject();
obj.addProperty(CURVE, getCrv());
obj.addProperty(X, getX());
obj.addProperty(Y, getY());
return obj;
}
public void init(JsonObject object){
super.init(object);
setCrv(object.get(CURVE).getAsString());
setX(object.get(X).getAsString());
setY(object.get(Y).getAsString());
}
@Override
public PublicKey getKey() throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException {
// TODO Auto-generated method stub
byte[] x_byte = Base64.decodeBase64(x);
BigInteger x_int = new BigInteger(x_byte);
byte[] y_byte = Base64.decodeBase64(y);
BigInteger y_int = new BigInteger(y_byte);
ECNamedCurveParameterSpec curveSpec = ECNamedCurveTable.getParameterSpec(crv);
BigInteger orderOfGen = curveSpec.getH();
int cofactor = Math.abs(curveSpec.getN().intValue());
ECCurve crv = curveSpec.getCurve();
BigInteger a = crv.getA().toBigInteger();
BigInteger b = crv.getB().toBigInteger();
int fieldSize = crv.getFieldSize();
ECFieldF2m field = new ECFieldF2m(fieldSize);
EllipticCurve curve = new EllipticCurve(field, a, b);
//ECPoint.Fp point = new ECPoint.Fp(curve, arg1, arg2);
return null;
//ECParameterSpec paramSpec = new ECParameterSpec(curve, point, orderOfGen, cofactor);
//ECPublicKeySpec spec = new ECPublicKeySpec(point, paramSpec);
//PublicKey key = new JCEECPublicKey("ECDCA", spec);
//return key;
}
}

View File

@ -1,18 +0,0 @@
package org.mitre.jwk.model;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.spec.InvalidKeySpecException;
public interface Jwk {
public abstract String getAlg();
public abstract String getKid();
public abstract String getUse();
public abstract Key getKey() throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException;
}

View File

@ -1,72 +0,0 @@
package org.mitre.jwk.model;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPublicKeySpec;
import org.apache.commons.codec.binary.Base64;
import com.google.gson.JsonObject;
public class Rsa extends AbstractJwk{
public static final String MODULUS = "mod";
public static final String EXPONENT = "exp";
private String mod;
private String exp;
public String getMod() {
return mod;
}
public void setMod(String mod) {
this.mod = mod;
}
public String getExp() {
return exp;
}
public void setExp(String exp) {
this.exp = exp;
}
public Rsa(JsonObject object){
super(object);
}
public void init(JsonObject object){
super.init(object);
setMod(object.get(MODULUS).getAsString());
setExp(object.get(EXPONENT).getAsString());
}
@Override
public JsonObject toJsonObject() {
JsonObject export = super.toJsonObject();
export.addProperty(MODULUS, getMod());
export.addProperty(EXPONENT, getExp());
return export;
}
@Override
public PublicKey getKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
byte[] modulusByte = Base64.decodeBase64(mod);
BigInteger modulus = new BigInteger(modulusByte);
byte[] exponentByte = Base64.decodeBase64(exp);
BigInteger exponent = new BigInteger(exponentByte);
RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent);
KeyFactory factory = KeyFactory.getInstance("RSA");
PublicKey pub = factory.generatePublic(spec);
return pub;
}
}

View File

@ -1,50 +0,0 @@
package org.mitre.jwt.encryption;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import com.google.common.primitives.Ints;
public abstract class AbstractJweDecrypter implements JweDecrypter {
long MAX_HASH_INPUTLEN = Long.MAX_VALUE;
long UNSIGNED_INT_MAX_VALUE = 4294967395L;
public byte[] generateContentKey(byte[] cmk, int keyDataLen, byte[] type) throws NoSuchAlgorithmException {
MessageDigest md = null;
//HUGE DISCLAIMER: this won't work on windows machines that don't have jce unlimited security files installed.
//without it, keys can't be over 128 bit in length, and SHA-128 doesn't work for message digest.
//use keyDataLen to determine instance
md = MessageDigest.getInstance("SHA-" + Integer.toString(keyDataLen));
keyDataLen = keyDataLen / 8;
byte[] key = new byte[keyDataLen];
int hashLen = md.getDigestLength();
int reps = keyDataLen / hashLen;
if (reps > UNSIGNED_INT_MAX_VALUE) {
throw new IllegalArgumentException("Key derivation failed");
}
int counter = 1;
byte[] counterInBytes = Ints.toByteArray(counter);
if ((counterInBytes.length + cmk.length + type.length) * 8 > MAX_HASH_INPUTLEN) {
throw new IllegalArgumentException("Key derivation failed");
}
for (int i = 0; i <= reps; i++) {
md.reset();
md.update(Ints.toByteArray(i + 1));
md.update(cmk);
md.update(type);
byte[] hash = md.digest();
if (i < reps) {
System.arraycopy(hash, 0, key, hashLen * i, hashLen);
} else {
System.arraycopy(hash, 0, key, hashLen * i, keyDataLen % hashLen);
}
}
return key;
}
}

View File

@ -1,50 +0,0 @@
package org.mitre.jwt.encryption;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import com.google.common.primitives.Ints;
public abstract class AbstractJweEncrypter implements JweEncrypter {
public MessageDigest md;
public byte[] generateContentKey(byte[] cmk, int keyDataLen, byte[] type) throws NoSuchAlgorithmException {
//HUGE DISCLAIMER: this won't work on windows machines that don't have jce unlimited security files installed.
//without it, keys can't be over 128 bit in length, and SHA-128 doesn't work for message digest.
//Use keyDataLen to determine instance
md = MessageDigest.getInstance("SHA-" + Integer.toString(keyDataLen));
long MAX_HASH_INPUTLEN = Long.MAX_VALUE;
long UNSIGNED_INT_MAX_VALUE = 4294967395L;
keyDataLen = keyDataLen / 8;
byte[] key = new byte[keyDataLen];
int hashLen = md.getDigestLength();
int reps = keyDataLen / hashLen;
if (reps > UNSIGNED_INT_MAX_VALUE) {
throw new IllegalArgumentException("Key derivation failed");
}
int counter = 1;
byte[] counterInBytes = Ints.toByteArray(counter);
if ((counterInBytes.length + cmk.length + type.length) * 8 > MAX_HASH_INPUTLEN) {
throw new IllegalArgumentException("Key derivation failed");
}
for (int i = 0; i <= reps; i++) {
md.reset();
md.update(Ints.toByteArray(i + 1));
md.update(cmk);
md.update(type);
byte[] hash = md.digest();
if (i < reps) {
System.arraycopy(hash, 0, key, hashLen * i, hashLen);
} else {
System.arraycopy(hash, 0, key, hashLen * i, keyDataLen % hashLen);
}
}
return key;
}
}

View File

@ -1,39 +0,0 @@
package org.mitre.jwt.encryption;
import org.apache.commons.lang.StringUtils;
public enum JweAlgorithms {
//Key Derivation Function Values
CS256("256"),
CS384("384"),
CS512("512"),
//Encryption Method Values
A128GCM("GCM"),
A256GCM("GCM"),
A128CBC("CBC"),
A256CBC("CBC");
private final String value;
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

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

View File

@ -1,29 +0,0 @@
package org.mitre.jwt.encryption;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
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;
import com.google.gson.JsonIOException;
import com.google.gson.JsonSyntaxException;
public interface JweEncrypter {
public byte[] encryptKey(Jwe jwe, byte[] cmk) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException;
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, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, InvalidKeySpecException;
public byte[] generateContentKey(byte[] cmk, int keyDataLen, byte[] type) throws NoSuchAlgorithmException;
}

View File

@ -1,112 +0,0 @@
package org.mitre.jwt.encryption.impl;
import java.security.InvalidAlgorithmParameterException;
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 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.JweAlgorithms;
public class RsaDecrypter extends AbstractJweDecrypter {
private PublicKey publicKey;
private PrivateKey privateKey;
@Override
public Jwe decrypt(String encryptedJwe) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
Jwe jwe = Jwe.parse(encryptedJwe);
String alg = jwe.getHeader().getAlgorithm();
if(alg.equals("RSA1_5") || alg.equals("RSA-OAEP")) {
//decrypt to get cmk to be used for cek and cik
jwe.setEncryptedKey(decryptEncryptionKey(jwe));
//generation of cek and cik
byte[] contentEncryptionKey = null;
//check what the key length is
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());
//decrypt ciphertext to get claims
jwe.setCiphertext(decryptCipherText(jwe, contentEncryptionKey));
} else {
throw new IllegalArgumentException(jwe.getHeader().getEncryptionMethod() + " is not a valid decrypting algorithm");
}
return jwe;
}
@Override
public byte[] decryptCipherText(Jwe jwe, byte[] contentEncryptionKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
byte[] iv = new byte[16];
iv = Base64.decodeBase64(jwe.getHeader().getInitializationVector());
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")) {
String mode = JweAlgorithms.getByName(encMethod);
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());
return clearText;
} else {
throw new IllegalArgumentException(jwe.getHeader().getEncryptionMethod() + " is not an implemented encryption method");
}
}
@Override
public byte[] decryptEncryptionKey(Jwe jwe) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
if(jwe.getHeader().getAlgorithm().equals("RSA1_5")){
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, getPrivateKey());
byte[] contentMasterKey = cipher.doFinal(jwe.getEncryptedKey());
return contentMasterKey;
} else {
throw new IllegalArgumentException(jwe.getHeader().getAlgorithm() + " is not an implemented algorithm");
}
}
public PublicKey getPublicKey() {
return publicKey;
}
public void setPublicKey(PublicKey publicKey) {
this.publicKey = publicKey;
}
public PrivateKey getPrivateKey() {
return privateKey;
}
public void setPrivateKey(PrivateKey privateKey) {
this.privateKey = privateKey;
}
}

View File

@ -1,132 +0,0 @@
package org.mitre.jwt.encryption.impl;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
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.JweAlgorithms;
import org.mitre.jwt.signer.impl.HmacSigner;
public class RsaEncrypter extends AbstractJweEncrypter {
private PublicKey publicKey;
private PrivateKey privateKey;
public Jwe encryptAndSign(Jwe jwe) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, InvalidKeySpecException {
String alg = jwe.getHeader().getAlgorithm();
String integrityAlg = jwe.getHeader().getIntegrity();
if(alg.equals("RSA1_5") || alg.equals("RSA-OAEP")) {
//generate random content master key
//check what the key length is
String kdf = jwe.getHeader().getKeyDerivationFunction();
String keyLength = JweAlgorithms.getByName(kdf);
int keyBitLength = Integer.parseInt(keyLength);
byte[] contentMasterKey = new byte[keyBitLength];
new Random().nextBytes(contentMasterKey);
byte[] contentEncryptionKey = null;
byte[] contentIntegrityKey = null;
//generate cek and cik
contentEncryptionKey = generateContentKey(contentMasterKey, keyBitLength, "Encryption".getBytes());
contentIntegrityKey = generateContentKey(contentMasterKey, keyBitLength, "Integrity".getBytes());
//encrypt claims and cmk to get ciphertext and encrypted key
jwe.setCiphertext(encryptClaims(jwe, contentEncryptionKey));
jwe.setEncryptedKey(encryptKey(jwe, contentMasterKey));
//Signer must be hmac
if(integrityAlg.equals("HS256") || integrityAlg.equals("HS384") || integrityAlg.equals("HS512")){
HmacSigner hmacSigner = new HmacSigner(contentIntegrityKey);
jwe = (Jwe) hmacSigner.sign(jwe);
} else {
throw new IllegalArgumentException(integrityAlg + " is not a valid integrity value algorithm for signing.");
}
} else {
throw new IllegalArgumentException(alg + " is not a valid encrypting algorithm.");
}
return jwe;
}
public byte[] encryptKey(Jwe jwe, byte[] contentMasterKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
if(jwe.getHeader().getAlgorithm().equals("RSA1_5")){
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, getPublicKey());
byte[] encryptedKey = cipher.doFinal(contentMasterKey);
return encryptedKey;
} else {
throw new IllegalArgumentException(jwe.getHeader().getAlgorithm() + " is not a supported algorithm");
}
}
public byte[] encryptClaims(Jwe jwe, byte[] contentEncryptionKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, InvalidKeySpecException {
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));
}
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")) {
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;
} else {
throw new IllegalArgumentException(jwe.getHeader().getEncryptionMethod() + " is not a supported encryption method");
}
}
public PublicKey getPublicKey() {
return publicKey;
}
public void setPublicKey(PublicKey publicKey) {
this.publicKey = publicKey;
}
public PrivateKey getPrivateKey() {
return privateKey;
}
public void setPrivateKey(PrivateKey privateKey) {
this.privateKey = privateKey;
}
}

View File

@ -1,266 +0,0 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.mitre.jwt.model;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.codec.binary.Base64;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import com.google.gson.reflect.TypeToken;
/**
* Generic container for JSON-based claims. Backed with a {@link Map} that preserves
* insertion order. Several convenience methods for getting and setting claims in different
* formats.
* @author jricher
*
*/
public class ClaimSet {
private String jsonString;
// the LinkedHashMap preserves insertion order
private Map<String, Object> claims = new LinkedHashMap<String, Object>();
public ClaimSet() {
}
public ClaimSet(JsonObject json) {
loadFromJsonObject(json);
}
public ClaimSet(String b64) {
loadFromBase64JsonObjectString(b64);
}
public ClaimSet(ClaimSet claimSet) {
loadFromClaimSet(claimSet);
}
/**
* Get an extension claim
*/
public Object getClaim(String key) {
return claims.get(key);
}
/**
* Get a claim as a string
*/
public String getClaimAsString(String key) {
Object v = claims.get(key);
if (v != null) {
return v.toString();
} else {
return null;
}
}
/**
* Get a claim as a Date
*/
public Date getClaimAsDate(String key) {
Object v = claims.get(key);
if (v != null) {
if (v instanceof Date) {
return (Date) v;
} else if (v instanceof Long) {
return new Date((Long) v);
} else {
return null;
}
} else {
return null;
}
}
// TODO: not convinced I like this construct
public List getClaimAsList(String key) {
Object v = claims.get(key);
if (v != null) {
if (v instanceof List<?>) {
return (List) v;
} else {
// return a list of the singular element
return Lists.newArrayList(v);
}
} else {
return null;
}
}
/**
* Set an extension claim
*/
public void setClaim(String key, Object value) {
invalidateString();
claims.put(key, value);
}
/**
* Set a primitive claim
*/
public void setClaim(String key, JsonPrimitive prim) {
invalidateString();
if (prim == null) {
// in case we get here with a primitive null
claims.put(key, prim);
} else if (prim.isBoolean()) {
claims.put(key, prim.getAsBoolean());
} else if (prim.isNumber()) {
claims.put(key, prim.getAsNumber());
} else if (prim.isString()) {
claims.put(key, prim.getAsString());
}
}
private void invalidateString() {
jsonString = null;
}
/**
* Remove an extension claim
*/
public Object removeClaim(String key) {
invalidateString();
return claims.remove(key);
}
/**
* Clear all claims from this ClaimSet
* @see java.util.Map#clear()
*/
public void clear() {
invalidateString();
claims.clear();
}
/**
* Get a copy of this claim set as a JsonObject. The JsonObject is not
* backed by a live copy of this ClaimSet.
* @return a copy of the data in this header in a JsonObject
*/
public JsonObject getAsJsonObject() {
Gson g = new Gson();
JsonObject o = new JsonObject();
/*
* We step through the claims object and serialize the internal values as
* appropriate to JsonElements.
*/
if (this.claims != null) {
for (Map.Entry<String, Object> claim : this.claims.entrySet()) {
if (claim.getValue() instanceof JsonElement) {
// raw JSON elements get passed through directly
o.add(claim.getKey(), (JsonElement)claim.getValue());
} else if (claim.getValue() instanceof String) {
o.addProperty(claim.getKey(), (String)claim.getValue());
} else if (claim.getValue() instanceof Number) {
o.addProperty(claim.getKey(), (Number)claim.getValue());
} else if (claim.getValue() instanceof Boolean) {
o.addProperty(claim.getKey(), (Boolean)claim.getValue());
} else if (claim.getValue() instanceof Character) {
o.addProperty(claim.getKey(), (Character)claim.getValue());
} else if (claim.getValue() instanceof Date) {
// dates get serialized out as integers
o.addProperty(claim.getKey(), ((Date)claim.getValue()).getTime() / 1000L);
} else if (claim.getValue() instanceof List) {
o.add(claim.getKey(), g.toJsonTree(claim.getValue(), new TypeToken<List<String>>(){}.getType()));
} else if (claim.getValue() != null) {
// try to put it in as a string
o.addProperty(claim.getKey(), g.toJson(claim.getValue()));
} else {
// otherwise add in as a null
o.add(claim.getKey(), null);
}
}
}
return o;
}
/**
* Load new claims from the given json object. Will replace any existing claims, but does not clear claim set.
*
* This function is intended to be overridden by subclasses for more exact data type and claim handling.
*
* @param json
*/
public void loadFromJsonObject(JsonObject json) {
for (Entry<String, JsonElement> element : json.entrySet()) {
if (element.getValue().isJsonNull()) {
// nulls get stored as java nulls
setClaim(element.getKey(), null);
} else if (element.getValue().isJsonPrimitive()){
// we handle all primitives in here
JsonPrimitive prim = element.getValue().getAsJsonPrimitive();
setClaim(element.getKey(), prim);
} else {
setClaim(element.getKey(), element.getValue());
}
}
}
/**
* Load a new claims set from a Base64 encoded JSON Object string and caches the string used
*/
public void loadFromBase64JsonObjectString(String b64) {
byte[] b64decoded = Base64.decodeBase64(b64);
JsonParser parser = new JsonParser();
JsonObject json = parser.parse(new InputStreamReader(new ByteArrayInputStream(b64decoded))).getAsJsonObject();
loadFromJsonObject(json);
// save the string we were passed in (decoded from base64)
jsonString = new String(b64decoded);
}
public void loadFromClaimSet(ClaimSet claimSet) {
loadFromJsonObject(claimSet.getAsJsonObject()); // we push to a JSON object and back to let subclasses override this
jsonString = claimSet.toJsonString(); // preserve the string on input
}
public String toJsonString() {
if(jsonString == null) {
jsonString = this.getAsJsonObject().toString();
}
return jsonString;
}
}

View File

@ -1,163 +0,0 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.mitre.jwt.model;
import java.util.List;
import org.apache.commons.codec.binary.Base64;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
public class Jwt {
private JwtHeader header;
private JwtClaims claims;
/**
* Base64Url encoded signature string
*/
private String signature;
public Jwt() {
setHeader(new JwtHeader());
setClaims(new JwtClaims());
setSignature(null); // unsigned by default
}
/**
* Create a Jwt from existing components
* @param header
* @param claims
* @param signature
*/
public Jwt(JwtHeader header, JwtClaims claims, String signature) {
setHeader(header);
setClaims(claims);
setSignature(signature);
}
/**
* @return the header
*/
public JwtHeader getHeader() {
return header;
}
/**
* @param header the header to set
*/
public void setHeader(JwtHeader header) {
this.header = header;
}
/**
* @return the claims
*/
public JwtClaims getClaims() {
return claims;
}
/**
* @param claims the claims to set
*/
public void setClaims(JwtClaims claims) {
this.claims = claims;
}
/**
* @return the signature
*/
public String getSignature() {
return signature;
}
/**
* @param signature the signature to set
*/
public void setSignature(String signature) {
this.signature = signature;
}
/**
* Return the canonical encoded string of this JWT, the header in Base64, a period ".", the claims in Base64, a period ".", and the signature in Base64.
*/
public String toString() {
return getSignatureBase() + "." + Strings.nullToEmpty(this.signature);
}
/**
* The signature base of a JWT is the header in Base64, a period ".", and the claims in Base64.
*/
public String getSignatureBase() {
String h64 = new String(Base64.encodeBase64URLSafe(header.toJsonString().getBytes()));
String c64 = new String(Base64.encodeBase64URLSafe(claims.toJsonString().getBytes()));
return h64 + "." + c64;
}
/**
* Parse a wire-encoded JWT
*/
public static Jwt parse(String s) {
// null string is a null token
if (s == null) {
return null;
}
// split on the dots
List<String> parts = Lists.newArrayList(Splitter.on(".").split(s));
if (parts.size() != 3) {
throw new IllegalArgumentException("Invalid JWT format.");
}
String h64 = parts.get(0);
String c64 = parts.get(1);
String s64 = parts.get(2);
// shuttle for return value
Jwt jwt = new Jwt(new JwtHeader(h64), new JwtClaims(c64), s64);
// TODO: save the wire-encoded string in the Jwt object itself?
return jwt;
}
}

View File

@ -1,256 +0,0 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.mitre.jwt.model;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.List;
import java.util.Map.Entry;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
public class JwtClaims extends ClaimSet {
public static final String TYPE = "typ";
public static final String JWT_ID = "jti";
public static final String SUBJECT = "sub";
public static final String AUDIENCE = "aud";
public static final String ISSUER = "iss";
public static final String ISSUED_AT = "iat";
public static final String NOT_BEFORE = "nbf";
public static final String EXPIRATION = "exp";
public static final String NONCE = "nonce";
/**
* ISO8601 / RFC3339 Date Format
*/
//public static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssz");
public JwtClaims() {
super();
}
public JwtClaims(JsonObject json) {
super(json);
}
public JwtClaims(String b64) {
super(b64);
}
public JwtClaims(JwtClaims jwtClaims) {
super(jwtClaims);
}
@Override
public void loadFromJsonObject(JsonObject json) {
JsonObject pass = new JsonObject();
for (Entry<String, JsonElement> element : json.entrySet()) {
if (element.getValue().isJsonNull()) {
pass.add(element.getKey(), element.getValue());
} else if (element.getKey().equals(EXPIRATION)) {
setExpiration(new Date(element.getValue().getAsLong() * 1000L));
} else if (element.getKey().equals(NOT_BEFORE)) {
setNotBefore(new Date(element.getValue().getAsLong() * 1000L));
} else if (element.getKey().equals(ISSUED_AT)) {
setIssuedAt(new Date(element.getValue().getAsLong() * 1000L));
} else if (element.getKey().equals(ISSUER)) {
setIssuer(element.getValue().getAsString());
} else if (element.getKey().equals(AUDIENCE)) {
if (element.getValue().isJsonArray()) {
// it's an array of strings, set it as such
//setAudience(element.getValue().getAsJsonArray());
Type collectionType = new TypeToken<List<String>>(){}.getType();
List<String> values = new Gson().fromJson(element.getValue(), collectionType);
setAudience(values);
} else {
// it's a single value
setAudience(element.getValue().getAsString());
}
} else if (element.getKey().equals(SUBJECT)) {
setSubject(element.getValue().getAsString());
} else if (element.getKey().equals(JWT_ID)) {
setJwtId(element.getValue().getAsString());
} else if (element.getKey().equals(TYPE)) {
setType(element.getValue().getAsString());
} else if (element.getKey().equals(NONCE)){
setNonce(element.getValue().getAsString());
}else {
pass.add(element.getKey(), element.getValue());
}
}
// load all the generic claims into this object
super.loadFromJsonObject(pass);
}
/**
* @return the expiration
*/
public Date getExpiration() {
return getClaimAsDate(EXPIRATION);
}
/**
* @param expiration the expiration to set
*/
public void setExpiration(Date expiration) {
setClaim(EXPIRATION, expiration);
}
/**
* @return the notBefore
*/
public Date getNotBefore() {
return getClaimAsDate(NOT_BEFORE);
}
/**
* @param notBefore the notBefore to set
*/
public void setNotBefore(Date notBefore) {
setClaim(NOT_BEFORE, notBefore);
}
/**
* @return the issuedAt
*/
public Date getIssuedAt() {
return getClaimAsDate(ISSUED_AT);
}
/**
* @param issuedAt the issuedAt to set
*/
public void setIssuedAt(Date issuedAt) {
setClaim(ISSUED_AT, issuedAt);
}
/**
* @return the issuer
*/
public String getIssuer() {
return getClaimAsString(ISSUER);
}
/**
* @param issuer the issuer to set
*/
public void setIssuer(String issuer) {
setClaim(ISSUER, issuer);
}
/**
* @return the audience
*/
public List<String> getAudience() {
return (List<String>) getClaimAsList(AUDIENCE);
}
/**
* @param audience the audience to set
*/
public void setAudience(String audience) {
setClaim(AUDIENCE, Lists.newArrayList(audience));
}
public void setAudience(List<String> audience) {
setClaim(AUDIENCE, audience);
}
/**
* @return the principal
*/
public String getSubject() {
return getClaimAsString(SUBJECT);
}
/**
* @param principal the principal to set
*/
public void setSubject(String principal) {
setClaim(SUBJECT, principal);
}
/**
* @return the jwtId
*/
public String getJwtId() {
return getClaimAsString(JWT_ID);
}
/**
* @param jwtId the jwtId to set
*/
public void setJwtId(String jwtId) {
setClaim(JWT_ID, jwtId);
}
/**
* @return the type
*/
public String getType() {
return getClaimAsString(TYPE);
}
/**
* @param type the type to set
*/
public void setType(String type) {
setClaim(TYPE, type);
}
/**
* @return the nonce
*/
public String getNonce() {
return getClaimAsString(NONCE);
}
/**
* @param nonce the nonce to set
*/
public void setNonce(String nonce) {
setClaim(NONCE, nonce);
}
/* (non-Javadoc)
* @see org.mitre.jwt.model.ClaimSet#getAsJsonObject()
*/
@Override
public JsonObject getAsJsonObject() {
JsonObject o = super.getAsJsonObject();
// special handling for audience claim
if (o.has(AUDIENCE) && o.get(AUDIENCE).isJsonArray()) {
JsonArray aud = o.get(AUDIENCE).getAsJsonArray();
// overwrite single-sized arrays as a string
if (aud.size() == 1) {
o.addProperty(AUDIENCE, aud.get(0).getAsString());
}
}
return o;
}
}

View File

@ -1,137 +0,0 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.mitre.jwt.model;
import java.util.Map.Entry;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
public class JwtHeader extends ClaimSet {
public static final String TYPE = "typ";
public static final String ALGORITHM = "alg";
public static final String ENCRYPTION_METHOD = "enc";
public static final String CONTENT_TYPE = "cty";
/**
* Make an empty header
*/
public JwtHeader() {
super();
}
/**
* Build a header from a JSON object
* @param json
*/
public JwtHeader(JsonObject json) {
super(json);
}
public JwtHeader(String b64) {
super(b64);
}
public JwtHeader(JwtHeader jwtHeader) {
super(jwtHeader);
}
/**
* Load all claims from the given json object into this object
*/
@Override
public void loadFromJsonObject(JsonObject json) {
JsonObject pass = new JsonObject();
for (Entry<String, JsonElement> element : json.entrySet()) {
if (element.getValue().isJsonNull()) {
pass.add(element.getKey(), element.getValue());
} else if (element.getKey().equals(TYPE)) {
this.setType(element.getValue().getAsString());
} else if (element.getKey().equals(ALGORITHM)) {
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());
}
}
// now load all the ones we didn't handle specially
super.loadFromJsonObject(pass);
}
/**
* @return the type
*/
public String getType() {
return getClaimAsString(TYPE);
}
/**
* @param type the type to set
*/
public void setType(String type) {
setClaim(TYPE, type);
}
/**
* @return the algorithm
*/
public String getAlgorithm() {
return getClaimAsString(ALGORITHM);
}
/**
* @param algorithm the algorithm to set
*/
public void setAlgorithm(String algorithm) {
setClaim(ALGORITHM, algorithm);
}
/**
* @return the encryptionMethod
*/
public String getEncryptionMethod() {
return getClaimAsString(ENCRYPTION_METHOD);
}
/**
* @param encryptionMethod the encryptionMethod to set
*/
public void setEncryptionMethod(String encryptionMethod) {
setClaim(ENCRYPTION_METHOD, encryptionMethod);
}
public static String getContentType() {
return CONTENT_TYPE;
}
public void setContentType(String cty) {
setClaim(CONTENT_TYPE, cty);
}
}

View File

@ -1,99 +0,0 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.mitre.jwt.signer;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import org.mitre.jwt.model.Jwt;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
public abstract class AbstractJwtSigner implements JwtSigner {
private JwsAlgorithm algorithm;
public AbstractJwtSigner(JwsAlgorithm algorithm) {
this.algorithm = algorithm;
}
/**
* @return the algorithm
*/
public JwsAlgorithm getAlgorithm() {
return algorithm;
}
/**
* @param algorithm the algorithm to set
*/
public void setAlgorithm(JwsAlgorithm algorithm) {
this.algorithm = algorithm;
}
/**
* Ensures that the 'alg' of the given JWT matches the {@link #algorithm} of this signer
* and signs the jwt.
*
* @param jwt the jwt to sign
* @return the signed jwt
* @throws NoSuchAlgorithmException
*/
@Override
public Jwt sign(Jwt jwt) throws NoSuchAlgorithmException {
//TODO: need a seperate check for Jwe. As is, it will change the alg param to be the enc param
/*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.getJwaName());
}*/
String sig = generateSignature(jwt.getSignatureBase());
jwt.setSignature(sig);
return jwt;
}
/* (non-Javadoc)
* @see org.mitre.jwt.JwtSigner#verify(java.lang.String)
*/
@Override
public boolean verify(String jwtString) throws NoSuchAlgorithmException {
// split on the dots
List<String> parts = Lists.newArrayList(Splitter.on(".").split(jwtString));
if (parts.size() != 3) {
throw new IllegalArgumentException("Invalid JWT format.");
}
String h64 = parts.get(0);
String c64 = parts.get(1);
String s64 = parts.get(2);
String expectedSignature = generateSignature(h64 + "." + c64);
return Strings.nullToEmpty(s64).equals(Strings.nullToEmpty(expectedSignature));
}
protected abstract String generateSignature(String signatureBase) throws NoSuchAlgorithmException;
}

View File

@ -1,95 +0,0 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.mitre.jwt.signer;
import java.util.HashMap;
import java.util.Map;
/**
* Enum to translate between the JWS defined algorithm names and the JSE algorithm names
*
* @author jricher
*
*/
public enum JwsAlgorithm {
// PLAINTEXT
NONE("plaintext", "none"),
// HMAC
HS256("HMACSHA256", "HS256"),
HS384("HMACSHA384", "HS384"),
HS512("HMACSHA512", "HS512"),
// RSA
RS256("SHA256withRSA", "RS256"),
RS384("SHA384withRSA", "RS384"),
RS512("SHA512withRSA", "RS512");
private static final Map<String, JwsAlgorithm> jwaLookup = new HashMap<String, JwsAlgorithm>();
private static final Map<String, JwsAlgorithm> jceLookup = new HashMap<String, JwsAlgorithm>();
static {
for (JwsAlgorithm alg : JwsAlgorithm.values()) {
jwaLookup.put(alg.getJwaName(), alg);
jceLookup.put(alg.getStandardName(), alg);
}
}
/**
* Returns the Algorithm for the JWS-registered name
*
* @param name
* @return
*/
public static JwsAlgorithm getByJwaName(String name) {
return jwaLookup.get(name);
}
public static JwsAlgorithm getByStandardName(String name) {
return jceLookup.get(name);
}
private final String standardName;
private final String jwaName;
/**
* Constructor of JwsAlgorithm
*
* @param standardName
*/
JwsAlgorithm(String standardName, String jwaName) {
this.standardName = standardName;
this.jwaName = jwaName;
}
/**
* Return the Java standard JwsAlgorithm name
*
* @return
*/
public String getStandardName() {
return standardName;
}
/**
* Return the JWA Standard name
* @return
*/
public String getJwaName() {
return jwaName;
}
}

View File

@ -1,30 +0,0 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.mitre.jwt.signer;
import java.security.NoSuchAlgorithmException;
import org.mitre.jwt.model.Jwt;
public interface JwtSigner {
public JwsAlgorithm getAlgorithm();
public Jwt sign(Jwt jwt) throws NoSuchAlgorithmException;
public boolean verify(String jwtString) throws NoSuchAlgorithmException;
}

View File

@ -1,192 +0,0 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.mitre.jwt.signer.impl;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.mitre.jwt.signer.AbstractJwtSigner;
import org.mitre.jwt.signer.JwsAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
/**
* JWT Signer using either the HMAC SHA-256, SHA-384, SHA-512 hash algorithm
*
* @author AANGANES, nemonik
*
*/
public class HmacSigner extends AbstractJwtSigner implements InitializingBean {
public static final String DEFAULT_PASSPHRASE = "changeit";
public static final JwsAlgorithm DEFAULT_ALGORITHM = JwsAlgorithm.HS256;
private static Logger logger = LoggerFactory.getLogger(HmacSigner.class);
private Mac mac;
private String passphrase = DEFAULT_PASSPHRASE;
/**
* Default constructor
*/
public HmacSigner() {
super(DEFAULT_ALGORITHM);
}
/**
* Create HMAC singer with default algorithm and passphrase as raw bytes
*
* @param passphraseAsRawBytes
* The passphrase as raw bytes
*/
public HmacSigner(byte[] passphraseAsRawBytes)
throws NoSuchAlgorithmException {
this(DEFAULT_ALGORITHM.getJwaName(), new String(passphraseAsRawBytes,
Charset.forName("UTF-8")));
}
/**
* Create HMAC singer with default algorithm and passphrase
*
* @param passwordAsRawBytes
* The passphrase as raw bytes
*/
public HmacSigner(String passphrase) throws NoSuchAlgorithmException {
this(DEFAULT_ALGORITHM.getJwaName(), passphrase);
}
/**
* Create HMAC singer with given algorithm and password as raw bytes
*
* @param algorithmName
* The Java standard name of the requested MAC algorithm
* @param passphraseAsRawBytes
* The passphrase as raw bytes
*/
public HmacSigner(String algorithmName, byte[] passphraseAsRawBytes)
throws NoSuchAlgorithmException {
this(algorithmName, new String(passphraseAsRawBytes,
Charset.forName("UTF-8")));
}
/**
* Create HMAC singer with given algorithm and passwords
*
* @param algorithmName
* The Java standard name of the requested MAC algorithm
* @param passphrase
* the passphrase
*/
public HmacSigner(String algorithmName, String passphrase) {
super(JwsAlgorithm.getByJwaName(algorithmName));
Assert.notNull(passphrase, "A passphrase must be supplied");
setPassphrase(passphrase);
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet(){
initializeMac();
}
/*
* (non-Javadoc)
*
* @see
* org.mitre.jwt.signer.AbstractJwtSigner#generateSignature(java.lang.String
* )
*/
@Override
public String generateSignature(String signatureBase) throws NoSuchAlgorithmException {
initializeMac();
if (passphrase == null) {
throw new IllegalArgumentException("Passphrase cannot be null");
}
try {
mac.init(new SecretKeySpec(getPassphrase().getBytes(), mac
.getAlgorithm()));
mac.update(signatureBase.getBytes("UTF-8"));
} catch (GeneralSecurityException e) {
logger.error("GeneralSecurityException in HmacSigner.java: ", e);
} catch (UnsupportedEncodingException e) {
logger.error("UnsupportedEncodingException in HmacSigner.java: ", e);
}
byte[] sigBytes = mac.doFinal();
String sig = new String(Base64.encodeBase64URLSafe(sigBytes));
// strip off any padding
sig = sig.replace("=", "");
return sig;
}
public String getPassphrase() {
return passphrase;
}
public void setPassphrase(byte[] rawbytes) {
this.setPassphrase(new String(rawbytes, Charset.forName("UTF-8")));
}
public void setPassphrase(String passphrase) {
this.passphrase = passphrase;
}
private void initializeMac() {
if (mac == null) {
try {
mac = Mac.getInstance(getAlgorithm().getStandardName());
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "HmacSigner [mac=" + mac + ", passphrase=" + passphrase + "]";
}
}

View File

@ -1,32 +0,0 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.mitre.jwt.signer.impl;
import org.mitre.jwt.signer.AbstractJwtSigner;
import org.mitre.jwt.signer.JwsAlgorithm;
public class PlaintextSigner extends AbstractJwtSigner {
public PlaintextSigner() {
super(JwsAlgorithm.NONE);
}
@Override
protected String generateSignature(String signatureBase) {
return null;
}
}

View File

@ -1,291 +0,0 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.mitre.jwt.signer.impl;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.util.List;
import org.apache.commons.codec.binary.Base64;
import org.mitre.jwt.encryption.impl.KeyStore;
import org.mitre.jwt.signer.AbstractJwtSigner;
import org.mitre.jwt.signer.JwsAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
/**
* JWT Signer using either the RSA SHA-256, SHA-384, SHA-512 hash algorithm
*
* @author AANGANES, nemonik
*
*/
public class RsaSigner extends AbstractJwtSigner implements InitializingBean {
private static Logger logger = LoggerFactory.getLogger(RsaSigner.class);
public static final String KEYPAIR_ALGORITHM = "RSA";
public static final String DEFAULT_PASSWORD = "changeit";
public static final JwsAlgorithm DEFAULT_ALGORITHM = JwsAlgorithm.RS256;
private KeyStore keystore;
private String alias;
private String password = DEFAULT_PASSWORD;
private PrivateKey privateKey;
private PublicKey publicKey;
private Signature signer;
/**
* Default constructor
*/
public RsaSigner() {
super(DEFAULT_ALGORITHM);
}
/**
* Creates an RsaSigner from an algorithm name, a Java Keystore, an alias
* for the key pair, and the default password to access. Key pairs created
* with larger bit sizes obviously create larger signatures.
*
* @param algorithmName
* The algorithm name
* @param keystore
* A Java Keystore containing the key pair
* @param alias
* The alias for the key pair
* @throws GeneralSecurityException
*/
public RsaSigner(String algorithmName, KeyStore keystore, String alias)
throws GeneralSecurityException {
this(algorithmName, keystore, alias, DEFAULT_PASSWORD);
}
/**
* Creates an RsaSigner from an algorithm name, a Java Keystore, an alias
* for the key pair, and the password to access. Key pairs created with
* larger bit sizes obviously create larger signatures.
*
* @param algorithmName
* The algorithm name
* @param keystore
* A Java Keystore containing the key pair
* @param alias
* The alias for the key pair
* @param password
* The password used to access and retrieve the key pair.
* @throws GeneralSecurityException
*/
public RsaSigner(String algorithmName, KeyStore keystore, String alias, String password) throws GeneralSecurityException {
super(JwsAlgorithm.getByJwaName(algorithmName));
setKeystore(keystore);
setAlias(alias);
setPassword(password);
loadKeysFromKeystore();
}
/**
* Creates an RsaSigner from an algorithm name, and key pair. Key pairs
* created with larger bit sizes obviously create larger signatures.
*
* @param algorithmName
* The JWA algorithm name
* @param publicKey
* The public key
* @param privateKey
* The private key
*/
public RsaSigner(String algorithmName, PublicKey publicKey, PrivateKey privateKey) {
super(JwsAlgorithm.getByJwaName(algorithmName));
this.publicKey = publicKey;
this.privateKey = privateKey;
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() throws NoSuchAlgorithmException, GeneralSecurityException {
initializeSigner();
}
/**
* Load the public and private keys from the keystore, identified with the configured alias and accessed with the configured password.
* @throws GeneralSecurityException
*/
private void loadKeysFromKeystore() {
Assert.notNull(keystore, "An keystore must be supplied");
Assert.notNull(alias, "A alias must be supplied");
Assert.notNull(password, "A password must be supplied");
KeyPair keyPair = null;
try {
keyPair = keystore.getKeyPairForAlias(alias, password);
} catch (GeneralSecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Assert.notNull(keyPair, "Either alias and/or password is not correct for keystore");
publicKey = keyPair.getPublic();
privateKey = keyPair.getPrivate();
}
/*
* (non-Javadoc)
*
* @see
* org.mitre.jwt.signer.AbstractJwtSigner#generateSignature(java.lang.String
* )
*/
@Override
public String generateSignature(String signatureBase) throws NoSuchAlgorithmException {
String sig = null;
initializeSigner();
try {
signer.initSign(privateKey);
signer.update(signatureBase.getBytes("UTF-8"));
byte[] sigBytes = signer.sign();
sig = (new String(Base64.encodeBase64URLSafe(sigBytes))).replace("=", "");
} catch (GeneralSecurityException e) {
logger.error("GeneralSecurityException in RsaSigner.java: ", e);
} catch (UnsupportedEncodingException e) {
logger.error("UnsupportedEncodingException in RsaSigner.java: ", e);
}
return sig;
}
public String getAlias() {
return alias;
}
public KeyStore getKeystore() {
return keystore;
}
public String getPassword() {
return password;
}
public PrivateKey getPrivateKey() {
return privateKey;
}
public PublicKey getPublicKey() {
return publicKey;
}
public void setAlias(String alias) {
this.alias = alias;
}
public void setKeystore(KeyStore keyStore) {
this.keystore = keyStore;
}
public void setPassword(String password) {
this.password = password;
}
public void setPrivateKey(RSAPrivateKey privateKey) {
this.privateKey = privateKey;
}
private void initializeSigner() throws NoSuchAlgorithmException{
if (this.keystore != null && this.alias != null && this.password != null) {
// if it looks like we're configured with a keystore, load it here
loadKeysFromKeystore();
}
if (signer == null) {
signer = Signature.getInstance(getAlgorithm().getStandardName());
}
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "RsaSigner [keystore=" + keystore + ", alias=" + alias
+ ", password=" + password + ", privateKey=" + privateKey
+ ", publicKey=" + publicKey + ", signer=" + signer + "]";
}
/*
* (non-Javadoc)
*
* @see org.mitre.jwt.signer.AbstractJwtSigner#verify(java.lang.String)
*/
@Override
public boolean verify(String jwtString) {
boolean value = false;
// split on the dots
List<String> parts = Lists.newArrayList(Splitter.on(".").split(
jwtString));
if (parts.size() != 3) {
throw new IllegalArgumentException("Invalid JWT format.");
}
String h64 = parts.get(0);
String c64 = parts.get(1);
String s64 = parts.get(2);
String signingInput = h64 + "." + c64;
try {
initializeSigner();
signer.initVerify(publicKey);
signer.update(signingInput.getBytes("UTF-8"));
value = signer.verify(Base64.decodeBase64(s64));
} catch (GeneralSecurityException e) {
logger.error("GeneralSecurityException in RsaSigner.java: ", e);
} catch (UnsupportedEncodingException e) {
logger.error("UnsupportedEncodingException in RsaSigner.java: ", e);
}
return value;
}
}

View File

@ -1,70 +0,0 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.mitre.jwt.signer.service;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import org.mitre.jwt.model.Jwt;
import org.mitre.jwt.signer.JwtSigner;
public interface JwtSigningAndValidationService {
/**
* Returns all public keys this service is configured with, indexed by key id
*
* @return
*/
public Map<String, JwtSigner> getAllSigners();
/**
* Checks the signature of the given JWT against all configured signers,
* returns true if at least one of the signers validates it.
*
* @param jwtString
* the string representation of the JWT as sent on the wire
* @return true if the signature is valid, false if not
* @throws NoSuchAlgorithmException
*/
public boolean validateSignature(String jwtString);
/**
* Called to sign a jwt in place for a client that hasn't registered a preferred signing algorithm.
* Use the default algorithm to sign.
*
* @param jwt the jwt to sign
* @return the signed jwt
* @throws NoSuchAlgorithmException
*/
public void signJwt(Jwt jwt) throws NoSuchAlgorithmException;
/**
* Sign a jwt using the selected algorithm. The algorithm is selected using the String parameter values specified
* in the JWT spec, section 6. I.E., "HS256" means HMAC with SHA-256 and corresponds to our HmacSigner class.
*
* @param jwt the jwt to sign
* @param alg the name of the algorithm to use, as specified in JWS s.6
* @return the signed jwt
*/
//TODO: implement later; only need signJwt(Jwt jwt) for now
//public Jwt signJwt(Jwt jwt, String alg);
/**
* TODO: method to sign a jwt using a specified algorithm and a key id
*/
}

View File

@ -1,166 +0,0 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.mitre.jwt.signer.service.impl;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import org.mitre.jwt.model.Jwt;
import org.mitre.jwt.signer.JwtSigner;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.mitre.openid.connect.config.ConfigurationPropertiesBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
public class DefaultJwtSigningAndValidationService implements JwtSigningAndValidationService, InitializingBean {
@Autowired
private ConfigurationPropertiesBean configBean;
// map of identifier to signer
private Map<String, ? extends JwtSigner> signers = new HashMap<String, JwtSigner>();
private static Logger logger = LoggerFactory.getLogger(DefaultJwtSigningAndValidationService.class);
/**
* default constructor
*/
public DefaultJwtSigningAndValidationService() {
}
/**
* Create DefaultJwtSigningAndValidationService
*
* @param signer
* List of JwtSigners to associate with this service
*/
public DefaultJwtSigningAndValidationService(Map<String, ? extends JwtSigner> signer) {
setSigners(signer);
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet(){
// used for debugging...
if (!signers.isEmpty()) {
logger.info(this.toString());
}
logger.info("DefaultJwtSigningAndValidationService is open for business");
}
/**
*
* Returns a copy of the collection of signers.
*
* @see
* org.mitre.jwt.signer.service.JwtSigningAndValidationService#getAllPublicKeys
* ()
*/
@Override
public Map<String, JwtSigner> getAllSigners() {
Map<String, JwtSigner> map = new HashMap<String, JwtSigner>();
map.putAll(signers);
return map;
}
/**
* Set the JwtSigners associated with this service
*
* @param signers
* List of JwtSigners to associate with this service
*/
public void setSigners(Map<String, ? extends JwtSigner> signers) {
this.signers = signers;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "DefaultJwtSigningAndValidationService [signers=" + signers + "]";
}
/**
* @return the configBean
*/
public ConfigurationPropertiesBean getConfigBean() {
return configBean;
}
/**
* @param configBean the configBean to set
*/
public void setConfigBean(ConfigurationPropertiesBean configBean) {
this.configBean = configBean;
}
/**
* Sign a jwt in place using the configured default signer.
* @throws NoSuchAlgorithmException
*/
@Override
public void signJwt(Jwt jwt) throws NoSuchAlgorithmException {
String signerId = configBean.getDefaultJwtSigner();
JwtSigner signer = getSigners().get(signerId);
// set the signing algorithm in the JWT
jwt.getHeader().setAlgorithm(signer.getAlgorithm().getJwaName());
signer.sign(jwt);
}
/**
* Return the JwtSigners associated with this service
*
* @return
*/
public Map<String, ? extends JwtSigner> getSigners() {
return signers;
}
@Override
public boolean validateSignature(String jwtString) {
for (JwtSigner signer : getSigners().values()) {
try {
if (signer.verify(jwtString)) {
return true;
}
} catch (NoSuchAlgorithmException e) {
// ignore, signer didn't verify signature, try the next one
e.printStackTrace();
}
}
return false;
}
}