additional signer service code

pull/59/head
nemonik 2012-02-17 12:16:26 -05:00
parent 89f9961c1a
commit 066cf62f3b
7 changed files with 101 additions and 13 deletions

View File

@ -256,7 +256,7 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.bouncycastle</groupId> <groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId> <artifactId>bcprov-ext-jdk16</artifactId>
<version>1.46</version> <version>1.46</version>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -3,13 +3,10 @@ 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.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.SignatureException;
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;
@ -22,6 +19,14 @@ import org.springframework.beans.factory.InitializingBean;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.collect.Lists; 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 { public class EcdsaSigner extends AbstractJwtSigner implements InitializingBean {
/** /**
@ -37,7 +42,8 @@ public class EcdsaSigner extends AbstractJwtSigner implements InitializingBean {
ES384("SHA384withECDSA"), ES384("SHA384withECDSA"),
ES512("SHA512withECDSA"); 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 * 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); private static Log logger = LogFactory.getLog(EcdsaSigner.class);
public static final String KEYPAIR_ALGORITHM = "EC"; public static final String KEYPAIR_ALGORITHM = "EC";
@ -118,8 +126,8 @@ public class EcdsaSigner extends AbstractJwtSigner implements InitializingBean {
setPassword(password); setPassword(password);
try { try {
signer = Signature.getInstance(Algorithm.getByName(algorithmName).getStandardName()); //, PROVIDER) signer = Signature.getInstance(Algorithm.getByName(algorithmName).getStandardName(), PROVIDER);
} catch (NoSuchAlgorithmException e) { } catch (GeneralSecurityException e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
} }

View File

@ -40,7 +40,9 @@ public class RsaSigner extends AbstractJwtSigner implements InitializingBean {
RS256("SHA256withRSA"), RS384("SHA384withRSA"), RS512("SHA512withRSA"); RS256("SHA256withRSA"), RS384("SHA384withRSA"), RS512("SHA512withRSA");
public static final String DEFAULT = Algorithm.RS256.toString(); public static final String DEFAULT = Algorithm.RS256.toString();
public static final String PREPEND = "RS";
/** /**
* Returns the Algorithm for the name * Returns the Algorithm for the name
* *

View File

@ -22,7 +22,7 @@ import org.springframework.core.io.Resource;
public class KeyStore implements InitializingBean { public class KeyStore implements InitializingBean {
private static Log logger = LogFactory.getLog(KeyStore.class); private static Log logger = LogFactory.getLog(KeyStore.class);
public static final String TYPE = java.security.KeyStore.getDefaultType(); public static final String TYPE = java.security.KeyStore.getDefaultType();
public static final String PASSWORD = "changeit"; public static final String PASSWORD = "changeit";

View File

@ -4,6 +4,7 @@ import java.util.List;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; 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.HmacSigner;
import org.mitre.jwt.signer.impl.RsaSigner; import org.mitre.jwt.signer.impl.RsaSigner;
import org.springframework.beans.BeanMetadataElement; import org.springframework.beans.BeanMetadataElement;
@ -42,7 +43,7 @@ public class ServiceDefinitionParser extends AbstractSingleBeanDefinitionParser
ManagedList<BeanMetadataElement> signers = new ManagedList<BeanMetadataElement>(); ManagedList<BeanMetadataElement> signers = new ManagedList<BeanMetadataElement>();
List<Element> signerElements = DomUtils.getChildElementsByTagName( List<Element> signerElements = DomUtils.getChildElementsByTagName(
element, new String[] { "rsa", "hmac" }); element, new String[] { "rsa", "ecdsa", "hmac" });
for (Element signerElement : signerElements) { for (Element signerElement : signerElements) {
@ -55,7 +56,7 @@ public class ServiceDefinitionParser extends AbstractSingleBeanDefinitionParser
String bits = signerElement.getAttribute("bits"); String bits = signerElement.getAttribute("bits");
if (StringUtils.hasText(bits)) { if (StringUtils.hasText(bits)) {
signer.addConstructorArgValue("RS".concat(bits)); signer.addConstructorArgValue(RsaSigner.Algorithm.PREPEND.concat(bits));
} else { } else {
signer.addConstructorArgValue(RsaSigner.Algorithm.DEFAULT); signer.addConstructorArgValue(RsaSigner.Algorithm.DEFAULT);
} }
@ -89,6 +90,49 @@ public class ServiceDefinitionParser extends AbstractSingleBeanDefinitionParser
signers.add(signer.getBeanDefinition()); 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")) { } else if (signerElement.getTagName().contains("hmac")) {
logger.debug("parsing hmac element"); logger.debug("parsing hmac element");
@ -114,7 +158,7 @@ public class ServiceDefinitionParser extends AbstractSingleBeanDefinitionParser
} }
signers.add(signer.getBeanDefinition()); signers.add(signer.getBeanDefinition());
} }
} }
builder.addPropertyValue("signers", signers); builder.addPropertyValue("signers", signers);

View File

@ -71,6 +71,40 @@
</xsd:attribute> </xsd:attribute>
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
<xsd:element name="ecdsa">
<xsd:annotation>
<xsd:documentation>
Configures an ECDSA signer.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:attribute name="bits" type="xsd:string" />
<xsd:attribute name="keystore-ref" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation>
The reference to the bean that defines the
KeyStore.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="key-alias" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation>
The alias to the KeyPair to use for
signing/verifying.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="password" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
The password to the KeyPair to use for
signing/verifying.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="hmac"> <xsd:element name="hmac">
<xsd:annotation> <xsd:annotation>
<xsd:documentation> <xsd:documentation>

View File

@ -15,7 +15,6 @@ import java.security.KeyPairGenerator;
import java.security.PrivateKey; 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.util.Date; import java.util.Date;
import org.bouncycastle.jce.X509Principal; import org.bouncycastle.jce.X509Principal;
@ -39,8 +38,9 @@ public class KeyStoreTest {
@Qualifier("testKeystore") @Qualifier("testKeystore")
KeyStore keystore; KeyStore keystore;
static final String PROVIDER = "BC";
static { static {
// Needed to create the certificate
Security.addProvider(new BouncyCastleProvider()); Security.addProvider(new BouncyCastleProvider());
} }