Permalink
Browse files

Changes to support retrieving certificates as beans.

  • Loading branch information...
iamthechad committed May 10, 2012
1 parent d1a9e96 commit b0c7e8dab8c3f9ead869055aa460feb0dc5af4f6
Showing with 456 additions and 0 deletions.
  1. +16 −0 src/main/java/com/google/code/springcryptoutils/core/certificate/CertificateChooserByAlias.java
  2. +25 −0 src/main/java/com/google/code/springcryptoutils/core/certificate/CertificateException.java
  3. +56 −0 src/main/java/com/google/code/springcryptoutils/core/certificate/CertificateFactoryBean.java
  4. +23 −0 src/main/java/com/google/code/springcryptoutils/core/certificate/CertificateRegistryByAlias.java
  5. +106 −0 src/main/java/com/google/code/springcryptoutils/core/certificate/CertificateRegistryByAliasImpl.java
  6. +7 −0 src/main/java/com/google/code/springcryptoutils/core/certificate/package-info.java
  7. +6 −0 src/main/java/com/google/code/springcryptoutils/core/spring/SpringCryptoUtilsNamespaceHandler.java
  8. +23 −0 ...va/com/google/code/springcryptoutils/core/spring/certificate/CertificateBeanDefinitionParser.java
  9. +22 −0 ...ode/springcryptoutils/core/spring/certificate/CertificateRegistryByaliasBeanDefinitionParser.java
  10. +23 −0 src/main/resources/com/google/code/springcryptoutils/core/spring/crypt.xsd
  11. +32 −0 .../java/com/google/code/springcryptoutils/core/certificate/CertificateFactoryBeanExceptionTest.java
  12. +26 −0 src/test/java/com/google/code/springcryptoutils/core/certificate/CertificateFactoryBeanTest.java
  13. +54 −0 ...t/java/com/google/code/springcryptoutils/core/certificate/CertificateRegistryByAliasImplTest.java
  14. +8 −0 ...om/google/code/springcryptoutils/core/certificate/CertificateFactoryBeanExceptionTest-context.xml
  15. +10 −0 ...sources/com/google/code/springcryptoutils/core/certificate/CertificateFactoryBeanTest-context.xml
  16. +19 −0 ...com/google/code/springcryptoutils/core/certificate/CertificateRegistryByAliasImplTest-context.xml
