From 066cf62f3bc8eccab32aff78e4d4dded7fd63336 Mon Sep 17 00:00:00 2001 From: nemonik Date: Fri, 17 Feb 2012 12:16:26 -0500 Subject: [PATCH] additional signer service code --- server/pom.xml | 2 +- .../mitre/jwt/signer/impl/EcdsaSigner.java | 20 +++++--- .../org/mitre/jwt/signer/impl/RsaSigner.java | 2 + .../jwt/signer/service/impl/KeyStore.java | 2 +- .../service/impl/ServiceDefinitionParser.java | 50 +++++++++++++++++-- .../signer/service/impl/jwt-signer-1.0.xsd | 34 +++++++++++++ .../jwt/signer/service/impl/KeyStoreTest.java | 4 +- 7 files changed, 101 insertions(+), 13 deletions(-) diff --git a/server/pom.xml b/server/pom.xml index 2002d6175..dec9d7e27 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -256,7 +256,7 @@ org.bouncycastle - bcprov-jdk16 + bcprov-ext-jdk16 1.46 diff --git a/server/src/main/java/org/mitre/jwt/signer/impl/EcdsaSigner.java b/server/src/main/java/org/mitre/jwt/signer/impl/EcdsaSigner.java index 2ac0d86ad..06c8dd3e7 100644 --- a/server/src/main/java/org/mitre/jwt/signer/impl/EcdsaSigner.java +++ b/server/src/main/java/org/mitre/jwt/signer/impl/EcdsaSigner.java @@ -3,13 +3,10 @@ package org.mitre.jwt.signer.impl; import java.io.UnsupportedEncodingException; import java.security.GeneralSecurityException; import java.security.KeyPair; -import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; import java.util.List; import org.apache.commons.codec.binary.Base64; @@ -22,6 +19,14 @@ import org.springframework.beans.factory.InitializingBean; import com.google.common.base.Splitter; import com.google.common.collect.Lists; +/** + * JWT Signer using either the ECDSA SHA-256, SHA-384, SHA-512 hash algorithm + * + * @author AANGANES, nemonik + * + * Requires static install of BC + * + */ public class EcdsaSigner extends AbstractJwtSigner implements InitializingBean { /** @@ -37,7 +42,8 @@ public class EcdsaSigner extends AbstractJwtSigner implements InitializingBean { ES384("SHA384withECDSA"), ES512("SHA512withECDSA"); - private static final String DEFAULT = Algorithm.ES256.toString(); + public static final String DEFAULT = Algorithm.ES256.toString(); + public static final String PREPEND = "ES"; /** * Returns the Algorithm for the name @@ -75,6 +81,8 @@ public class EcdsaSigner extends AbstractJwtSigner implements InitializingBean { } }; + static final String PROVIDER = "BC"; + private static Log logger = LogFactory.getLog(EcdsaSigner.class); public static final String KEYPAIR_ALGORITHM = "EC"; @@ -118,8 +126,8 @@ public class EcdsaSigner extends AbstractJwtSigner implements InitializingBean { setPassword(password); try { - signer = Signature.getInstance(Algorithm.getByName(algorithmName).getStandardName()); //, PROVIDER) - } catch (NoSuchAlgorithmException e) { + signer = Signature.getInstance(Algorithm.getByName(algorithmName).getStandardName(), PROVIDER); + } catch (GeneralSecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } diff --git a/server/src/main/java/org/mitre/jwt/signer/impl/RsaSigner.java b/server/src/main/java/org/mitre/jwt/signer/impl/RsaSigner.java index 3c933e062..95b0f2a81 100644 --- a/server/src/main/java/org/mitre/jwt/signer/impl/RsaSigner.java +++ b/server/src/main/java/org/mitre/jwt/signer/impl/RsaSigner.java @@ -40,7 +40,9 @@ public class RsaSigner extends AbstractJwtSigner implements InitializingBean { RS256("SHA256withRSA"), RS384("SHA384withRSA"), RS512("SHA512withRSA"); public static final String DEFAULT = Algorithm.RS256.toString(); + public static final String PREPEND = "RS"; + /** * Returns the Algorithm for the name * diff --git a/server/src/main/java/org/mitre/jwt/signer/service/impl/KeyStore.java b/server/src/main/java/org/mitre/jwt/signer/service/impl/KeyStore.java index dc6431d36..9592316e7 100644 --- a/server/src/main/java/org/mitre/jwt/signer/service/impl/KeyStore.java +++ b/server/src/main/java/org/mitre/jwt/signer/service/impl/KeyStore.java @@ -22,7 +22,7 @@ import org.springframework.core.io.Resource; public class KeyStore implements InitializingBean { private static Log logger = LogFactory.getLog(KeyStore.class); - + public static final String TYPE = java.security.KeyStore.getDefaultType(); public static final String PASSWORD = "changeit"; diff --git a/server/src/main/java/org/mitre/jwt/signer/service/impl/ServiceDefinitionParser.java b/server/src/main/java/org/mitre/jwt/signer/service/impl/ServiceDefinitionParser.java index 2a7d53aa7..2bd381f85 100644 --- a/server/src/main/java/org/mitre/jwt/signer/service/impl/ServiceDefinitionParser.java +++ b/server/src/main/java/org/mitre/jwt/signer/service/impl/ServiceDefinitionParser.java @@ -4,6 +4,7 @@ import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.mitre.jwt.signer.impl.EcdsaSigner; import org.mitre.jwt.signer.impl.HmacSigner; import org.mitre.jwt.signer.impl.RsaSigner; import org.springframework.beans.BeanMetadataElement; @@ -42,7 +43,7 @@ public class ServiceDefinitionParser extends AbstractSingleBeanDefinitionParser ManagedList signers = new ManagedList(); List signerElements = DomUtils.getChildElementsByTagName( - element, new String[] { "rsa", "hmac" }); + element, new String[] { "rsa", "ecdsa", "hmac" }); for (Element signerElement : signerElements) { @@ -55,7 +56,7 @@ public class ServiceDefinitionParser extends AbstractSingleBeanDefinitionParser String bits = signerElement.getAttribute("bits"); if (StringUtils.hasText(bits)) { - signer.addConstructorArgValue("RS".concat(bits)); + signer.addConstructorArgValue(RsaSigner.Algorithm.PREPEND.concat(bits)); } else { signer.addConstructorArgValue(RsaSigner.Algorithm.DEFAULT); } @@ -89,6 +90,49 @@ public class ServiceDefinitionParser extends AbstractSingleBeanDefinitionParser signers.add(signer.getBeanDefinition()); + } else if (signerElement.getTagName().contains("ecdsa")) { + + logger.debug("parsing ecdsa element"); + + BeanDefinitionBuilder signer = BeanDefinitionBuilder + .rootBeanDefinition(EcdsaSigner.class); + + String bits = signerElement.getAttribute("bits"); + if (StringUtils.hasText(bits)) { + signer.addConstructorArgValue(EcdsaSigner.Algorithm.PREPEND.concat(bits)); + } else { + signer.addConstructorArgValue(EcdsaSigner.Algorithm.DEFAULT); + } + + String keystoreRef = signerElement.getAttribute("keystore-ref"); + if (!StringUtils.hasText(keystoreRef)) { + parserContext + .getReaderContext() + .error("A keystore-ref must be supplied with the definition of a ecdsa.", + signerElement); + } else { + signer.addConstructorArgReference(keystoreRef); + } + + String alias = signerElement.getAttribute("key-alias"); + if (!StringUtils.hasText(alias)) { + parserContext + .getReaderContext() + .error("An key-alias must be supplied with the definition of a ecdsa.", + signerElement); + } else { + signer.addConstructorArgValue(alias); + } + + String password = signerElement.getAttribute("password"); + if (StringUtils.hasText(password)) { + signer.addConstructorArgValue(password); + } else { + signer.addConstructorArgValue(EcdsaSigner.DEFAULT_PASSWORD); + } + + signers.add(signer.getBeanDefinition()); + } else if (signerElement.getTagName().contains("hmac")) { logger.debug("parsing hmac element"); @@ -114,7 +158,7 @@ public class ServiceDefinitionParser extends AbstractSingleBeanDefinitionParser } signers.add(signer.getBeanDefinition()); - } + } } builder.addPropertyValue("signers", signers); diff --git a/server/src/main/resources/org/mitre/jwt/signer/service/impl/jwt-signer-1.0.xsd b/server/src/main/resources/org/mitre/jwt/signer/service/impl/jwt-signer-1.0.xsd index 81b06f12c..cb3e606fa 100644 --- a/server/src/main/resources/org/mitre/jwt/signer/service/impl/jwt-signer-1.0.xsd +++ b/server/src/main/resources/org/mitre/jwt/signer/service/impl/jwt-signer-1.0.xsd @@ -71,6 +71,40 @@ + + + + Configures an ECDSA signer. + + + + + + + + The reference to the bean that defines the + KeyStore. + + + + + + + The alias to the KeyPair to use for + signing/verifying. + + + + + + + The password to the KeyPair to use for + signing/verifying. + + + + + diff --git a/server/src/test/java/org/mitre/jwt/signer/service/impl/KeyStoreTest.java b/server/src/test/java/org/mitre/jwt/signer/service/impl/KeyStoreTest.java index f07a6cafd..1be36f671 100644 --- a/server/src/test/java/org/mitre/jwt/signer/service/impl/KeyStoreTest.java +++ b/server/src/test/java/org/mitre/jwt/signer/service/impl/KeyStoreTest.java @@ -15,7 +15,6 @@ import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.Security; import java.security.cert.X509Certificate; -import java.security.interfaces.RSAPrivateKey; import java.util.Date; import org.bouncycastle.jce.X509Principal; @@ -39,8 +38,9 @@ public class KeyStoreTest { @Qualifier("testKeystore") KeyStore keystore; + static final String PROVIDER = "BC"; + static { - // Needed to create the certificate Security.addProvider(new BouncyCastleProvider()); }