initial implementation of x509 and JWK key retrieval
parent
68483536a6
commit
ee28d56031
|
@ -1,6 +1,8 @@
|
||||||
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<classpath>
|
<classpath>
|
||||||
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
|
<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.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">
|
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||||
<attributes>
|
<attributes>
|
||||||
|
|
|
@ -3,5 +3,6 @@
|
||||||
<wb-module deploy-name="openid-connect-client">
|
<wb-module deploy-name="openid-connect-client">
|
||||||
<wb-resource deploy-path="/" source-path="/src/main/java"/>
|
<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/main/resources"/>
|
||||||
|
<wb-resource deploy-path="/" source-path="/src/test/java"/>
|
||||||
</wb-module>
|
</wb-module>
|
||||||
</project-modules>
|
</project-modules>
|
||||||
|
|
|
@ -132,4 +132,20 @@ public class OIDCAuthenticationFilter extends AbstractOIDCAuthenticationFilter {
|
||||||
public void setTokenEndpointURI(String tokenEndpointURI) {
|
public void setTokenEndpointURI(String tokenEndpointURI) {
|
||||||
oidcServerConfig.setTokenEndpointURI(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;
|
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
|
* @author nemonik
|
||||||
*
|
*
|
||||||
|
@ -31,6 +40,18 @@ public class OIDCServerConfiguration {
|
||||||
|
|
||||||
private String clientId;
|
private String clientId;
|
||||||
|
|
||||||
|
private String x509EncryptUrl;
|
||||||
|
|
||||||
|
private String x509SigningUrl;
|
||||||
|
|
||||||
|
private String jwkEncryptUrl;
|
||||||
|
|
||||||
|
private String jwkSigningUrl;
|
||||||
|
|
||||||
|
private Key encryptKey;
|
||||||
|
|
||||||
|
private Key signingKey;
|
||||||
|
|
||||||
public String getAuthorizationEndpointURI() {
|
public String getAuthorizationEndpointURI() {
|
||||||
return authorizationEndpointURI;
|
return authorizationEndpointURI;
|
||||||
}
|
}
|
||||||
|
@ -71,13 +92,88 @@ public class OIDCServerConfiguration {
|
||||||
this.tokenEndpointURI = 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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "OIDCServerConfiguration [authorizationEndpointURI="
|
return "OIDCServerConfiguration [authorizationEndpointURI="
|
||||||
+ authorizationEndpointURI + ", tokenEndpointURI="
|
+ authorizationEndpointURI + ", tokenEndpointURI="
|
||||||
+ tokenEndpointURI + ", checkIDEndpointURI="
|
+ tokenEndpointURI + ", checkIDEndpointURI="
|
||||||
+ checkIDEndpointURI + ", clientSecret=" + clientSecret
|
+ 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"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<classpath>
|
<classpath>
|
||||||
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
|
<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.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">
|
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||||
<attributes>
|
<attributes>
|
||||||
|
@ -9,3 +11,4 @@
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry kind="output" path="target/classes"/>
|
<classpathentry kind="output" path="target/classes"/>
|
||||||
</classpath>
|
</classpath>
|
||||||
|
|
||||||
|
|
|
@ -2,5 +2,6 @@
|
||||||
<project-modules id="moduleCoreId" project-version="1.5.0">
|
<project-modules id="moduleCoreId" project-version="1.5.0">
|
||||||
<wb-module deploy-name="openid-connect-common">
|
<wb-module deploy-name="openid-connect-common">
|
||||||
<wb-resource deploy-path="/" source-path="/src/main/java"/>
|
<wb-resource deploy-path="/" source-path="/src/main/java"/>
|
||||||
|
<wb-resource deploy-path="/" source-path="/src/test/java"/>
|
||||||
</wb-module>
|
</wb-module>
|
||||||
</project-modules>
|
</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;
|
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 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.
|
* A collection of utility methods.
|
||||||
*
|
*
|
||||||
|
@ -43,4 +69,57 @@ public class Utility {
|
||||||
}
|
}
|
||||||
return issuer;
|
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