From fca30cd13f40d273b5868c05de9b19a70f85f4e7 Mon Sep 17 00:00:00 2001
From: Justin Richer <jricher@mitre.org>
Date: Tue, 19 Feb 2013 15:16:55 -0500
Subject: [PATCH] added provisions to bootstrap signing and validation service
 from config files

---
 .../JwtSigningAndValidationService.java       |   5 -
 ...DefaultJwtSigningAndValidationService.java |  20 ++-
 .../impl/RSASSASignerVerifierBuilder.java     | 125 ++++++++++++++++++
 .../src/main/webapp/WEB-INF/crypto-config.xml |  13 +-
 4 files changed, 146 insertions(+), 17 deletions(-)
 create mode 100644 openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/RSASSASignerVerifierBuilder.java

diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/JwtSigningAndValidationService.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/JwtSigningAndValidationService.java
index fb3751956..a892a1bf5 100644
--- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/JwtSigningAndValidationService.java
+++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/JwtSigningAndValidationService.java
@@ -16,12 +16,7 @@
 package org.mitre.jwt.signer.service;
 
 import java.security.NoSuchAlgorithmException;
-import java.util.Map;
 
-import org.mitre.jwt.model.Jwt;
-import org.mitre.jwt.signer.JwtSigner;
-
-import com.nimbusds.jwt.JWT;
 import com.nimbusds.jwt.SignedJWT;
 
 public interface JwtSigningAndValidationService {
diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DefaultJwtSigningAndValidationService.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DefaultJwtSigningAndValidationService.java
index 84f1dc614..3ad8cbd55 100644
--- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DefaultJwtSigningAndValidationService.java
+++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DefaultJwtSigningAndValidationService.java
@@ -18,6 +18,7 @@ package org.mitre.jwt.signer.service.impl;
 import java.security.NoSuchAlgorithmException;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Map.Entry;
 
 import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
 import org.mitre.openid.connect.config.ConfigurationPropertiesBean;
@@ -37,9 +38,9 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
 	private ConfigurationPropertiesBean configBean;
 	
 	// map of identifier to signer
-	private Map<String, ? extends JWSSigner> signers = new HashMap<String, JWSSigner>();
+	private Map<String, JWSSigner> signers = new HashMap<String, JWSSigner>();
 	// map of identifier to verifier
-	private Map<String, ? extends JWSVerifier> verifiers = new HashMap<String, JWSVerifier>();
+	private Map<String, JWSVerifier> verifiers = new HashMap<String, JWSVerifier>();
 
 	private static Logger logger = LoggerFactory.getLogger(DefaultJwtSigningAndValidationService.class);
 
@@ -47,6 +48,21 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
 	 * default constructor
 	 */
 	public DefaultJwtSigningAndValidationService() {
+
+	}
+	
+	public DefaultJwtSigningAndValidationService(Map<String, RSASSASignerVerifierBuilder> builders) {
+		
+		for (Entry<String, RSASSASignerVerifierBuilder> e : builders.entrySet()) {
+	        
+			JWSSigner signer = e.getValue().buildSigner();
+			signers.put(e.getKey(), signer);
+			
+	        JWSVerifier verifier = e.getValue().buildVerifier();
+	        verifiers.put(e.getKey(), verifier);
+	        
+        }
+		
 	}
 
 	/*
diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/RSASSASignerVerifierBuilder.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/RSASSASignerVerifierBuilder.java
new file mode 100644
index 000000000..576ada0d4
--- /dev/null
+++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/RSASSASignerVerifierBuilder.java
@@ -0,0 +1,125 @@
+/**
+ * 
+ */
+package org.mitre.jwt.signer.service.impl;
+
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+
+import org.mitre.jwt.encryption.impl.KeyStore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.nimbusds.jose.crypto.RSASSASigner;
+import com.nimbusds.jose.crypto.RSASSAVerifier;
+
+/**
+ * @author jricher
+ *
+ */
+public class RSASSASignerVerifierBuilder {
+	
+	private static Logger log = LoggerFactory.getLogger(RSASSASignerVerifierBuilder.class);
+
+	private String alias;
+	private String password;
+	private KeyStore keystore;
+	/**
+	 * @return the alias
+	 */
+	public String getAlias() {
+		return alias;
+	}
+	/**
+	 * @param alias the alias to set
+	 */
+	public void setAlias(String alias) {
+		this.alias = alias;
+	}
+	/**
+	 * @return the password
+	 */
+	public String getPassword() {
+		return password;
+	}
+	/**
+	 * @param password the password to set
+	 */
+	public void setPassword(String password) {
+		this.password = password;
+	}
+	/**
+	 * @return the keystore
+	 */
+	public KeyStore getKeystore() {
+		return keystore;
+	}
+	/**
+	 * @param keystore the keystore to set
+	 */
+	public void setKeystore(KeyStore keystore) {
+		this.keystore = keystore;
+	}
+	
+	/**
+	 * Build the signer as configured from the given keystore, null if it can't be built for some reason
+	 * @return
+	 */
+	public RSASSASigner buildSigner() {
+		
+		try {
+	        KeyPair keyPair = keystore.getKeyPairForAlias(alias, password);
+	        
+	        PrivateKey privateKey = keyPair.getPrivate();
+	        
+	        if (privateKey instanceof RSAPrivateKey) {
+	        	RSASSASigner signer = new RSASSASigner((RSAPrivateKey) privateKey);
+	        	return signer;
+	        } else {
+	        	log.warn("Couldn't build signer, referenced key is not RSA");
+	        	return null;
+	        }
+        } catch (GeneralSecurityException e) {
+	        // TODO Auto-generated catch block
+	        log.warn("Couldn't buld signer:", e);
+	        
+        }
+		
+		log.warn("Couldn't build signer");
+		return null;
+		
+	}
+	
+	/**
+	 * Build the signer as configured from the given keystore, null if it can't be built for some reason
+	 * @return
+	 */
+	public RSASSAVerifier buildVerifier() {
+		
+		try {
+	        KeyPair keyPair = keystore.getKeyPairForAlias(alias, password);
+	        
+	        PublicKey publicKey = keyPair.getPublic();
+	        
+	        if (publicKey instanceof RSAPublicKey) {
+	        	RSASSAVerifier signer = new RSASSAVerifier((RSAPublicKey) publicKey);
+	        	return signer;
+	        } else {
+	        	log.warn("Couldn't build verifier, referenced key is not RSA");
+	        	return null;
+	        }
+        } catch (GeneralSecurityException e) {
+	        // TODO Auto-generated catch block
+	        log.warn("Couldn't buld verifier:", e);
+	        
+        }
+		
+		log.warn("Couldn't build verifier");
+		return null;
+		
+	}
+}
diff --git a/openid-connect-server/src/main/webapp/WEB-INF/crypto-config.xml b/openid-connect-server/src/main/webapp/WEB-INF/crypto-config.xml
index 382d5baca..2b938a328 100644
--- a/openid-connect-server/src/main/webapp/WEB-INF/crypto-config.xml
+++ b/openid-connect-server/src/main/webapp/WEB-INF/crypto-config.xml
@@ -10,24 +10,17 @@
 
 	<bean id="defaultsignerService"
 		class="org.mitre.jwt.signer.service.impl.DefaultJwtSigningAndValidationService">
-		<property name="signers">
+		<constructor-arg name="builders">
 			<map>
 				<entry key="rsa1">
-					<bean id="rsaSigner" class="org.mitre.jwt.signer.impl.RsaSigner">
-						<property name="algorithm" value="RS256" />
+					<bean id="rsaSignerBuilder" class="org.mitre.jwt.signer.service.impl.RSASSASignerVerifierBuilder">
 						<property name="keystore" ref="defaultKeystore" />
 						<property name="alias" value="rsa" />
 						<property name="password" value="changeit" />
 					</bean>
 				</entry>
-				<entry key="hmac1">
-					<bean id="hmacSigner" class="org.mitre.jwt.signer.impl.HmacSigner">
-						<property name="algorithm" value="HS256" />
-						<property name="passphrase" value="changeit" />
-					</bean>
-				</entry>
 			</map>
-		</property>
+		</constructor-arg>
 	</bean>
 
 </beans>