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