<classpathentry kind="lib" path="lib/junit-4.11.jar"/>\r
<classpathentry kind="lib" path="ooxml-lib/ooxml-schemas-1.1.jar" sourcepath="ooxml-lib/ooxml-schemas-src-1.1.jar"/>\r
<classpathentry kind="lib" path="ooxml-lib/ooxml-encryption-1.2.jar" sourcepath="ooxml-lib/ooxml-encryption-src-1.2.jar"/>\r
- <classpathentry kind="lib" path="lib/com.springsource.org.objenesis-1.0.0.jar"/>\r
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>\r
- <classpathentry kind="lib" path="lib/mockito-core-1.9.5.jar" sourcepath="E:/tmp/mavenRepo/org/mockito/mockito-core/1.9.5/mockito-core-1.9.5-sources.jar"/>\r
<classpathentry kind="output" path="build/eclipse"/>\r
</classpath>\r
<property name="test.bouncycastle-prov.url" value="${repository.m2}/maven2/org/bouncycastle/bcprov-ext-jdk15on/1.51/bcprov-ext-jdk15on-1.51.jar"/>
<property name="test.bouncycastle-pkix.jar" location="${main.lib}/bcpkix-jdk15on-151.jar"/>
<property name="test.bouncycastle-pkix.url" value="${repository.m2}/maven2/org/bouncycastle/bcpkix-jdk15on/1.51/bcpkix-jdk15on-151.jar"/>
- <property name="test.mockito.jar" location="${main.lib}/mockito-core-1.9.5.jar"/>
- <property name="test.mockito.url" value="${repository.m2}/maven2/org/mockito/mockito-core/1.9.5/mockito-core-1.9.5.jar"/>
- <property name="test.objenesis.jar" location="${main.lib}/com.springsource.org.objenesis-1.0.0.jar"/>
- <property name="test.objenesis.url" value="http://repository.springsource.com/ivy/bundles/external/org.objenesis/com.springsource.org.objenesis/1.0.0/com.springsource.org.objenesis-1.0.0.jar"/>
<!-- jars in the lib-ooxml directory, see the fetch-ooxml-jars target-->
<property name="ooxml.xmlbeans23.jar" location="${ooxml.lib}/xmlbeans-2.3.0.jar"/>
<pathelement location="${ooxml.output.dir}"/>
<pathelement location="${ooxml.output.test.dir}"/>
<pathelement location="${main.output.test.dir}"/>
- <pathelement location="${test.mockito.jar}"/>
- <pathelement location="${test.objenesis.jar}"/>
</path>
<path id="ooxml-lite.classpath">
<param name="sourcefile" value="${rat.url}"/>
<param name="destfile" value="${rat.jar}"/>
</antcall>
- <antcall target="downloadfile">
- <param name="sourcefile" value="${test.mockito.url}"/>
- <param name="destfile" value="${test.mockito.jar}"/>
- </antcall>
- <antcall target="downloadfile">
- <param name="sourcefile" value="${test.objenesis.url}"/>
- <param name="destfile" value="${test.objenesis.jar}"/>
- </antcall>
<antcall target="downloadfile">
<param name="sourcefile" value="${test.bouncycastle-prov.url}"/>
<param name="destfile" value="${test.bouncycastle-prov.jar}"/>
\r
package org.apache.poi.poifs.crypt.dsig.services;\r
\r
+import static org.apache.poi.poifs.crypt.dsig.HorribleProxy.createProxy;\r
+import static org.apache.poi.poifs.crypt.dsig.HorribleProxy.newProxy;\r
+\r
import java.io.ByteArrayInputStream;\r
import java.io.ByteArrayOutputStream;\r
import java.io.OutputStream;\r
\r
import org.apache.commons.codec.binary.Hex;\r
import org.apache.poi.poifs.crypt.CryptoFunctions;\r
+import org.apache.poi.poifs.crypt.HashAlgorithm;\r
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ASN1InputStreamIf;\r
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ASN1OctetStringIf;\r
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.AuthorityKeyIdentifierIf;\r
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.TimeStampResponseIf;\r
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.TimeStampTokenIf;\r
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.X509CertificateHolderIf;\r
-import org.apache.poi.poifs.crypt.dsig.HorribleProxy;\r
import org.apache.poi.util.IOUtils;\r
import org.apache.poi.util.POILogFactory;\r
import org.apache.poi.util.POILogger;\r
CryptoFunctions.registerBouncyCastle();\r
}\r
\r
- public static final String DEFAULT_USER_AGENT = "eID Applet Service TSP Client";\r
+ public static final String DEFAULT_USER_AGENT = "POI XmlSign Service TSP Client";\r
\r
private final String tspServiceUrl;\r
\r
\r
private int proxyPort;\r
\r
- private String digestAlgo;\r
+ private HashAlgorithm digestAlgo;\r
\r
private String digestAlgoOid;\r
\r
} else {\r
this.userAgent = DEFAULT_USER_AGENT;\r
}\r
-\r
- this.digestAlgo = "SHA-1";\r
- this.digestAlgoOid = "1.3.14.3.2.26";\r
+ \r
+ setDigestAlgo(HashAlgorithm.sha1);\r
}\r
\r
/**\r
* \r
* @param digestAlgo\r
*/\r
- public void setDigestAlgo(String digestAlgo) {\r
- if ("SHA-1".equals(digestAlgo)) {\r
- this.digestAlgoOid = "1.3.14.3.2.26";\r
- } else if ("SHA-256".equals(digestAlgo)) {\r
- this.digestAlgoOid = "2.16.840.1.101.3.4.2.1";\r
- } else if ("SHA-384".equals(digestAlgo)) {\r
- this.digestAlgoOid = "2.16.840.1.101.3.4.2.2";\r
- } else if ("SHA-512".equals(digestAlgo)) {\r
- this.digestAlgoOid = "2.16.840.1.101.3.4.2.3";\r
- } else {\r
+ public void setDigestAlgo(HashAlgorithm digestAlgo) {\r
+ switch (digestAlgo) {\r
+ case sha1:\r
+ digestAlgoOid = "1.3.14.3.2.26";\r
+ break;\r
+ case sha256:\r
+ digestAlgoOid = "2.16.840.1.101.3.4.2.1";\r
+ break;\r
+ case sha384:\r
+ digestAlgoOid = "2.16.840.1.101.3.4.2.2";\r
+ break;\r
+ case sha512:\r
+ digestAlgoOid = "2.16.840.1.101.3.4.2.3";\r
+ break;\r
+ default:\r
throw new IllegalArgumentException("unsupported digest algo: " + digestAlgo);\r
}\r
\r
public byte[] timeStamp(byte[] data, RevocationData revocationData)\r
throws Exception {\r
// digest the message\r
- MessageDigest messageDigest = MessageDigest\r
- .getInstance(this.digestAlgo);\r
+ MessageDigest messageDigest = CryptoFunctions.getMessageDigest(this.digestAlgo);\r
byte[] digest = messageDigest.digest(data);\r
\r
// generate the TSP request\r
BigInteger nonce = new BigInteger(128, new SecureRandom());\r
- TimeStampRequestGeneratorIf requestGenerator = HorribleProxy.newProxy(TimeStampRequestGeneratorIf.class);\r
+ TimeStampRequestGeneratorIf requestGenerator = newProxy(TimeStampRequestGeneratorIf.class);\r
requestGenerator.setCertReq(true);\r
if (null != this.requestPolicy) {\r
requestGenerator.setReqPolicy(this.requestPolicy);\r
\r
huc.setDoOutput(true); // also sets method to POST.\r
huc.setRequestProperty("User-Agent", this.userAgent);\r
- huc.setRequestProperty("Content-Type", "application/timestamp-query;charset=ISO-8859-1");\r
+ // "application/timestamp-query;charset=ISO-8859-1"\r
+ huc.setRequestProperty("Content-Type", "application/timestamp-request");\r
\r
OutputStream hucOut = huc.getOutputStream();\r
hucOut.write(encodedRequest);\r
IOUtils.copy(huc.getInputStream(), bos);\r
LOG.log(POILogger.DEBUG, "response content: ", bos.toString());\r
\r
- if (!contentType.startsWith("application/timestamp-reply")) {\r
+ // "application/timestamp-reply"\r
+ if (!contentType.startsWith("application/timestamp-response")) {\r
throw new RuntimeException("invalid Content-Type: " + contentType);\r
}\r
\r
}\r
\r
// TSP response parsing and validation\r
- TimeStampResponseIf timeStampResponse = HorribleProxy.newProxy(TimeStampResponseIf.class, bos.toByteArray());\r
+ TimeStampResponseIf timeStampResponse = newProxy(TimeStampResponseIf.class, bos.toByteArray());\r
timeStampResponse.validate(request);\r
\r
if (0 != timeStampResponse.getStatus()) {\r
} while (null != certificate);\r
\r
// verify TSP signer signature\r
- X509CertificateHolderIf holder = HorribleProxy.newProxy(X509CertificateHolderIf.class, tspCertificateChain.get(0).getEncoded());\r
- DefaultDigestAlgorithmIdentifierFinderIf finder = HorribleProxy.newProxy(DefaultDigestAlgorithmIdentifierFinderIf.class);\r
- BcDigestCalculatorProviderIf calculator = HorribleProxy.newProxy(BcDigestCalculatorProviderIf.class);\r
- BcRSASignerInfoVerifierBuilderIf verifierBuilder = HorribleProxy.newProxy(BcRSASignerInfoVerifierBuilderIf.class, finder, calculator);\r
+ X509CertificateHolderIf holder = newProxy(X509CertificateHolderIf.class, tspCertificateChain.get(0).getEncoded());\r
+ DefaultDigestAlgorithmIdentifierFinderIf finder = newProxy(DefaultDigestAlgorithmIdentifierFinderIf.class);\r
+ BcDigestCalculatorProviderIf calculator = newProxy(BcDigestCalculatorProviderIf.class);\r
+ BcRSASignerInfoVerifierBuilderIf verifierBuilder = newProxy(BcRSASignerInfoVerifierBuilderIf.class, finder, calculator);\r
SignerInformationVerifierIf verifier = verifierBuilder.build(holder);\r
\r
timeStampToken.validate(verifier);\r
byte[] extvalue = cert.getExtensionValue("2.5.29.14");\r
if (extvalue == null) return null;\r
\r
- ASN1InputStreamIf keyCntStream = HorribleProxy.newProxy(ASN1InputStreamIf.class, new ByteArrayInputStream(extvalue));\r
- ASN1OctetStringIf cntStr = HorribleProxy.createProxy(ASN1OctetStringIf.class, "getInstance", keyCntStream.readObject$Object());\r
- ASN1InputStreamIf keyIdStream = HorribleProxy.newProxy(ASN1InputStreamIf.class, new ByteArrayInputStream(cntStr.getOctets()));\r
- SubjectKeyIdentifierIf keyId = HorribleProxy.createProxy(SubjectKeyIdentifierIf.class, "getInstance", keyIdStream.readObject$Object());\r
+ ASN1InputStreamIf keyCntStream = newProxy(ASN1InputStreamIf.class, new ByteArrayInputStream(extvalue));\r
+ ASN1OctetStringIf cntStr = createProxy(ASN1OctetStringIf.class, "getInstance", keyCntStream.readObject$Object());\r
+ ASN1InputStreamIf keyIdStream = newProxy(ASN1InputStreamIf.class, new ByteArrayInputStream(cntStr.getOctets()));\r
+ SubjectKeyIdentifierIf keyId = createProxy(SubjectKeyIdentifierIf.class, "getInstance", keyIdStream.readObject$Object());\r
\r
return keyId.getKeyIdentifier();\r
}\r
byte[] extvalue = cert.getExtensionValue("2.5.29.35");\r
if (extvalue == null) return null;\r
\r
- ASN1InputStreamIf keyCntStream = HorribleProxy.newProxy(ASN1InputStreamIf.class, new ByteArrayInputStream(extvalue));\r
+ ASN1InputStreamIf keyCntStream = newProxy(ASN1InputStreamIf.class, new ByteArrayInputStream(extvalue));\r
DEROctetStringIf cntStr = keyCntStream.readObject$DERString();\r
- ASN1InputStreamIf keyIdStream = HorribleProxy.newProxy(ASN1InputStreamIf.class, new ByteArrayInputStream(cntStr.getOctets()));\r
- AuthorityKeyIdentifierIf keyId = HorribleProxy.newProxy(AuthorityKeyIdentifierIf.class, keyIdStream.readObject$Sequence());\r
+ ASN1InputStreamIf keyIdStream = newProxy(ASN1InputStreamIf.class, new ByteArrayInputStream(cntStr.getOctets()));\r
+ AuthorityKeyIdentifierIf keyId = newProxy(AuthorityKeyIdentifierIf.class, keyIdStream.readObject$Sequence());\r
\r
return keyId.getKeyIdentifier();\r
}\r
import static org.junit.Assert.assertEquals;\r
import static org.junit.Assert.assertNotNull;\r
import static org.junit.Assert.assertTrue;\r
-import static org.mockito.Matchers.any;\r
-import static org.mockito.Matchers.eq;\r
-import static org.mockito.Mockito.mock;\r
-import static org.mockito.Mockito.times;\r
-import static org.mockito.Mockito.verify;\r
-import static org.mockito.Mockito.when;\r
\r
import java.io.File;\r
import java.io.FileInputStream;\r
import org.apache.poi.poifs.crypt.dsig.facets.XAdESXLSignatureFacet;\r
import org.apache.poi.poifs.crypt.dsig.services.RevocationData;\r
import org.apache.poi.poifs.crypt.dsig.services.RevocationDataService;\r
+import org.apache.poi.poifs.crypt.dsig.services.TSPTimeStampService;\r
import org.apache.poi.poifs.crypt.dsig.services.TimeStampService;\r
+import org.apache.poi.poifs.crypt.dsig.services.TimeStampServiceValidator;\r
import org.apache.poi.poifs.crypt.dsig.services.XmlSignatureService;\r
import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo;\r
import org.apache.poi.util.IOUtils;\r
import org.etsi.uri.x01903.v13.QualifyingPropertiesType;\r
import org.junit.BeforeClass;\r
import org.junit.Test;\r
-import org.mockito.invocation.InvocationOnMock;\r
-import org.mockito.stubbing.Answer;\r
import org.w3.x2000.x09.xmldsig.SignatureDocument;\r
\r
public class TestSignatureInfo {\r
String testFile = "hello-world-unsigned.xlsx";\r
OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE);\r
\r
+ initKeyPair("Test", "CN=Test");\r
+ \r
// setup\r
EnvelopedSignatureFacet envelopedSignatureFacet = new EnvelopedSignatureFacet();\r
KeyInfoSignatureFacet keyInfoSignatureFacet = new KeyInfoSignatureFacet(true, false, false);\r
SignaturePolicyService signaturePolicyService = null;\r
XAdESSignatureFacet xadesSignatureFacet = new XAdESSignatureFacet(null, null, signaturePolicyService);\r
+ final X509CRL crl = PkiTestUtils.generateCrl(x509, keyPair.getPrivate());\r
\r
+// TimeStampService timeStampService = new TimeStampService(){\r
+// public byte[] timeStamp(byte[] data, RevocationData revocationData) throws Exception {\r
+// revocationData.addCRL(crl);\r
+// return "time-stamp-token".getBytes(); \r
+// }\r
+// };\r
+\r
+ // http://timestamping.edelweb.fr/service/tsp\r
+ // http://tsa.belgium.be/connect\r
+ String tspServiceUrl = "http://timestamping.edelweb.fr/service/tsp";\r
+ TimeStampServiceValidator tspValidator = new TimeStampServiceValidator() {\r
+ @Override\r
+ public void validate(List<X509Certificate> certificateChain,\r
+ RevocationData revocationData) throws Exception {\r
+ for (X509Certificate certificate : certificateChain) {\r
+ LOG.log(POILogger.DEBUG, "certificate: " + certificate.getSubjectX500Principal());\r
+ LOG.log(POILogger.DEBUG, "validity: " + certificate.getNotBefore() + " - " + certificate.getNotAfter());\r
+ }\r
+ }\r
+ };\r
\r
- TimeStampService mockTimeStampService = mock(TimeStampService.class);\r
- RevocationDataService mockRevocationDataService = mock(RevocationDataService.class);\r
-\r
- XAdESXLSignatureFacet xadesXLSignatureFacet = new XAdESXLSignatureFacet(\r
- mockTimeStampService, mockRevocationDataService);\r
- XmlSignatureService testedInstance = new XmlSignatureService(HashAlgorithm.sha1, pkg);\r
- testedInstance.addSignatureFacet(envelopedSignatureFacet, keyInfoSignatureFacet,\r
- xadesSignatureFacet, xadesXLSignatureFacet);\r
+ TimeStampService timeStampService = new TSPTimeStampService(tspServiceUrl, tspValidator);\r
\r
- initKeyPair("Test", "CN=Test");\r
List<X509Certificate> certificateChain = new ArrayList<X509Certificate>();\r
/*\r
* We need at least 2 certificates for the XAdES-C complete certificate\r
certificateChain.add(x509);\r
certificateChain.add(x509);\r
\r
- RevocationData revocationData = new RevocationData();\r
- final X509CRL crl = PkiTestUtils.generateCrl(x509, keyPair.getPrivate());\r
+ final RevocationData revocationData = new RevocationData();\r
revocationData.addCRL(crl);\r
OCSPRespIf ocspResp = PkiTestUtils.createOcspResp(x509, false,\r
x509, x509, keyPair.getPrivate(), "SHA1withRSA", cal.getTimeInMillis());\r
revocationData.addOCSP(ocspResp.getEncoded());\r
+\r
+ RevocationDataService revocationDataService = new RevocationDataService(){\r
+ public RevocationData getRevocationData(List<X509Certificate> certificateChain) {\r
+ return revocationData;\r
+ }\r
+ };\r
+\r
+ XAdESXLSignatureFacet xadesXLSignatureFacet = new XAdESXLSignatureFacet(\r
+ timeStampService, revocationDataService);\r
+ XmlSignatureService testedInstance = new XmlSignatureService(HashAlgorithm.sha1, pkg);\r
+ testedInstance.addSignatureFacet(envelopedSignatureFacet, keyInfoSignatureFacet,\r
+ xadesSignatureFacet, xadesXLSignatureFacet);\r
\r
- when(mockTimeStampService.timeStamp(any(byte[].class), any(RevocationData.class)))\r
- .thenAnswer(new Answer<byte[]>(){\r
- public byte[] answer(InvocationOnMock invocation) throws Throwable {\r
- Object[] arguments = invocation.getArguments();\r
- RevocationData revocationData = (RevocationData) arguments[1];\r
- revocationData.addCRL(crl);\r
- return "time-stamp-token".getBytes();\r
- } \r
- });\r
\r
- when(mockRevocationDataService.getRevocationData(eq(certificateChain)))\r
- .thenReturn(revocationData);\r
\r
// operate\r
DigestInfo digestInfo = testedInstance.preSign(null, certificateChain, null, null, null);\r
// Operate: postSign\r
testedInstance.postSign(signatureValue, certificateChain);\r
\r
- // verify\r
- verify(mockTimeStampService, times(2)).timeStamp(any(byte[].class), any(RevocationData.class));\r
- verify(mockRevocationDataService).getRevocationData(certificateChain);\r
- \r
DOMValidateContext domValidateContext = new DOMValidateContext(\r
KeySelector.singletonKeySelector(keyPair.getPublic()),\r
testedInstance.getSignatureDocument().getDomNode());\r
fos.close();\r
return tmpFile;\r
}\r
+\r
}\r