import javax.xml.crypto.dsig.XMLSignatureFactory;\r
\r
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;\r
-import org.apache.poi.openxml4j.opc.OPCPackage;\r
import org.apache.poi.openxml4j.opc.PackagePart;\r
import org.apache.poi.openxml4j.opc.PackagePartName;\r
import org.apache.poi.openxml4j.opc.PackagingURIHelper;\r
\r
private static final POILogger LOG = POILogFactory.getLogger(OOXMLURIDereferencer.class);\r
\r
- private final OPCPackage pkg;\r
+ private SignatureInfoConfig signatureConfig;\r
+ private URIDereferencer baseUriDereferencer;\r
\r
- private final URIDereferencer baseUriDereferencer;\r
-\r
- public OOXMLURIDereferencer(OPCPackage pkg) {\r
- if (null == pkg) {\r
- throw new IllegalArgumentException("OPCPackage is null");\r
- }\r
- this.pkg = pkg;\r
+ public OOXMLURIDereferencer() {\r
XMLSignatureFactory xmlSignatureFactory = SignatureInfo.getSignatureFactory();\r
this.baseUriDereferencer = xmlSignatureFactory.getURIDereferencer();\r
}\r
+ \r
+ public void setSignatureConfig(SignatureInfoConfig signatureConfig) {\r
+ this.signatureConfig = signatureConfig;\r
+ }\r
\r
public Data dereference(URIReference uriReference, XMLCryptoContext context) throws URIReferenceException {\r
if (null == uriReference) {\r
return null;\r
}\r
\r
- return pkg.getPart(ppn);\r
+ return signatureConfig.getOpcPackage().getPart(ppn);\r
}\r
}\r
import java.security.cert.X509Certificate;\r
import java.util.ArrayList;\r
import java.util.Collections;\r
-import java.util.Date;\r
import java.util.List;\r
\r
import javax.crypto.Cipher;\r
\r
public void confirmSignature(PrivateKey key, X509Certificate x509, HashAlgorithm hashAlgo)\r
throws NoSuchAlgorithmException, IOException, MarshalException, ParserConfigurationException, XmlException {\r
- XmlSignatureService signatureService = createSignatureService(hashAlgo, pkg);\r
+ SignatureInfoConfig signatureConfig = new SignatureInfoConfig();\r
+ signatureConfig.setOpcPackage(pkg);\r
+ signatureConfig.setDigestAlgo(hashAlgo);\r
+ signatureConfig.setSigningCertificateChain(Collections.singletonList(x509));\r
+ signatureConfig.setKey(key);\r
+ signatureConfig.addDefaultFacets();\r
+ XmlSignatureService signatureService = new XmlSignatureService(signatureConfig);\r
\r
Document document = DocumentHelper.createDocument();\r
\r
// operate\r
- List<X509Certificate> x509Chain = Collections.singletonList(x509);\r
- DigestInfo digestInfo = signatureService.preSign(document, null, key, x509Chain, null, null, null);\r
+ DigestInfo digestInfo = signatureService.preSign(document, null);\r
\r
// setup: key material, signature value\r
byte[] signatureValue = signDigest(key, hashAlgo, digestInfo.digestValue);\r
\r
// operate: postSign\r
- signatureService.postSign(document, signatureValue, Collections.singletonList(x509));\r
+ signatureService.postSign(document, signatureValue);\r
}\r
\r
public static byte[] signDigest(PrivateKey key, HashAlgorithm hashAlgo, byte digest[]) {\r
}\r
}\r
\r
- public XmlSignatureService createSignatureService(HashAlgorithm hashAlgo, OPCPackage pkg) {\r
- XmlSignatureService signatureService = new XmlSignatureService(hashAlgo, pkg);\r
- signatureService.initFacets(new Date());\r
- return signatureService;\r
- }\r
- \r
public List<X509Certificate> getSigners() {\r
initXmlProvider();\r
List<X509Certificate> signers = new ArrayList<X509Certificate>();\r
LOG.log(POILogger.DEBUG, "no signature resources");\r
allValid = false;\r
}\r
+\r
+ SignatureInfoConfig signatureConfig = new SignatureInfoConfig();\r
+ signatureConfig.setOpcPackage(pkg);\r
\r
for (PackagePart signaturePart : signatureParts) {\r
KeyInfoKeySelector keySelector = new KeyInfoKeySelector();\r
\r
try {\r
Document doc = DocumentHelper.readDocument(signaturePart.getInputStream());\r
- // dummy call to createSignatureService to tweak document afterwards\r
- createSignatureService(HashAlgorithm.sha1, pkg).registerIds(doc);\r
+ XmlSignatureService.registerIds(doc);\r
\r
DOMValidateContext domValidateContext = new DOMValidateContext(keySelector, doc);\r
domValidateContext.setProperty("org.jcp.xml.dsig.validateManifests", Boolean.TRUE);\r
- OOXMLURIDereferencer dereferencer = new OOXMLURIDereferencer(pkg);\r
- domValidateContext.setURIDereferencer(dereferencer);\r
+ domValidateContext.setURIDereferencer(signatureConfig.getUriDereferencer());\r
\r
XMLSignatureFactory xmlSignatureFactory = getSignatureFactory();\r
XMLSignature xmlSignature = xmlSignatureFactory.unmarshalXMLSignature(domValidateContext);\r
--- /dev/null
+/* ====================================================================\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+==================================================================== */\r
+\r
+package org.apache.poi.poifs.crypt.dsig;\r
+\r
+import java.security.PrivateKey;\r
+import java.security.cert.X509Certificate;\r
+import java.util.ArrayList;\r
+import java.util.Date;\r
+import java.util.List;\r
+\r
+import javax.xml.crypto.URIDereferencer;\r
+\r
+import org.apache.poi.openxml4j.opc.OPCPackage;\r
+import org.apache.poi.poifs.crypt.HashAlgorithm;\r
+import org.apache.poi.poifs.crypt.dsig.facets.KeyInfoSignatureFacet;\r
+import org.apache.poi.poifs.crypt.dsig.facets.OOXMLSignatureFacet;\r
+import org.apache.poi.poifs.crypt.dsig.facets.Office2010SignatureFacet;\r
+import org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet;\r
+import org.apache.poi.poifs.crypt.dsig.facets.SignaturePolicyService;\r
+import org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet;\r
+import org.apache.poi.poifs.crypt.dsig.spi.AddressDTO;\r
+import org.apache.poi.poifs.crypt.dsig.spi.IdentityDTO;\r
+\r
+public class SignatureInfoConfig {\r
+ \r
+ private List<SignatureFacet> signatureFacets = new ArrayList<SignatureFacet>();\r
+ private HashAlgorithm digestAlgo = HashAlgorithm.sha1;\r
+ private Date executionTime = new Date();\r
+ private OPCPackage opcPackage;\r
+ private PrivateKey key;\r
+ private List<X509Certificate> signingCertificateChain;\r
+ private IdentityDTO identity;\r
+ private AddressDTO address;\r
+ private byte[] photo;\r
+ private SignaturePolicyService signaturePolicyService;\r
+ private URIDereferencer uriDereferencer; \r
+\r
+ public SignatureInfoConfig() {\r
+ OOXMLURIDereferencer uriDereferencer = new OOXMLURIDereferencer();\r
+ uriDereferencer.setSignatureConfig(this);\r
+ this.uriDereferencer = uriDereferencer;\r
+ }\r
+ \r
+ public void addSignatureFacet(SignatureFacet sf) {\r
+ signatureFacets.add(sf);\r
+ }\r
+ \r
+ public void addDefaultFacets() {\r
+ addSignatureFacet(new OOXMLSignatureFacet(this));\r
+ addSignatureFacet(new KeyInfoSignatureFacet(true, false, false));\r
+\r
+ XAdESSignatureFacet xadesSignatureFacet = new XAdESSignatureFacet(this);\r
+ xadesSignatureFacet.setIdSignedProperties("idSignedProperties");\r
+ xadesSignatureFacet.setSignaturePolicyImplied(true);\r
+ /*\r
+ * Work-around for Office 2010.\r
+ */\r
+ xadesSignatureFacet.setIssuerNameNoReverseOrder(true);\r
+ addSignatureFacet(xadesSignatureFacet);\r
+ addSignatureFacet(new Office2010SignatureFacet());\r
+ }\r
+ \r
+ /**\r
+ * Gives back the used XAdES signature facet.\r
+ * \r
+ * @return\r
+ */\r
+ public XAdESSignatureFacet getXAdESSignatureFacet() {\r
+ for (SignatureFacet sf : getSignatureFacets()) {\r
+ if (sf instanceof XAdESSignatureFacet) {\r
+ return (XAdESSignatureFacet)sf;\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+ \r
+ \r
+ public List<SignatureFacet> getSignatureFacets() {\r
+ return signatureFacets;\r
+ }\r
+ public void setSignatureFacets(List<SignatureFacet> signatureFacets) {\r
+ this.signatureFacets = signatureFacets;\r
+ }\r
+ public HashAlgorithm getDigestAlgo() {\r
+ return digestAlgo;\r
+ }\r
+ public void setDigestAlgo(HashAlgorithm digestAlgo) {\r
+ this.digestAlgo = digestAlgo;\r
+ }\r
+ public OPCPackage getOpcPackage() {\r
+ return opcPackage;\r
+ }\r
+ public void setOpcPackage(OPCPackage opcPackage) {\r
+ this.opcPackage = opcPackage;\r
+ }\r
+ public PrivateKey getKey() {\r
+ return key;\r
+ }\r
+ public void setKey(PrivateKey key) {\r
+ this.key = key;\r
+ }\r
+ public List<X509Certificate> getSigningCertificateChain() {\r
+ return signingCertificateChain;\r
+ }\r
+ public void setSigningCertificateChain(\r
+ List<X509Certificate> signingCertificateChain) {\r
+ this.signingCertificateChain = signingCertificateChain;\r
+ }\r
+ public IdentityDTO getIdentity() {\r
+ return identity;\r
+ }\r
+ public void setIdentity(IdentityDTO identity) {\r
+ this.identity = identity;\r
+ }\r
+ public AddressDTO getAddress() {\r
+ return address;\r
+ }\r
+ public void setAddress(AddressDTO address) {\r
+ this.address = address;\r
+ }\r
+ public byte[] getPhoto() {\r
+ return photo;\r
+ }\r
+ public void setPhoto(byte[] photo) {\r
+ this.photo = photo;\r
+ }\r
+ public Date getExecutionTime() {\r
+ return executionTime;\r
+ }\r
+ public void setExecutionTime(Date executionTime) {\r
+ this.executionTime = executionTime;\r
+ }\r
+ public SignaturePolicyService getSignaturePolicyService() {\r
+ return signaturePolicyService;\r
+ }\r
+ public void setSignaturePolicyService(\r
+ SignaturePolicyService signaturePolicyService) {\r
+ this.signaturePolicyService = signaturePolicyService;\r
+ }\r
+ public URIDereferencer getUriDereferencer() {\r
+ return uriDereferencer;\r
+ }\r
+ public void setUriDereferencer(URIDereferencer uriDereferencer) {\r
+ this.uriDereferencer = uriDereferencer;\r
+ }\r
+\r
+\r
+}\r
import java.text.DateFormat;\r
import java.text.SimpleDateFormat;\r
import java.util.ArrayList;\r
-import java.util.Date;\r
import java.util.HashMap;\r
import java.util.HashSet;\r
import java.util.List;\r
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;\r
import org.apache.poi.openxml4j.opc.PackagingURIHelper;\r
import org.apache.poi.openxml4j.opc.TargetMode;\r
-import org.apache.poi.poifs.crypt.HashAlgorithm;\r
+import org.apache.poi.poifs.crypt.dsig.SignatureInfoConfig;\r
import org.apache.poi.poifs.crypt.dsig.services.RelationshipTransformService;\r
import org.apache.poi.poifs.crypt.dsig.services.RelationshipTransformService.RelationshipTransformParameterSpec;\r
-import org.apache.poi.poifs.crypt.dsig.services.XmlSignatureService;\r
import org.apache.poi.util.POILogFactory;\r
import org.apache.poi.util.POILogger;\r
import org.apache.xmlbeans.XmlException;\r
public static final String OOXML_DIGSIG_NS = "http://schemas.openxmlformats.org/package/2006/digital-signature";\r
public static final String OFFICE_DIGSIG_NS = "http://schemas.microsoft.com/office/2006/digsig";\r
\r
- private final XmlSignatureService signatureService;\r
-\r
- private final Date clock;\r
-\r
- private final HashAlgorithm hashAlgo;\r
+ private final SignatureInfoConfig signatureConfig;\r
\r
/**\r
* Main constructor.\r
*/\r
- public OOXMLSignatureFacet(XmlSignatureService signatureService, Date clock, HashAlgorithm hashAlgo) {\r
- this.signatureService = signatureService;\r
- this.clock = (clock == null ? new Date() : clock);\r
- this.hashAlgo = (hashAlgo == null ? HashAlgorithm.sha1 : hashAlgo);\r
+ public OOXMLSignatureFacet(SignatureInfoConfig signatureConfig) {\r
+ this.signatureConfig = signatureConfig;\r
}\r
\r
@Override\r
XMLObject xo = signatureFactory.newXMLObject(objectContent, objectId, null, null);\r
objects.add(xo);\r
\r
- DigestMethod digestMethod = signatureFactory.newDigestMethod(this.hashAlgo.xmlSignUri, null);\r
+ DigestMethod digestMethod = signatureFactory.newDigestMethod(signatureConfig.getDigestAlgo().xmlSignUri, null);\r
Reference reference = signatureFactory.newReference\r
("#" + objectId, digestMethod, null, XmlDSigNS+"Object", null);\r
references.add(reference);\r
throws IOException, NoSuchAlgorithmException,\r
InvalidAlgorithmParameterException, URISyntaxException, XmlException {\r
\r
- OPCPackage ooxml = this.signatureService.getOfficeOpenXMLDocument();\r
+ OPCPackage ooxml = this.signatureConfig.getOpcPackage();\r
List<PackagePart> relsEntryNames = ooxml.getPartsByContentType(ContentTypes.RELATIONSHIPS_PART);\r
\r
\r
- DigestMethod digestMethod = signatureFactory.newDigestMethod(this.hashAlgo.xmlSignUri, null);\r
+ DigestMethod digestMethod = signatureFactory.newDigestMethod(signatureConfig.getDigestAlgo().xmlSignUri, null);\r
Set<String> digestedPartNames = new HashSet<String>();\r
for (PackagePart pp : relsEntryNames) {\r
String baseUri = pp.getPartName().getName().replaceFirst("(.*)/_rels/.*", "$1");\r
*/\r
DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");\r
fmt.setTimeZone(TimeZone.getTimeZone("UTC"));\r
- String nowStr = fmt.format(this.clock);\r
+ String nowStr = fmt.format(this.signatureConfig.getExecutionTime());\r
LOG.log(POILogger.DEBUG, "now: " + nowStr);\r
\r
SignatureTimeDocument sigTime = SignatureTimeDocument.Factory.newInstance();\r
signaturePropertyContent.add(signatureTimeSignatureProperty);\r
SignatureProperties signatureProperties = signatureFactory\r
.newSignatureProperties(signaturePropertyContent,\r
- "id-signature-time-" + this.clock.getTime());\r
+ "id-signature-time-" + signatureConfig.getExecutionTime());\r
objectContent.add(signatureProperties);\r
}\r
\r
\r
SignatureInfoV1Document sigV1 = SignatureInfoV1Document.Factory.newInstance();\r
CTSignatureInfoV1 ctSigV1 = sigV1.addNewSignatureInfoV1();\r
- ctSigV1.setManifestHashAlgorithm(hashAlgo.xmlSignUri);\r
+ ctSigV1.setManifestHashAlgorithm(signatureConfig.getDigestAlgo().xmlSignUri);\r
Element n = (Element)document.importNode(ctSigV1.getDomNode(), true);\r
n.setAttributeNS(XmlNS, "xmlns", "http://schemas.microsoft.com/office/2006/digsig");\r
\r
String objectId = "idOfficeObject";\r
objects.add(signatureFactory.newXMLObject(objectContent, objectId, null, null));\r
\r
- DigestMethod digestMethod = signatureFactory.newDigestMethod(this.hashAlgo.xmlSignUri, null);\r
+ DigestMethod digestMethod = signatureFactory.newDigestMethod(signatureConfig.getDigestAlgo().xmlSignUri, null);\r
Reference reference = signatureFactory.newReference\r
("#" + objectId, digestMethod, null, XmlDSigNS+"Object", null);\r
references.add(reference);\r
import java.security.cert.X509Certificate;\r
import java.util.ArrayList;\r
import java.util.Calendar;\r
-import java.util.Date;\r
import java.util.HashMap;\r
import java.util.List;\r
import java.util.Map;\r
import org.apache.poi.poifs.crypt.CryptoFunctions;\r
import org.apache.poi.poifs.crypt.HashAlgorithm;\r
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;\r
+import org.apache.poi.poifs.crypt.dsig.SignatureInfoConfig;\r
import org.apache.poi.poifs.crypt.dsig.services.XmlSignatureService;\r
import org.apache.poi.util.POILogFactory;\r
import org.apache.poi.util.POILogger;\r
\r
private static final String XADES_TYPE = "http://uri.etsi.org/01903#SignedProperties";\r
\r
- private final Date clock;\r
-\r
- private final HashAlgorithm hashAlgo;\r
-\r
- private final SignaturePolicyService signaturePolicyService;\r
-\r
+ private SignatureInfoConfig signatureConfig;\r
+ \r
private String idSignedProperties;\r
\r
private boolean signaturePolicyImplied;\r
\r
private boolean issuerNameNoReverseOrder = false;\r
\r
- private Map<String, String> dataObjectFormatMimeTypes;\r
+ private Map<String, String> dataObjectFormatMimeTypes = new HashMap<String, String>();\r
\r
/**\r
* Main constructor.\r
* @param signaturePolicyService\r
* the optional signature policy service used for XAdES-EPES.\r
*/\r
- public XAdESSignatureFacet(Date clock, HashAlgorithm hashAlgo,\r
- SignaturePolicyService signaturePolicyService) {\r
- this.clock = (clock == null ? new Date() : clock);\r
- this.hashAlgo = (hashAlgo == null ? HashAlgorithm.sha1 : hashAlgo);\r
- this.signaturePolicyService = signaturePolicyService;\r
- this.dataObjectFormatMimeTypes = new HashMap<String, String>();\r
+ public XAdESSignatureFacet(SignatureInfoConfig signatureConfig) {\r
+ this.signatureConfig = signatureConfig;\r
}\r
\r
@Override\r
// SigningTime\r
Calendar xmlGregorianCalendar = Calendar.getInstance();\r
xmlGregorianCalendar.setTimeZone(TimeZone.getTimeZone("Z"));\r
- xmlGregorianCalendar.setTime(this.clock);\r
+ xmlGregorianCalendar.setTime(this.signatureConfig.getExecutionTime());\r
xmlGregorianCalendar.clear(Calendar.MILLISECOND);\r
signedSignatureProperties.setSigningTime(xmlGregorianCalendar);\r
\r
CertIDListType signingCertificates = signedSignatureProperties.addNewSigningCertificate();\r
CertIDType certId = signingCertificates.addNewCert();\r
X509Certificate signingCertificate = signingCertificateChain.get(0);\r
- setCertID(certId, signingCertificate, this.hashAlgo, this.issuerNameNoReverseOrder);\r
+ setCertID(certId, signingCertificate, this.signatureConfig.getDigestAlgo(), this.issuerNameNoReverseOrder);\r
\r
// ClaimedRole\r
if (null != this.role && false == this.role.isEmpty()) {\r
}\r
\r
// XAdES-EPES\r
- if (null != this.signaturePolicyService) {\r
+ SignaturePolicyService policyService = this.signatureConfig.getSignaturePolicyService();\r
+ if (policyService != null) {\r
SignaturePolicyIdentifierType signaturePolicyIdentifier =\r
signedSignatureProperties.addNewSignaturePolicyIdentifier();\r
\r
SignaturePolicyIdType signaturePolicyId = signaturePolicyIdentifier.addNewSignaturePolicyId();\r
\r
ObjectIdentifierType objectIdentifier = signaturePolicyId.addNewSigPolicyId();\r
- objectIdentifier.setDescription(this.signaturePolicyService.getSignaturePolicyDescription());\r
+ objectIdentifier.setDescription(policyService.getSignaturePolicyDescription());\r
\r
IdentifierType identifier = objectIdentifier.addNewIdentifier();\r
- identifier.setStringValue(this.signaturePolicyService.getSignaturePolicyIdentifier());\r
+ identifier.setStringValue(policyService.getSignaturePolicyIdentifier());\r
\r
- byte[] signaturePolicyDocumentData = this.signaturePolicyService.getSignaturePolicyDocument();\r
+ byte[] signaturePolicyDocumentData = policyService.getSignaturePolicyDocument();\r
DigestAlgAndValueType sigPolicyHash = signaturePolicyId.addNewSigPolicyHash();\r
- setDigestAlgAndValue(sigPolicyHash, signaturePolicyDocumentData, this.hashAlgo);\r
+ setDigestAlgAndValue(sigPolicyHash, signaturePolicyDocumentData, this.signatureConfig.getDigestAlgo());\r
\r
- String signaturePolicyDownloadUrl = this.signaturePolicyService\r
- .getSignaturePolicyDownloadUrl();\r
+ String signaturePolicyDownloadUrl = policyService.getSignaturePolicyDownloadUrl();\r
if (null != signaturePolicyDownloadUrl) {\r
SigPolicyQualifiersListType sigPolicyQualifiers = signaturePolicyId.addNewSigPolicyQualifiers(); \r
AnyType sigPolicyQualifier = sigPolicyQualifiers.addNewSigPolicyQualifier();\r
objects.add(xadesObject);\r
\r
// add XAdES ds:Reference\r
- DigestMethod digestMethod = signatureFactory.newDigestMethod(hashAlgo.xmlSignUri, null);\r
+ DigestMethod digestMethod = signatureFactory.newDigestMethod(this.signatureConfig.getDigestAlgo().xmlSignUri, null);\r
List<Transform> transforms = new ArrayList<Transform>();\r
Transform exclusiveTransform = signatureFactory\r
.newTransform(CanonicalizationMethod.INCLUSIVE,\r
\r
import java.io.IOException;\r
import java.security.NoSuchAlgorithmException;\r
-import java.security.PrivateKey;\r
-import java.security.cert.X509Certificate;\r
import java.util.List;\r
\r
import javax.xml.crypto.MarshalException;\r
import javax.xml.parsers.ParserConfigurationException;\r
\r
-import org.apache.poi.poifs.crypt.dsig.spi.AddressDTO;\r
import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo;\r
-import org.apache.poi.poifs.crypt.dsig.spi.IdentityDTO;\r
import org.apache.xmlbeans.XmlException;\r
import org.w3c.dom.Document;\r
\r
*/\r
public interface SignatureService {\r
\r
- /**\r
- * Gives back the digest algorithm to be used for construction of the digest\r
- * infos of the preSign method. Return a digest algorithm here if you want\r
- * to let the client sign some locally stored files. Return\r
- * <code>null</code> if no pre-sign digest infos are required.\r
- * \r
- * @return the digest algorithm to be used when digesting local files.\r
- * @see #preSign(List, List)\r
- */\r
- String getFilesDigestAlgorithm();\r
-\r
/**\r
* Pre-sign callback method. Depending on the configuration some parameters\r
* are passed. The returned value will be signed by the eID Applet.\r
* \r
- * <p>\r
- * TODO: service must be able to throw some exception on failure.\r
- * </p>\r
- * \r
* @param digestInfos\r
* the optional list of digest infos.\r
- * @param signingCertificateChain\r
- * the optional list of certificates.\r
- * @param identity\r
- * the optional identity.\r
- * @param address\r
- * the optional identity address.\r
- * @param photo\r
- * the optional identity photo.\r
- * @param timestamp\r
- * the optional timestamp, defaults to now\r
* @return the digest to be signed.\r
* @throws NoSuchAlgorithmException\r
*/\r
- DigestInfo preSign(Document document, List<DigestInfo> digestInfos,\r
- PrivateKey privateKey,\r
- List<X509Certificate> signingCertificateChain,\r
- IdentityDTO identity, AddressDTO address, byte[] photo)\r
- throws NoSuchAlgorithmException;\r
+ DigestInfo preSign(Document document, List<DigestInfo> digestInfos)\r
+ throws NoSuchAlgorithmException;\r
\r
/**\r
* Post-sign callback method. Received the signature value. Depending on the\r
* @param signingCertificateChain\r
* the optional chain of signing certificates.\r
*/\r
- void postSign(Document document, byte[] signatureValue,\r
- List<X509Certificate> signingCertificateChain)\r
- throws IOException, MarshalException, ParserConfigurationException, XmlException;\r
+ void postSign(Document document, byte[] signatureValue)\r
+ throws IOException, MarshalException, ParserConfigurationException, XmlException;\r
}\r
import java.security.MessageDigest;\r
import java.security.NoSuchAlgorithmException;\r
import java.security.NoSuchProviderException;\r
-import java.security.PrivateKey;\r
-import java.security.cert.X509Certificate;\r
import java.util.ArrayList;\r
import java.util.Collections;\r
-import java.util.Date;\r
import java.util.HashMap;\r
import java.util.List;\r
import java.util.Map;\r
import org.apache.poi.openxml4j.opc.TargetMode;\r
import org.apache.poi.poifs.crypt.CryptoFunctions;\r
import org.apache.poi.poifs.crypt.HashAlgorithm;\r
-import org.apache.poi.poifs.crypt.dsig.OOXMLURIDereferencer;\r
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;\r
-import org.apache.poi.poifs.crypt.dsig.facets.KeyInfoSignatureFacet;\r
-import org.apache.poi.poifs.crypt.dsig.facets.OOXMLSignatureFacet;\r
-import org.apache.poi.poifs.crypt.dsig.facets.Office2010SignatureFacet;\r
+import org.apache.poi.poifs.crypt.dsig.SignatureInfoConfig;\r
import org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet;\r
-import org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet;\r
-import org.apache.poi.poifs.crypt.dsig.spi.AddressDTO;\r
import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo;\r
-import org.apache.poi.poifs.crypt.dsig.spi.IdentityDTO;\r
import org.apache.poi.util.POILogFactory;\r
import org.apache.poi.util.POILogger;\r
import org.apache.xml.security.signature.XMLSignature;\r
public class XmlSignatureService implements SignatureService {\r
private static final POILogger LOG = POILogFactory.getLogger(XmlSignatureService.class);\r
\r
- protected final List<SignatureFacet> signatureFacets;\r
-\r
+ protected SignatureInfoConfig signatureConfig;\r
+ \r
private String signatureNamespacePrefix;\r
private String signatureId = "idPackageSignature";\r
- private final HashAlgorithm hashAlgo;\r
- private final OPCPackage opcPackage;\r
- // private SignatureDocument sigDoc;\r
- private XAdESSignatureFacet xadesSignatureFacet;\r
\r
/**\r
* Main constructor.\r
*/\r
- public XmlSignatureService(HashAlgorithm digestAlgo, OPCPackage opcPackage) {\r
- this.signatureFacets = new ArrayList<SignatureFacet>();\r
+ public XmlSignatureService(SignatureInfoConfig signatureConfig) {\r
this.signatureNamespacePrefix = null;\r
- this.hashAlgo = digestAlgo;\r
- this.opcPackage = opcPackage;\r
- // this.sigDoc = null;\r
+ this.signatureConfig = signatureConfig;\r
}\r
-\r
- public void initFacets(Date clock) {\r
- if (clock == null) clock = new Date();\r
- addSignatureFacet(new OOXMLSignatureFacet(this, clock, hashAlgo));\r
- addSignatureFacet(new KeyInfoSignatureFacet(true, false, false));\r
-\r
- this.xadesSignatureFacet = new XAdESSignatureFacet(clock, hashAlgo, null);\r
- this.xadesSignatureFacet.setIdSignedProperties("idSignedProperties");\r
- this.xadesSignatureFacet.setSignaturePolicyImplied(true);\r
- /*\r
- * Work-around for Office 2010.\r
- */\r
- this.xadesSignatureFacet.setIssuerNameNoReverseOrder(true);\r
- addSignatureFacet(this.xadesSignatureFacet);\r
- addSignatureFacet(new Office2010SignatureFacet());\r
- }\r
- \r
\r
+ public SignatureInfoConfig getSignatureConfig() {\r
+ return signatureConfig;\r
+ }\r
+\r
/**\r
* Sets the signature Id attribute value used to create the XML signature. A\r
* <code>null</code> value will trigger an automatically generated signature\r
this.signatureNamespacePrefix = signatureNamespacePrefix;\r
}\r
\r
- /**\r
- * Adds a signature facet to this XML signature service.\r
- * \r
- * @param signatureFacet\r
- */\r
- public void addSignatureFacet(SignatureFacet... signatureFacets) {\r
- for (SignatureFacet sf : signatureFacets) {\r
- this.signatureFacets.add(sf);\r
- }\r
- }\r
-\r
- /**\r
- * Gives back the signature digest algorithm. Allowed values are SHA-1,\r
- * SHA-256, SHA-384, SHA-512, RIPEND160. The default algorithm is SHA-1.\r
- * Override this method to select another signature digest algorithm.\r
- * \r
- * @return\r
- */\r
- protected HashAlgorithm getSignatureDigestAlgorithm() {\r
- return null != this.hashAlgo ? this.hashAlgo : HashAlgorithm.sha1;\r
- }\r
-\r
- /**\r
- * Override this method to change the URI dereferener used by the signing\r
- * engine.\r
- * \r
- * @return\r
- */\r
- protected URIDereferencer getURIDereferencer() {\r
- OPCPackage ooxmlDocument = getOfficeOpenXMLDocument();\r
- return new OOXMLURIDereferencer(ooxmlDocument);\r
- }\r
-\r
/**\r
* Gives back the human-readable description of what the citizen will be\r
* signing. The default value is "XML Document". Override this method to\r
return "Office OpenXML Document";\r
}\r
\r
- /**\r
- * Gives back the URL of the OOXML to be signed.\r
- * \r
- * @return\r
- */\r
- public OPCPackage getOfficeOpenXMLDocument() {\r
- return opcPackage;\r
- }\r
- \r
-\r
- \r
/**\r
* Gives back the output stream to which to write the signed XML document.\r
* \r
*/\r
// protected abstract OutputStream getSignedDocumentOutputStream();\r
@Override\r
- public DigestInfo preSign(Document document, List<DigestInfo> digestInfos,\r
- PrivateKey key,\r
- List<X509Certificate> signingCertificateChain,\r
- IdentityDTO identity, AddressDTO address, byte[] photo)\r
+ public DigestInfo preSign(Document document, List<DigestInfo> digestInfos)\r
throws NoSuchAlgorithmException {\r
SignatureInfo.initXmlProvider();\r
\r
LOG.log(POILogger.DEBUG, "preSign");\r
- HashAlgorithm hashAlgo = getSignatureDigestAlgorithm();\r
+ HashAlgorithm hashAlgo = this.signatureConfig.getDigestAlgo();\r
\r
byte[] digestValue;\r
try {\r
- digestValue = getXmlSignatureDigestValue(document, hashAlgo, digestInfos, key, signingCertificateChain);\r
+ digestValue = getXmlSignatureDigestValue(document, digestInfos);\r
} catch (Exception e) {\r
throw new RuntimeException("XML signature error: " + e.getMessage(), e);\r
}\r
}\r
\r
@Override\r
- public void postSign(Document document, byte[] signatureValue, List<X509Certificate> signingCertificateChain)\r
+ public void postSign(Document document, byte[] signatureValue)\r
throws IOException, MarshalException, ParserConfigurationException, XmlException {\r
LOG.log(POILogger.DEBUG, "postSign");\r
SignatureInfo.initXmlProvider();\r
/*\r
* Allow signature facets to inject their own stuff.\r
*/\r
- for (SignatureFacet signatureFacet : this.signatureFacets) {\r
- signatureFacet.postSign(document, signingCertificateChain);\r
+ for (SignatureFacet signatureFacet : this.signatureConfig.getSignatureFacets()) {\r
+ signatureFacet.postSign(document, this.signatureConfig.getSigningCertificateChain());\r
}\r
\r
registerIds(document);\r
}\r
\r
@SuppressWarnings("unchecked")\r
- private byte[] getXmlSignatureDigestValue(Document document, HashAlgorithm hashAlgo,\r
- List<DigestInfo> digestInfos,\r
- PrivateKey privateKey,\r
- List<X509Certificate> signingCertificateChain)\r
+ private byte[] getXmlSignatureDigestValue(Document document, List<DigestInfo> digestInfos)\r
throws ParserConfigurationException, NoSuchAlgorithmException,\r
InvalidAlgorithmParameterException, MarshalException,\r
javax.xml.crypto.dsig.XMLSignatureException,\r
/*\r
* Signature context construction.\r
*/\r
- XMLSignContext xmlSignContext = new DOMSignContext(privateKey, document);\r
- URIDereferencer uriDereferencer = getURIDereferencer();\r
+ XMLSignContext xmlSignContext = new DOMSignContext(this.signatureConfig.getKey(), document);\r
+ URIDereferencer uriDereferencer = this.signatureConfig.getUriDereferencer();\r
if (null != uriDereferencer) {\r
xmlSignContext.setURIDereferencer(uriDereferencer);\r
}\r
localSignatureId = "xmldsig-" + UUID.randomUUID().toString();\r
}\r
List<XMLObject> objects = new ArrayList<XMLObject>();\r
- for (SignatureFacet signatureFacet : this.signatureFacets) {\r
+ for (SignatureFacet signatureFacet : this.signatureConfig.getSignatureFacets()) {\r
LOG.log(POILogger.DEBUG, "invoking signature facet: " + signatureFacet.getClass().getSimpleName());\r
- signatureFacet.preSign(document, signatureFactory, localSignatureId, signingCertificateChain, references, objects);\r
+ signatureFacet.preSign(document, signatureFactory, localSignatureId, this.signatureConfig.getSigningCertificateChain(), references, objects);\r
}\r
\r
/*\r
* ds:SignedInfo\r
*/\r
- SignatureMethod signatureMethod = signatureFactory.newSignatureMethod(getSignatureMethod(hashAlgo), null);\r
+ SignatureMethod signatureMethod = signatureFactory.newSignatureMethod(getSignatureMethod(this.signatureConfig.getDigestAlgo()), null);\r
CanonicalizationMethod canonicalizationMethod = signatureFactory\r
.newCanonicalizationMethod(getCanonicalizationMethod(),\r
(C14NMethodParameterSpec) null);\r
* usage.\r
*/\r
\r
- MessageDigest jcaMessageDigest = CryptoFunctions.getMessageDigest(hashAlgo);\r
+ MessageDigest jcaMessageDigest = CryptoFunctions.getMessageDigest(this.signatureConfig.getDigestAlgo());\r
byte[] digestValue = jcaMessageDigest.digest(octets);\r
return digestValue;\r
}\r
*\r
* @param doc\r
*/\r
- public void registerIds(Document doc) {\r
+ public static void registerIds(Document doc) {\r
NodeList nl = doc.getElementsByTagNameNS(XmlDSigNS, "Object");\r
registerIdAttribute(nl);\r
nl = doc.getElementsByTagNameNS("http://uri.etsi.org/01903/v1.3.2#", "SignedProperties");\r
throw new RuntimeException("unsupported sign algo: " + hashAlgo);\r
}\r
\r
- /**\r
- * Gives back the used XAdES signature facet.\r
- * \r
- * @return\r
- */\r
- protected XAdESSignatureFacet getXAdESSignatureFacet() {\r
- return this.xadesSignatureFacet;\r
- }\r
-\r
- public String getFilesDigestAlgorithm() {\r
- return null;\r
- }\r
- \r
protected String getCanonicalizationMethod() {\r
return CanonicalizationMethod.INCLUSIVE;\r
}\r
protected void writeDocument(Document document) throws IOException, XmlException {\r
XmlOptions xo = new XmlOptions();\r
Map<String,String> namespaceMap = new HashMap<String,String>();\r
- for (SignatureFacet sf : this.signatureFacets) {\r
+ for (SignatureFacet sf : this.signatureConfig.getSignatureFacets()) {\r
Map<String,String> sfm = sf.getNamespacePrefixMapping();\r
if (sfm != null) {\r
namespaceMap.putAll(sfm);\r
* Copy the original OOXML content to the signed OOXML package. During\r
* copying some files need to changed.\r
*/\r
- OPCPackage pkg = this.getOfficeOpenXMLDocument();\r
+ OPCPackage pkg = this.signatureConfig.getOpcPackage();\r
\r
PackagePartName sigPartName, sigsPartName;\r
try {\r
import javax.xml.crypto.dsig.XMLSignature;\r
import javax.xml.crypto.dsig.XMLSignatureFactory;\r
import javax.xml.crypto.dsig.dom.DOMValidateContext;\r
-import javax.xml.parsers.DocumentBuilderFactory;\r
\r
import org.apache.poi.POIDataSamples;\r
import org.apache.poi.openxml4j.opc.OPCPackage;\r
import org.apache.poi.openxml4j.opc.PackageAccess;\r
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;\r
+import org.apache.poi.poifs.crypt.dsig.SignatureInfoConfig;\r
import org.apache.poi.poifs.crypt.dsig.facets.EnvelopedSignatureFacet;\r
import org.apache.poi.poifs.crypt.dsig.facets.KeyInfoSignatureFacet;\r
-import org.apache.poi.poifs.crypt.dsig.facets.SignaturePolicyService;\r
import org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet;\r
import org.apache.poi.poifs.crypt.dsig.facets.XAdESXLSignatureFacet;\r
import org.apache.poi.poifs.crypt.dsig.services.RevocationData;\r
OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE);\r
\r
initKeyPair("Test", "CN=Test");\r
+ final X509CRL crl = PkiTestUtils.generateCrl(x509, keyPair.getPrivate());\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
+ SignatureInfoConfig signatureConfig = new SignatureInfoConfig();\r
+ signatureConfig.setOpcPackage(pkg);\r
+ signatureConfig.setKey(keyPair.getPrivate());\r
+\r
+ /*\r
+ * We need at least 2 certificates for the XAdES-C complete certificate\r
+ * refs construction.\r
+ */\r
+ List<X509Certificate> certificateChain = new ArrayList<X509Certificate>();\r
+ certificateChain.add(x509);\r
+ certificateChain.add(x509);\r
+ signatureConfig.setSigningCertificateChain(certificateChain);\r
+ \r
+ signatureConfig.addSignatureFacet(new EnvelopedSignatureFacet());\r
+ signatureConfig.addSignatureFacet(new KeyInfoSignatureFacet(true, false, false));\r
+ signatureConfig.addSignatureFacet(new XAdESSignatureFacet(signatureConfig));\r
+ \r
\r
// http://timestamping.edelweb.fr/service/tsp\r
// http://tsa.belgium.be/connect\r
timeStampService = tspService;\r
}\r
\r
- List<X509Certificate> certificateChain = new ArrayList<X509Certificate>();\r
- /*\r
- * We need at least 2 certificates for the XAdES-C complete certificate\r
- * refs construction.\r
- */\r
- certificateChain.add(x509);\r
- certificateChain.add(x509);\r
- \r
final RevocationData revocationData = new RevocationData();\r
revocationData.addCRL(crl);\r
OCSPResp ocspResp = PkiTestUtils.createOcspResp(x509, false,\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
+ XmlSignatureService testedInstance = new XmlSignatureService(signatureConfig);\r
\r
- DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();\r
- dbf.setNamespaceAware(true);\r
- Document document = dbf.newDocumentBuilder().newDocument();\r
+ Document document = DocumentHelper.createDocument();\r
\r
// operate\r
- DigestInfo digestInfo = testedInstance.preSign(document, null, keyPair.getPrivate(), certificateChain, null, null, null);\r
+ DigestInfo digestInfo = testedInstance.preSign(document, null);\r
\r
// verify\r
assertNotNull(digestInfo);\r
byte[] signatureValue = SignatureInfo.signDigest(keyPair.getPrivate(), HashAlgorithm.sha1, digestInfo.digestValue);\r
\r
// Operate: postSign\r
- testedInstance.postSign(document, signatureValue, certificateChain);\r
+ testedInstance.postSign(document, signatureValue);\r
\r
DOMValidateContext domValidateContext = new DOMValidateContext(\r
KeySelector.singletonKeySelector(keyPair.getPublic()),\r
}\r
\r
private OPCPackage sign(OPCPackage pkgCopy, String alias, String signerDn, int signerCount) throws Exception {\r
- XmlSignatureService signatureService = new XmlSignatureService(HashAlgorithm.sha1, pkgCopy);\r
- signatureService.initFacets(cal.getTime());\r
initKeyPair(alias, signerDn);\r
\r
+ SignatureInfoConfig signatureConfig = new SignatureInfoConfig();\r
+ signatureConfig.setKey(keyPair.getPrivate());\r
+ signatureConfig.setSigningCertificateChain(Collections.singletonList(x509));\r
+ signatureConfig.setExecutionTime(cal.getTime());\r
+ signatureConfig.setDigestAlgo(HashAlgorithm.sha1);\r
+ signatureConfig.setOpcPackage(pkgCopy);\r
+ signatureConfig.addDefaultFacets();\r
+ \r
+ XmlSignatureService signatureService = new XmlSignatureService(signatureConfig);\r
+\r
Document document = DocumentHelper.createDocument();\r
\r
// operate\r
- List<X509Certificate> x509Chain = Collections.singletonList(x509);\r
- DigestInfo digestInfo = signatureService.preSign(document, null, keyPair.getPrivate(), x509Chain, null, null, null);\r
+ DigestInfo digestInfo = signatureService.preSign(document, null);\r
\r
// verify\r
assertNotNull(digestInfo);\r
byte[] signatureValue = SignatureInfo.signDigest(keyPair.getPrivate(), HashAlgorithm.sha1, digestInfo.digestValue);\r
\r
// operate: postSign\r
- signatureService.postSign(document, signatureValue, Collections.singletonList(x509));\r
+ signatureService.postSign(document, signatureValue);\r
\r
// verify: signature\r
SignatureInfo si = new SignatureInfo(pkgCopy);\r