|
|
|
@ -3,10 +3,10 @@ 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.SignatureException;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
|
|
import org.apache.commons.codec.binary.Base64;
|
|
|
|
@ -15,6 +15,7 @@ import org.apache.commons.logging.LogFactory;
|
|
|
|
|
import org.mitre.jwt.signer.AbstractJwtSigner;
|
|
|
|
|
import org.mitre.jwt.signer.service.impl.KeyStore;
|
|
|
|
|
import org.springframework.beans.factory.InitializingBean;
|
|
|
|
|
import org.springframework.util.Assert;
|
|
|
|
|
|
|
|
|
|
import com.google.common.base.Splitter;
|
|
|
|
|
import com.google.common.collect.Lists;
|
|
|
|
@ -38,15 +39,15 @@ public class EcdsaSigner extends AbstractJwtSigner implements InitializingBean {
|
|
|
|
|
public enum Algorithm {
|
|
|
|
|
|
|
|
|
|
// Algorithm constants
|
|
|
|
|
ES256("SHA256withECDSA"),
|
|
|
|
|
ES384("SHA384withECDSA"),
|
|
|
|
|
ES512("SHA512withECDSA");
|
|
|
|
|
ES256("SHA256withECDSA"), ES384("SHA384withECDSA"), ES512(
|
|
|
|
|
"SHA512withECDSA");
|
|
|
|
|
|
|
|
|
|
public static final String DEFAULT = Algorithm.ES256.toString();
|
|
|
|
|
public static final String PREPEND = "ES";
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the Algorithm for the name
|
|
|
|
|
*
|
|
|
|
|
* @param name
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
@ -58,7 +59,8 @@ public class EcdsaSigner extends AbstractJwtSigner implements InitializingBean {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// corresponding type not found
|
|
|
|
|
throw new IllegalArgumentException("Algorithm name does not have a corresponding Algorithm");
|
|
|
|
|
throw new IllegalArgumentException(
|
|
|
|
|
"Algorithm name does not have a corresponding Algorithm");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private final String standardName;
|
|
|
|
@ -74,6 +76,7 @@ public class EcdsaSigner extends AbstractJwtSigner implements InitializingBean {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Return the Java standard algorithm name
|
|
|
|
|
*
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
public String getStandardName() {
|
|
|
|
@ -81,8 +84,6 @@ public class EcdsaSigner extends AbstractJwtSigner implements InitializingBean {
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static final String PROVIDER = "BC";
|
|
|
|
|
|
|
|
|
|
private static Log logger = LogFactory.getLog(EcdsaSigner.class);
|
|
|
|
|
|
|
|
|
|
public static final String KEYPAIR_ALGORITHM = "EC";
|
|
|
|
@ -90,7 +91,7 @@ public class EcdsaSigner extends AbstractJwtSigner implements InitializingBean {
|
|
|
|
|
|
|
|
|
|
private KeyStore keystore;
|
|
|
|
|
private String alias;
|
|
|
|
|
private String password;
|
|
|
|
|
private String password = DEFAULT_PASSWORD;
|
|
|
|
|
|
|
|
|
|
private PrivateKey privateKey;
|
|
|
|
|
private PublicKey publicKey;
|
|
|
|
@ -100,88 +101,123 @@ public class EcdsaSigner extends AbstractJwtSigner implements InitializingBean {
|
|
|
|
|
* Default constructor
|
|
|
|
|
*/
|
|
|
|
|
public EcdsaSigner() {
|
|
|
|
|
this(Algorithm.DEFAULT, null, null, DEFAULT_PASSWORD);
|
|
|
|
|
super(Algorithm.DEFAULT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates an EcdsaSigner 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 EcdsaSigner(String algorithmName, KeyStore keystore, String alias) {
|
|
|
|
|
public EcdsaSigner(String algorithmName, KeyStore keystore, String alias)
|
|
|
|
|
throws GeneralSecurityException {
|
|
|
|
|
this(algorithmName, keystore, alias, DEFAULT_PASSWORD);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates an EcdsaSigner 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 EcdsaSigner(String algorithmName, KeyStore keystore, String alias, String password) {
|
|
|
|
|
public EcdsaSigner(String algorithmName, KeyStore keystore, String alias,
|
|
|
|
|
String password) throws GeneralSecurityException {
|
|
|
|
|
super(algorithmName);
|
|
|
|
|
|
|
|
|
|
Assert.notNull(keystore, "A keystore must be supplied");
|
|
|
|
|
Assert.notNull(alias, "A alias must be supplied");
|
|
|
|
|
Assert.notNull(password, "A password must be supplied");
|
|
|
|
|
|
|
|
|
|
setKeystore(keystore);
|
|
|
|
|
setAlias(alias);
|
|
|
|
|
setPassword(password);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
signer = Signature.getInstance(Algorithm.getByName(algorithmName).getStandardName(), PROVIDER);
|
|
|
|
|
} catch (GeneralSecurityException e) {
|
|
|
|
|
// TODO Auto-generated catch block
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
KeyPair keyPair = keystore.getKeyPairForAlias(alias, password);
|
|
|
|
|
|
|
|
|
|
publicKey = keyPair.getPublic();
|
|
|
|
|
privateKey = keyPair.getPrivate();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates an RsaSigner from an algorithm name, and key pair. Key pairs
|
|
|
|
|
* created with larger bit sizes obviously create larger signatures.
|
|
|
|
|
*
|
|
|
|
|
* @param algorithmName
|
|
|
|
|
* The algorithm name
|
|
|
|
|
* @param publicKey
|
|
|
|
|
* The public key
|
|
|
|
|
* @param privateKey
|
|
|
|
|
* The private key
|
|
|
|
|
*/
|
|
|
|
|
public EcdsaSigner(String algorithmName, PublicKey publicKey, PrivateKey privateKey) {
|
|
|
|
|
public EcdsaSigner(String algorithmName, PublicKey publicKey,
|
|
|
|
|
PrivateKey privateKey) {
|
|
|
|
|
super(algorithmName);
|
|
|
|
|
|
|
|
|
|
Assert.notNull(publicKey, "A publicKey must be supplied");
|
|
|
|
|
Assert.notNull(privateKey, "A privateKey must be supplied");
|
|
|
|
|
|
|
|
|
|
this.publicKey = publicKey;
|
|
|
|
|
this.privateKey = privateKey;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* (non-Javadoc)
|
|
|
|
|
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
|
|
|
|
/*
|
|
|
|
|
* (non-Javadoc)
|
|
|
|
|
*
|
|
|
|
|
* @see
|
|
|
|
|
* org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public void afterPropertiesSet() throws Exception {
|
|
|
|
|
KeyPair keyPair = keystore.getKeyPairForAlias(alias, password);
|
|
|
|
|
|
|
|
|
|
publicKey = keyPair.getPublic();
|
|
|
|
|
privateKey = keyPair.getPrivate();
|
|
|
|
|
// Can throw a GeneralException
|
|
|
|
|
signer = Signature.getInstance(Algorithm.getByName(super.getAlgorithm())
|
|
|
|
|
.getStandardName()); // PROVIDER);
|
|
|
|
|
|
|
|
|
|
logger.debug( Algorithm.getByName(getAlgorithm()).getStandardName() + " ECDSA Signer ready for business");
|
|
|
|
|
logger.debug(Algorithm.getByName(getAlgorithm()).getStandardName()
|
|
|
|
|
+ " ECDSA Signer ready for business");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* (non-Javadoc)
|
|
|
|
|
* @see org.mitre.jwt.signer.AbstractJwtSigner#generateSignature(java.lang.String)
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
protected String generateSignature(String signatureBase) {
|
|
|
|
|
|
|
|
|
|
String sig = null;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
|
|
signer.initSign(privateKey);
|
|
|
|
|
signer.update(signatureBase.getBytes("UTF-8"));
|
|
|
|
|
} catch (GeneralSecurityException e) {
|
|
|
|
|
// TODO Auto-generated catch block
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
} catch (UnsupportedEncodingException e) {
|
|
|
|
|
// TODO Auto-generated catch block
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
byte[] sigBytes;
|
|
|
|
|
String sig = "";
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
sigBytes = signer.sign();
|
|
|
|
|
byte[] sigBytes = signer.sign();
|
|
|
|
|
sig = new String(Base64.encodeBase64URLSafe(sigBytes));
|
|
|
|
|
|
|
|
|
|
// strip off any padding
|
|
|
|
|
sig = sig.replace("=", "");
|
|
|
|
|
} catch (SignatureException e) {
|
|
|
|
|
// TODO Auto-generated catch block
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
|
|
|
|
|
} catch (GeneralSecurityException e) {
|
|
|
|
|
logger.error(e);
|
|
|
|
|
} catch (UnsupportedEncodingException e) {
|
|
|
|
|
logger.error(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return sig;
|
|
|
|
@ -215,8 +251,9 @@ public class EcdsaSigner extends AbstractJwtSigner implements InitializingBean {
|
|
|
|
|
this.password = password;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* (non-Javadoc)
|
|
|
|
|
/*
|
|
|
|
|
* (non-Javadoc)
|
|
|
|
|
*
|
|
|
|
|
* @see java.lang.Object#toString()
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
@ -226,7 +263,9 @@ public class EcdsaSigner extends AbstractJwtSigner implements InitializingBean {
|
|
|
|
|
+ ", publicKey=" + publicKey + ", signer=" + signer + "]";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* (non-Javadoc)
|
|
|
|
|
/*
|
|
|
|
|
* (non-Javadoc)
|
|
|
|
|
*
|
|
|
|
|
* @see org.mitre.jwt.signer.AbstractJwtSigner#verify(java.lang.String)
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
@ -251,14 +290,11 @@ public class EcdsaSigner extends AbstractJwtSigner implements InitializingBean {
|
|
|
|
|
signer.update(signingInput.getBytes("UTF-8"));
|
|
|
|
|
signer.verify(s64.getBytes("UTF-8"));
|
|
|
|
|
} catch (GeneralSecurityException e) {
|
|
|
|
|
// TODO Auto-generated catch block
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
logger.error(e);
|
|
|
|
|
} catch (UnsupportedEncodingException e) {
|
|
|
|
|
// TODO Auto-generated catch block
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
logger.error(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|