/*
* eID Applet Project.
* Copyright (C) 2009 FedICT.
* Copyright (C) 2014 e-Contract.be BVBA.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version
* 3.0 as published by the Free Software Foundation.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, see
* http://www.gnu.org/licenses/.
*/
package test.unit.test.be.fedict.eid.applet.model;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.math.BigInteger;
import java.net.URI;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.RSAKeyGenParameterSpec;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.crypto.Cipher;
import javax.security.jacc.PolicyContext;
import javax.security.jacc.PolicyContextException;
import javax.security.jacc.PolicyContextHandler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.xml.crypto.dom.DOMCryptoContext;
import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.SignatureMethod;
import javax.xml.crypto.dsig.XMLSignContext;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.X509Data;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jcp.xml.dsig.internal.dom.DOMSignedInfo;
import org.apache.jcp.xml.dsig.internal.dom.DOMXMLSignature;
import org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI;
import org.apache.xml.security.Init;
import org.apache.xml.security.algorithms.MessageDigestAlgorithm;
import org.apache.xml.security.c14n.Canonicalizer;
import org.apache.xml.security.signature.ObjectContainer;
import org.apache.xml.security.signature.SignedInfo;
import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.signature.XMLSignatureInput;
import org.apache.xml.security.transforms.Transforms;
import org.apache.xml.security.utils.Base64;
import org.apache.xml.security.utils.resolver.ResourceResolverException;
import org.apache.xml.security.utils.resolver.ResourceResolverSpi;
import org.apache.xpath.XPathAPI;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.x509.AuthorityInformationAccess;
import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x509.X509Extensions;
import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
import org.bouncycastle.jce.X509Principal;
import org.bouncycastle.x509.X509V3CertificateGenerator;
import org.easymock.Capture;
import org.easymock.EasyMock;
import org.joda.time.DateTime;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import be.fedict.eid.applet.service.spi.DigestInfo;
import test.be.fedict.eid.applet.model.XmlSignatureServiceBean;
public class XmlSignatureServiceBeanTest {
public class ResourceTestResolver extends ResourceResolverSpi {
private final Log LOG = LogFactory.getLog(ResourceTestResolver.class);
private final Map<String, byte[]> resources;
public ResourceTestResolver() {
this.resources = new HashMap<String, byte[]>();
}
public void addResource(String uri, byte[] value) {
this.resources.put(uri, value);
}
@Override
public boolean engineCanResolve(Attr uri, String baseURI) {
LOG.debug("engine can resolve: " + uri.getValue());
return this.resources.containsKey(uri.getValue());
}
@Override
public XMLSignatureInput engineResolve(Attr uri, String baseURI) throws ResourceResolverException {
LOG.debug("engine resolve: " + uri.getValue());
if (false == this.resources.containsKey(uri.getValue())) {
return null;
}
return new XMLSignatureInput(this.resources.get(uri.getValue()));
}
}
private static final Log LOG = LogFactory.getLog(XmlSignatureServiceBeanTest.class);
private XmlSignatureServiceBean testedInstance;
@Before
public void setUp() throws Exception {
Init.init();
this.testedInstance = new XmlSignatureServiceBean();
}
public static final byte[] SHA1_DIGEST_INFO_PREFIX = new byte[] { 0x30, 0x1f, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e,
0x03, 0x02, 0x1a, 0x04, 0x14 };
@Test
public void testFilenamesForUri() throws Exception {
LOG.debug("test.txt: " + new URI("test.txt"));
LOG.debug("1234.txt: " + new URI("1234.txt"));
LOG.debug("hello world.txt: " + new File("hello world.txt").toURI().toURL().getFile());
LOG.debug("hello world.txt: " + FilenameUtils.getName(new File("hello world.txt").toURI().toURL().getFile()));
}
@Test
public void testExternalXmlSignature() throws Exception {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.newDocument();
XMLSignature xmlSignature = new XMLSignature(document, "", XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1,
Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS);
Element signatureElement = xmlSignature.getElement();
document.appendChild(signatureElement);
ObjectContainer objectContainer = new ObjectContainer(document);
objectContainer.appendChild(document.createTextNode("Test Message"));
String id = "object-" + UUID.randomUUID().toString();
objectContainer.setId(id);
xmlSignature.appendObject(objectContainer);
Transforms transforms = new Transforms(document);
transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_WITH_COMMENTS);
xmlSignature.addDocument("#" + id, transforms, MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA512, null, null);
KeyPair keyPair = generateKeyPair();
DateTime notBefore = new DateTime();
DateTime notAfter = notBefore.plusYears(1);
X509Certificate certificate = generateCertificate(keyPair.getPublic(), "CN=Test", notBefore, notAfter, null,
keyPair.getPrivate(), true, 0, null, new KeyUsage(KeyUsage.nonRepudiation));
xmlSignature.addKeyInfo(certificate);
SignedInfo signedInfo = xmlSignature.getSignedInfo();
signedInfo.generateDigestValues();
byte[] octets = signedInfo.getCanonicalizedOctetStream();
MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
byte[] digestValue = messageDigest.digest(octets);
byte[] digestInfoValue = ArrayUtils.addAll(SHA1_DIGEST_INFO_PREFIX, digestValue);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPrivate());
byte[] signatureValue = cipher.doFinal(digestInfoValue);
String encodedSignatureValue = Base64.encode(signatureValue);
Element xmlSignatureElement = xmlSignature.getElement();
Element signatureValueElement = (Element) XPathAPI.selectSingleNode(xmlSignatureElement, "ds:SignatureValue");
signatureValueElement.setTextContent(encodedSignatureValue);
xmlSignature = new XMLSignature(xmlSignatureElement, null);
assertTrue(xmlSignature.checkSignatureValue(keyPair.getPublic()));
Source source = new DOMSource(document);
StringWriter stringWriter = new StringWriter();
Result result = new StreamResult(stringWriter);
Transformer xformer = TransformerFactory.newInstance().newTransformer();
xformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
xformer.transform(source, result);
String signedDocumentStr = stringWriter.getBuffer().toString();
LOG.debug("signed document: " + signedDocumentStr);
File tmpFile = File.createTempFile("signature-", ".xml");
IOUtils.write(signedDocumentStr.getBytes(), new FileOutputStream(tmpFile));
StringReader stringReader = new StringReader(signedDocumentStr);
InputSource inputSource = new InputSource(stringReader);
Document signedDocument = documentBuilder.parse(inputSource);
signatureElement = (Element) XPathAPI.selectSingleNode(signedDocument, "ds:Signature");
assertNotNull(signatureElement);
xmlSignature = new XMLSignature(signatureElement, null);
LOG.debug("tmp signature file: " + tmpFile.getAbsolutePath());
boolean signatureResult = xmlSignature.checkSignatureValue(keyPair.getPublic());
assertTrue(signatureResult);
}
@Test
public void testJsr105ReferenceUri() throws Exception {
String uri = FilenameUtils.getName(new File("foo bar.txt").toURI().toURL().getFile());
KeyPair keyPair = generateKeyPair();
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.newDocument();
XMLSignatureFactory signatureFactory = XMLSignatureFactory.getInstance("DOM", new XMLDSigRI());
XMLSignContext signContext = new DOMSignContext(keyPair.getPrivate(), document);
byte[] externalDocument = "hello world".getBytes();
MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
messageDigest.update(externalDocument);
byte[] documentDigestValue = messageDigest.digest();
DigestMethod digestMethod = signatureFactory.newDigestMethod(DigestMethod.SHA1, null);
Reference reference = signatureFactory.newReference(uri, digestMethod, null, null, null, documentDigestValue);
SignatureMethod signatureMethod = signatureFactory.newSignatureMethod(SignatureMethod.RSA_SHA1, null);
CanonicalizationMethod canonicalizationMethod = signatureFactory.newCanonicalizationMethod(
CanonicalizationMethod.EXCLUSIVE_WITH_COMMENTS, (C14NMethodParameterSpec) null);
javax.xml.crypto.dsig.SignedInfo signedInfo = signatureFactory.newSignedInfo(canonicalizationMethod,
signatureMethod, Collections.singletonList(reference));
javax.xml.crypto.dsig.XMLSignature xmlSignature = signatureFactory.newXMLSignature(signedInfo, null);
xmlSignature.sign(signContext);
}
@Test
public void testJsr105Signature() throws Exception {
KeyPair keyPair = generateKeyPair();
DateTime notBefore = new DateTime();
DateTime notAfter = notBefore.plusYears(1);
X509Certificate certificate = generateCertificate(keyPair.getPublic(), "CN=Test", notBefore, notAfter, null,
keyPair.getPrivate(), true, 0, null, new KeyUsage(KeyUsage.nonRepudiation));
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.newDocument();
XMLSignatureFactory signatureFactory = XMLSignatureFactory.getInstance("DOM", new XMLDSigRI());
XMLSignContext signContext = new DOMSignContext(keyPair.getPrivate(), document);
signContext.putNamespacePrefix(javax.xml.crypto.dsig.XMLSignature.XMLNS, "ds");
byte[] externalDocument = "hello world".getBytes();
MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
messageDigest.update(externalDocument);
byte[] documentDigestValue = messageDigest.digest();
DigestMethod digestMethod = signatureFactory.newDigestMethod(DigestMethod.SHA1, null);
Reference reference = signatureFactory.newReference("some-uri", digestMethod, null, null, null,
documentDigestValue);
SignatureMethod signatureMethod = signatureFactory.newSignatureMethod(SignatureMethod.RSA_SHA1, null);
CanonicalizationMethod canonicalizationMethod = signatureFactory.newCanonicalizationMethod(
CanonicalizationMethod.EXCLUSIVE_WITH_COMMENTS, (C14NMethodParameterSpec) null);
javax.xml.crypto.dsig.SignedInfo signedInfo = signatureFactory.newSignedInfo(canonicalizationMethod,
signatureMethod, Collections.singletonList(reference));
KeyInfoFactory keyInfoFactory = signatureFactory.getKeyInfoFactory();
X509Data x509Data = keyInfoFactory.newX509Data(Collections.singletonList(certificate));
KeyInfo keyInfo = keyInfoFactory.newKeyInfo(Collections.singletonList(x509Data));
javax.xml.crypto.dsig.XMLSignature xmlSignature = signatureFactory.newXMLSignature(signedInfo, keyInfo);
DOMXMLSignature domXmlSignature = (DOMXMLSignature) xmlSignature;
domXmlSignature.marshal(document, "ds", (DOMCryptoContext) signContext);
DOMSignedInfo domSignedInfo = (DOMSignedInfo) signedInfo;
ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
domSignedInfo.canonicalize(signContext, dataStream);
byte[] octets = dataStream.toByteArray();
MessageDigest jcaMessageDigest = MessageDigest.getInstance("SHA1");
byte[] digestValue = jcaMessageDigest.digest(octets);
byte[] digestInfoValue = ArrayUtils.addAll(SHA1_DIGEST_INFO_PREFIX, digestValue);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPrivate());
byte[] signatureValue = cipher.doFinal(digestInfoValue);
NodeList signatureValueNodeList = document.getElementsByTagNameNS(javax.xml.crypto.dsig.XMLSignature.XMLNS,
"SignatureValue");
assertEquals(1, signatureValueNodeList.getLength());
Element signatureValueElement = (Element) signatureValueNodeList.item(0);
signatureValueElement.setTextContent(Base64.encode(signatureValue));
Source source = new DOMSource(document);
StringWriter stringWriter = new StringWriter();
Result result = new StreamResult(stringWriter);
Transformer xformer = TransformerFactory.newInstance().newTransformer();
xformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
xformer.transform(source, result);
String signedDocumentStr = stringWriter.getBuffer().toString();
LOG.debug("signed document: " + signedDocumentStr);
File tmpFile = File.createTempFile("xml-signature-", ".xml");
FileUtils.writeStringToFile(tmpFile, signedDocumentStr);
StringReader stringReader = new StringReader(signedDocumentStr);
InputSource inputSource = new InputSource(stringReader);
Document signedDocument = documentBuilder.parse(inputSource);
Element signatureElement = (Element) XPathAPI.selectSingleNode(signedDocument, "ds:Signature");
assertNotNull(signatureElement);
XMLSignature apacheXmlSignature = new XMLSignature(signatureElement, null);
ResourceTestResolver resourceResolver = new ResourceTestResolver();
resourceResolver.addResource("some-uri", "hello world".getBytes());
apacheXmlSignature.addResourceResolver(resourceResolver);
boolean signatureResult = apacheXmlSignature.checkSignatureValue(keyPair.getPublic());
assertTrue(signatureResult);
LOG.debug("file: " + tmpFile.getAbsolutePath());
}
private KeyPair generateKeyPair() throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
SecureRandom random = new SecureRandom();
keyPairGenerator.initialize(new RSAKeyGenParameterSpec(1024, RSAKeyGenParameterSpec.F4), random);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
return keyPair;
}
private SubjectKeyIdentifier createSubjectKeyId(PublicKey publicKey) throws IOException {
ByteArrayInputStream bais = new ByteArrayInputStream(publicKey.getEncoded());
SubjectPublicKeyInfo info = new SubjectPublicKeyInfo((ASN1Sequence) new ASN1InputStream(bais).readObject());
return new SubjectKeyIdentifier(info);
}
private AuthorityKeyIdentifier createAuthorityKeyId(PublicKey publicKey) throws IOException {
ByteArrayInputStream bais = new ByteArrayInputStream(publicKey.getEncoded());
SubjectPublicKeyInfo info = new SubjectPublicKeyInfo((ASN1Sequence) new ASN1InputStream(bais).readObject());
return new AuthorityKeyIdentifier(info);
}
private X509Certificate generateCertificate(PublicKey subjectPublicKey, String subjectDn, DateTime notBefore,
DateTime notAfter, X509Certificate issuerCertificate, PrivateKey issuerPrivateKey, boolean caFlag,
int pathLength, String ocspUri, KeyUsage keyUsage) throws IOException, InvalidKeyException,
IllegalStateException, NoSuchAlgorithmException, SignatureException, CertificateException {
String signatureAlgorithm = "SHA1withRSA";
X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();
certificateGenerator.reset();
certificateGenerator.setPublicKey(subjectPublicKey);
certificateGenerator.setSignatureAlgorithm(signatureAlgorithm);
certificateGenerator.setNotBefore(notBefore.toDate());
certificateGenerator.setNotAfter(notAfter.toDate());
X509Principal issuerDN;
if (null != issuerCertificate) {
issuerDN = new X509Principal(issuerCertificate.getSubjectX500Principal().toString());
} else {
issuerDN = new X509Principal(subjectDn);
}
certificateGenerator.setIssuerDN(issuerDN);
certificateGenerator.setSubjectDN(new X509Principal(subjectDn));
certificateGenerator.setSerialNumber(new BigInteger(128, new SecureRandom()));
certificateGenerator.addExtension(X509Extensions.SubjectKeyIdentifier, false,
createSubjectKeyId(subjectPublicKey));
PublicKey issuerPublicKey;
issuerPublicKey = subjectPublicKey;
certificateGenerator.addExtension(X509Extensions.AuthorityKeyIdentifier, false,
createAuthorityKeyId(issuerPublicKey));
if (caFlag) {
if (-1 == pathLength) {
certificateGenerator.addExtension(X509Extensions.BasicConstraints, false, new BasicConstraints(true));
} else {
certificateGenerator.addExtension(X509Extensions.BasicConstraints, false,
new BasicConstraints(pathLength));
}
}
if (null != ocspUri) {
GeneralName ocspName = new GeneralName(GeneralName.uniformResourceIdentifier, ocspUri);
AuthorityInformationAccess authorityInformationAccess = new AuthorityInformationAccess(
X509ObjectIdentifiers.ocspAccessMethod, ocspName);
certificateGenerator.addExtension(X509Extensions.AuthorityInfoAccess.getId(), false,
authorityInformationAccess);
}
if (null != keyUsage) {
certificateGenerator.addExtension(X509Extensions.KeyUsage, true, keyUsage);
}
X509Certificate certificate;
certificate = certificateGenerator.generate(issuerPrivateKey);
/*
* Next certificate factory trick is needed to make sure that the
* certificate delivered to the caller is provided by the default
* security provider instead of BouncyCastle. If we don't do this trick
* we might run into trouble when trying to use the CertPath validator.
*/
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
certificate = (X509Certificate) certificateFactory
.generateCertificate(new ByteArrayInputStream(certificate.getEncoded()));
return certificate;
}
@Test
public void testPreSignPostSign() throws Exception {
// setup
KeyPair keyPair = generateKeyPair();
DateTime notBefore = new DateTime();
DateTime notAfter = notBefore.plusYears(1);
X509Certificate certificate = generateCertificate(keyPair.getPublic(), "CN=Test", notBefore, notAfter, null,
keyPair.getPrivate(), true, 0, null, new KeyUsage(KeyUsage.nonRepudiation));
byte[] toBeSigned = "hello world".getBytes();
MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
byte[] digestValue = messageDigest.digest(toBeSigned);
List<DigestInfo> digestInfos = new LinkedList<DigestInfo>();
digestInfos.add(new DigestInfo(digestValue, "SHA-1", "test-file-name"));
HttpServletRequest mockHttpServletRequest = EasyMock.createMock(HttpServletRequest.class);
HttpSession mockHttpSession = EasyMock.createMock(HttpSession.class);
EasyMock.expect(mockHttpServletRequest.getSession()).andStubReturn(mockHttpSession);
// XML signature digest algorithm
EasyMock.expect(mockHttpSession.getAttribute("signDigestAlgo")).andStubReturn("SHA-1");
PolicyContextHandler handler = new PolicyContextTestHandler(mockHttpServletRequest);
PolicyContext.registerHandler("javax.servlet.http.HttpServletRequest", handler, false);
Capture<String> xmlDocumentCapture = new Capture<String>();
mockHttpSession.setAttribute(EasyMock.eq("xmlDocument"), EasyMock.capture(xmlDocumentCapture));
// prepare
EasyMock.replay(mockHttpServletRequest, mockHttpSession);
// operate
DigestInfo resultDigestInfo = this.testedInstance.preSign(digestInfos, null, null, null, null);
// verify
EasyMock.verify(mockHttpServletRequest, mockHttpSession);
assertNotNull(resultDigestInfo);
assertNotNull(resultDigestInfo.digestValue);
assertNotNull(resultDigestInfo.digestAlgo);
assertNotNull(resultDigestInfo.description);
LOG.debug("digest algo: " + resultDigestInfo.digestAlgo);
LOG.debug("description: " + resultDigestInfo.description);
// create the external signature
byte[] digestInfoValue = ArrayUtils.addAll(SHA1_DIGEST_INFO_PREFIX, resultDigestInfo.digestValue);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPrivate());
byte[] signatureValue = cipher.doFinal(digestInfoValue);
List<X509Certificate> signingCertificateChain = new LinkedList<X509Certificate>();
signingCertificateChain.add(certificate);
// setup
EasyMock.reset(mockHttpServletRequest, mockHttpSession);
EasyMock.expect(mockHttpServletRequest.getSession()).andStubReturn(mockHttpSession);
EasyMock.expect(mockHttpSession.getAttribute("xmlDocument")).andReturn(xmlDocumentCapture.getValue());
mockHttpSession.setAttribute(EasyMock.eq("xmlDocument"), EasyMock.capture(xmlDocumentCapture));
// prepare
EasyMock.replay(mockHttpServletRequest, mockHttpSession);
// operate
this.testedInstance.postSign(signatureValue, signingCertificateChain);
// verify
EasyMock.verify(mockHttpServletRequest, mockHttpSession);
String signedDocumentStr = xmlDocumentCapture.getValue();
StringReader stringReader = new StringReader(signedDocumentStr);
InputSource inputSource = new InputSource(stringReader);
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document signedDocument = documentBuilder.parse(inputSource);
Element signatureElement = (Element) XPathAPI.selectSingleNode(signedDocument, "ds:Signature");
assertNotNull(signatureElement);
XMLSignature apacheXmlSignature = new XMLSignature(signatureElement, null);
ResourceTestResolver resourceResolver = new ResourceTestResolver();
resourceResolver.addResource("test-file-name", toBeSigned);
apacheXmlSignature.addResourceResolver(resourceResolver);
boolean signatureResult = apacheXmlSignature.checkSignatureValue(keyPair.getPublic());
assertTrue(signatureResult);
LOG.debug("XML signature: " + xmlDocumentCapture.getValue());
}
private static class PolicyContextTestHandler implements PolicyContextHandler {
private final HttpServletRequest httpServletRequest;
public PolicyContextTestHandler(HttpServletRequest httpServletRequest) {
this.httpServletRequest = httpServletRequest;
}
public Object getContext(String key, Object data) throws PolicyContextException {
if (false == "javax.servlet.http.HttpServletRequest".equals(key)) {
return null;
}
return this.httpServletRequest;
}
public String[] getKeys() throws PolicyContextException {
return new String[] { "javax.servlet.http.HttpServletRequest" };
}
public boolean supports(String key) throws PolicyContextException {
return "javax.servlet.http.HttpServletRequest".equals(key);
}
}
@Test
public void testRegisterOwnJceProvider() throws Exception {
MyTestProvider provider = new MyTestProvider();
assertTrue(-1 != Security.addProvider(provider));
MessageDigest messageDigest = MessageDigest.getInstance("SHA-1", MyTestProvider.NAME);
assertEquals(MyTestProvider.NAME, messageDigest.getProvider().getName());
messageDigest.update("hello world".getBytes());
byte[] result = messageDigest.digest();
Assert.assertArrayEquals("hello world".getBytes(), result);
Security.removeProvider(MyTestProvider.NAME);
}
private static class MyTestProvider extends Provider {
private static final long serialVersionUID = 1L;
public static final String NAME = MyTestProvider.class.getSimpleName();
protected MyTestProvider() {
super(NAME, 1.0, "Test JCE Provider");
put("MessageDigest.SHA-1", MyTestMessageDigest.class.getName());
}
}
/**
* This is a non-digesting message digest implementation. We assume we
* already receive a digested value.
*
* @author Frank Cornelis
*
*/
public static class MyTestMessageDigest extends MessageDigest {
private final ByteArrayOutputStream byteArrayOutputStream;
public MyTestMessageDigest() {
super("SHA-1");
this.byteArrayOutputStream = new ByteArrayOutputStream();
}
@Override
protected byte[] engineDigest() {
return this.byteArrayOutputStream.toByteArray();
}
@Override
protected void engineReset() {
this.byteArrayOutputStream.reset();
}
@Override
protected void engineUpdate(byte input) {
this.byteArrayOutputStream.write(input);
}
@Override
protected void engineUpdate(byte[] input, int offset, int len) {
this.byteArrayOutputStream.write(input, offset, len);
}
}
}