work on EcdsaSigner; and supporting unit test and code.
parent
6c7527aaec
commit
89f9961c1a
|
@ -1,15 +1,27 @@
|
||||||
package org.mitre.jwt.signer.impl;
|
package org.mitre.jwt.signer.impl;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.security.Signature;
|
import java.security.Signature;
|
||||||
|
import java.security.SignatureException;
|
||||||
|
import java.security.interfaces.RSAPrivateKey;
|
||||||
|
import java.security.interfaces.RSAPublicKey;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.mitre.jwt.signer.AbstractJwtSigner;
|
import org.mitre.jwt.signer.AbstractJwtSigner;
|
||||||
import org.mitre.jwt.signer.service.impl.KeyStore;
|
import org.mitre.jwt.signer.service.impl.KeyStore;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
public class EcdsaSigner extends AbstractJwtSigner implements InitializingBean {
|
public class EcdsaSigner extends AbstractJwtSigner implements InitializingBean {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,6 +75,11 @@ public class EcdsaSigner extends AbstractJwtSigner implements InitializingBean {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static Log logger = LogFactory.getLog(EcdsaSigner.class);
|
||||||
|
|
||||||
|
public static final String KEYPAIR_ALGORITHM = "EC";
|
||||||
|
public static final String DEFAULT_PASSWORD = "changeit";
|
||||||
|
|
||||||
private KeyStore keystore;
|
private KeyStore keystore;
|
||||||
private String alias;
|
private String alias;
|
||||||
private String password;
|
private String password;
|
||||||
|
@ -71,10 +88,28 @@ public class EcdsaSigner extends AbstractJwtSigner implements InitializingBean {
|
||||||
private PublicKey publicKey;
|
private PublicKey publicKey;
|
||||||
private Signature signer;
|
private Signature signer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor
|
||||||
|
*/
|
||||||
public EcdsaSigner() {
|
public EcdsaSigner() {
|
||||||
this(Algorithm.DEFAULT, null, null, null);
|
this(Algorithm.DEFAULT, null, null, DEFAULT_PASSWORD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param algorithmName
|
||||||
|
* @param keystore
|
||||||
|
* @param alias
|
||||||
|
*/
|
||||||
|
public EcdsaSigner(String algorithmName, KeyStore keystore, String alias) {
|
||||||
|
this(algorithmName, keystore, alias, DEFAULT_PASSWORD);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param algorithmName
|
||||||
|
* @param keystore
|
||||||
|
* @param alias
|
||||||
|
* @param password
|
||||||
|
*/
|
||||||
public EcdsaSigner(String algorithmName, KeyStore keystore, String alias, String password) {
|
public EcdsaSigner(String algorithmName, KeyStore keystore, String alias, String password) {
|
||||||
super(algorithmName);
|
super(algorithmName);
|
||||||
|
|
||||||
|
@ -83,36 +118,65 @@ public class EcdsaSigner extends AbstractJwtSigner implements InitializingBean {
|
||||||
setPassword(password);
|
setPassword(password);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
signer = Signature.getInstance(Algorithm.getByName(algorithmName).getStandardName());
|
signer = Signature.getInstance(Algorithm.getByName(algorithmName).getStandardName()); //, PROVIDER)
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param algorithmName
|
||||||
|
* @param publicKey
|
||||||
|
* @param privateKey
|
||||||
|
*/
|
||||||
|
public EcdsaSigner(String algorithmName, PublicKey publicKey, PrivateKey privateKey) {
|
||||||
|
super(algorithmName);
|
||||||
|
this.publicKey = publicKey;
|
||||||
|
this.privateKey = privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void afterPropertiesSet() throws Exception {
|
public void afterPropertiesSet() throws Exception {
|
||||||
KeyPair keyPair = keystore.getKeyPairForAlias(alias, password);
|
KeyPair keyPair = keystore.getKeyPairForAlias(alias, password);
|
||||||
|
|
||||||
publicKey = keyPair.getPublic();
|
publicKey = keyPair.getPublic();
|
||||||
privateKey = keyPair.getPrivate();
|
privateKey = keyPair.getPrivate();
|
||||||
|
|
||||||
|
logger.debug( Algorithm.getByName(getAlgorithm()).getStandardName() + " ECDSA Signer ready for business");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String generateSignature(String signatureBase) {
|
protected String generateSignature(String signatureBase) {
|
||||||
|
|
||||||
/*
|
try {
|
||||||
1) Generate a digital signature of the UTF-8 representation of the JWS Signing Input
|
signer.initSign(privateKey);
|
||||||
using ECDSA P-256 SHA-256 with the desired private key. The output will be the
|
signer.update(signatureBase.getBytes("UTF-8"));
|
||||||
EC point (R, S), where R and S are unsigned integers.
|
} catch (GeneralSecurityException e) {
|
||||||
2) Turn R and S into byte arrays in big endian order. Each array will be 32 bytes long.
|
// TODO Auto-generated catch block
|
||||||
3) Concatenate the two byte arrays in the order R and then S.
|
e.printStackTrace();
|
||||||
4) Base64url encode the resulting 64 byte array.
|
} catch (UnsupportedEncodingException e) {
|
||||||
*/
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
byte[] sigBytes;
|
||||||
|
String sig = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
return sig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAlias() {
|
public String getAlias() {
|
||||||
|
@ -142,23 +206,51 @@ public class EcdsaSigner extends AbstractJwtSigner implements InitializingBean {
|
||||||
public void setPassword(String password) {
|
public void setPassword(String password) {
|
||||||
this.password = password;
|
this.password = password;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see java.lang.Object#toString()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "EcdsaSigner [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
|
@Override
|
||||||
public boolean verify(String jwtString) {
|
public boolean verify(String jwtString) {
|
||||||
|
|
||||||
|
// split on the dots
|
||||||
|
List<String> parts = Lists.newArrayList(Splitter.on(".").split(
|
||||||
|
jwtString));
|
||||||
|
|
||||||
/*
|
if (parts.size() != 3) {
|
||||||
1) Take the Encoded JWS Signature and base64url decode it into a byte array.
|
throw new IllegalArgumentException("Invalid JWT format.");
|
||||||
If decoding fails, the signed content MUST be rejected.
|
}
|
||||||
2) The output of the base64url decoding MUST be a 64 byte array.
|
|
||||||
3) Split the 64 byte array into two 32 byte arrays. The first array will be R and
|
|
||||||
the second S. Remember that the byte arrays are in big endian byte order;
|
|
||||||
please check the ECDSA validator in use to see what byte order it requires.
|
|
||||||
4) Submit the UTF-8 representation of the JWS Signing Input, R, S and the public
|
|
||||||
key (x, y) to the ECDSA P-256 SHA-256 validator.
|
|
||||||
5) If the validation fails, the signed content MUST be rejected.
|
|
||||||
*/
|
|
||||||
|
|
||||||
return false;
|
String h64 = parts.get(0);
|
||||||
|
String c64 = parts.get(1);
|
||||||
|
String s64 = parts.get(2);
|
||||||
|
|
||||||
|
String signingInput = h64 + "." + c64;
|
||||||
|
|
||||||
|
try {
|
||||||
|
signer.initVerify(publicKey);
|
||||||
|
signer.update(signingInput.getBytes("UTF-8"));
|
||||||
|
signer.verify(s64.getBytes("UTF-8"));
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -3,13 +3,11 @@ package org.mitre.jwt.signer.impl;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.security.KeyPairGenerator;
|
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.security.Signature;
|
import java.security.Signature;
|
||||||
import java.security.SignatureException;
|
import java.security.SignatureException;
|
||||||
import java.security.interfaces.RSAPrivateKey;
|
import java.security.interfaces.RSAPrivateKey;
|
||||||
import java.security.interfaces.RSAPublicKey;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
@ -84,6 +82,7 @@ public class RsaSigner extends AbstractJwtSigner implements InitializingBean {
|
||||||
|
|
||||||
private static Log logger = LogFactory.getLog(RsaSigner.class);
|
private static Log logger = LogFactory.getLog(RsaSigner.class);
|
||||||
|
|
||||||
|
public static final String KEYPAIR_ALGORITHM = "RSA";
|
||||||
public static final String DEFAULT_PASSWORD = "changeit";
|
public static final String DEFAULT_PASSWORD = "changeit";
|
||||||
|
|
||||||
private KeyStore keystore;
|
private KeyStore keystore;
|
||||||
|
@ -132,10 +131,13 @@ public class RsaSigner extends AbstractJwtSigner implements InitializingBean {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor
|
* @param algorithmName
|
||||||
|
* @param publicKey
|
||||||
|
* @param privateKey
|
||||||
*/
|
*/
|
||||||
public RsaSigner(String algorithmName, RSAPublicKey publicKey, RSAPrivateKey privateKey) {
|
public RsaSigner(String algorithmName, PublicKey publicKey, PrivateKey privateKey) {
|
||||||
super(algorithmName);
|
super(algorithmName);
|
||||||
this.publicKey = publicKey;
|
this.publicKey = publicKey;
|
||||||
this.privateKey = privateKey;
|
this.privateKey = privateKey;
|
||||||
|
@ -162,12 +164,10 @@ public class RsaSigner extends AbstractJwtSigner implements InitializingBean {
|
||||||
signer.initSign(privateKey);
|
signer.initSign(privateKey);
|
||||||
signer.update(signatureBase.getBytes("UTF-8"));
|
signer.update(signatureBase.getBytes("UTF-8"));
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException e) {
|
||||||
System.out.println("boooom 1");
|
|
||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
System.out.println("boooom 2");
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,6 +235,9 @@ public class RsaSigner extends AbstractJwtSigner implements InitializingBean {
|
||||||
+ ", publicKey=" + publicKey + ", signer=" + signer + "]";
|
+ ", publicKey=" + publicKey + ", signer=" + signer + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.mitre.jwt.signer.AbstractJwtSigner#verify(java.lang.String)
|
||||||
|
*/
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.mitre.jwt.signer.AbstractJwtSigner#verify(java.lang.String)
|
* @see org.mitre.jwt.signer.AbstractJwtSigner#verify(java.lang.String)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -103,7 +103,7 @@ public class KeyStore implements InitializingBean {
|
||||||
|
|
||||||
// Get public key
|
// Get public key
|
||||||
PublicKey publicKey = cert.getPublicKey();
|
PublicKey publicKey = cert.getPublicKey();
|
||||||
|
|
||||||
return new KeyPair(publicKey, (PrivateKey) key);
|
return new KeyPair(publicKey, (PrivateKey) key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,5 +152,5 @@ public class KeyStore implements InitializingBean {
|
||||||
return "KeyStore [password=" + password + ", location=" + location
|
return "KeyStore [password=" + password + ", location=" + location
|
||||||
+ ", keystore=" + keystore + "]";
|
+ ", keystore=" + keystore + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
|
@ -60,7 +60,7 @@
|
||||||
<jwt-signer:keystore id="defaultKeystore" location="classpath:keystore.jks" password="changeit" />
|
<jwt-signer:keystore id="defaultKeystore" location="classpath:keystore.jks" password="changeit" />
|
||||||
|
|
||||||
<jwt-signer:service id="defaultSignerService">
|
<jwt-signer:service id="defaultSignerService">
|
||||||
<jwt-signer:rsa bits="256" keystore-ref="defaultKeystore" key-alias="test" password="changeit" />
|
<jwt-signer:rsa bits="256" keystore-ref="defaultKeystore" key-alias="rsa" password="changeit" />
|
||||||
<jwt-signer:hmac bits="256" passphrase="changeit" />
|
<jwt-signer:hmac bits="256" passphrase="changeit" />
|
||||||
</jwt-signer:service>
|
</jwt-signer:service>
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ import org.mitre.jwt.signer.impl.HmacSigner;
|
||||||
import org.mitre.jwt.signer.impl.PlaintextSigner;
|
import org.mitre.jwt.signer.impl.PlaintextSigner;
|
||||||
import org.mitre.jwt.signer.impl.RsaSigner;
|
import org.mitre.jwt.signer.impl.RsaSigner;
|
||||||
import org.mitre.jwt.signer.service.impl.KeyStore;
|
import org.mitre.jwt.signer.service.impl.KeyStore;
|
||||||
|
import org.mitre.jwt.signer.service.impl.KeyStoreTest;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
@ -85,7 +86,12 @@ public class JwtTest {
|
||||||
jwt.getClaims().setIssuer("joe");
|
jwt.getClaims().setIssuer("joe");
|
||||||
jwt.getClaims().setClaim("http://example.com/is_root", Boolean.TRUE);
|
jwt.getClaims().setClaim("http://example.com/is_root", Boolean.TRUE);
|
||||||
|
|
||||||
JwtSigner signer = new RsaSigner(RsaSigner.Algorithm.RS256.toString(), keystore, "test", "changeit");
|
KeyStoreTest.generateKeyPair(keystore,
|
||||||
|
RsaSigner.KEYPAIR_ALGORITHM, 2048,
|
||||||
|
"SHA256WithRSAEncryption", "OpenID Connect Server",
|
||||||
|
"rsa", RsaSigner.DEFAULT_PASSWORD, 30, 365);
|
||||||
|
|
||||||
|
JwtSigner signer = new RsaSigner(RsaSigner.Algorithm.RS256.toString(), keystore, "rsa", RsaSigner.DEFAULT_PASSWORD);
|
||||||
((RsaSigner)signer).afterPropertiesSet();
|
((RsaSigner)signer).afterPropertiesSet();
|
||||||
|
|
||||||
signer.sign(jwt);
|
signer.sign(jwt);
|
||||||
|
|
|
@ -4,12 +4,15 @@ import static org.hamcrest.CoreMatchers.not;
|
||||||
import static org.hamcrest.CoreMatchers.nullValue;
|
import static org.hamcrest.CoreMatchers.nullValue;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.security.Key;
|
import java.security.Key;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.security.KeyPairGenerator;
|
import java.security.KeyPairGenerator;
|
||||||
|
import java.security.PrivateKey;
|
||||||
import java.security.Security;
|
import java.security.Security;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.security.interfaces.RSAPrivateKey;
|
import java.security.interfaces.RSAPrivateKey;
|
||||||
|
@ -20,6 +23,8 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
import org.bouncycastle.x509.X509V3CertificateGenerator;
|
import org.bouncycastle.x509.X509V3CertificateGenerator;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mitre.jwt.signer.impl.EcdsaSigner;
|
||||||
|
import org.mitre.jwt.signer.impl.RsaSigner;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
@ -27,8 +32,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@ContextConfiguration(locations = {
|
@ContextConfiguration(locations = { "classpath:test-context.xml" })
|
||||||
"classpath:test-context.xml" })
|
|
||||||
public class KeyStoreTest {
|
public class KeyStoreTest {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
|
@ -81,17 +85,19 @@ public class KeyStoreTest {
|
||||||
* @throws GeneralSecurityException
|
* @throws GeneralSecurityException
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public static java.security.KeyStore generateRsaKeyPair(KeyStore keystore,
|
public static java.security.KeyStore generateKeyPair(KeyStore keystore,
|
||||||
String domainName, String alias, String aliasPassword, int daysNotValidBefore, int daysNotValidAfter)
|
String keyPairAlgorithm, int keySize, String signatureAlgorithm,
|
||||||
|
String domainName, String alias, String aliasPassword,
|
||||||
|
int daysNotValidBefore, int daysNotValidAfter)
|
||||||
throws GeneralSecurityException, IOException {
|
throws GeneralSecurityException, IOException {
|
||||||
|
|
||||||
java.security.KeyStore ks = keystore.getKeystore();
|
java.security.KeyStore ks = keystore.getKeystore();
|
||||||
|
|
||||||
KeyPairGenerator rsaKeyPairGenerator = null;
|
KeyPairGenerator rsaKeyPairGenerator = null;
|
||||||
|
|
||||||
rsaKeyPairGenerator = KeyPairGenerator.getInstance("RSA");
|
rsaKeyPairGenerator = KeyPairGenerator.getInstance(keyPairAlgorithm);
|
||||||
|
|
||||||
rsaKeyPairGenerator.initialize(2048);
|
rsaKeyPairGenerator.initialize(keySize);
|
||||||
KeyPair rsaKeyPair = rsaKeyPairGenerator.generateKeyPair();
|
KeyPair rsaKeyPair = rsaKeyPairGenerator.generateKeyPair();
|
||||||
|
|
||||||
// BC sez X509V3CertificateGenerator is deprecated and the docs say to
|
// BC sez X509V3CertificateGenerator is deprecated and the docs say to
|
||||||
|
@ -99,32 +105,56 @@ public class KeyStoreTest {
|
||||||
X509V3CertificateGenerator v3CertGen = createCertificate(domainName,
|
X509V3CertificateGenerator v3CertGen = createCertificate(domainName,
|
||||||
daysNotValidBefore, daysNotValidAfter);
|
daysNotValidBefore, daysNotValidAfter);
|
||||||
|
|
||||||
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) rsaKeyPair.getPrivate();
|
PrivateKey privateKey = rsaKeyPair.getPrivate();
|
||||||
|
|
||||||
v3CertGen.setPublicKey(rsaKeyPair.getPublic());
|
v3CertGen.setPublicKey(rsaKeyPair.getPublic());
|
||||||
v3CertGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
|
v3CertGen.setSignatureAlgorithm(signatureAlgorithm);
|
||||||
|
|
||||||
// BC docs say to use another, but it seemingly isn't included...
|
// BC docs say to use another, but it seemingly isn't included...
|
||||||
X509Certificate certificate = v3CertGen
|
X509Certificate certificate = v3CertGen
|
||||||
.generateX509Certificate(rsaPrivateKey);
|
.generateX509Certificate(privateKey);
|
||||||
|
|
||||||
// if exist, overwrite
|
// if exist, overwrite
|
||||||
ks.setKeyEntry(alias, rsaPrivateKey, aliasPassword.toCharArray(),
|
ks.setKeyEntry(alias, privateKey, aliasPassword.toCharArray(),
|
||||||
new java.security.cert.Certificate[] { certificate });
|
new java.security.cert.Certificate[] { certificate });
|
||||||
|
|
||||||
keystore.setKeystore(ks);
|
keystore.setKeystore(ks);
|
||||||
|
|
||||||
return ks;
|
return ks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void storeKeyPair() throws GeneralSecurityException, IOException {
|
public void storeRsaKeyPair() throws GeneralSecurityException, IOException {
|
||||||
|
|
||||||
|
java.security.KeyStore ks = null;
|
||||||
|
|
||||||
java.security.KeyStore ks = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ks = KeyStoreTest.generateRsaKeyPair(keystore, "OpenID Connect Server", "storeKeyPair", "changeit", 30, 365);
|
ks = KeyStoreTest.generateKeyPair(keystore,
|
||||||
|
RsaSigner.KEYPAIR_ALGORITHM, 2048,
|
||||||
|
"SHA256WithRSAEncryption", "OpenID Connect Server",
|
||||||
|
"rsa", RsaSigner.DEFAULT_PASSWORD, 30, 365);
|
||||||
|
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(ks, not(nullValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void storeEcKeyPair() throws GeneralSecurityException, IOException {
|
||||||
|
|
||||||
|
java.security.KeyStore ks = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
ks = KeyStoreTest.generateKeyPair(keystore,
|
||||||
|
EcdsaSigner.KEYPAIR_ALGORITHM, 256, "SHA1withECDSA",
|
||||||
|
"OpenID Connect Server", "ec", EcdsaSigner.DEFAULT_PASSWORD, 30,
|
||||||
|
365);
|
||||||
|
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException e) {
|
||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
|
@ -134,15 +164,40 @@ public class KeyStoreTest {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//KeyStoreTest.persistKeystoreToFile(ks, System.getProperty("java.io.tmpdir") + System.getProperty("path.separator") + "keystore.jks" , KeyStore.PASSWORD);
|
||||||
|
|
||||||
assertThat(ks, not(nullValue()));
|
assertThat(ks, not(nullValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void readKey() throws GeneralSecurityException {
|
public void readKey() throws GeneralSecurityException {
|
||||||
|
|
||||||
Key key = keystore.getKeystore().getKey("storeKeyPair",
|
Key key = keystore.getKeystore().getKey("rsa",
|
||||||
KeyStore.PASSWORD.toCharArray());
|
KeyStore.PASSWORD.toCharArray());
|
||||||
|
|
||||||
assertThat(key, not(nullValue()));
|
assertThat(key, not(nullValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the keystore for future use.
|
||||||
|
*
|
||||||
|
* @param keystore
|
||||||
|
* @param path
|
||||||
|
* @param password
|
||||||
|
* @throws GeneralSecurityException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static void persistKeystoreToFile(final java.security.KeyStore keystore,
|
||||||
|
final String path, final String password) throws GeneralSecurityException,
|
||||||
|
IOException {
|
||||||
|
|
||||||
|
FileOutputStream fos = new FileOutputStream(new File(path));
|
||||||
|
try {
|
||||||
|
keystore.store(fos, password.toCharArray());
|
||||||
|
System.out.println("Wrote keystore to " + path);
|
||||||
|
} finally {
|
||||||
|
fos.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue