Merge remote branch 'origin/master'

pull/59/head
Michael Jett 2012-02-17 15:23:21 -05:00
commit 21c88df5ed
9 changed files with 101 additions and 106 deletions

View File

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

View File

@ -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();
}

View File

@ -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
*

View File

@ -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";

View File

@ -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<BeanMetadataElement> signers = new ManagedList<BeanMetadataElement>();
List<Element> 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);

View File

@ -71,6 +71,40 @@
</xsd:attribute>
</xsd:complexType>
</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:annotation>
<xsd:documentation>

View File

@ -1,93 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema xmlns="http://www.mitre.org/schema/openid-connect/jwt-signer"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans"
targetNamespace="http://www.mitre.org/schema/openid-connect/jwt-signer"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"/>
<xs:element name="keystore">
<xs:annotation>
<xs:documentation>
Describes the JCE KeyStore necessary for certain
signers.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:complexContent>
<xs:extension base="beans:identifiedType">
<xs:attribute name="location" type="xs:string" use="required" />
<xs:attribute name="password" type="xs:string" />
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element name="service">
<xs:annotation>
<xs:documentation>
Configures the signer service with these signers.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:complexContent>
<xs:extension base="beans:identifiedType">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="rsa">
<xs:annotation>
<xs:documentation>
Configures an RSA signer.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="bits" type="xs:string" />
<xs:attribute name="keystore-ref" type="xs:string" use="required">
<xs:annotation>
<xs:documentation>
The reference to the bean that defines the
KeyStore.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="key-alias" type="xs:string"
use="required">
<xs:annotation>
<xs:documentation>
The alias to the KeyPair to use for
signing/verifying.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="password" type="xs:string">
<xs:annotation>
<xs:documentation>
The password to the KeyPair to use for
signing/verifying.
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="hmac">
<xs:annotation>
<xs:documentation>
Configures an HMAC signer.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="bits" type="xs:integer" />
<xs:attribute name="passphrase" type="xs:string">
<xs:annotation>
<xs:documentation>
The passphrase used for signing/verifying.
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@ -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());
}