Modified: poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TSPTimeStampService.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TSPTimeStampService.java?rev=1874671&r1=1874670&r2=1874671&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TSPTimeStampService.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TSPTimeStampService.java Sun Mar 1 22:20:38 2020 @@ -18,9 +18,9 @@ /* ==================================================================== This product contains an ASLv2 licensed version of the OOXML signer package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt Copyright (C) 2008-2014 FedICT. - ================================================================= */ + ================================================================= */ package org.apache.poi.poifs.crypt.dsig.services; @@ -47,6 +47,7 @@ import java.util.Map; import org.apache.poi.poifs.crypt.CryptoFunctions; import org.apache.poi.poifs.crypt.HashAlgorithm; import org.apache.poi.poifs.crypt.dsig.SignatureConfig; +import org.apache.poi.poifs.crypt.dsig.SignatureInfo; import org.apache.poi.util.HexDump; import org.apache.poi.util.IOUtils; import org.apache.poi.util.POILogFactory; @@ -72,16 +73,14 @@ import org.bouncycastle.tsp.TimeStampTok /** * A TSP time-stamp service implementation. - * + * * @author Frank Cornelis - * + * */ public class TSPTimeStampService implements TimeStampService { private static final POILogger LOG = POILogFactory.getLogger(TSPTimeStampService.class); - private SignatureConfig signatureConfig; - /** * Maps the digest algorithm to corresponding OID value. */ @@ -97,8 +96,9 @@ public class TSPTimeStampService impleme } @SuppressWarnings({"unchecked","squid:S2647"}) - public byte[] timeStamp(byte[] data, RevocationData revocationData) - throws Exception { + public byte[] timeStamp(SignatureInfo signatureInfo, byte[] data, RevocationData revocationData) throws Exception { + SignatureConfig signatureConfig = signatureInfo.getSignatureConfig(); + // digest the message MessageDigest messageDigest = CryptoFunctions.getMessageDigest(signatureConfig.getTspDigestAlgo()); byte[] digest = messageDigest.digest(data); @@ -170,7 +170,7 @@ public class TSPTimeStampService impleme huc.disconnect(); } - if (!contentType.startsWith(signatureConfig.isTspOldProtocol() + if (!contentType.startsWith(signatureConfig.isTspOldProtocol() ? "application/timestamp-response" : "application/timestamp-reply" )) { @@ -178,7 +178,7 @@ public class TSPTimeStampService impleme // dump the first few bytes ": " + HexDump.dump(bos.toByteArray(), 0, 0, 200)); } - + if (bos.size() == 0) { throw new RuntimeException("Content-Length is zero"); } @@ -209,7 +209,7 @@ public class TSPTimeStampService impleme // TSP signer certificates retrieval Collection<X509CertificateHolder> certificates = timeStampToken.getCertificates().getMatches(null); - + X509CertificateHolder signerCert = null; Map<X500Name, X509CertificateHolder> certificateMap = new HashMap<>(); for (X509CertificateHolder certificate : certificates) { @@ -245,7 +245,7 @@ public class TSPTimeStampService impleme BcDigestCalculatorProvider calculator = new BcDigestCalculatorProvider(); BcRSASignerInfoVerifierBuilder verifierBuilder = new BcRSASignerInfoVerifierBuilder(nameGen, sigAlgoFinder, hashAlgoFinder, calculator); SignerInformationVerifier verifier = verifierBuilder.build(holder); - + timeStampToken.validate(verifier); // verify TSP signer certificate @@ -258,8 +258,4 @@ public class TSPTimeStampService impleme return timeStampToken.getEncoded(); } - - public void setSignatureConfig(SignatureConfig signatureConfig) { - this.signatureConfig = signatureConfig; - } } \ No newline at end of file
Modified: poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TimeStampService.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TimeStampService.java?rev=1874671&r1=1874670&r2=1874671&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TimeStampService.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TimeStampService.java Sun Mar 1 22:20:38 2020 @@ -18,28 +18,26 @@ /* ==================================================================== This product contains an ASLv2 licensed version of the OOXML signer package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt Copyright (C) 2008-2014 FedICT. - ================================================================= */ + ================================================================= */ package org.apache.poi.poifs.crypt.dsig.services; -import org.apache.poi.poifs.crypt.dsig.SignatureConfig.SignatureConfigurable; - +import org.apache.poi.poifs.crypt.dsig.SignatureInfo; /** * Interface for a time-stamp service. - * + * * @author Frank Cornelis - * */ -public interface TimeStampService extends SignatureConfigurable { +public interface TimeStampService { /** * Gives back the encoded time-stamp token for the given array of data * bytes. We assume that the time-stamp token itself contains its full * certificate chain required for proper validation. - * + * * @param data * the data to be time-stamped. * @param revocationData @@ -49,6 +47,5 @@ public interface TimeStampService extend * @throws Exception * in case something went wrong. */ - byte[] timeStamp(byte[] data, RevocationData revocationData) - throws Exception; + byte[] timeStamp(SignatureInfo signatureInfo, byte[] data, RevocationData revocationData) throws Exception; } Modified: poi/trunk/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java?rev=1874671&r1=1874670&r2=1874671&view=diff ============================================================================== --- poi/trunk/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java (original) +++ poi/trunk/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java Sun Mar 1 22:20:38 2020 @@ -104,27 +104,18 @@ import org.apache.poi.xssf.streaming.SXS import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.xmlbeans.SystemProperties; import org.apache.xmlbeans.XmlObject; -import org.bouncycastle.asn1.DERIA5String; import org.bouncycastle.asn1.DEROctetString; -import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.ocsp.OCSPObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.x500.X500Name; -import org.bouncycastle.asn1.x509.AuthorityInformationAccess; import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier; import org.bouncycastle.asn1.x509.BasicConstraints; import org.bouncycastle.asn1.x509.CRLNumber; -import org.bouncycastle.asn1.x509.CRLReason; -import org.bouncycastle.asn1.x509.DistributionPoint; -import org.bouncycastle.asn1.x509.DistributionPointName; import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.asn1.x509.Extensions; -import org.bouncycastle.asn1.x509.GeneralName; -import org.bouncycastle.asn1.x509.GeneralNames; import org.bouncycastle.asn1.x509.KeyUsage; import org.bouncycastle.asn1.x509.SubjectKeyIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; -import org.bouncycastle.asn1.x509.X509ObjectIdentifiers; import org.bouncycastle.cert.X509CRLHolder; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.X509ExtensionUtils; @@ -141,7 +132,6 @@ import org.bouncycastle.cert.ocsp.OCSPRe import org.bouncycastle.cert.ocsp.OCSPResp; import org.bouncycastle.cert.ocsp.OCSPRespBuilder; import org.bouncycastle.cert.ocsp.Req; -import org.bouncycastle.cert.ocsp.RevokedStatus; import org.bouncycastle.crypto.params.RSAKeyParameters; import org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory; import org.bouncycastle.openssl.PEMParser; @@ -196,7 +186,7 @@ public class TestSignatureInfo { String additionalJar = System.getProperty("additionaljar"); //System.out.println("Having: " + additionalJar); Assume.assumeTrue("Not running TestSignatureInfo because we are testing with additionaljar set to " + additionalJar, - additionalJar == null || additionalJar.trim().length() == 0); + additionalJar == null || additionalJar.trim().length() == 0); System.setProperty("org.apache.xml.security.ignoreLineBreaks", "true"); @@ -207,98 +197,97 @@ public class TestSignatureInfo { @Ignore("This test is very sensitive, it breaks with every little change to the produced XML") @Test public void bug61182() throws Exception { - String pfxInput = - "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"; + final String pfxInput = + "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"; + + // Unix + final String unixSignExp = + "QkqTFQZjXagjRAoOWKpAGa8AR0rKqkSfBtfSWqtjBmTgyjarn+t2POHkpySIpheHAbg+90GKSH88ACMtPHbG7q" + + "FL4gtgAD9Kjew6j16j0IRBwy145UlPrSLFMfF7YF7UlU1k1LBkIlRJ6Fv4MAJl6XspuzZOZIUmHZrWrdxycUQ="; + + // Windows + final String winSignExp = + "GmAlL7+bT1r3FsMHJOp3pKg8betblYieZTjhMIrPZPRBbSzjO7KsYRGNtr0aOE3qr8xzyYJN6/8QdF5X7pUEUc" + + "2m8ctrm7s5o2vZTkAqk9ENJGDjBPXX7TnuVOiVeL1cJdtjHC2QpjtRwkFR+B54G6b1OXLOFuQpP3vqR3+/XXE="; + + // Mac + final String macSignExp = + "NZedY/LNTYU4nAUEUhIOg5+fKdgVtzRXKmdD3v+47E7Mb84oeiUGv9cCEE91DU3StF/JFIhjOJqavOzKnCsNcz" + + "NJ4j/inggUl1OJUsicqIGQnA7E8vzWnN1kf5lINgJLv+0PyrrX9sQZbItzxUpgqyOFYcD0trid+31nRt4wtaA="; + + Calendar cal = LocaleUtil.getLocaleCalendar(LocaleUtil.TIMEZONE_UTC); cal.clear(); cal.setTimeZone(LocaleUtil.TIMEZONE_UTC); cal.set(2017, Calendar.JULY, 1); - SignatureConfig signatureConfig = prepareConfig("test", "CN=Test", pfxInput); + SignatureConfig signatureConfig = prepareConfig(pfxInput); signatureConfig.setExecutionTime(cal.getTime()); SignatureInfo si = new SignatureInfo(); si.setSignatureConfig(signatureConfig); - XSSFWorkbook wb1 = new XSSFWorkbook(); - wb1.createSheet().createRow(1).createCell(1).setCellValue("Test"); ByteArrayOutputStream bos = new ByteArrayOutputStream(100000); - wb1.write(bos); - wb1.close(); - - OPCPackage pkg1 = OPCPackage.open(new ByteArrayInputStream(bos.toByteArray())); + try (XSSFWorkbook wb1 = new XSSFWorkbook()) { + wb1.createSheet().createRow(1).createCell(1).setCellValue("Test"); + wb1.write(bos); + } - signatureConfig.setOpcPackage(pkg1); - si.confirmSignature(); - assertTrue(si.verifySignature()); - bos.reset(); - pkg1.save(bos); - pkg1.close(); - - XSSFWorkbook wb2 = new XSSFWorkbook(new ByteArrayInputStream(bos.toByteArray())); - assertEquals("Test", wb2.getSheetAt(0).getRow(1).getCell(1).getStringCellValue()); - OPCPackage pkg2 = wb2.getPackage(); - signatureConfig.setOpcPackage(pkg2); - assertTrue(si.verifySignature()); - - // xmlbeans adds line-breaks depending on the system setting, so we get different - // test results on Unix/Mac/Windows - // if the xml documents eventually change, this test needs to be run with the - // separator set to the various system configurations - String sep = SystemProperties.getProperty( "line.separator" ); - String signExp; - assumeTrue("Hashes only known for Windows/Unix/Mac", sep == null || "\n".equals(sep) || "\r\n".equals(sep) || "\r".equals(sep)); - if (sep == null || "\n".equals(sep)) { - // Unix - signExp = - "QkqTFQZjXagjRAoOWKpAGa8AR0rKqkSfBtfSWqtjBmTgyjarn+t2POHkpySIpheHAbg+90GKSH88ACMtPHbG7q"+ - "FL4gtgAD9Kjew6j16j0IRBwy145UlPrSLFMfF7YF7UlU1k1LBkIlRJ6Fv4MAJl6XspuzZOZIUmHZrWrdxycUQ="; - } else if ("\r\n".equals(sep)){ - // Windows - signExp = - "GmAlL7+bT1r3FsMHJOp3pKg8betblYieZTjhMIrPZPRBbSzjO7KsYRGNtr0aOE3qr8xzyYJN6/8QdF5X7pUEUc"+ - "2m8ctrm7s5o2vZTkAqk9ENJGDjBPXX7TnuVOiVeL1cJdtjHC2QpjtRwkFR+B54G6b1OXLOFuQpP3vqR3+/XXE="; - } else { - // Mac - signExp = - "NZedY/LNTYU4nAUEUhIOg5+fKdgVtzRXKmdD3v+47E7Mb84oeiUGv9cCEE91DU3StF/JFIhjOJqavOzKnCsNcz"+ - "NJ4j/inggUl1OJUsicqIGQnA7E8vzWnN1kf5lINgJLv+0PyrrX9sQZbItzxUpgqyOFYcD0trid+31nRt4wtaA="; + try (OPCPackage pkg1 = OPCPackage.open(new ByteArrayInputStream(bos.toByteArray()))) { + si.setOpcPackage(pkg1); + si.confirmSignature(); + assertTrue(si.verifySignature()); + bos.reset(); + pkg1.save(bos); } - String signAct = si.getSignatureParts().iterator().next(). - getSignatureDocument().getSignature().getSignatureValue().getStringValue(); - assertEquals(signExp, signAct); + try (XSSFWorkbook wb2 = new XSSFWorkbook(new ByteArrayInputStream(bos.toByteArray()))) { + assertEquals("Test", wb2.getSheetAt(0).getRow(1).getCell(1).getStringCellValue()); + OPCPackage pkg2 = wb2.getPackage(); + si.setOpcPackage(pkg2); + assertTrue(si.verifySignature()); - pkg2.close(); - wb2.close(); + // xmlbeans adds line-breaks depending on the system setting, so we get different + // test results on Unix/Mac/Windows + // if the xml documents eventually change, this test needs to be run with the + // separator set to the various system configurations + String sep = SystemProperties.getProperty("line.separator"); + String signExp; + assumeTrue("Hashes only known for Windows/Unix/Mac", sep == null || "\n".equals(sep) || "\r\n".equals(sep) || "\r".equals(sep)); + signExp = (sep == null || "\n".equals(sep)) ? unixSignExp : ("\r\n".equals(sep)) ? winSignExp : macSignExp; + + String signAct = si.getSignatureParts().iterator().next(). + getSignatureDocument().getSignature().getSignatureValue().getStringValue(); + assertEquals(signExp, signAct); + } } @Test public void office2007prettyPrintedRels() throws Exception { try (OPCPackage pkg = OPCPackage.open(testdata.getFile("office2007prettyPrintedRels.docx"), PackageAccess.READ)) { SignatureConfig sic = new SignatureConfig(); - sic.setOpcPackage(pkg); SignatureInfo si = new SignatureInfo(); + si.setOpcPackage(pkg); si.setSignatureConfig(sic); boolean isValid = si.verifySignature(); assertTrue(isValid); @@ -315,19 +304,19 @@ public class TestSignatureInfo { }; for (String testFile : testFiles) { - OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ); - SignatureConfig sic = new SignatureConfig(); - sic.setOpcPackage(pkg); - SignatureInfo si = new SignatureInfo(); - si.setSignatureConfig(sic); List<X509Certificate> result = new ArrayList<>(); - for (SignaturePart sp : si.getSignatureParts()) { - if (sp.validate()) { - result.add(sp.getSigner()); + try (OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ)) { + SignatureConfig sic = new SignatureConfig(); + SignatureInfo si = new SignatureInfo(); + si.setOpcPackage(pkg); + si.setSignatureConfig(sic); + for (SignaturePart sp : si.getSignatureParts()) { + if (sp.validate()) { + result.add(sp.getSigner()); + } } + pkg.revert(); } - pkg.revert(); - pkg.close(); assertNotNull(result); assertTrue(result.isEmpty()); } @@ -345,14 +334,14 @@ public class TestSignatureInfo { "ms-office-2010-signed.pptx", "ms-office-2010-signed.xlsx", "Office2010-SP1-XAdES-X-L.docx", - "signed.docx", + "signed.docx" }; for (String testFile : testFiles) { try (OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ)) { SignatureConfig sic = new SignatureConfig(); - sic.setOpcPackage(pkg); SignatureInfo si = new SignatureInfo(); + si.setOpcPackage(pkg); si.setSignatureConfig(sic); List<X509Certificate> result = new ArrayList<>(); for (SignaturePart sp : si.getSignatureParts()) { @@ -378,8 +367,8 @@ public class TestSignatureInfo { String testFile = "hello-world-signed-twice.docx"; try (OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ)) { SignatureConfig sic = new SignatureConfig(); - sic.setOpcPackage(pkg); SignatureInfo si = new SignatureInfo(); + si.setOpcPackage(pkg); si.setSignatureConfig(sic); List<X509Certificate> result = new ArrayList<>(); for (SignaturePart sp : si.getSignatureParts()) { @@ -404,9 +393,9 @@ public class TestSignatureInfo { @Test public void testSignSpreadsheet() throws Exception { String testFile = "hello-world-unsigned.xlsx"; - OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE); - sign(pkg, "Test", "CN=Test", 1); - pkg.close(); + try (OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE)) { + sign(pkg); + } } private static class CommitableWorkbook extends XSSFWorkbook { @@ -423,7 +412,7 @@ public class TestSignatureInfo { // sign & validate String testFile = "hello-world-unsigned.xlsx"; try (OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE)) { - sign(pkg, "Test", "CN=Test", 1); + sign(pkg); // manipulate try (CommitableWorkbook wb = new CommitableWorkbook(pkg)) { @@ -436,8 +425,8 @@ public class TestSignatureInfo { // validate SignatureConfig sic = new SignatureConfig(); - sic.setOpcPackage(pkg); SignatureInfo si = new SignatureInfo(); + si.setOpcPackage(pkg); si.setSignatureConfig(sic); boolean b = si.verifySignature(); assertFalse("signature should be broken", b); @@ -449,14 +438,14 @@ public class TestSignatureInfo { @Test public void testSignSpreadsheetWithSignatureInfo() throws Exception { - initKeyPair("Test", "CN=Test"); + initKeyPair(); String testFile = "hello-world-unsigned.xlsx"; try (OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE)) { SignatureConfig sic = new SignatureConfig(); - sic.setOpcPackage(pkg); sic.setKey(keyPair.getPrivate()); sic.setSigningCertificateChain(Collections.singletonList(x509)); SignatureInfo si = new SignatureInfo(); + si.setOpcPackage(pkg); si.setSignatureConfig(sic); // hash > sha1 doesn't work in excel viewer ... si.confirmSignature(); @@ -481,12 +470,11 @@ public class TestSignatureInfo { try (OPCPackage pkg = OPCPackage.open(copy(sigCopy), PackageAccess.READ_WRITE)) { - initKeyPair("Test", "CN=Test"); + initKeyPair(); final X509CRL crl = generateCrl(x509, keyPair.getPrivate()); // setup SignatureConfig signatureConfig = new SignatureConfig(); - signatureConfig.setOpcPackage(pkg); signatureConfig.setKey(keyPair.getPrivate()); /* @@ -529,17 +517,9 @@ public class TestSignatureInfo { } if (mockTsp) { - TimeStampService tspService = new TimeStampService() { - @Override - public byte[] timeStamp(byte[] data, RevocationData revocationData) { - revocationData.addCRL(crl); - return "time-stamp-token".getBytes(LocaleUtil.CHARSET_1252); - } - - @Override - public void setSignatureConfig(SignatureConfig config) { - // empty on purpose - } + TimeStampService tspService = (signatureInfo, data, revocationData) -> { + revocationData.addCRL(crl); + return "time-stamp-token".getBytes(LocaleUtil.CHARSET_1252); }; signatureConfig.setTspService(tspService); } else { @@ -555,8 +535,7 @@ public class TestSignatureInfo { final RevocationData revocationData = new RevocationData(); revocationData.addCRL(crl); - OCSPResp ocspResp = createOcspResp(x509, false, - x509, x509, keyPair.getPrivate(), "SHA1withRSA", cal.getTimeInMillis()); + OCSPResp ocspResp = createOcspResp(x509, x509, x509, keyPair.getPrivate(), cal.getTimeInMillis()); revocationData.addOCSP(ocspResp.getEncoded()); RevocationDataService revocationDataService = revocationChain -> revocationData; @@ -564,33 +543,31 @@ public class TestSignatureInfo { // operate SignatureInfo si = new SignatureInfo(); + si.setOpcPackage(pkg); si.setSignatureConfig(signatureConfig); try { si.confirmSignature(); } catch (RuntimeException e) { - pkg.close(); // only allow a ConnectException because of timeout, we see this in Jenkins from time to time... if (e.getCause() == null) { throw e; } if ((e.getCause() instanceof ConnectException) || (e.getCause() instanceof SocketTimeoutException)) { Assume.assumeFalse("Only allowing ConnectException with 'timed out' as message here, but had: " + e, - e.getCause().getMessage().contains("timed out")); + e.getCause().getMessage().contains("timed out")); } else if (e.getCause() instanceof IOException) { Assume.assumeFalse("Only allowing IOException with 'Error contacting TSP server' as message here, but had: " + e, - e.getCause().getMessage().contains("Error contacting TSP server")); + e.getCause().getMessage().contains("Error contacting TSP server")); } else if (e.getCause() instanceof RuntimeException) { Assume.assumeFalse("Only allowing RuntimeException with 'This site is cur' as message here, but had: " + e, - e.getCause().getMessage().contains("This site is cur")); + e.getCause().getMessage().contains("This site is cur")); } throw e; } // verify Iterator<SignaturePart> spIter = si.getSignatureParts().iterator(); - assertTrue("Had: " + si.getSignatureConfig().getOpcPackage(). - getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN), - spIter.hasNext()); + assertTrue("Had: " + pkg.getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN), spIter.hasNext()); SignaturePart sp = spIter.next(); boolean valid = sp.validate(); assertTrue(valid); @@ -627,10 +604,10 @@ public class TestSignatureInfo { try (OPCPackage pkg = OPCPackage.open(new ByteArrayInputStream(bos.toByteArray()))) { SignatureConfig signatureConfig = new SignatureConfig(); - signatureConfig.setOpcPackage(pkg); signatureConfig.setUpdateConfigOnValidate(true); SignatureInfo si = new SignatureInfo(); + si.setOpcPackage(pkg); si.setSignatureConfig(signatureConfig); assertTrue(si.verifySignature()); @@ -667,13 +644,7 @@ public class TestSignatureInfo { conn.connect(); if (fireRequest) { - InputStream is = null; - try { - is = conn.getInputStream(); - } finally { - IOUtils.closeQuietly(is); - } - + conn.getInputStream().close(); } /* if connecting is possible we return true here */ return null; @@ -692,9 +663,9 @@ public class TestSignatureInfo { public void testCertChain() throws Exception { KeyStore keystore = KeyStore.getInstance("PKCS12"); String password = "test"; - InputStream is = testdata.openResourceAsStream("chaintest.pfx"); - keystore.load(is, password.toCharArray()); - is.close(); + try (InputStream is = testdata.openResourceAsStream("chaintest.pfx")) { + keystore.load(is, password.toCharArray()); + } Key key = keystore.getKey("poitest", password.toCharArray()); Certificate[] chainList = keystore.getCertificateChain("poitest"); @@ -714,9 +685,9 @@ public class TestSignatureInfo { Calendar oldCal = LocaleUtil.getLocaleCalendar(2007, 7, 1); signatureConfig.setExecutionTime(oldCal.getTime()); signatureConfig.setDigestAlgo(HashAlgorithm.sha1); - signatureConfig.setOpcPackage(pkg); SignatureInfo si = new SignatureInfo(); + si.setOpcPackage(pkg); si.setSignatureConfig(signatureConfig); si.confirmSignature(); @@ -735,7 +706,7 @@ public class TestSignatureInfo { @Test public void testNonSha1() throws Exception { String testFile = "hello-world-unsigned.xlsx"; - initKeyPair("Test", "CN=Test"); + initKeyPair(); SignatureConfig signatureConfig = new SignatureConfig(); signatureConfig.setKey(keyPair.getPrivate()); @@ -745,13 +716,10 @@ public class TestSignatureInfo { , HashAlgorithm.sha384, HashAlgorithm.sha512, HashAlgorithm.ripemd160}; for (HashAlgorithm ha : testAlgo) { - OPCPackage pkg = null; - try { - signatureConfig.setDigestAlgo(ha); - pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE); - signatureConfig.setOpcPackage(pkg); - + signatureConfig.setDigestAlgo(ha); + try (OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE)) { SignatureInfo si = new SignatureInfo(); + si.setOpcPackage(pkg); si.setSignatureConfig(signatureConfig); si.confirmSignature(); @@ -759,10 +727,6 @@ public class TestSignatureInfo { assertTrue("Signature not correctly calculated for " + ha, b); } catch (EncryptedDocumentException e) { Assume.assumeTrue(e.getMessage().startsWith("Export Restrictions")); - } finally { - if (pkg != null) { - pkg.close(); - } } } } @@ -776,20 +740,18 @@ public class TestSignatureInfo { wb1.removeSheetAt(0); ByteArrayOutputStream os = new ByteArrayOutputStream(); wb1.write(os); - wb1.close(); - try (OPCPackage pkg = OPCPackage.open(new ByteArrayInputStream(os.toByteArray()))) { - initKeyPair("Test", "CN=Test"); + try (OPCPackage pkg = OPCPackage.open(new ByteArrayInputStream(os.toByteArray()))) { + initKeyPair(); SignatureConfig signatureConfig = new SignatureConfig(); signatureConfig.setKey(keyPair.getPrivate()); signatureConfig.setSigningCertificateChain(Collections.singletonList(x509)); - signatureConfig.setOpcPackage(pkg); SignatureInfo si = new SignatureInfo(); + si.setOpcPackage(pkg); si.setSignatureConfig(signatureConfig); si.confirmSignature(); assertTrue("invalid signature", si.verifySignature()); - } } } @@ -833,8 +795,8 @@ public class TestSignatureInfo { private void verifyPkg63011(File tpl, boolean multi) throws InvalidFormatException, IOException { try (OPCPackage pkg = OPCPackage.open(tpl, PackageAccess.READ)) { SignatureConfig sic = new SignatureConfig(); - sic.setOpcPackage(pkg); SignatureInfo si = new SignatureInfo(); + si.setOpcPackage(pkg); si.setSignatureConfig(sic); List<X509Certificate> result = new ArrayList<>(); for (SignaturePart sp : si.getSignatureParts()) { @@ -860,7 +822,7 @@ public class TestSignatureInfo { } private void signPkg63011(OPCPackage pkg, String pemFile, boolean multi) - throws IOException, CertificateException, XMLSignatureException, MarshalException { + throws IOException, CertificateException, XMLSignatureException, MarshalException { assertNotNull(pkg); initKeyFromPEM(testdata.getFile(pemFile)); @@ -869,9 +831,9 @@ public class TestSignatureInfo { config.setSigningCertificateChain(Collections.singletonList(x509)); config.setExecutionTime(cal.getTime()); config.setAllowMultipleSignatures(multi); - config.setOpcPackage(pkg); SignatureInfo si = new SignatureInfo(); + si.setOpcPackage(pkg); si.setSignatureConfig(config); si.confirmSignature(); } @@ -881,9 +843,9 @@ public class TestSignatureInfo { SignatureConfig sic = new SignatureConfig(); final File file = testdata.getFile("PPT2016withComment.pptx"); try (final OPCPackage pkg = OPCPackage.open(file, PackageAccess.READ)) { - sic.setOpcPackage(pkg); sic.setUpdateConfigOnValidate(true); SignatureInfo si = new SignatureInfo(); + si.setOpcPackage(pkg); si.setSignatureConfig(sic); assertTrue(si.verifySignature()); } @@ -897,8 +859,8 @@ public class TestSignatureInfo { assertEquals(CanonicalizationMethod.INCLUSIVE, sic.getCanonicalizationMethod()); } - private SignatureConfig prepareConfig(String alias, String signerDn, String pfxInput) throws Exception { - initKeyPair(alias, signerDn, pfxInput); + private SignatureConfig prepareConfig(String pfxInput) throws Exception { + initKeyPair(pfxInput); SignatureConfig signatureConfig = new SignatureConfig(); signatureConfig.setKey(keyPair.getPrivate()); @@ -909,11 +871,13 @@ public class TestSignatureInfo { return signatureConfig; } - private void sign(OPCPackage pkgCopy, String alias, String signerDn, int signerCount) throws Exception { - SignatureConfig signatureConfig = prepareConfig(alias, signerDn, null); - signatureConfig.setOpcPackage(pkgCopy); + private void sign(OPCPackage pkgCopy) throws Exception { + int signerCount = 1; + + SignatureConfig signatureConfig = prepareConfig(null); SignatureInfo si = new SignatureInfo(); + si.setOpcPackage(pkgCopy); si.setSignatureConfig(signatureConfig); final Document document = DocumentHelper.createDocument(); @@ -933,7 +897,7 @@ public class TestSignatureInfo { si.postSign(xmlSignContext, signatureValue); // verify: signature - si.getSignatureConfig().setOpcPackage(pkgCopy); + si.setOpcPackage(pkgCopy); List<X509Certificate> result = new ArrayList<>(); for (SignaturePart sp : si.getSignatureParts()) { if (sp.validate()) { @@ -943,24 +907,25 @@ public class TestSignatureInfo { assertEquals(signerCount, result.size()); } - private void initKeyPair(String alias, String subjectDN) throws Exception { - initKeyPair(alias, subjectDN, null); + private void initKeyPair() throws Exception { + initKeyPair(null); } - private void initKeyPair(String alias, String subjectDN, String pfxInput) throws Exception { + private void initKeyPair(String pfxInput) throws Exception { + final String alias = "Test"; final char[] password = "test".toCharArray(); File file = new File("build/test.pfx"); KeyStore keystore = KeyStore.getInstance("PKCS12"); if (pfxInput != null) { - InputStream fis = new ByteArrayInputStream(RawDataUtil.decompress(pfxInput)); - keystore.load(fis, password); - fis.close(); + try (InputStream fis = new ByteArrayInputStream(RawDataUtil.decompress(pfxInput))) { + keystore.load(fis, password); + } } else if (file.exists()) { - InputStream fis = new FileInputStream(file); - keystore.load(fis, password); - fis.close(); + try (InputStream fis = new FileInputStream(file)) { + keystore.load(fis, password); + } } else { keystore.load(null, password); } @@ -977,15 +942,14 @@ public class TestSignatureInfo { Date notAfter = cal2.getTime(); KeyUsage keyUsage = new KeyUsage(KeyUsage.digitalSignature); - x509 = generateCertificate(keyPair.getPublic(), subjectDN - , notBefore, notAfter, null, keyPair.getPrivate(), true, 0, null, null, keyUsage); + x509 = generateCertificate(keyPair.getPublic(), notBefore, notAfter, keyPair.getPrivate(), keyUsage); keystore.setKeyEntry(alias, keyPair.getPrivate(), password, new Certificate[]{x509}); if (pfxInput == null) { - FileOutputStream fos = new FileOutputStream(file); - keystore.store(fos, password); - fos.close(); + try (FileOutputStream fos = new FileOutputStream(file)) { + keystore.store(fos, password); + } } } } @@ -1038,24 +1002,18 @@ public class TestSignatureInfo { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); SecureRandom random = new SecureRandom(); keyPairGenerator.initialize(new RSAKeyGenParameterSpec(1024, - RSAKeyGenParameterSpec.F4), random); + RSAKeyGenParameterSpec.F4), random); return keyPairGenerator.generateKeyPair(); } private static X509Certificate generateCertificate(PublicKey subjectPublicKey, - String subjectDn, Date notBefore, Date notAfter, - X509Certificate issuerCertificate, PrivateKey issuerPrivateKey, - boolean caFlag, int pathLength, String crlUri, String ocspUri, - KeyUsage keyUsage) - throws IOException, OperatorCreationException, CertificateException - { - String signatureAlgorithm = "SHA1withRSA"; - X500Name issuerName; - if (issuerCertificate != null) { - issuerName = new X509CertificateHolder(issuerCertificate.getEncoded()).getIssuer(); - } else { - issuerName = new X500Name(subjectDn); - } + Date notBefore, Date notAfter, + PrivateKey issuerPrivateKey, + KeyUsage keyUsage) + throws IOException, OperatorCreationException, CertificateException { + final String signatureAlgorithm = "SHA1withRSA"; + final String subjectDn = "CN=Test"; + X500Name issuerName = new X500Name(subjectDn); RSAPublicKey rsaPubKey = (RSAPublicKey)subjectPublicKey; RSAKeyParameters rsaSpec = new RSAKeyParameters(false, rsaPubKey.getModulus(), rsaPubKey.getPublicExponent()); @@ -1077,47 +1035,13 @@ public class TestSignatureInfo { X509ExtensionUtils exUtils = new X509ExtensionUtils(digestCalc); SubjectKeyIdentifier subKeyId = exUtils.createSubjectKeyIdentifier(subjectPublicKeyInfo); - AuthorityKeyIdentifier autKeyId = (issuerCertificate != null) - ? exUtils.createAuthorityKeyIdentifier(new X509CertificateHolder(issuerCertificate.getEncoded())) - : exUtils.createAuthorityKeyIdentifier(subjectPublicKeyInfo); + AuthorityKeyIdentifier autKeyId = exUtils.createAuthorityKeyIdentifier(subjectPublicKeyInfo); certificateGenerator.addExtension(Extension.subjectKeyIdentifier, false, subKeyId); certificateGenerator.addExtension(Extension.authorityKeyIdentifier, false, autKeyId); - if (caFlag) { - BasicConstraints bc; - - if (-1 == pathLength) { - bc = new BasicConstraints(true); - } else { - bc = new BasicConstraints(pathLength); - } - certificateGenerator.addExtension(Extension.basicConstraints, false, bc); - } - - if (null != crlUri) { - int uri = GeneralName.uniformResourceIdentifier; - DERIA5String crlUriDer = new DERIA5String(crlUri); - GeneralName gn = new GeneralName(uri, crlUriDer); - - DERSequence gnDer = new DERSequence(gn); - GeneralNames gns = GeneralNames.getInstance(gnDer); - - DistributionPointName dpn = new DistributionPointName(0, gns); - DistributionPoint distp = new DistributionPoint(dpn, null, null); - DERSequence distpDer = new DERSequence(distp); - certificateGenerator.addExtension(Extension.cRLDistributionPoints, false, distpDer); - } - - if (null != ocspUri) { - int uri = GeneralName.uniformResourceIdentifier; - GeneralName ocspName = new GeneralName(uri, ocspUri); - - AuthorityInformationAccess authorityInformationAccess = - new AuthorityInformationAccess(X509ObjectIdentifiers.ocspAccessMethod, ocspName); - - certificateGenerator.addExtension(Extension.authorityInfoAccess, false, authorityInformationAccess); - } + BasicConstraints bc = new BasicConstraints(0); + certificateGenerator.addExtension(Extension.basicConstraints, false, bc); if (null != keyUsage) { certificateGenerator.addExtension(Extension.keyUsage, true, keyUsage); @@ -1158,10 +1082,10 @@ public class TestSignatureInfo { } private static OCSPResp createOcspResp(X509Certificate certificate, - boolean revoked, X509Certificate issuerCertificate, - X509Certificate ocspResponderCertificate, - PrivateKey ocspResponderPrivateKey, String signatureAlgorithm, - long nonceTimeinMillis) + X509Certificate issuerCertificate, + X509Certificate ocspResponderCertificate, + PrivateKey ocspResponderPrivateKey, + long nonceTimeinMillis) throws Exception { DigestCalculator digestCalc = new JcaDigestCalculatorProviderBuilder() .setProvider("BC").build().get(CertificateID.HASH_SHA1); @@ -1192,9 +1116,6 @@ public class TestSignatureInfo { for (Req ocspRequest : requestList) { CertificateID certificateID = ocspRequest.getCertID(); CertificateStatus certificateStatus = CertificateStatus.GOOD; - if (revoked) { - certificateStatus = new RevokedStatus(new Date(), CRLReason.privilegeWithdrawn); - } basicOCSPRespBuilder.addResponse(certificateID, certificateStatus); } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