@@ -0,0 +1,16 @@
package com.google.code.springcryptoutils.core.certificate;
/**
* An interface for choosing certificates from a keystore.
*
* @author Chad Johnston (cjohnston@megatome.com)
*/
public interface CertificateChooserByAlias {
/**
* Must return the alias the key has in the keystore.
*
* @return the alias
*/
String getAlias();
}
@@ -0,0 +1,25 @@
package com.google.code.springcryptoutils.core.certificate;
/**
* @author Chad Johnston (cjohnston@megatome.com)
*/
public class CertificateException extends RuntimeException {
/**
* Creates a new exception instance.
*
* @param message the exception message
*/
public CertificateException(String message) {
super(message);
}
/**
* Creates a new exception instance.
*
* @param message the exception message
* @param cause the root cause
*/
public CertificateException(String message, Throwable cause) {
super(message, cause);
}
}
@@ -0,0 +1,56 @@
package com.google.code.springcryptoutils.core.certificate;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.cert.Certificate;
public class CertificateFactoryBean implements FactoryBean, InitializingBean {
private KeyStore keystore;
private String alias;
private Certificate certificate;
/**
* Sets the keystore holding the public key.
*
* @param keystore the keystore
*/
public void setKeystore(KeyStore keystore) {
this.keystore = keystore;
}
/**
* Sets the certificate alias as known in the keystore.
*
* @param alias the certificate alias
*/
public void setAlias(String alias) {
this.alias = alias;
}
public Object getObject() {
return certificate;
}
public Class getObjectType() {
return Certificate.class;
}
public boolean isSingleton() {
return true;
}
public void afterPropertiesSet() throws KeyStoreException {
Certificate cert = keystore.getCertificate(alias);
if (cert == null) {
throw new CertificateException("no such certificate with alias: " + alias);
}
certificate = cert;
}
}
@@ -0,0 +1,23 @@
package com.google.code.springcryptoutils.core.certificate;
import com.google.code.springcryptoutils.core.keystore.KeyStoreChooser;
import java.security.cert.Certificate;
/**
* An interface for selecting a certificate at runtime from an
* underlying certificate registry.
*
* @author Chad Johnston (cjohnston@megatome.com)
*/
public interface CertificateRegistryByAlias {
/**
* Returns the selected certificate or null if not found.
*
* @param keyStoreChooser the keystore chooser
* @param certificateChooserByAlias the certificate chooser by alias
* @return the selected certificate or null if not found
*/
Certificate get(KeyStoreChooser keyStoreChooser, CertificateChooserByAlias certificateChooserByAlias);
}
@@ -0,0 +1,106 @@
package com.google.code.springcryptoutils.core.certificate;
import com.google.code.springcryptoutils.core.keystore.KeyStoreChooser;
import com.google.code.springcryptoutils.core.keystore.KeyStoreRegistry;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.util.HashMap;
import java.util.Map;
/**
* @author Chad Johnston (cjohnston@megatome.com)
*/
public class CertificateRegistryByAliasImpl implements CertificateRegistryByAlias {
private KeyStoreRegistry keyStoreRegistry;
private Map<CacheCert, Certificate> cache = new HashMap<CacheCert, Certificate>();
/**
* Sets the keystore registry.
*
* @param keyStoreRegistry the keystore registry
*/
public void setKeyStoreRegistry(KeyStoreRegistry keyStoreRegistry) {
this.keyStoreRegistry = keyStoreRegistry;
}
/**
* Returns the selected certificate or null if not found.
*
* @param keyStoreChooser the keystore chooser
* @param certificateChooserByAlias the public key chooser by alias
* @return the selected public key or null if not found
*/
public Certificate get(KeyStoreChooser keyStoreChooser, CertificateChooserByAlias certificateChooserByAlias) {
CacheCert cacheCert = new CacheCert(keyStoreChooser.getKeyStoreName(), certificateChooserByAlias.getAlias());
Certificate retrievedPublicKey = cache.get(cacheCert);
if (retrievedPublicKey != null) {
return retrievedPublicKey;
}
KeyStore keyStore = keyStoreRegistry.get(keyStoreChooser);
if (keyStore != null) {
CertificateFactoryBean factory = new CertificateFactoryBean();
factory.setKeystore(keyStore);
factory.setAlias(certificateChooserByAlias.getAlias());
try {
factory.afterPropertiesSet();
Certificate certificate = (Certificate) factory.getObject();
if (certificate != null) {
cache.put(cacheCert, certificate);
}
return certificate;
} catch (Exception e) {
throw new CertificateException("error initializing the certificate factory bean", e);
}
}
return null;
}
private static final class CacheCert {
private static final int INT_HASHCODE_BASE = 31;
private String keyStoreName;
private String certificateAlias;
private CacheCert(String keyStoreName, String certificateAlias) {
this.keyStoreName = keyStoreName;
this.certificateAlias = certificateAlias;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
CacheCert cacheCert = (CacheCert) o;
return !(keyStoreName != null ? !keyStoreName.equals(cacheCert.keyStoreName) : cacheCert.keyStoreName != null) && !(certificateAlias != null ? !certificateAlias.equals(cacheCert.certificateAlias) : cacheCert.certificateAlias != null);
}
@Override
public int hashCode() {
int result = keyStoreName != null ? keyStoreName.hashCode() : 0;
result = INT_HASHCODE_BASE * result + (certificateAlias != null ? certificateAlias.hashCode() : 0);
return result;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("CacheKey");
sb.append("{keyStoreName='").append(keyStoreName).append('\'');
sb.append(", certificateAlias='").append(certificateAlias).append('\'');
sb.append('}');
return sb.toString();
}
}
}
@@ -0,0 +1,7 @@
/**
* Interfaces and classes used to load cryptographic certificates
* and map references to them.
*
* @author Chad Johnston (cjohnston@megatome.com)
*/
package com.google.code.springcryptoutils.core.certificate;
@@ -1,5 +1,7 @@
package com.google.code.springcryptoutils.core.spring;
import com.google.code.springcryptoutils.core.spring.certificate.CertificateBeanDefinitionParser;
import com.google.code.springcryptoutils.core.spring.certificate.CertificateRegistryByAliasBeanDefinitionParser;
import com.google.code.springcryptoutils.core.spring.cipher.asymmetric.AsymmetricCiphererBeanDefinitionParser;
import com.google.code.springcryptoutils.core.spring.cipher.asymmetric.AsymmetricCiphererWithChooserByKeyIdBeanDefinitionParser;
import com.google.code.springcryptoutils.core.spring.cipher.asymmetric.Base64EncodedAsymmetricCiphererBeanDefinitionParser;
@@ -32,6 +34,10 @@ public void init() {
registerBeanDefinitionParser("publicKeyRegistryByAlias", new PublicKeyRegistryByAliasBeanDefinitionParser());
registerBeanDefinitionParser("privateKeyRegistryByAlias", new PrivateKeyRegistryByAliasBeanDefinitionParser());
// certificate
registerBeanDefinitionParser("certificateRegistryByAlias", new CertificateRegistryByAliasBeanDefinitionParser());
registerBeanDefinitionParser("certificate", new CertificateBeanDefinitionParser());
// signature
registerBeanDefinitionParser("signer", new SignerBeanDefinitionParser());
registerBeanDefinitionParser("verifier", new VerifierBeanDefinitionParser());
@@ -0,0 +1,23 @@
package com.google.code.springcryptoutils.core.spring.certificate;
import com.google.code.springcryptoutils.core.certificate.CertificateFactoryBean;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.w3c.dom.Element;
/**
* @author Chad Johnston (cjohnston@megatome.com)
*/
public class CertificateBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
@Override
protected Class getBeanClass(Element element) {
return CertificateFactoryBean.class;
}
@Override
protected void doParse(Element element, BeanDefinitionBuilder bean) {
bean.addPropertyReference("keystore", element.getAttribute("keystore-ref"));
bean.addPropertyValue("alias", element.getAttribute("alias"));
}
}
@@ -0,0 +1,22 @@
package com.google.code.springcryptoutils.core.spring.certificate;
import com.google.code.springcryptoutils.core.certificate.CertificateRegistryByAliasImpl;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.w3c.dom.Element;
/**
* @author Chad Johnston (cjohnston@megatome.com)
*/
public class CertificateRegistryByAliasBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
@Override
protected Class getBeanClass(Element element) {
return CertificateRegistryByAliasImpl.class;
}
@Override
protected void doParse(Element element, BeanDefinitionBuilder bean) {
bean.addPropertyReference("keyStoreRegistry", element.getAttribute("keystoreRegistry-ref"));
}
}
@@ -111,6 +111,29 @@
</xsd:complexType>
</xsd:element>
<!-- CERTIFICATE -->
<xsd:element name="certificateRegistryByAlias">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:attribute name="keystoreRegistry-ref" type="xsd:string" use="required"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="certificate">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:attribute name="keystore-ref" type="xsd:string" use="required"/>
<xsd:attribute name="alias" type="xsd:string" use="required"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<!-- DIGITAL SIGNATURE -->
<xsd:element name="signer">
@@ -0,0 +1,32 @@
package com.google.code.springcryptoutils.core.certificate;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.security.KeyStore;
import java.security.KeyStoreException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class CertificateFactoryBeanExceptionTest {
@Autowired
private KeyStore keyStore;
@Test(expected = CertificateException.class)
public void testInvalidAlias() throws KeyStoreException {
assertNotNull(keyStore);
assertEquals("keyStoreType", "JKS", keyStore.getType());
CertificateFactoryBean cfb = new CertificateFactoryBean();
cfb.setKeystore(keyStore);
cfb.setAlias("*** INVALID ***");
cfb.afterPropertiesSet();
}
}
@@ -0,0 +1,26 @@
package com.google.code.springcryptoutils.core.certificate;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.security.cert.Certificate;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class CertificateFactoryBeanTest {
@Autowired
private Certificate certificate;
@Test
public void testCertificateProperlyLoaded() {
assertNotNull(certificate);
assertEquals("certificate type", "X.509", certificate.getType());
}
}
Oops, something went wrong.

0 comments on commit b0c7e8d

Please sign in to comment.