/* ==================================================================== | |
Licensed to the Apache Software Foundation (ASF) under one or more | |
contributor license agreements. See the NOTICE file distributed with | |
this work for additional information regarding copyright ownership. | |
The ASF licenses this file to You under the Apache License, Version 2.0 | |
(the "License"); you may not use this file except in compliance with | |
the License. You may obtain a copy of the License at | |
http://www.apache.org/licenses/LICENSE-2.0 | |
Unless required by applicable law or agreed to in writing, software | |
distributed under the License is distributed on an "AS IS" BASIS, | |
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
See the License for the specific language governing permissions and | |
limitations under the License. | |
==================================================================== */ | |
/* ==================================================================== | |
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 | |
Copyright (C) 2008-2014 FedICT. | |
================================================================= */ | |
package org.apache.poi.poifs.crypt; | |
import static org.junit.Assert.assertEquals; | |
import static org.junit.Assert.assertFalse; | |
import static org.junit.Assert.assertNotNull; | |
import static org.junit.Assert.assertTrue; | |
import java.io.File; | |
import java.io.FileInputStream; | |
import java.io.FileOutputStream; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.lang.reflect.Method; | |
import java.net.ConnectException; | |
import java.net.HttpURLConnection; | |
import java.net.MalformedURLException; | |
import java.net.URL; | |
import java.security.Key; | |
import java.security.KeyPair; | |
import java.security.KeyStore; | |
import java.security.PrivateKey; | |
import java.security.cert.Certificate; | |
import java.security.cert.X509CRL; | |
import java.security.cert.X509Certificate; | |
import java.util.ArrayList; | |
import java.util.Calendar; | |
import java.util.Collections; | |
import java.util.Date; | |
import java.util.Iterator; | |
import java.util.List; | |
import java.util.TimeZone; | |
import org.apache.poi.POIDataSamples; | |
import org.apache.poi.openxml4j.opc.OPCPackage; | |
import org.apache.poi.openxml4j.opc.PackageAccess; | |
import org.apache.poi.poifs.crypt.dsig.DigestInfo; | |
import org.apache.poi.poifs.crypt.dsig.SignatureConfig; | |
import org.apache.poi.poifs.crypt.dsig.SignatureInfo; | |
import org.apache.poi.poifs.crypt.dsig.SignatureInfo.SignaturePart; | |
import org.apache.poi.poifs.crypt.dsig.facets.EnvelopedSignatureFacet; | |
import org.apache.poi.poifs.crypt.dsig.facets.KeyInfoSignatureFacet; | |
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.TimeStampService; | |
import org.apache.poi.poifs.crypt.dsig.services.TimeStampServiceValidator; | |
import org.apache.poi.util.DocumentHelper; | |
import org.apache.poi.util.IOUtils; | |
import org.apache.poi.util.POILogFactory; | |
import org.apache.poi.util.POILogger; | |
import org.apache.poi.xssf.usermodel.XSSFWorkbook; | |
import org.apache.xmlbeans.XmlObject; | |
import org.bouncycastle.asn1.x509.KeyUsage; | |
import org.bouncycastle.cert.ocsp.OCSPResp; | |
import org.etsi.uri.x01903.v13.DigestAlgAndValueType; | |
import org.etsi.uri.x01903.v13.QualifyingPropertiesType; | |
import org.junit.Assume; | |
import org.junit.BeforeClass; | |
import org.junit.Test; | |
import org.w3.x2000.x09.xmldsig.ReferenceType; | |
import org.w3.x2000.x09.xmldsig.SignatureDocument; | |
import org.w3c.dom.Document; | |
public class TestSignatureInfo { | |
private static final POILogger LOG = POILogFactory.getLogger(TestSignatureInfo.class); | |
private static final POIDataSamples testdata = POIDataSamples.getXmlDSignInstance(); | |
private static Calendar cal; | |
private KeyPair keyPair = null; | |
private X509Certificate x509 = null; | |
@BeforeClass | |
public static void initBouncy() throws IOException { | |
CryptoFunctions.registerBouncyCastle(); | |
/*** TODO : set cal to now ... only set to fixed date for debugging ... */ | |
cal = Calendar.getInstance(); | |
cal.clear(); | |
cal.setTimeZone(TimeZone.getTimeZone("UTC")); | |
cal.set(2014, 7, 6, 21, 42, 12); | |
// don't run this test when we are using older Xerces as it triggers an XML Parser backwards compatibility issue | |
// in the xmlsec jar file | |
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); | |
} | |
@Test | |
public void office2007prettyPrintedRels() throws Exception { | |
OPCPackage pkg = OPCPackage.open(testdata.getFile("office2007prettyPrintedRels.docx"), PackageAccess.READ); | |
try { | |
SignatureConfig sic = new SignatureConfig(); | |
sic.setOpcPackage(pkg); | |
SignatureInfo si = new SignatureInfo(); | |
si.setSignatureConfig(sic); | |
boolean isValid = si.verifySignature(); | |
assertTrue(isValid); | |
} finally { | |
pkg.close(); | |
} | |
} | |
@Test | |
public void getSignerUnsigned() throws Exception { | |
String testFiles[] = { | |
"hello-world-unsigned.docx", | |
"hello-world-unsigned.pptx", | |
"hello-world-unsigned.xlsx", | |
"hello-world-office-2010-technical-preview-unsigned.docx" | |
}; | |
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<X509Certificate>(); | |
for (SignaturePart sp : si.getSignatureParts()) { | |
if (sp.validate()) { | |
result.add(sp.getSigner()); | |
} | |
} | |
pkg.revert(); | |
pkg.close(); | |
assertNotNull(result); | |
assertTrue(result.isEmpty()); | |
} | |
} | |
@Test | |
public void getSigner() throws Exception { | |
String testFiles[] = { | |
"hyperlink-example-signed.docx", | |
"hello-world-signed.docx", | |
"hello-world-signed.pptx", | |
"hello-world-signed.xlsx", | |
"hello-world-office-2010-technical-preview.docx", | |
"ms-office-2010-signed.docx", | |
"ms-office-2010-signed.pptx", | |
"ms-office-2010-signed.xlsx", | |
"Office2010-SP1-XAdES-X-L.docx", | |
"signed.docx", | |
}; | |
for (String testFile : testFiles) { | |
OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ); | |
try { | |
SignatureConfig sic = new SignatureConfig(); | |
sic.setOpcPackage(pkg); | |
SignatureInfo si = new SignatureInfo(); | |
si.setSignatureConfig(sic); | |
List<X509Certificate> result = new ArrayList<X509Certificate>(); | |
for (SignaturePart sp : si.getSignatureParts()) { | |
if (sp.validate()) { | |
result.add(sp.getSigner()); | |
} | |
} | |
assertNotNull(result); | |
assertEquals("test-file: "+testFile, 1, result.size()); | |
X509Certificate signer = result.get(0); | |
LOG.log(POILogger.DEBUG, "signer: " + signer.getSubjectX500Principal()); | |
boolean b = si.verifySignature(); | |
assertTrue("test-file: "+testFile, b); | |
pkg.revert(); | |
} finally { | |
pkg.close(); | |
} | |
} | |
} | |
@Test | |
public void getMultiSigners() throws Exception { | |
String testFile = "hello-world-signed-twice.docx"; | |
OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ); | |
try { | |
SignatureConfig sic = new SignatureConfig(); | |
sic.setOpcPackage(pkg); | |
SignatureInfo si = new SignatureInfo(); | |
si.setSignatureConfig(sic); | |
List<X509Certificate> result = new ArrayList<X509Certificate>(); | |
for (SignaturePart sp : si.getSignatureParts()) { | |
if (sp.validate()) { | |
result.add(sp.getSigner()); | |
} | |
} | |
assertNotNull(result); | |
assertEquals("test-file: "+testFile, 2, result.size()); | |
X509Certificate signer1 = result.get(0); | |
X509Certificate signer2 = result.get(1); | |
LOG.log(POILogger.DEBUG, "signer 1: " + signer1.getSubjectX500Principal()); | |
LOG.log(POILogger.DEBUG, "signer 2: " + signer2.getSubjectX500Principal()); | |
boolean b = si.verifySignature(); | |
assertTrue("test-file: "+testFile, b); | |
pkg.revert(); | |
} finally { | |
pkg.close(); | |
} | |
} | |
@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(); | |
} | |
@Test | |
public void testManipulation() throws Exception { | |
// sign & validate | |
String testFile = "hello-world-unsigned.xlsx"; | |
OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE); | |
sign(pkg, "Test", "CN=Test", 1); | |
// manipulate | |
XSSFWorkbook wb = new XSSFWorkbook(pkg); | |
wb.setSheetName(0, "manipulated"); | |
// ... I don't know, why commit is protected ... | |
Method m = XSSFWorkbook.class.getDeclaredMethod("commit"); | |
m.setAccessible(true); | |
m.invoke(wb); | |
// todo: test a manipulation on a package part, which is not signed | |
// ... maybe in combination with #56164 | |
// validate | |
SignatureConfig sic = new SignatureConfig(); | |
sic.setOpcPackage(pkg); | |
SignatureInfo si = new SignatureInfo(); | |
si.setSignatureConfig(sic); | |
boolean b = si.verifySignature(); | |
assertFalse("signature should be broken", b); | |
wb.close(); | |
} | |
@Test | |
public void testSignSpreadsheetWithSignatureInfo() throws Exception { | |
initKeyPair("Test", "CN=Test"); | |
String testFile = "hello-world-unsigned.xlsx"; | |
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.setSignatureConfig(sic); | |
// hash > sha1 doesn't work in excel viewer ... | |
si.confirmSignature(); | |
List<X509Certificate> result = new ArrayList<X509Certificate>(); | |
for (SignaturePart sp : si.getSignatureParts()) { | |
if (sp.validate()) { | |
result.add(sp.getSigner()); | |
} | |
} | |
assertEquals(1, result.size()); | |
pkg.close(); | |
} | |
@Test | |
public void testSignEnvelopingDocument() throws Exception { | |
String testFile = "hello-world-unsigned.xlsx"; | |
OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE); | |
initKeyPair("Test", "CN=Test"); | |
final X509CRL crl = PkiTestUtils.generateCrl(x509, keyPair.getPrivate()); | |
// setup | |
SignatureConfig signatureConfig = new SignatureConfig(); | |
signatureConfig.setOpcPackage(pkg); | |
signatureConfig.setKey(keyPair.getPrivate()); | |
/* | |
* We need at least 2 certificates for the XAdES-C complete certificate | |
* refs construction. | |
*/ | |
List<X509Certificate> certificateChain = new ArrayList<X509Certificate>(); | |
certificateChain.add(x509); | |
certificateChain.add(x509); | |
signatureConfig.setSigningCertificateChain(certificateChain); | |
signatureConfig.addSignatureFacet(new EnvelopedSignatureFacet()); | |
signatureConfig.addSignatureFacet(new KeyInfoSignatureFacet()); | |
signatureConfig.addSignatureFacet(new XAdESSignatureFacet()); | |
signatureConfig.addSignatureFacet(new XAdESXLSignatureFacet()); | |
// check for internet, no error means it works | |
boolean mockTsp = (getAccessError("http://timestamp.comodoca.com/rfc3161", true, 10000) != null); | |
// http://timestamping.edelweb.fr/service/tsp | |
// http://tsa.belgium.be/connect | |
// http://timestamp.comodoca.com/authenticode | |
// http://timestamp.comodoca.com/rfc3161 | |
// http://services.globaltrustfinder.com/adss/tsa | |
signatureConfig.setTspUrl("http://timestamp.comodoca.com/rfc3161"); | |
signatureConfig.setTspRequestPolicy(null); // comodoca request fails, if default policy is set ... | |
signatureConfig.setTspOldProtocol(false); | |
//set proxy info if any | |
String proxy = System.getProperty("http_proxy"); | |
if (proxy != null && proxy.trim().length() > 0) { | |
signatureConfig.setProxyUrl(proxy); | |
} | |
if (mockTsp) { | |
TimeStampService tspService = new TimeStampService(){ | |
@Override | |
public byte[] timeStamp(byte[] data, RevocationData revocationData) throws Exception { | |
revocationData.addCRL(crl); | |
return "time-stamp-token".getBytes(); | |
} | |
@Override | |
public void setSignatureConfig(SignatureConfig config) { | |
// empty on purpose | |
} | |
}; | |
signatureConfig.setTspService(tspService); | |
} else { | |
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()); | |
} | |
} | |
}; | |
signatureConfig.setTspValidator(tspValidator); | |
signatureConfig.setTspOldProtocol(signatureConfig.getTspUrl().contains("edelweb")); | |
} | |
final RevocationData revocationData = new RevocationData(); | |
revocationData.addCRL(crl); | |
OCSPResp ocspResp = PkiTestUtils.createOcspResp(x509, false, | |
x509, x509, keyPair.getPrivate(), "SHA1withRSA", cal.getTimeInMillis()); | |
revocationData.addOCSP(ocspResp.getEncoded()); | |
RevocationDataService revocationDataService = new RevocationDataService(){ | |
@Override | |
public RevocationData getRevocationData(List<X509Certificate> certificateChain) { | |
return revocationData; | |
} | |
}; | |
signatureConfig.setRevocationDataService(revocationDataService); | |
// operate | |
SignatureInfo si = new SignatureInfo(); | |
si.setSignatureConfig(signatureConfig); | |
try { | |
si.confirmSignature(); | |
} catch (RuntimeException e) { | |
// 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)) { | |
throw e; | |
} | |
assertTrue("Only allowing ConnectException with 'timed out' as message here, but had: " + e, e.getCause().getMessage().contains("timed out")); | |
} | |
// verify | |
Iterator<SignaturePart> spIter = si.getSignatureParts().iterator(); | |
assertTrue(spIter.hasNext()); | |
SignaturePart sp = spIter.next(); | |
boolean valid = sp.validate(); | |
assertTrue(valid); | |
SignatureDocument sigDoc = sp.getSignatureDocument(); | |
String declareNS = | |
"declare namespace xades='http://uri.etsi.org/01903/v1.3.2#'; " | |
+ "declare namespace ds='http://www.w3.org/2000/09/xmldsig#'; "; | |
String digestValXQuery = declareNS + | |
"$this/ds:Signature/ds:SignedInfo/ds:Reference"; | |
for (ReferenceType rt : (ReferenceType[])sigDoc.selectPath(digestValXQuery)) { | |
assertNotNull(rt.getDigestValue()); | |
assertEquals(signatureConfig.getDigestMethodUri(), rt.getDigestMethod().getAlgorithm()); | |
} | |
String certDigestXQuery = declareNS + | |
"$this//xades:SigningCertificate/xades:Cert/xades:CertDigest"; | |
XmlObject xoList[] = sigDoc.selectPath(certDigestXQuery); | |
assertEquals(xoList.length, 1); | |
DigestAlgAndValueType certDigest = (DigestAlgAndValueType)xoList[0]; | |
assertNotNull(certDigest.getDigestValue()); | |
String qualPropXQuery = declareNS + | |
"$this/ds:Signature/ds:Object/xades:QualifyingProperties"; | |
xoList = sigDoc.selectPath(qualPropXQuery); | |
assertEquals(xoList.length, 1); | |
QualifyingPropertiesType qualProp = (QualifyingPropertiesType)xoList[0]; | |
boolean qualPropXsdOk = qualProp.validate(); | |
assertTrue(qualPropXsdOk); | |
pkg.close(); | |
} | |
public static String getAccessError(String destinationUrl, boolean fireRequest, int timeout) { | |
URL url; | |
try { | |
url = new URL(destinationUrl); | |
} catch (MalformedURLException e) { | |
throw new IllegalArgumentException("Invalid destination URL", e); | |
} | |
HttpURLConnection conn = null; | |
try { | |
conn = (HttpURLConnection) url.openConnection(); | |
// set specified timeout if non-zero | |
if(timeout != 0) { | |
conn.setConnectTimeout(timeout); | |
conn.setReadTimeout(timeout); | |
} | |
conn.setDoOutput(false); | |
conn.setDoInput(true); | |
/* if connecting is not possible this will throw a connection refused exception */ | |
conn.connect(); | |
if (fireRequest) { | |
InputStream is = null; | |
try { | |
is = conn.getInputStream(); | |
} finally { | |
IOUtils.closeQuietly(is); | |
} | |
} | |
/* if connecting is possible we return true here */ | |
return null; | |
} catch (IOException e) { | |
/* exception is thrown -> server not available */ | |
return e.getClass().getName() + ": " + e.getMessage(); | |
} finally { | |
if (conn != null) { | |
conn.disconnect(); | |
} | |
} | |
} | |
@Test | |
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(); | |
Key key = keystore.getKey("poitest", password.toCharArray()); | |
Certificate chainList[] = keystore.getCertificateChain("poitest"); | |
List<X509Certificate> certChain = new ArrayList<X509Certificate>(); | |
for (Certificate c : chainList) { | |
certChain.add((X509Certificate)c); | |
} | |
x509 = certChain.get(0); | |
keyPair = new KeyPair(x509.getPublicKey(), (PrivateKey)key); | |
String testFile = "hello-world-unsigned.xlsx"; | |
OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE); | |
SignatureConfig signatureConfig = new SignatureConfig(); | |
signatureConfig.setKey(keyPair.getPrivate()); | |
signatureConfig.setSigningCertificateChain(certChain); | |
Calendar cal = Calendar.getInstance(); | |
cal.set(2007, 7, 1); | |
signatureConfig.setExecutionTime(cal.getTime()); | |
signatureConfig.setDigestAlgo(HashAlgorithm.sha1); | |
signatureConfig.setOpcPackage(pkg); | |
SignatureInfo si = new SignatureInfo(); | |
si.setSignatureConfig(signatureConfig); | |
si.confirmSignature(); | |
for (SignaturePart sp : si.getSignatureParts()){ | |
assertTrue("Could not validate", sp.validate()); | |
X509Certificate signer = sp.getSigner(); | |
assertNotNull("signer undefined?!", signer); | |
List<X509Certificate> certChainRes = sp.getCertChain(); | |
assertEquals(3, certChainRes.size()); | |
} | |
pkg.close(); | |
} | |
@Test | |
public void testNonSha1() throws Exception { | |
String testFile = "hello-world-unsigned.xlsx"; | |
initKeyPair("Test", "CN=Test"); | |
SignatureConfig signatureConfig = new SignatureConfig(); | |
signatureConfig.setKey(keyPair.getPrivate()); | |
signatureConfig.setSigningCertificateChain(Collections.singletonList(x509)); | |
HashAlgorithm testAlgo[] = { HashAlgorithm.sha224, HashAlgorithm.sha256 | |
, 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); | |
SignatureInfo si = new SignatureInfo(); | |
si.setSignatureConfig(signatureConfig); | |
si.confirmSignature(); | |
boolean b = si.verifySignature(); | |
assertTrue("Signature not correctly calculated for " + ha, b); | |
} finally { | |
if (pkg != null) pkg.close(); | |
} | |
} | |
} | |
private void sign(OPCPackage pkgCopy, String alias, String signerDn, int signerCount) throws Exception { | |
initKeyPair(alias, signerDn); | |
SignatureConfig signatureConfig = new SignatureConfig(); | |
signatureConfig.setKey(keyPair.getPrivate()); | |
signatureConfig.setSigningCertificateChain(Collections.singletonList(x509)); | |
signatureConfig.setExecutionTime(cal.getTime()); | |
signatureConfig.setDigestAlgo(HashAlgorithm.sha1); | |
signatureConfig.setOpcPackage(pkgCopy); | |
SignatureInfo si = new SignatureInfo(); | |
si.setSignatureConfig(signatureConfig); | |
Document document = DocumentHelper.createDocument(); | |
// operate | |
DigestInfo digestInfo = si.preSign(document, null); | |
// verify | |
assertNotNull(digestInfo); | |
LOG.log(POILogger.DEBUG, "digest algo: " + digestInfo.hashAlgo); | |
LOG.log(POILogger.DEBUG, "digest description: " + digestInfo.description); | |
assertEquals("Office OpenXML Document", digestInfo.description); | |
assertNotNull(digestInfo.hashAlgo); | |
assertNotNull(digestInfo.digestValue); | |
// setup: key material, signature value | |
byte[] signatureValue = si.signDigest(digestInfo.digestValue); | |
// operate: postSign | |
si.postSign(document, signatureValue); | |
// verify: signature | |
si.getSignatureConfig().setOpcPackage(pkgCopy); | |
List<X509Certificate> result = new ArrayList<X509Certificate>(); | |
for (SignaturePart sp : si.getSignatureParts()) { | |
if (sp.validate()) { | |
result.add(sp.getSigner()); | |
} | |
} | |
assertEquals(signerCount, result.size()); | |
} | |
private void initKeyPair(String alias, String subjectDN) throws Exception { | |
final char password[] = "test".toCharArray(); | |
File file = new File("build/test.pfx"); | |
KeyStore keystore = KeyStore.getInstance("PKCS12"); | |
if (file.exists()) { | |
FileInputStream fis = new FileInputStream(file); | |
keystore.load(fis, password); | |
fis.close(); | |
} else { | |
keystore.load(null, password); | |
} | |
if (keystore.isKeyEntry(alias)) { | |
Key key = keystore.getKey(alias, password); | |
x509 = (X509Certificate)keystore.getCertificate(alias); | |
keyPair = new KeyPair(x509.getPublicKey(), (PrivateKey)key); | |
} else { | |
keyPair = PkiTestUtils.generateKeyPair(); | |
Calendar cal = Calendar.getInstance(); | |
Date notBefore = cal.getTime(); | |
cal.add(Calendar.YEAR, 1); | |
Date notAfter = cal.getTime(); | |
KeyUsage keyUsage = new KeyUsage(KeyUsage.digitalSignature); | |
x509 = PkiTestUtils.generateCertificate(keyPair.getPublic(), subjectDN | |
, notBefore, notAfter, null, keyPair.getPrivate(), true, 0, null, null, keyUsage); | |
keystore.setKeyEntry(alias, keyPair.getPrivate(), password, new Certificate[]{x509}); | |
FileOutputStream fos = new FileOutputStream(file); | |
keystore.store(fos, password); | |
fos.close(); | |
} | |
} | |
private static File copy(File input) throws IOException { | |
String extension = input.getName().replaceAll(".*?(\\.[^.]+)?$", "$1"); | |
if (extension == null || "".equals(extension)) extension = ".zip"; | |
File tmpFile = new File("build", "sigtest"+extension); | |
FileOutputStream fos = new FileOutputStream(tmpFile); | |
FileInputStream fis = new FileInputStream(input); | |
IOUtils.copy(fis, fos); | |
fis.close(); | |
fos.close(); | |
return tmpFile; | |
} | |
} |