initial implementation of x509 and JWK key retrieval
parent
68483536a6
commit
ee28d56031
|
@ -1,6 +1,8 @@
|
|||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
|
||||
<classpathentry kind="src" path="src/test/java"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
|
|
|
@ -3,5 +3,6 @@
|
|||
<wb-module deploy-name="openid-connect-client">
|
||||
<wb-resource deploy-path="/" source-path="/src/main/java"/>
|
||||
<wb-resource deploy-path="/" source-path="/src/main/resources"/>
|
||||
<wb-resource deploy-path="/" source-path="/src/test/java"/>
|
||||
</wb-module>
|
||||
</project-modules>
|
||||
|
|
|
@ -132,4 +132,20 @@ public class OIDCAuthenticationFilter extends AbstractOIDCAuthenticationFilter {
|
|||
public void setTokenEndpointURI(String tokenEndpointURI) {
|
||||
oidcServerConfig.setTokenEndpointURI(tokenEndpointURI);
|
||||
}
|
||||
|
||||
public void setX509EncryptUrl(String x509EncryptUrl) {
|
||||
oidcServerConfig.setX509EncryptUrl(x509EncryptUrl);
|
||||
}
|
||||
|
||||
public void setX509SigningUrl(String x509SigningUrl) {
|
||||
oidcServerConfig.setX509SigningUrl(x509SigningUrl);
|
||||
}
|
||||
|
||||
public void setJwkEncryptUrl(String jwkEncryptUrl) {
|
||||
oidcServerConfig.setJwkEncryptUrl(jwkEncryptUrl);
|
||||
}
|
||||
|
||||
public void setJwkSigningUrl(String jwkSigningUrl) {
|
||||
oidcServerConfig.setJwkSigningUrl(jwkSigningUrl);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,15 @@
|
|||
******************************************************************************/
|
||||
package org.mitre.openid.connect.client;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.security.Key;
|
||||
|
||||
import org.mitre.util.Utility;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* @author nemonik
|
||||
*
|
||||
|
@ -30,6 +39,18 @@ public class OIDCServerConfiguration {
|
|||
private String clientSecret;
|
||||
|
||||
private String clientId;
|
||||
|
||||
private String x509EncryptUrl;
|
||||
|
||||
private String x509SigningUrl;
|
||||
|
||||
private String jwkEncryptUrl;
|
||||
|
||||
private String jwkSigningUrl;
|
||||
|
||||
private Key encryptKey;
|
||||
|
||||
private Key signingKey;
|
||||
|
||||
public String getAuthorizationEndpointURI() {
|
||||
return authorizationEndpointURI;
|
||||
|
@ -70,6 +91,77 @@ public class OIDCServerConfiguration {
|
|||
public void setTokenEndpointURI(String tokenEndpointURI) {
|
||||
this.tokenEndpointURI = tokenEndpointURI;
|
||||
}
|
||||
|
||||
public String getX509EncryptUrl() {
|
||||
return x509EncryptUrl;
|
||||
}
|
||||
|
||||
public String getX509SigningUrl() {
|
||||
return x509SigningUrl;
|
||||
}
|
||||
|
||||
public String getJwkEncryptUrl() {
|
||||
return jwkEncryptUrl;
|
||||
}
|
||||
|
||||
public String getJwkSigningUrl() {
|
||||
return jwkSigningUrl;
|
||||
}
|
||||
|
||||
public void setX509EncryptUrl(String x509EncryptUrl) {
|
||||
this.x509EncryptUrl = x509EncryptUrl;
|
||||
}
|
||||
|
||||
public void setX509SigningUrl(String x509SigningUrl) {
|
||||
this.x509SigningUrl = x509SigningUrl;
|
||||
}
|
||||
|
||||
public void setJwkEncryptUrl(String jwkEncryptUrl) {
|
||||
this.jwkEncryptUrl = jwkEncryptUrl;
|
||||
}
|
||||
|
||||
public void setJwkSigningUrl(String jwkSigningUrl) {
|
||||
this.jwkSigningUrl = jwkSigningUrl;
|
||||
}
|
||||
|
||||
public Key getSigningKey() throws Exception {
|
||||
if(signingKey == null){
|
||||
if(x509SigningUrl != null){
|
||||
File file = new File(x509SigningUrl);
|
||||
URL url = file.toURI().toURL();
|
||||
signingKey = Utility.retrieveX509Key(url);
|
||||
}
|
||||
else if (jwkSigningUrl != null){
|
||||
File file = new File(jwkSigningUrl);
|
||||
URL url = file.toURI().toURL();
|
||||
signingKey = Utility.retrieveJwkKey(url);
|
||||
}
|
||||
}
|
||||
return signingKey;
|
||||
}
|
||||
|
||||
public Key getEncryptionKey() throws Exception {
|
||||
if(encryptKey == null){
|
||||
if(x509EncryptUrl != null){
|
||||
File file = new File(x509EncryptUrl);
|
||||
URL url = file.toURI().toURL();
|
||||
encryptKey = Utility.retrieveX509Key(url);
|
||||
}
|
||||
else if (jwkEncryptUrl != null){
|
||||
File file = new File(jwkEncryptUrl);
|
||||
URL url = file.toURI().toURL();
|
||||
encryptKey = Utility.retrieveJwkKey(url);
|
||||
}
|
||||
}
|
||||
return encryptKey;
|
||||
}
|
||||
|
||||
public void checkKeys() throws Exception {
|
||||
encryptKey = null;
|
||||
signingKey = null;
|
||||
getEncryptionKey();
|
||||
getSigningKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
@ -77,7 +169,11 @@ public class OIDCServerConfiguration {
|
|||
+ authorizationEndpointURI + ", tokenEndpointURI="
|
||||
+ tokenEndpointURI + ", checkIDEndpointURI="
|
||||
+ checkIDEndpointURI + ", clientSecret=" + clientSecret
|
||||
+ ", clientId=" + clientId + "]";
|
||||
+ ", clientId=" + clientId + ", x509EncryptedUrl="
|
||||
+ x509EncryptUrl + ", jwkEncryptedUrl="
|
||||
+ jwkEncryptUrl + ", x509SigningUrl="
|
||||
+ x509SigningUrl + ", jwkSigningUrl="
|
||||
+ jwkSigningUrl + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package org.mitre.openid.connect.client;
|
||||
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.validation.ValidationUtils;
|
||||
import org.springframework.validation.Validator;
|
||||
|
||||
public class UrlValidator implements Validator{
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean supports(Class clzz) {
|
||||
return OIDCServerConfiguration.class.equals(clzz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(Object obj, Errors e) {
|
||||
ValidationUtils.rejectIfEmpty(e, "x509EncryptUrl", "x509EncryptUrl.empty");
|
||||
|
||||
}
|
||||
|
||||
public void validate1(Object obj, Errors e) {
|
||||
ValidationUtils.rejectIfEmpty(e, "x509SigningUrl", "x509SigningUrl.empty");
|
||||
}
|
||||
|
||||
public void validate2(Object obj, Errors e) {
|
||||
ValidationUtils.rejectIfEmpty(e, "jwkEncryptUrl", "jwkEncryptUrl.empty");
|
||||
}
|
||||
|
||||
public void validate3(Object obj, Errors e) {
|
||||
ValidationUtils.rejectIfEmpty(e, "jwkSigningUrl", "jwkSigningUrl.empty");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
package org.mitre.openid.connect.client;
|
||||
|
||||
import java.net.URL;
|
||||
import java.security.Key;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mitre.util.Utility;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class OIDCServerConfigurationTest extends TestCase {
|
||||
|
||||
URL jwkUrl = this.getClass().getResource("/jwk/jwk");
|
||||
URL x509Url = this.getClass().getResource("/x509/x509");
|
||||
URL jwkEncryptedUrl = this.getClass().getResource("/jwk/jwkEncrypted");
|
||||
URL x509EncryptedUrl = this.getClass().getResource("/x509/x509Encrypted");
|
||||
OIDCServerConfiguration oidc;
|
||||
|
||||
/**
|
||||
* @throws java.lang.Exception
|
||||
*/
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
oidc = new OIDCServerConfiguration();
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws java.lang.Exception
|
||||
*/
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.mitre.util.Utility#retrieveJwk(java.lang.String)}.
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testGetSigningKeyBoth() throws Exception {
|
||||
oidc.setX509SigningUrl(x509Url.getPath());
|
||||
oidc.setJwkSigningUrl(jwkUrl.getPath());
|
||||
Key key = oidc.getSigningKey();
|
||||
assertEquals(key, Utility.retrieveX509Key(x509Url));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSigningKeyJwk() throws Exception {
|
||||
oidc.setX509SigningUrl(null);
|
||||
oidc.setJwkSigningUrl(jwkUrl.getPath());
|
||||
Key key1 = oidc.getSigningKey();
|
||||
assertEquals(key1, Utility.retrieveJwkKey(jwkUrl));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSigningKeyX509() throws Exception {
|
||||
oidc.setX509SigningUrl(x509Url.getPath());
|
||||
oidc.setJwkSigningUrl(null);
|
||||
Key key2 = oidc.getSigningKey();
|
||||
assertEquals(key2, Utility.retrieveX509Key(x509Url));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSigningKeyNone() throws Exception {
|
||||
oidc.setX509SigningUrl(null);
|
||||
oidc.setJwkSigningUrl(null);
|
||||
Key key3 = oidc.getSigningKey();
|
||||
assertEquals(key3, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEncryptionKeyBoth() throws Exception {
|
||||
oidc.setX509EncryptUrl(x509EncryptedUrl.getPath());
|
||||
oidc.setJwkEncryptUrl(jwkEncryptedUrl.getPath());
|
||||
Key key = oidc.getEncryptionKey();
|
||||
assertEquals(key, Utility.retrieveX509Key(x509EncryptedUrl));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEncryptionKeyJwk() throws Exception {
|
||||
oidc.setX509EncryptUrl(null);
|
||||
oidc.setJwkEncryptUrl(jwkEncryptedUrl.getPath());
|
||||
Key key1 = oidc.getEncryptionKey();
|
||||
assertEquals(key1, Utility.retrieveJwkKey(jwkEncryptedUrl));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEncryptionKeyX509() throws Exception {
|
||||
oidc.setX509EncryptUrl(x509EncryptedUrl.getPath());
|
||||
oidc.setJwkEncryptUrl(null);
|
||||
Key key2 = oidc.getEncryptionKey();
|
||||
assertEquals(key2, Utility.retrieveX509Key(x509EncryptedUrl));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEncryptionKeyNone() throws Exception {
|
||||
oidc.setX509EncryptUrl(null);
|
||||
oidc.setJwkEncryptUrl(null);
|
||||
Key key3 = oidc.getEncryptionKey();
|
||||
assertEquals(key3, null);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
|
||||
<classpathentry kind="src" path="src/test/java"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
|
@ -9,3 +11,4 @@
|
|||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
|
||||
|
|
|
@ -2,5 +2,6 @@
|
|||
<project-modules id="moduleCoreId" project-version="1.5.0">
|
||||
<wb-module deploy-name="openid-connect-common">
|
||||
<wb-resource deploy-path="/" source-path="/src/main/java"/>
|
||||
<wb-resource deploy-path="/" source-path="/src/test/java"/>
|
||||
</wb-module>
|
||||
</project-modules>
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
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;
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
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.provider.JCEECPublicKey;
|
||||
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
|
||||
import org.bouncycastle.jce.spec.ECParameterSpec;
|
||||
import org.bouncycastle.jce.spec.ECPublicKeySpec;
|
||||
import org.bouncycastle.math.ec.ECCurve;
|
||||
import org.bouncycastle.math.ec.ECPoint;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
public class EC 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 EC(JsonObject object) {
|
||||
super(object);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
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;
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package org.mitre.jwk.model;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.Key;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
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;
|
||||
|
||||
JsonObject object = new JsonObject();
|
||||
|
||||
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 PublicKey getKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||
// TODO Auto-generated method stub
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -15,8 +15,34 @@
|
|||
******************************************************************************/
|
||||
package org.mitre.util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URL;
|
||||
import java.security.Key;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.spec.RSAPublicKeySpec;
|
||||
import java.security.PublicKey;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.mitre.jwk.model.AbstractJwk;
|
||||
import org.mitre.jwk.model.EC;
|
||||
import org.mitre.jwk.model.Jwk;
|
||||
import org.mitre.jwk.model.Rsa;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonIOException;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
/**
|
||||
* A collection of utility methods.
|
||||
*
|
||||
|
@ -43,4 +69,57 @@ public class Utility {
|
|||
}
|
||||
return issuer;
|
||||
}
|
||||
|
||||
public static List<Jwk> retrieveJwk(URL path) throws Exception {
|
||||
List<Jwk> keys = new ArrayList<Jwk>();
|
||||
|
||||
JsonParser parser = new JsonParser();
|
||||
JsonObject json = parser.parse(new BufferedReader(new InputStreamReader(path.openStream()))).getAsJsonObject();
|
||||
JsonArray getArray = json.getAsJsonArray("jwk");
|
||||
|
||||
for(int i = 0; i < getArray.size(); i++){
|
||||
|
||||
JsonObject object = getArray.get(i).getAsJsonObject();
|
||||
String algorithm = object.get("alg").getAsString();
|
||||
|
||||
if(algorithm.equals("RSA")){
|
||||
Rsa rsa = new Rsa(object);
|
||||
keys.add(rsa);
|
||||
}
|
||||
|
||||
else{
|
||||
EC ec = new EC(object);
|
||||
keys.add(ec);
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
public static Key retrieveX509Key(URL url) throws Exception {
|
||||
|
||||
CertificateFactory factory = CertificateFactory.getInstance("X.509");
|
||||
X509Certificate cert = (X509Certificate) factory.generateCertificate(url.openStream());
|
||||
Key key = cert.getPublicKey();
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
public static Key retrieveJwkKey(URL url) throws Exception {
|
||||
|
||||
JsonParser parser = new JsonParser();
|
||||
JsonObject json = parser.parse(new BufferedReader(new InputStreamReader(url.openStream()))).getAsJsonObject();
|
||||
JsonArray getArray = json.getAsJsonArray("jwk");
|
||||
JsonObject object = getArray.get(0).getAsJsonObject();
|
||||
|
||||
byte[] modulusByte = Base64.decodeBase64(object.get("mod").getAsString());
|
||||
BigInteger modulus = new BigInteger(modulusByte);
|
||||
byte[] exponentByte = Base64.decodeBase64(object.get("exp").getAsString());
|
||||
BigInteger exponent = new BigInteger(exponentByte);
|
||||
|
||||
RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent);
|
||||
KeyFactory factory = KeyFactory.getInstance("RSA");
|
||||
PublicKey pub = factory.generatePublic(spec);
|
||||
|
||||
return pub;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
/**
|
||||
*
|
||||
*/
|
||||
package org.mitre.util;
|
||||
|
||||
import java.security.Key;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.interfaces.ECKey;
|
||||
import java.security.interfaces.ECPublicKey;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.security.spec.RSAPublicKeySpec;
|
||||
import java.util.List;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URL;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mitre.jwk.model.Jwk;
|
||||
import org.mitre.jwk.model.Rsa;
|
||||
import org.mitre.jwk.model.EC;
|
||||
import org.mitre.util.Utility;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import org.apache.commons.codec.binary.*;
|
||||
import org.bouncycastle.jce.ECNamedCurveTable;
|
||||
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
|
||||
import org.bouncycastle.math.ec.ECCurve;
|
||||
import org.bouncycastle.jce.provider.JCEECPublicKey;
|
||||
|
||||
/**
|
||||
* @author DERRYBERRY
|
||||
*
|
||||
*/
|
||||
public class UtilityTest extends TestCase{
|
||||
|
||||
URL url = this.getClass().getResource("/jwk/jwkSuccess");
|
||||
URL certUrl = this.getClass().getResource("/x509/certTest");
|
||||
URL rsaUrl = this.getClass().getResource("/jwk/rsaOnly");
|
||||
|
||||
/**
|
||||
* @throws java.lang.Exception
|
||||
*/
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws java.lang.Exception
|
||||
*/
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.mitre.util.Utility#retrieveJwk(java.lang.String)}.
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testRetrieveJwk() throws Exception {
|
||||
|
||||
JsonParser parser = new JsonParser();
|
||||
JsonObject json = parser.parse(new BufferedReader(new InputStreamReader(url.openStream()))).getAsJsonObject();
|
||||
JsonArray getArray = json.getAsJsonArray("jwk");
|
||||
|
||||
List<Jwk> list = Utility.retrieveJwk(url);
|
||||
|
||||
for(int i = 0; i < list.size(); i++){
|
||||
|
||||
Jwk jwk = list.get(i);
|
||||
JsonObject object = getArray.get(i).getAsJsonObject();
|
||||
|
||||
assertEquals(object.get("alg").getAsString(), jwk.getAlg());
|
||||
if(object.get("kid") != null){
|
||||
assertEquals(object.get("kid").getAsString(), jwk.getKid());
|
||||
}
|
||||
if(object.get("use") != null){
|
||||
assertEquals(object.get("use").getAsString(), jwk.getUse());
|
||||
}
|
||||
|
||||
if(jwk instanceof Rsa){
|
||||
assertEquals(object.get("mod").getAsString(), ((Rsa) jwk).getMod());
|
||||
assertEquals(object.get("exp").getAsString(), ((Rsa) jwk).getExp());
|
||||
}
|
||||
else {
|
||||
assertEquals(object.get("crv").getAsString(), ((EC) jwk).getCrv());
|
||||
assertEquals(object.get("x").getAsString(), ((EC) jwk).getX());
|
||||
assertEquals(object.get("y").getAsString(), ((EC) jwk).getY());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMakeRsa() throws Exception{
|
||||
|
||||
JsonParser parser = new JsonParser();
|
||||
JsonObject json = parser.parse(new BufferedReader(new InputStreamReader(url.openStream()))).getAsJsonObject();
|
||||
JsonArray getArray = json.getAsJsonArray("jwk");
|
||||
|
||||
List<Jwk> list = Utility.retrieveJwk(url);
|
||||
|
||||
for(int i = 0; i < list.size(); i++){
|
||||
Jwk jwk = list.get(i);
|
||||
JsonObject object = getArray.get(i).getAsJsonObject();
|
||||
|
||||
if(jwk instanceof Rsa){
|
||||
|
||||
RSAPublicKey key = ((RSAPublicKey) ((Rsa) jwk).getKey());
|
||||
|
||||
byte[] mod = Base64.decodeBase64(object.get("mod").getAsString());
|
||||
BigInteger modInt = new BigInteger(mod);
|
||||
assertEquals(modInt, key.getModulus());
|
||||
|
||||
byte[] exp = Base64.decodeBase64(object.get("exp").getAsString());
|
||||
BigInteger expInt = new BigInteger(exp);
|
||||
assertEquals(expInt, key.getPublicExponent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetriveX509Key() throws Exception {
|
||||
CertificateFactory factory = CertificateFactory.getInstance("X.509");
|
||||
X509Certificate x509 = (X509Certificate) factory.generateCertificate(certUrl.openStream());
|
||||
Key key = Utility.retrieveX509Key(certUrl);
|
||||
assertEquals(x509.getPublicKey(), key);
|
||||
assertEquals("RSA", key.getAlgorithm());
|
||||
assertEquals("X.509", key.getFormat());
|
||||
}
|
||||
|
||||
public void testRetriveJwkKey() throws Exception {
|
||||
Key key = Utility.retrieveJwkKey(rsaUrl);
|
||||
|
||||
JsonParser parser = new JsonParser();
|
||||
JsonObject json = parser.parse(new BufferedReader(new InputStreamReader(rsaUrl.openStream()))).getAsJsonObject();
|
||||
JsonArray getArray = json.getAsJsonArray("jwk");
|
||||
JsonObject object = getArray.get(0).getAsJsonObject();
|
||||
|
||||
byte[] modulusByte = Base64.decodeBase64(object.get("mod").getAsString());
|
||||
BigInteger modulus = new BigInteger(modulusByte);
|
||||
byte[] exponentByte = Base64.decodeBase64(object.get("exp").getAsString());
|
||||
BigInteger exponent = new BigInteger(exponentByte);
|
||||
|
||||
RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent);
|
||||
KeyFactory factory = KeyFactory.getInstance("RSA");
|
||||
PublicKey pub = factory.generatePublic(spec);
|
||||
|
||||
assertEquals(pub, key);
|
||||
}
|
||||
|
||||
//@Test
|
||||
//public void testMakeEC() throws Exception{
|
||||
|
||||
/*JsonParser parser = new JsonParser();
|
||||
JsonObject json = parser.parse(new BufferedReader(new InputStreamReader(url.openStream()))).getAsJsonObject();
|
||||
JsonArray getArray = json.getAsJsonArray("jwk");
|
||||
|
||||
List<Jwk> list = Utility.retrieveJwk(url);
|
||||
|
||||
for(int i = 0; i < list.size(); i++){
|
||||
Jwk jwk = list.get(i);
|
||||
JsonObject object = getArray.get(i).getAsJsonObject();
|
||||
|
||||
if(jwk instanceof EC){
|
||||
|
||||
ECPublicKey key = ((ECPublicKey) ((EC) jwk).getKey());
|
||||
|
||||
byte[] xArray = Base64.decodeBase64(object.get("x").getAsString());
|
||||
BigInteger xInt = new BigInteger(xArray);
|
||||
byte[] yArray = Base64.decodeBase64(object.get("y").getAsString());
|
||||
BigInteger yInt = new BigInteger(yArray);
|
||||
|
||||
String curveName = object.get("crv").getAsString();
|
||||
ECNamedCurveParameterSpec curveSpec = ECNamedCurveTable.getParameterSpec(curveName);
|
||||
ECCurve crv = curveSpec.getCurve();
|
||||
BigInteger a = crv.getA().toBigInteger();
|
||||
BigInteger b = crv.getB().toBigInteger();
|
||||
int fieldSize = crv.getFieldSize();
|
||||
BigInteger orderOfGen = curveSpec.getH();
|
||||
int cofactor = Math.abs(curveSpec.getN().intValue());
|
||||
|
||||
assertEquals(a, key.getParams().getCurve().getA());
|
||||
assertEquals(b, key.getParams().getCurve().getB());
|
||||
assertEquals(fieldSize, key.getParams().getCurve().getField());
|
||||
assertEquals(orderOfGen, key.getParams().getOrder());
|
||||
assertEquals(cofactor, key.getParams().getCofactor());
|
||||
assertEquals(xInt, key.getW().getAffineX());
|
||||
assertEquals(yInt, key.getW().getAffineY());
|
||||
}
|
||||
}*/
|
||||
//fail("method not implemented");
|
||||
//}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
{"jwk":
|
||||
[
|
||||
{"alg":"never",
|
||||
"crv":"gonna",
|
||||
"x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
|
||||
"y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
|
||||
"use":"give",
|
||||
"kid":"1"},
|
||||
|
||||
{"alg":"you",
|
||||
"mod": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
|
||||
"exp":"up",
|
||||
"kid":"rick astley"}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
{"jwk":
|
||||
[
|
||||
{"alg":"EC",
|
||||
"crv":"P-256",
|
||||
"x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
|
||||
"y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
|
||||
"use":"enc",
|
||||
"kid":"1"},
|
||||
|
||||
{"alg":"RSA",
|
||||
"mod": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
|
||||
"exp":"AQAB",
|
||||
"kid":"2011-04-29"}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue