mirror of https://github.com/apache/poi.git
starting tsp tests / removed mockito stuff again
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/xml_signature@1618515 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
93e4a2ac10
commit
750ff718f0
|
@ -24,8 +24,6 @@
|
|||
<classpathentry kind="lib" path="lib/junit-4.11.jar"/>
|
||||
<classpathentry kind="lib" path="ooxml-lib/ooxml-schemas-1.1.jar" sourcepath="ooxml-lib/ooxml-schemas-src-1.1.jar"/>
|
||||
<classpathentry kind="lib" path="ooxml-lib/ooxml-encryption-1.2.jar" sourcepath="ooxml-lib/ooxml-encryption-src-1.2.jar"/>
|
||||
<classpathentry kind="lib" path="lib/com.springsource.org.objenesis-1.0.0.jar"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<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"/>
|
||||
<classpathentry kind="output" path="build/eclipse"/>
|
||||
</classpath>
|
||||
|
|
14
build.xml
14
build.xml
|
@ -151,10 +151,6 @@ under the License.
|
|||
<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"/>
|
||||
|
@ -267,8 +263,6 @@ under the License.
|
|||
<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">
|
||||
|
@ -443,14 +437,6 @@ under the License.
|
|||
<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}"/>
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
|
||||
package org.apache.poi.poifs.crypt.dsig.services;
|
||||
|
||||
import static org.apache.poi.poifs.crypt.dsig.HorribleProxy.createProxy;
|
||||
import static org.apache.poi.poifs.crypt.dsig.HorribleProxy.newProxy;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.OutputStream;
|
||||
|
@ -48,6 +51,7 @@ import javax.xml.bind.DatatypeConverter;
|
|||
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.apache.poi.poifs.crypt.CryptoFunctions;
|
||||
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ASN1InputStreamIf;
|
||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ASN1OctetStringIf;
|
||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.AuthorityKeyIdentifierIf;
|
||||
|
@ -64,7 +68,6 @@ import org.apache.poi.poifs.crypt.dsig.HorribleProxies.TimeStampRequestIf;
|
|||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.TimeStampResponseIf;
|
||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.TimeStampTokenIf;
|
||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.X509CertificateHolderIf;
|
||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxy;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
|
@ -83,7 +86,7 @@ public class TSPTimeStampService implements TimeStampService {
|
|||
CryptoFunctions.registerBouncyCastle();
|
||||
}
|
||||
|
||||
public static final String DEFAULT_USER_AGENT = "eID Applet Service TSP Client";
|
||||
public static final String DEFAULT_USER_AGENT = "POI XmlSign Service TSP Client";
|
||||
|
||||
private final String tspServiceUrl;
|
||||
|
||||
|
@ -101,7 +104,7 @@ public class TSPTimeStampService implements TimeStampService {
|
|||
|
||||
private int proxyPort;
|
||||
|
||||
private String digestAlgo;
|
||||
private HashAlgorithm digestAlgo;
|
||||
|
||||
private String digestAlgoOid;
|
||||
|
||||
|
@ -143,9 +146,8 @@ public class TSPTimeStampService implements TimeStampService {
|
|||
} else {
|
||||
this.userAgent = DEFAULT_USER_AGENT;
|
||||
}
|
||||
|
||||
this.digestAlgo = "SHA-1";
|
||||
this.digestAlgoOid = "1.3.14.3.2.26";
|
||||
|
||||
setDigestAlgo(HashAlgorithm.sha1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -183,16 +185,21 @@ public class TSPTimeStampService implements TimeStampService {
|
|||
*
|
||||
* @param digestAlgo
|
||||
*/
|
||||
public void setDigestAlgo(String digestAlgo) {
|
||||
if ("SHA-1".equals(digestAlgo)) {
|
||||
this.digestAlgoOid = "1.3.14.3.2.26";
|
||||
} else if ("SHA-256".equals(digestAlgo)) {
|
||||
this.digestAlgoOid = "2.16.840.1.101.3.4.2.1";
|
||||
} else if ("SHA-384".equals(digestAlgo)) {
|
||||
this.digestAlgoOid = "2.16.840.1.101.3.4.2.2";
|
||||
} else if ("SHA-512".equals(digestAlgo)) {
|
||||
this.digestAlgoOid = "2.16.840.1.101.3.4.2.3";
|
||||
} else {
|
||||
public void setDigestAlgo(HashAlgorithm digestAlgo) {
|
||||
switch (digestAlgo) {
|
||||
case sha1:
|
||||
digestAlgoOid = "1.3.14.3.2.26";
|
||||
break;
|
||||
case sha256:
|
||||
digestAlgoOid = "2.16.840.1.101.3.4.2.1";
|
||||
break;
|
||||
case sha384:
|
||||
digestAlgoOid = "2.16.840.1.101.3.4.2.2";
|
||||
break;
|
||||
case sha512:
|
||||
digestAlgoOid = "2.16.840.1.101.3.4.2.3";
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("unsupported digest algo: " + digestAlgo);
|
||||
}
|
||||
|
||||
|
@ -222,13 +229,12 @@ public class TSPTimeStampService implements TimeStampService {
|
|||
public byte[] timeStamp(byte[] data, RevocationData revocationData)
|
||||
throws Exception {
|
||||
// digest the message
|
||||
MessageDigest messageDigest = MessageDigest
|
||||
.getInstance(this.digestAlgo);
|
||||
MessageDigest messageDigest = CryptoFunctions.getMessageDigest(this.digestAlgo);
|
||||
byte[] digest = messageDigest.digest(data);
|
||||
|
||||
// generate the TSP request
|
||||
BigInteger nonce = new BigInteger(128, new SecureRandom());
|
||||
TimeStampRequestGeneratorIf requestGenerator = HorribleProxy.newProxy(TimeStampRequestGeneratorIf.class);
|
||||
TimeStampRequestGeneratorIf requestGenerator = newProxy(TimeStampRequestGeneratorIf.class);
|
||||
requestGenerator.setCertReq(true);
|
||||
if (null != this.requestPolicy) {
|
||||
requestGenerator.setReqPolicy(this.requestPolicy);
|
||||
|
@ -250,7 +256,8 @@ public class TSPTimeStampService implements TimeStampService {
|
|||
|
||||
huc.setDoOutput(true); // also sets method to POST.
|
||||
huc.setRequestProperty("User-Agent", this.userAgent);
|
||||
huc.setRequestProperty("Content-Type", "application/timestamp-query;charset=ISO-8859-1");
|
||||
// "application/timestamp-query;charset=ISO-8859-1"
|
||||
huc.setRequestProperty("Content-Type", "application/timestamp-request");
|
||||
|
||||
OutputStream hucOut = huc.getOutputStream();
|
||||
hucOut.write(encodedRequest);
|
||||
|
@ -274,7 +281,8 @@ public class TSPTimeStampService implements TimeStampService {
|
|||
IOUtils.copy(huc.getInputStream(), bos);
|
||||
LOG.log(POILogger.DEBUG, "response content: ", bos.toString());
|
||||
|
||||
if (!contentType.startsWith("application/timestamp-reply")) {
|
||||
// "application/timestamp-reply"
|
||||
if (!contentType.startsWith("application/timestamp-response")) {
|
||||
throw new RuntimeException("invalid Content-Type: " + contentType);
|
||||
}
|
||||
|
||||
|
@ -283,7 +291,7 @@ public class TSPTimeStampService implements TimeStampService {
|
|||
}
|
||||
|
||||
// TSP response parsing and validation
|
||||
TimeStampResponseIf timeStampResponse = HorribleProxy.newProxy(TimeStampResponseIf.class, bos.toByteArray());
|
||||
TimeStampResponseIf timeStampResponse = newProxy(TimeStampResponseIf.class, bos.toByteArray());
|
||||
timeStampResponse.validate(request);
|
||||
|
||||
if (0 != timeStampResponse.getStatus()) {
|
||||
|
@ -346,10 +354,10 @@ public class TSPTimeStampService implements TimeStampService {
|
|||
} while (null != certificate);
|
||||
|
||||
// verify TSP signer signature
|
||||
X509CertificateHolderIf holder = HorribleProxy.newProxy(X509CertificateHolderIf.class, tspCertificateChain.get(0).getEncoded());
|
||||
DefaultDigestAlgorithmIdentifierFinderIf finder = HorribleProxy.newProxy(DefaultDigestAlgorithmIdentifierFinderIf.class);
|
||||
BcDigestCalculatorProviderIf calculator = HorribleProxy.newProxy(BcDigestCalculatorProviderIf.class);
|
||||
BcRSASignerInfoVerifierBuilderIf verifierBuilder = HorribleProxy.newProxy(BcRSASignerInfoVerifierBuilderIf.class, finder, calculator);
|
||||
X509CertificateHolderIf holder = newProxy(X509CertificateHolderIf.class, tspCertificateChain.get(0).getEncoded());
|
||||
DefaultDigestAlgorithmIdentifierFinderIf finder = newProxy(DefaultDigestAlgorithmIdentifierFinderIf.class);
|
||||
BcDigestCalculatorProviderIf calculator = newProxy(BcDigestCalculatorProviderIf.class);
|
||||
BcRSASignerInfoVerifierBuilderIf verifierBuilder = newProxy(BcRSASignerInfoVerifierBuilderIf.class, finder, calculator);
|
||||
SignerInformationVerifierIf verifier = verifierBuilder.build(holder);
|
||||
|
||||
timeStampToken.validate(verifier);
|
||||
|
@ -369,10 +377,10 @@ public class TSPTimeStampService implements TimeStampService {
|
|||
byte[] extvalue = cert.getExtensionValue("2.5.29.14");
|
||||
if (extvalue == null) return null;
|
||||
|
||||
ASN1InputStreamIf keyCntStream = HorribleProxy.newProxy(ASN1InputStreamIf.class, new ByteArrayInputStream(extvalue));
|
||||
ASN1OctetStringIf cntStr = HorribleProxy.createProxy(ASN1OctetStringIf.class, "getInstance", keyCntStream.readObject$Object());
|
||||
ASN1InputStreamIf keyIdStream = HorribleProxy.newProxy(ASN1InputStreamIf.class, new ByteArrayInputStream(cntStr.getOctets()));
|
||||
SubjectKeyIdentifierIf keyId = HorribleProxy.createProxy(SubjectKeyIdentifierIf.class, "getInstance", keyIdStream.readObject$Object());
|
||||
ASN1InputStreamIf keyCntStream = newProxy(ASN1InputStreamIf.class, new ByteArrayInputStream(extvalue));
|
||||
ASN1OctetStringIf cntStr = createProxy(ASN1OctetStringIf.class, "getInstance", keyCntStream.readObject$Object());
|
||||
ASN1InputStreamIf keyIdStream = newProxy(ASN1InputStreamIf.class, new ByteArrayInputStream(cntStr.getOctets()));
|
||||
SubjectKeyIdentifierIf keyId = createProxy(SubjectKeyIdentifierIf.class, "getInstance", keyIdStream.readObject$Object());
|
||||
|
||||
return keyId.getKeyIdentifier();
|
||||
}
|
||||
|
@ -382,10 +390,10 @@ public class TSPTimeStampService implements TimeStampService {
|
|||
byte[] extvalue = cert.getExtensionValue("2.5.29.35");
|
||||
if (extvalue == null) return null;
|
||||
|
||||
ASN1InputStreamIf keyCntStream = HorribleProxy.newProxy(ASN1InputStreamIf.class, new ByteArrayInputStream(extvalue));
|
||||
ASN1InputStreamIf keyCntStream = newProxy(ASN1InputStreamIf.class, new ByteArrayInputStream(extvalue));
|
||||
DEROctetStringIf cntStr = keyCntStream.readObject$DERString();
|
||||
ASN1InputStreamIf keyIdStream = HorribleProxy.newProxy(ASN1InputStreamIf.class, new ByteArrayInputStream(cntStr.getOctets()));
|
||||
AuthorityKeyIdentifierIf keyId = HorribleProxy.newProxy(AuthorityKeyIdentifierIf.class, keyIdStream.readObject$Sequence());
|
||||
ASN1InputStreamIf keyIdStream = newProxy(ASN1InputStreamIf.class, new ByteArrayInputStream(cntStr.getOctets()));
|
||||
AuthorityKeyIdentifierIf keyId = newProxy(AuthorityKeyIdentifierIf.class, keyIdStream.readObject$Sequence());
|
||||
|
||||
return keyId.getKeyIdentifier();
|
||||
}
|
||||
|
|
|
@ -26,12 +26,6 @@ package org.apache.poi.poifs.crypt;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
@ -73,7 +67,9 @@ import org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet;
|
|||
import org.apache.poi.poifs.crypt.dsig.facets.XAdESXLSignatureFacet;
|
||||
import org.apache.poi.poifs.crypt.dsig.services.RevocationData;
|
||||
import org.apache.poi.poifs.crypt.dsig.services.RevocationDataService;
|
||||
import org.apache.poi.poifs.crypt.dsig.services.TSPTimeStampService;
|
||||
import org.apache.poi.poifs.crypt.dsig.services.TimeStampService;
|
||||
import org.apache.poi.poifs.crypt.dsig.services.TimeStampServiceValidator;
|
||||
import org.apache.poi.poifs.crypt.dsig.services.XmlSignatureService;
|
||||
import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
|
@ -84,8 +80,6 @@ import org.etsi.uri.x01903.v13.DigestAlgAndValueType;
|
|||
import org.etsi.uri.x01903.v13.QualifyingPropertiesType;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.w3.x2000.x09.xmldsig.SignatureDocument;
|
||||
|
||||
public class TestSignatureInfo {
|
||||
|
@ -210,23 +204,38 @@ public class TestSignatureInfo {
|
|||
String testFile = "hello-world-unsigned.xlsx";
|
||||
OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE);
|
||||
|
||||
initKeyPair("Test", "CN=Test");
|
||||
|
||||
// setup
|
||||
EnvelopedSignatureFacet envelopedSignatureFacet = new EnvelopedSignatureFacet();
|
||||
KeyInfoSignatureFacet keyInfoSignatureFacet = new KeyInfoSignatureFacet(true, false, false);
|
||||
SignaturePolicyService signaturePolicyService = null;
|
||||
XAdESSignatureFacet xadesSignatureFacet = new XAdESSignatureFacet(null, null, signaturePolicyService);
|
||||
final X509CRL crl = PkiTestUtils.generateCrl(x509, keyPair.getPrivate());
|
||||
|
||||
|
||||
TimeStampService mockTimeStampService = mock(TimeStampService.class);
|
||||
RevocationDataService mockRevocationDataService = mock(RevocationDataService.class);
|
||||
// TimeStampService timeStampService = new TimeStampService(){
|
||||
// public byte[] timeStamp(byte[] data, RevocationData revocationData) throws Exception {
|
||||
// revocationData.addCRL(crl);
|
||||
// return "time-stamp-token".getBytes();
|
||||
// }
|
||||
// };
|
||||
|
||||
XAdESXLSignatureFacet xadesXLSignatureFacet = new XAdESXLSignatureFacet(
|
||||
mockTimeStampService, mockRevocationDataService);
|
||||
XmlSignatureService testedInstance = new XmlSignatureService(HashAlgorithm.sha1, pkg);
|
||||
testedInstance.addSignatureFacet(envelopedSignatureFacet, keyInfoSignatureFacet,
|
||||
xadesSignatureFacet, xadesXLSignatureFacet);
|
||||
// http://timestamping.edelweb.fr/service/tsp
|
||||
// http://tsa.belgium.be/connect
|
||||
String tspServiceUrl = "http://timestamping.edelweb.fr/service/tsp";
|
||||
TimeStampServiceValidator tspValidator = new TimeStampServiceValidator() {
|
||||
@Override
|
||||
public void validate(List<X509Certificate> certificateChain,
|
||||
RevocationData revocationData) throws Exception {
|
||||
for (X509Certificate certificate : certificateChain) {
|
||||
LOG.log(POILogger.DEBUG, "certificate: " + certificate.getSubjectX500Principal());
|
||||
LOG.log(POILogger.DEBUG, "validity: " + certificate.getNotBefore() + " - " + certificate.getNotAfter());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TimeStampService timeStampService = new TSPTimeStampService(tspServiceUrl, tspValidator);
|
||||
|
||||
initKeyPair("Test", "CN=Test");
|
||||
List<X509Certificate> certificateChain = new ArrayList<X509Certificate>();
|
||||
/*
|
||||
* We need at least 2 certificates for the XAdES-C complete certificate
|
||||
|
@ -235,25 +244,25 @@ public class TestSignatureInfo {
|
|||
certificateChain.add(x509);
|
||||
certificateChain.add(x509);
|
||||
|
||||
RevocationData revocationData = new RevocationData();
|
||||
final X509CRL crl = PkiTestUtils.generateCrl(x509, keyPair.getPrivate());
|
||||
final RevocationData revocationData = new RevocationData();
|
||||
revocationData.addCRL(crl);
|
||||
OCSPRespIf ocspResp = PkiTestUtils.createOcspResp(x509, false,
|
||||
x509, x509, keyPair.getPrivate(), "SHA1withRSA", cal.getTimeInMillis());
|
||||
revocationData.addOCSP(ocspResp.getEncoded());
|
||||
|
||||
RevocationDataService revocationDataService = new RevocationDataService(){
|
||||
public RevocationData getRevocationData(List<X509Certificate> certificateChain) {
|
||||
return revocationData;
|
||||
}
|
||||
};
|
||||
|
||||
XAdESXLSignatureFacet xadesXLSignatureFacet = new XAdESXLSignatureFacet(
|
||||
timeStampService, revocationDataService);
|
||||
XmlSignatureService testedInstance = new XmlSignatureService(HashAlgorithm.sha1, pkg);
|
||||
testedInstance.addSignatureFacet(envelopedSignatureFacet, keyInfoSignatureFacet,
|
||||
xadesSignatureFacet, xadesXLSignatureFacet);
|
||||
|
||||
when(mockTimeStampService.timeStamp(any(byte[].class), any(RevocationData.class)))
|
||||
.thenAnswer(new Answer<byte[]>(){
|
||||
public byte[] answer(InvocationOnMock invocation) throws Throwable {
|
||||
Object[] arguments = invocation.getArguments();
|
||||
RevocationData revocationData = (RevocationData) arguments[1];
|
||||
revocationData.addCRL(crl);
|
||||
return "time-stamp-token".getBytes();
|
||||
}
|
||||
});
|
||||
|
||||
when(mockRevocationDataService.getRevocationData(eq(certificateChain)))
|
||||
.thenReturn(revocationData);
|
||||
|
||||
// operate
|
||||
DigestInfo digestInfo = testedInstance.preSign(null, certificateChain, null, null, null);
|
||||
|
@ -279,10 +288,6 @@ public class TestSignatureInfo {
|
|||
// Operate: postSign
|
||||
testedInstance.postSign(signatureValue, certificateChain);
|
||||
|
||||
// verify
|
||||
verify(mockTimeStampService, times(2)).timeStamp(any(byte[].class), any(RevocationData.class));
|
||||
verify(mockRevocationDataService).getRevocationData(certificateChain);
|
||||
|
||||
DOMValidateContext domValidateContext = new DOMValidateContext(
|
||||
KeySelector.singletonKeySelector(keyPair.getPublic()),
|
||||
testedInstance.getSignatureDocument().getDomNode());
|
||||
|
@ -389,4 +394,5 @@ public class TestSignatureInfo {
|
|||
fos.close();
|
||||
return tmpFile;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue