Switched to config object

git-svn-id: https://svn.apache.org/repos/asf/poi/branches/xml_signature@1625850 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2014-09-17 23:12:16 +00:00
parent b410e72196
commit c9757d974f
8 changed files with 276 additions and 251 deletions

View File

@ -37,7 +37,6 @@ import javax.xml.crypto.XMLCryptoContext;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
@ -51,19 +50,18 @@ public class OOXMLURIDereferencer implements URIDereferencer {
private static final POILogger LOG = POILogFactory.getLogger(OOXMLURIDereferencer.class);
private final OPCPackage pkg;
private SignatureInfoConfig signatureConfig;
private URIDereferencer baseUriDereferencer;
private final URIDereferencer baseUriDereferencer;
public OOXMLURIDereferencer(OPCPackage pkg) {
if (null == pkg) {
throw new IllegalArgumentException("OPCPackage is null");
}
this.pkg = pkg;
public OOXMLURIDereferencer() {
XMLSignatureFactory xmlSignatureFactory = SignatureInfo.getSignatureFactory();
this.baseUriDereferencer = xmlSignatureFactory.getURIDereferencer();
}
public void setSignatureConfig(SignatureInfoConfig signatureConfig) {
this.signatureConfig = signatureConfig;
}
public Data dereference(URIReference uriReference, XMLCryptoContext context) throws URIReferenceException {
if (null == uriReference) {
throw new NullPointerException("URIReference cannot be null");
@ -109,6 +107,6 @@ public class OOXMLURIDereferencer implements URIDereferencer {
return null;
}
return pkg.getPart(ppn);
return signatureConfig.getOpcPackage().getPart(ppn);
}
}

View File

@ -32,7 +32,6 @@ import java.security.Provider;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import javax.crypto.Cipher;
@ -125,19 +124,24 @@ public class SignatureInfo {
public void confirmSignature(PrivateKey key, X509Certificate x509, HashAlgorithm hashAlgo)
throws NoSuchAlgorithmException, IOException, MarshalException, ParserConfigurationException, XmlException {
XmlSignatureService signatureService = createSignatureService(hashAlgo, pkg);
SignatureInfoConfig signatureConfig = new SignatureInfoConfig();
signatureConfig.setOpcPackage(pkg);
signatureConfig.setDigestAlgo(hashAlgo);
signatureConfig.setSigningCertificateChain(Collections.singletonList(x509));
signatureConfig.setKey(key);
signatureConfig.addDefaultFacets();
XmlSignatureService signatureService = new XmlSignatureService(signatureConfig);
Document document = DocumentHelper.createDocument();
// operate
List<X509Certificate> x509Chain = Collections.singletonList(x509);
DigestInfo digestInfo = signatureService.preSign(document, null, key, x509Chain, null, null, null);
DigestInfo digestInfo = signatureService.preSign(document, null);
// setup: key material, signature value
byte[] signatureValue = signDigest(key, hashAlgo, digestInfo.digestValue);
// operate: postSign
signatureService.postSign(document, signatureValue, Collections.singletonList(x509));
signatureService.postSign(document, signatureValue);
}
public static byte[] signDigest(PrivateKey key, HashAlgorithm hashAlgo, byte digest[]) {
@ -156,12 +160,6 @@ public class SignatureInfo {
}
}
public XmlSignatureService createSignatureService(HashAlgorithm hashAlgo, OPCPackage pkg) {
XmlSignatureService signatureService = new XmlSignatureService(hashAlgo, pkg);
signatureService.initFacets(new Date());
return signatureService;
}
public List<X509Certificate> getSigners() {
initXmlProvider();
List<X509Certificate> signers = new ArrayList<X509Certificate>();
@ -177,18 +175,19 @@ public class SignatureInfo {
allValid = false;
}
SignatureInfoConfig signatureConfig = new SignatureInfoConfig();
signatureConfig.setOpcPackage(pkg);
for (PackagePart signaturePart : signatureParts) {
KeyInfoKeySelector keySelector = new KeyInfoKeySelector();
try {
Document doc = DocumentHelper.readDocument(signaturePart.getInputStream());
// dummy call to createSignatureService to tweak document afterwards
createSignatureService(HashAlgorithm.sha1, pkg).registerIds(doc);
XmlSignatureService.registerIds(doc);
DOMValidateContext domValidateContext = new DOMValidateContext(keySelector, doc);
domValidateContext.setProperty("org.jcp.xml.dsig.validateManifests", Boolean.TRUE);
OOXMLURIDereferencer dereferencer = new OOXMLURIDereferencer(pkg);
domValidateContext.setURIDereferencer(dereferencer);
domValidateContext.setURIDereferencer(signatureConfig.getUriDereferencer());
XMLSignatureFactory xmlSignatureFactory = getSignatureFactory();
XMLSignature xmlSignature = xmlSignatureFactory.unmarshalXMLSignature(domValidateContext);

View File

@ -0,0 +1,163 @@
/* ====================================================================
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.
==================================================================== */
package org.apache.poi.poifs.crypt.dsig;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.xml.crypto.URIDereferencer;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.poifs.crypt.HashAlgorithm;
import org.apache.poi.poifs.crypt.dsig.facets.KeyInfoSignatureFacet;
import org.apache.poi.poifs.crypt.dsig.facets.OOXMLSignatureFacet;
import org.apache.poi.poifs.crypt.dsig.facets.Office2010SignatureFacet;
import org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet;
import org.apache.poi.poifs.crypt.dsig.facets.SignaturePolicyService;
import org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet;
import org.apache.poi.poifs.crypt.dsig.spi.AddressDTO;
import org.apache.poi.poifs.crypt.dsig.spi.IdentityDTO;
public class SignatureInfoConfig {
private List<SignatureFacet> signatureFacets = new ArrayList<SignatureFacet>();
private HashAlgorithm digestAlgo = HashAlgorithm.sha1;
private Date executionTime = new Date();
private OPCPackage opcPackage;
private PrivateKey key;
private List<X509Certificate> signingCertificateChain;
private IdentityDTO identity;
private AddressDTO address;
private byte[] photo;
private SignaturePolicyService signaturePolicyService;
private URIDereferencer uriDereferencer;
public SignatureInfoConfig() {
OOXMLURIDereferencer uriDereferencer = new OOXMLURIDereferencer();
uriDereferencer.setSignatureConfig(this);
this.uriDereferencer = uriDereferencer;
}
public void addSignatureFacet(SignatureFacet sf) {
signatureFacets.add(sf);
}
public void addDefaultFacets() {
addSignatureFacet(new OOXMLSignatureFacet(this));
addSignatureFacet(new KeyInfoSignatureFacet(true, false, false));
XAdESSignatureFacet xadesSignatureFacet = new XAdESSignatureFacet(this);
xadesSignatureFacet.setIdSignedProperties("idSignedProperties");
xadesSignatureFacet.setSignaturePolicyImplied(true);
/*
* Work-around for Office 2010.
*/
xadesSignatureFacet.setIssuerNameNoReverseOrder(true);
addSignatureFacet(xadesSignatureFacet);
addSignatureFacet(new Office2010SignatureFacet());
}
/**
* Gives back the used XAdES signature facet.
*
* @return
*/
public XAdESSignatureFacet getXAdESSignatureFacet() {
for (SignatureFacet sf : getSignatureFacets()) {
if (sf instanceof XAdESSignatureFacet) {
return (XAdESSignatureFacet)sf;
}
}
return null;
}
public List<SignatureFacet> getSignatureFacets() {
return signatureFacets;
}
public void setSignatureFacets(List<SignatureFacet> signatureFacets) {
this.signatureFacets = signatureFacets;
}
public HashAlgorithm getDigestAlgo() {
return digestAlgo;
}
public void setDigestAlgo(HashAlgorithm digestAlgo) {
this.digestAlgo = digestAlgo;
}
public OPCPackage getOpcPackage() {
return opcPackage;
}
public void setOpcPackage(OPCPackage opcPackage) {
this.opcPackage = opcPackage;
}
public PrivateKey getKey() {
return key;
}
public void setKey(PrivateKey key) {
this.key = key;
}
public List<X509Certificate> getSigningCertificateChain() {
return signingCertificateChain;
}
public void setSigningCertificateChain(
List<X509Certificate> signingCertificateChain) {
this.signingCertificateChain = signingCertificateChain;
}
public IdentityDTO getIdentity() {
return identity;
}
public void setIdentity(IdentityDTO identity) {
this.identity = identity;
}
public AddressDTO getAddress() {
return address;
}
public void setAddress(AddressDTO address) {
this.address = address;
}
public byte[] getPhoto() {
return photo;
}
public void setPhoto(byte[] photo) {
this.photo = photo;
}
public Date getExecutionTime() {
return executionTime;
}
public void setExecutionTime(Date executionTime) {
this.executionTime = executionTime;
}
public SignaturePolicyService getSignaturePolicyService() {
return signaturePolicyService;
}
public void setSignaturePolicyService(
SignaturePolicyService signaturePolicyService) {
this.signaturePolicyService = signaturePolicyService;
}
public URIDereferencer getUriDereferencer() {
return uriDereferencer;
}
public void setUriDereferencer(URIDereferencer uriDereferencer) {
this.uriDereferencer = uriDereferencer;
}
}

View File

@ -37,7 +37,6 @@ import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -68,10 +67,9 @@ import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
import org.apache.poi.openxml4j.opc.TargetMode;
import org.apache.poi.poifs.crypt.HashAlgorithm;
import org.apache.poi.poifs.crypt.dsig.SignatureInfoConfig;
import org.apache.poi.poifs.crypt.dsig.services.RelationshipTransformService;
import org.apache.poi.poifs.crypt.dsig.services.RelationshipTransformService.RelationshipTransformParameterSpec;
import org.apache.poi.poifs.crypt.dsig.services.XmlSignatureService;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.xmlbeans.XmlException;
@ -96,19 +94,13 @@ public class OOXMLSignatureFacet implements SignatureFacet {
public static final String OOXML_DIGSIG_NS = "http://schemas.openxmlformats.org/package/2006/digital-signature";
public static final String OFFICE_DIGSIG_NS = "http://schemas.microsoft.com/office/2006/digsig";
private final XmlSignatureService signatureService;
private final Date clock;
private final HashAlgorithm hashAlgo;
private final SignatureInfoConfig signatureConfig;
/**
* Main constructor.
*/
public OOXMLSignatureFacet(XmlSignatureService signatureService, Date clock, HashAlgorithm hashAlgo) {
this.signatureService = signatureService;
this.clock = (clock == null ? new Date() : clock);
this.hashAlgo = (hashAlgo == null ? HashAlgorithm.sha1 : hashAlgo);
public OOXMLSignatureFacet(SignatureInfoConfig signatureConfig) {
this.signatureConfig = signatureConfig;
}
@Override
@ -142,7 +134,7 @@ public class OOXMLSignatureFacet implements SignatureFacet {
XMLObject xo = signatureFactory.newXMLObject(objectContent, objectId, null, null);
objects.add(xo);
DigestMethod digestMethod = signatureFactory.newDigestMethod(this.hashAlgo.xmlSignUri, null);
DigestMethod digestMethod = signatureFactory.newDigestMethod(signatureConfig.getDigestAlgo().xmlSignUri, null);
Reference reference = signatureFactory.newReference
("#" + objectId, digestMethod, null, XmlDSigNS+"Object", null);
references.add(reference);
@ -152,11 +144,11 @@ public class OOXMLSignatureFacet implements SignatureFacet {
throws IOException, NoSuchAlgorithmException,
InvalidAlgorithmParameterException, URISyntaxException, XmlException {
OPCPackage ooxml = this.signatureService.getOfficeOpenXMLDocument();
OPCPackage ooxml = this.signatureConfig.getOpcPackage();
List<PackagePart> relsEntryNames = ooxml.getPartsByContentType(ContentTypes.RELATIONSHIPS_PART);
DigestMethod digestMethod = signatureFactory.newDigestMethod(this.hashAlgo.xmlSignUri, null);
DigestMethod digestMethod = signatureFactory.newDigestMethod(signatureConfig.getDigestAlgo().xmlSignUri, null);
Set<String> digestedPartNames = new HashSet<String>();
for (PackagePart pp : relsEntryNames) {
String baseUri = pp.getPartName().getName().replaceFirst("(.*)/_rels/.*", "$1");
@ -240,7 +232,7 @@ public class OOXMLSignatureFacet implements SignatureFacet {
*/
DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
fmt.setTimeZone(TimeZone.getTimeZone("UTC"));
String nowStr = fmt.format(this.clock);
String nowStr = fmt.format(this.signatureConfig.getExecutionTime());
LOG.log(POILogger.DEBUG, "now: " + nowStr);
SignatureTimeDocument sigTime = SignatureTimeDocument.Factory.newInstance();
@ -261,7 +253,7 @@ public class OOXMLSignatureFacet implements SignatureFacet {
signaturePropertyContent.add(signatureTimeSignatureProperty);
SignatureProperties signatureProperties = signatureFactory
.newSignatureProperties(signaturePropertyContent,
"id-signature-time-" + this.clock.getTime());
"id-signature-time-" + signatureConfig.getExecutionTime());
objectContent.add(signatureProperties);
}
@ -274,7 +266,7 @@ public class OOXMLSignatureFacet implements SignatureFacet {
SignatureInfoV1Document sigV1 = SignatureInfoV1Document.Factory.newInstance();
CTSignatureInfoV1 ctSigV1 = sigV1.addNewSignatureInfoV1();
ctSigV1.setManifestHashAlgorithm(hashAlgo.xmlSignUri);
ctSigV1.setManifestHashAlgorithm(signatureConfig.getDigestAlgo().xmlSignUri);
Element n = (Element)document.importNode(ctSigV1.getDomNode(), true);
n.setAttributeNS(XmlNS, "xmlns", "http://schemas.microsoft.com/office/2006/digsig");
@ -293,7 +285,7 @@ public class OOXMLSignatureFacet implements SignatureFacet {
String objectId = "idOfficeObject";
objects.add(signatureFactory.newXMLObject(objectContent, objectId, null, null));
DigestMethod digestMethod = signatureFactory.newDigestMethod(this.hashAlgo.xmlSignUri, null);
DigestMethod digestMethod = signatureFactory.newDigestMethod(signatureConfig.getDigestAlgo().xmlSignUri, null);
Reference reference = signatureFactory.newReference
("#" + objectId, digestMethod, null, XmlDSigNS+"Object", null);
references.add(reference);

View File

@ -34,7 +34,6 @@ import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -53,6 +52,7 @@ import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import org.apache.poi.poifs.crypt.CryptoFunctions;
import org.apache.poi.poifs.crypt.HashAlgorithm;
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
import org.apache.poi.poifs.crypt.dsig.SignatureInfoConfig;
import org.apache.poi.poifs.crypt.dsig.services.XmlSignatureService;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
@ -97,11 +97,7 @@ public class XAdESSignatureFacet implements SignatureFacet {
private static final String XADES_TYPE = "http://uri.etsi.org/01903#SignedProperties";
private final Date clock;
private final HashAlgorithm hashAlgo;
private final SignaturePolicyService signaturePolicyService;
private SignatureInfoConfig signatureConfig;
private String idSignedProperties;
@ -111,7 +107,7 @@ public class XAdESSignatureFacet implements SignatureFacet {
private boolean issuerNameNoReverseOrder = false;
private Map<String, String> dataObjectFormatMimeTypes;
private Map<String, String> dataObjectFormatMimeTypes = new HashMap<String, String>();
/**
* Main constructor.
@ -126,12 +122,8 @@ public class XAdESSignatureFacet implements SignatureFacet {
* @param signaturePolicyService
* the optional signature policy service used for XAdES-EPES.
*/
public XAdESSignatureFacet(Date clock, HashAlgorithm hashAlgo,
SignaturePolicyService signaturePolicyService) {
this.clock = (clock == null ? new Date() : clock);
this.hashAlgo = (hashAlgo == null ? HashAlgorithm.sha1 : hashAlgo);
this.signaturePolicyService = signaturePolicyService;
this.dataObjectFormatMimeTypes = new HashMap<String, String>();
public XAdESSignatureFacet(SignatureInfoConfig signatureConfig) {
this.signatureConfig = signatureConfig;
}
@Override
@ -167,7 +159,7 @@ public class XAdESSignatureFacet implements SignatureFacet {
// SigningTime
Calendar xmlGregorianCalendar = Calendar.getInstance();
xmlGregorianCalendar.setTimeZone(TimeZone.getTimeZone("Z"));
xmlGregorianCalendar.setTime(this.clock);
xmlGregorianCalendar.setTime(this.signatureConfig.getExecutionTime());
xmlGregorianCalendar.clear(Calendar.MILLISECOND);
signedSignatureProperties.setSigningTime(xmlGregorianCalendar);
@ -179,7 +171,7 @@ public class XAdESSignatureFacet implements SignatureFacet {
CertIDListType signingCertificates = signedSignatureProperties.addNewSigningCertificate();
CertIDType certId = signingCertificates.addNewCert();
X509Certificate signingCertificate = signingCertificateChain.get(0);
setCertID(certId, signingCertificate, this.hashAlgo, this.issuerNameNoReverseOrder);
setCertID(certId, signingCertificate, this.signatureConfig.getDigestAlgo(), this.issuerNameNoReverseOrder);
// ClaimedRole
if (null != this.role && false == this.role.isEmpty()) {
@ -193,24 +185,24 @@ public class XAdESSignatureFacet implements SignatureFacet {
}
// XAdES-EPES
if (null != this.signaturePolicyService) {
SignaturePolicyService policyService = this.signatureConfig.getSignaturePolicyService();
if (policyService != null) {
SignaturePolicyIdentifierType signaturePolicyIdentifier =
signedSignatureProperties.addNewSignaturePolicyIdentifier();
SignaturePolicyIdType signaturePolicyId = signaturePolicyIdentifier.addNewSignaturePolicyId();
ObjectIdentifierType objectIdentifier = signaturePolicyId.addNewSigPolicyId();
objectIdentifier.setDescription(this.signaturePolicyService.getSignaturePolicyDescription());
objectIdentifier.setDescription(policyService.getSignaturePolicyDescription());
IdentifierType identifier = objectIdentifier.addNewIdentifier();
identifier.setStringValue(this.signaturePolicyService.getSignaturePolicyIdentifier());
identifier.setStringValue(policyService.getSignaturePolicyIdentifier());
byte[] signaturePolicyDocumentData = this.signaturePolicyService.getSignaturePolicyDocument();
byte[] signaturePolicyDocumentData = policyService.getSignaturePolicyDocument();
DigestAlgAndValueType sigPolicyHash = signaturePolicyId.addNewSigPolicyHash();
setDigestAlgAndValue(sigPolicyHash, signaturePolicyDocumentData, this.hashAlgo);
setDigestAlgAndValue(sigPolicyHash, signaturePolicyDocumentData, this.signatureConfig.getDigestAlgo());
String signaturePolicyDownloadUrl = this.signaturePolicyService
.getSignaturePolicyDownloadUrl();
String signaturePolicyDownloadUrl = policyService.getSignaturePolicyDownloadUrl();
if (null != signaturePolicyDownloadUrl) {
SigPolicyQualifiersListType sigPolicyQualifiers = signaturePolicyId.addNewSigPolicyQualifiers();
AnyType sigPolicyQualifier = sigPolicyQualifiers.addNewSigPolicyQualifier();
@ -254,7 +246,7 @@ public class XAdESSignatureFacet implements SignatureFacet {
objects.add(xadesObject);
// add XAdES ds:Reference
DigestMethod digestMethod = signatureFactory.newDigestMethod(hashAlgo.xmlSignUri, null);
DigestMethod digestMethod = signatureFactory.newDigestMethod(this.signatureConfig.getDigestAlgo().xmlSignUri, null);
List<Transform> transforms = new ArrayList<Transform>();
Transform exclusiveTransform = signatureFactory
.newTransform(CanonicalizationMethod.INCLUSIVE,

View File

@ -26,16 +26,12 @@ package org.apache.poi.poifs.crypt.dsig.services;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.List;
import javax.xml.crypto.MarshalException;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.poi.poifs.crypt.dsig.spi.AddressDTO;
import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo;
import org.apache.poi.poifs.crypt.dsig.spi.IdentityDTO;
import org.apache.xmlbeans.XmlException;
import org.w3c.dom.Document;
@ -47,45 +43,17 @@ import org.w3c.dom.Document;
*/
public interface SignatureService {
/**
* Gives back the digest algorithm to be used for construction of the digest
* infos of the preSign method. Return a digest algorithm here if you want
* to let the client sign some locally stored files. Return
* <code>null</code> if no pre-sign digest infos are required.
*
* @return the digest algorithm to be used when digesting local files.
* @see #preSign(List, List)
*/
String getFilesDigestAlgorithm();
/**
* Pre-sign callback method. Depending on the configuration some parameters
* are passed. The returned value will be signed by the eID Applet.
*
* <p>
* TODO: service must be able to throw some exception on failure.
* </p>
*
* @param digestInfos
* the optional list of digest infos.
* @param signingCertificateChain
* the optional list of certificates.
* @param identity
* the optional identity.
* @param address
* the optional identity address.
* @param photo
* the optional identity photo.
* @param timestamp
* the optional timestamp, defaults to now
* @return the digest to be signed.
* @throws NoSuchAlgorithmException
*/
DigestInfo preSign(Document document, List<DigestInfo> digestInfos,
PrivateKey privateKey,
List<X509Certificate> signingCertificateChain,
IdentityDTO identity, AddressDTO address, byte[] photo)
throws NoSuchAlgorithmException;
DigestInfo preSign(Document document, List<DigestInfo> digestInfos)
throws NoSuchAlgorithmException;
/**
* Post-sign callback method. Received the signature value. Depending on the
@ -95,7 +63,6 @@ public interface SignatureService {
* @param signingCertificateChain
* the optional chain of signing certificates.
*/
void postSign(Document document, byte[] signatureValue,
List<X509Certificate> signingCertificateChain)
throws IOException, MarshalException, ParserConfigurationException, XmlException;
void postSign(Document document, byte[] signatureValue)
throws IOException, MarshalException, ParserConfigurationException, XmlException;
}

View File

@ -37,11 +37,8 @@ import java.security.InvalidAlgorithmParameterException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -79,16 +76,10 @@ import org.apache.poi.openxml4j.opc.PackagingURIHelper;
import org.apache.poi.openxml4j.opc.TargetMode;
import org.apache.poi.poifs.crypt.CryptoFunctions;
import org.apache.poi.poifs.crypt.HashAlgorithm;
import org.apache.poi.poifs.crypt.dsig.OOXMLURIDereferencer;
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
import org.apache.poi.poifs.crypt.dsig.facets.KeyInfoSignatureFacet;
import org.apache.poi.poifs.crypt.dsig.facets.OOXMLSignatureFacet;
import org.apache.poi.poifs.crypt.dsig.facets.Office2010SignatureFacet;
import org.apache.poi.poifs.crypt.dsig.SignatureInfoConfig;
import org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet;
import org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet;
import org.apache.poi.poifs.crypt.dsig.spi.AddressDTO;
import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo;
import org.apache.poi.poifs.crypt.dsig.spi.IdentityDTO;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.xml.security.signature.XMLSignature;
@ -112,43 +103,23 @@ import org.xml.sax.SAXException;
public class XmlSignatureService implements SignatureService {
private static final POILogger LOG = POILogFactory.getLogger(XmlSignatureService.class);
protected final List<SignatureFacet> signatureFacets;
protected SignatureInfoConfig signatureConfig;
private String signatureNamespacePrefix;
private String signatureId = "idPackageSignature";
private final HashAlgorithm hashAlgo;
private final OPCPackage opcPackage;
// private SignatureDocument sigDoc;
private XAdESSignatureFacet xadesSignatureFacet;
/**
* Main constructor.
*/
public XmlSignatureService(HashAlgorithm digestAlgo, OPCPackage opcPackage) {
this.signatureFacets = new ArrayList<SignatureFacet>();
public XmlSignatureService(SignatureInfoConfig signatureConfig) {
this.signatureNamespacePrefix = null;
this.hashAlgo = digestAlgo;
this.opcPackage = opcPackage;
// this.sigDoc = null;
this.signatureConfig = signatureConfig;
}
public void initFacets(Date clock) {
if (clock == null) clock = new Date();
addSignatureFacet(new OOXMLSignatureFacet(this, clock, hashAlgo));
addSignatureFacet(new KeyInfoSignatureFacet(true, false, false));
this.xadesSignatureFacet = new XAdESSignatureFacet(clock, hashAlgo, null);
this.xadesSignatureFacet.setIdSignedProperties("idSignedProperties");
this.xadesSignatureFacet.setSignaturePolicyImplied(true);
/*
* Work-around for Office 2010.
*/
this.xadesSignatureFacet.setIssuerNameNoReverseOrder(true);
addSignatureFacet(this.xadesSignatureFacet);
addSignatureFacet(new Office2010SignatureFacet());
public SignatureInfoConfig getSignatureConfig() {
return signatureConfig;
}
/**
* Sets the signature Id attribute value used to create the XML signature. A
* <code>null</code> value will trigger an automatically generated signature
@ -170,39 +141,6 @@ public class XmlSignatureService implements SignatureService {
this.signatureNamespacePrefix = signatureNamespacePrefix;
}
/**
* Adds a signature facet to this XML signature service.
*
* @param signatureFacet
*/
public void addSignatureFacet(SignatureFacet... signatureFacets) {
for (SignatureFacet sf : signatureFacets) {
this.signatureFacets.add(sf);
}
}
/**
* Gives back the signature digest algorithm. Allowed values are SHA-1,
* SHA-256, SHA-384, SHA-512, RIPEND160. The default algorithm is SHA-1.
* Override this method to select another signature digest algorithm.
*
* @return
*/
protected HashAlgorithm getSignatureDigestAlgorithm() {
return null != this.hashAlgo ? this.hashAlgo : HashAlgorithm.sha1;
}
/**
* Override this method to change the URI dereferener used by the signing
* engine.
*
* @return
*/
protected URIDereferencer getURIDereferencer() {
OPCPackage ooxmlDocument = getOfficeOpenXMLDocument();
return new OOXMLURIDereferencer(ooxmlDocument);
}
/**
* Gives back the human-readable description of what the citizen will be
* signing. The default value is "XML Document". Override this method to
@ -214,17 +152,6 @@ public class XmlSignatureService implements SignatureService {
return "Office OpenXML Document";
}
/**
* Gives back the URL of the OOXML to be signed.
*
* @return
*/
public OPCPackage getOfficeOpenXMLDocument() {
return opcPackage;
}
/**
* Gives back the output stream to which to write the signed XML document.
*
@ -232,19 +159,16 @@ public class XmlSignatureService implements SignatureService {
*/
// protected abstract OutputStream getSignedDocumentOutputStream();
@Override
public DigestInfo preSign(Document document, List<DigestInfo> digestInfos,
PrivateKey key,
List<X509Certificate> signingCertificateChain,
IdentityDTO identity, AddressDTO address, byte[] photo)
public DigestInfo preSign(Document document, List<DigestInfo> digestInfos)
throws NoSuchAlgorithmException {
SignatureInfo.initXmlProvider();
LOG.log(POILogger.DEBUG, "preSign");
HashAlgorithm hashAlgo = getSignatureDigestAlgorithm();
HashAlgorithm hashAlgo = this.signatureConfig.getDigestAlgo();
byte[] digestValue;
try {
digestValue = getXmlSignatureDigestValue(document, hashAlgo, digestInfos, key, signingCertificateChain);
digestValue = getXmlSignatureDigestValue(document, digestInfos);
} catch (Exception e) {
throw new RuntimeException("XML signature error: " + e.getMessage(), e);
}
@ -254,7 +178,7 @@ public class XmlSignatureService implements SignatureService {
}
@Override
public void postSign(Document document, byte[] signatureValue, List<X509Certificate> signingCertificateChain)
public void postSign(Document document, byte[] signatureValue)
throws IOException, MarshalException, ParserConfigurationException, XmlException {
LOG.log(POILogger.DEBUG, "postSign");
SignatureInfo.initXmlProvider();
@ -278,8 +202,8 @@ public class XmlSignatureService implements SignatureService {
/*
* Allow signature facets to inject their own stuff.
*/
for (SignatureFacet signatureFacet : this.signatureFacets) {
signatureFacet.postSign(document, signingCertificateChain);
for (SignatureFacet signatureFacet : this.signatureConfig.getSignatureFacets()) {
signatureFacet.postSign(document, this.signatureConfig.getSigningCertificateChain());
}
registerIds(document);
@ -287,10 +211,7 @@ public class XmlSignatureService implements SignatureService {
}
@SuppressWarnings("unchecked")
private byte[] getXmlSignatureDigestValue(Document document, HashAlgorithm hashAlgo,
List<DigestInfo> digestInfos,
PrivateKey privateKey,
List<X509Certificate> signingCertificateChain)
private byte[] getXmlSignatureDigestValue(Document document, List<DigestInfo> digestInfos)
throws ParserConfigurationException, NoSuchAlgorithmException,
InvalidAlgorithmParameterException, MarshalException,
javax.xml.crypto.dsig.XMLSignatureException,
@ -321,8 +242,8 @@ public class XmlSignatureService implements SignatureService {
/*
* Signature context construction.
*/
XMLSignContext xmlSignContext = new DOMSignContext(privateKey, document);
URIDereferencer uriDereferencer = getURIDereferencer();
XMLSignContext xmlSignContext = new DOMSignContext(this.signatureConfig.getKey(), document);
URIDereferencer uriDereferencer = this.signatureConfig.getUriDereferencer();
if (null != uriDereferencer) {
xmlSignContext.setURIDereferencer(uriDereferencer);
}
@ -354,15 +275,15 @@ public class XmlSignatureService implements SignatureService {
localSignatureId = "xmldsig-" + UUID.randomUUID().toString();
}
List<XMLObject> objects = new ArrayList<XMLObject>();
for (SignatureFacet signatureFacet : this.signatureFacets) {
for (SignatureFacet signatureFacet : this.signatureConfig.getSignatureFacets()) {
LOG.log(POILogger.DEBUG, "invoking signature facet: " + signatureFacet.getClass().getSimpleName());
signatureFacet.preSign(document, signatureFactory, localSignatureId, signingCertificateChain, references, objects);
signatureFacet.preSign(document, signatureFactory, localSignatureId, this.signatureConfig.getSigningCertificateChain(), references, objects);
}
/*
* ds:SignedInfo
*/
SignatureMethod signatureMethod = signatureFactory.newSignatureMethod(getSignatureMethod(hashAlgo), null);
SignatureMethod signatureMethod = signatureFactory.newSignatureMethod(getSignatureMethod(this.signatureConfig.getDigestAlgo()), null);
CanonicalizationMethod canonicalizationMethod = signatureFactory
.newCanonicalizationMethod(getCanonicalizationMethod(),
(C14NMethodParameterSpec) null);
@ -432,7 +353,7 @@ public class XmlSignatureService implements SignatureService {
* usage.
*/
MessageDigest jcaMessageDigest = CryptoFunctions.getMessageDigest(hashAlgo);
MessageDigest jcaMessageDigest = CryptoFunctions.getMessageDigest(this.signatureConfig.getDigestAlgo());
byte[] digestValue = jcaMessageDigest.digest(octets);
return digestValue;
}
@ -443,7 +364,7 @@ public class XmlSignatureService implements SignatureService {
*
* @param doc
*/
public void registerIds(Document doc) {
public static void registerIds(Document doc) {
NodeList nl = doc.getElementsByTagNameNS(XmlDSigNS, "Object");
registerIdAttribute(nl);
nl = doc.getElementsByTagNameNS("http://uri.etsi.org/01903/v1.3.2#", "SignedProperties");
@ -492,19 +413,6 @@ public class XmlSignatureService implements SignatureService {
throw new RuntimeException("unsupported sign algo: " + hashAlgo);
}
/**
* Gives back the used XAdES signature facet.
*
* @return
*/
protected XAdESSignatureFacet getXAdESSignatureFacet() {
return this.xadesSignatureFacet;
}
public String getFilesDigestAlgorithm() {
return null;
}
protected String getCanonicalizationMethod() {
return CanonicalizationMethod.INCLUSIVE;
}
@ -512,7 +420,7 @@ public class XmlSignatureService implements SignatureService {
protected void writeDocument(Document document) throws IOException, XmlException {
XmlOptions xo = new XmlOptions();
Map<String,String> namespaceMap = new HashMap<String,String>();
for (SignatureFacet sf : this.signatureFacets) {
for (SignatureFacet sf : this.signatureConfig.getSignatureFacets()) {
Map<String,String> sfm = sf.getNamespacePrefixMapping();
if (sfm != null) {
namespaceMap.putAll(sfm);
@ -527,7 +435,7 @@ public class XmlSignatureService implements SignatureService {
* Copy the original OOXML content to the signed OOXML package. During
* copying some files need to changed.
*/
OPCPackage pkg = this.getOfficeOpenXMLDocument();
OPCPackage pkg = this.signatureConfig.getOpcPackage();
PackagePartName sigPartName, sigsPartName;
try {

View File

@ -52,15 +52,14 @@ import javax.xml.crypto.KeySelector;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMValidateContext;
import javax.xml.parsers.DocumentBuilderFactory;
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.SignatureInfo;
import org.apache.poi.poifs.crypt.dsig.SignatureInfoConfig;
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.SignaturePolicyService;
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;
@ -208,13 +207,26 @@ public class TestSignatureInfo {
OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE);
initKeyPair("Test", "CN=Test");
final X509CRL crl = PkiTestUtils.generateCrl(x509, keyPair.getPrivate());
// setup
EnvelopedSignatureFacet envelopedSignatureFacet = new EnvelopedSignatureFacet();
KeyInfoSignatureFacet keyInfoSignatureFacet = new KeyInfoSignatureFacet(true, false, false);
SignaturePolicyService signaturePolicyService = null;
XAdESSignatureFacet xadesSignatureFacet = new XAdESSignatureFacet(null, null, signaturePolicyService);
final X509CRL crl = PkiTestUtils.generateCrl(x509, keyPair.getPrivate());
SignatureInfoConfig signatureConfig = new SignatureInfoConfig();
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(true, false, false));
signatureConfig.addSignatureFacet(new XAdESSignatureFacet(signatureConfig));
// http://timestamping.edelweb.fr/service/tsp
// http://tsa.belgium.be/connect
@ -248,14 +260,6 @@ public class TestSignatureInfo {
timeStampService = tspService;
}
List<X509Certificate> certificateChain = new ArrayList<X509Certificate>();
/*
* We need at least 2 certificates for the XAdES-C complete certificate
* refs construction.
*/
certificateChain.add(x509);
certificateChain.add(x509);
final RevocationData revocationData = new RevocationData();
revocationData.addCRL(crl);
OCSPResp ocspResp = PkiTestUtils.createOcspResp(x509, false,
@ -270,17 +274,12 @@ public class TestSignatureInfo {
XAdESXLSignatureFacet xadesXLSignatureFacet = new XAdESXLSignatureFacet(
timeStampService, revocationDataService);
XmlSignatureService testedInstance = new XmlSignatureService(HashAlgorithm.sha1, pkg);
testedInstance.addSignatureFacet(envelopedSignatureFacet, keyInfoSignatureFacet,
xadesSignatureFacet, xadesXLSignatureFacet);
XmlSignatureService testedInstance = new XmlSignatureService(signatureConfig);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document document = dbf.newDocumentBuilder().newDocument();
Document document = DocumentHelper.createDocument();
// operate
DigestInfo digestInfo = testedInstance.preSign(document, null, keyPair.getPrivate(), certificateChain, null, null, null);
DigestInfo digestInfo = testedInstance.preSign(document, null);
// verify
assertNotNull(digestInfo);
@ -301,7 +300,7 @@ public class TestSignatureInfo {
byte[] signatureValue = SignatureInfo.signDigest(keyPair.getPrivate(), HashAlgorithm.sha1, digestInfo.digestValue);
// Operate: postSign
testedInstance.postSign(document, signatureValue, certificateChain);
testedInstance.postSign(document, signatureValue);
DOMValidateContext domValidateContext = new DOMValidateContext(
KeySelector.singletonKeySelector(keyPair.getPublic()),
@ -332,15 +331,22 @@ public class TestSignatureInfo {
}
private OPCPackage sign(OPCPackage pkgCopy, String alias, String signerDn, int signerCount) throws Exception {
XmlSignatureService signatureService = new XmlSignatureService(HashAlgorithm.sha1, pkgCopy);
signatureService.initFacets(cal.getTime());
initKeyPair(alias, signerDn);
SignatureInfoConfig signatureConfig = new SignatureInfoConfig();
signatureConfig.setKey(keyPair.getPrivate());
signatureConfig.setSigningCertificateChain(Collections.singletonList(x509));
signatureConfig.setExecutionTime(cal.getTime());
signatureConfig.setDigestAlgo(HashAlgorithm.sha1);
signatureConfig.setOpcPackage(pkgCopy);
signatureConfig.addDefaultFacets();
XmlSignatureService signatureService = new XmlSignatureService(signatureConfig);
Document document = DocumentHelper.createDocument();
// operate
List<X509Certificate> x509Chain = Collections.singletonList(x509);
DigestInfo digestInfo = signatureService.preSign(document, null, keyPair.getPrivate(), x509Chain, null, null, null);
DigestInfo digestInfo = signatureService.preSign(document, null);
// verify
assertNotNull(digestInfo);
@ -354,7 +360,7 @@ public class TestSignatureInfo {
byte[] signatureValue = SignatureInfo.signDigest(keyPair.getPrivate(), HashAlgorithm.sha1, digestInfo.digestValue);
// operate: postSign
signatureService.postSign(document, signatureValue, Collections.singletonList(x509));
signatureService.postSign(document, signatureValue);
// verify: signature
SignatureInfo si = new SignatureInfo(pkgCopy);