removed HorribleProxy
added current version of BouncyCastle and xmlsec (using xmlsec instead of jdk internal classes, because of interoperabiltiy with e.g. IBM JDK) heaps of changes because of above git-svn-id: https://svn.apache.org/repos/asf/poi/branches/xml_signature@1620230 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
d0cc2e4267
commit
687194fd91
@ -3,7 +3,7 @@ package org.apache.poi.poifs.crypt.dsig.facets;
|
|||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.LinkedList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ import javax.xml.crypto.dsig.XMLSignatureFactory;
|
|||||||
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
|
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
|
||||||
|
|
||||||
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
||||||
import org.w3.x2000.x09.xmldsig.SignatureType;
|
import org.w3c.dom.Document;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signature Facet implementation to create enveloped signatures.
|
* Signature Facet implementation to create enveloped signatures.
|
||||||
@ -47,13 +47,13 @@ public class EnvelopedSignatureFacet implements SignatureFacet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postSign(SignatureType signatureElement
|
public void postSign(Document document, List<X509Certificate> signingCertificateChain) {
|
||||||
, List<X509Certificate> signingCertificateChain) {
|
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void preSign(XMLSignatureFactory signatureFactory,
|
public void preSign(Document document,
|
||||||
|
XMLSignatureFactory signatureFactory,
|
||||||
String signatureId,
|
String signatureId,
|
||||||
List<X509Certificate> signingCertificateChain,
|
List<X509Certificate> signingCertificateChain,
|
||||||
List<Reference> references, List<XMLObject> objects)
|
List<Reference> references, List<XMLObject> objects)
|
||||||
@ -61,7 +61,7 @@ public class EnvelopedSignatureFacet implements SignatureFacet {
|
|||||||
DigestMethod digestMethod = signatureFactory.newDigestMethod(
|
DigestMethod digestMethod = signatureFactory.newDigestMethod(
|
||||||
this.hashAlgo.xmlSignUri, null);
|
this.hashAlgo.xmlSignUri, null);
|
||||||
|
|
||||||
List<Transform> transforms = new LinkedList<Transform>();
|
List<Transform> transforms = new ArrayList<Transform>();
|
||||||
Transform envelopedTransform = signatureFactory
|
Transform envelopedTransform = signatureFactory
|
||||||
.newTransform(CanonicalizationMethod.ENVELOPED,
|
.newTransform(CanonicalizationMethod.ENVELOPED,
|
||||||
(TransformParameterSpec) null);
|
(TransformParameterSpec) null);
|
||||||
|
@ -24,19 +24,21 @@
|
|||||||
|
|
||||||
package org.apache.poi.poifs.crypt.dsig.facets;
|
package org.apache.poi.poifs.crypt.dsig.facets;
|
||||||
|
|
||||||
|
import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlDSigNS;
|
||||||
|
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.Key;
|
import java.security.Key;
|
||||||
import java.security.KeyException;
|
import java.security.KeyException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.Provider;
|
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.xml.crypto.MarshalException;
|
import javax.xml.crypto.MarshalException;
|
||||||
import javax.xml.crypto.dom.DOMCryptoContext;
|
import javax.xml.crypto.dom.DOMCryptoContext;
|
||||||
|
import javax.xml.crypto.dom.DOMStructure;
|
||||||
import javax.xml.crypto.dsig.Reference;
|
import javax.xml.crypto.dsig.Reference;
|
||||||
import javax.xml.crypto.dsig.XMLObject;
|
import javax.xml.crypto.dsig.XMLObject;
|
||||||
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
||||||
@ -46,13 +48,14 @@ import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
|
|||||||
import javax.xml.crypto.dsig.keyinfo.KeyValue;
|
import javax.xml.crypto.dsig.keyinfo.KeyValue;
|
||||||
import javax.xml.crypto.dsig.keyinfo.X509Data;
|
import javax.xml.crypto.dsig.keyinfo.X509Data;
|
||||||
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxy;
|
import org.apache.jcp.xml.dsig.internal.dom.DOMKeyInfo;
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DOMKeyInfoIf;
|
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
|
||||||
import org.apache.poi.util.POILogFactory;
|
import org.apache.poi.util.POILogFactory;
|
||||||
import org.apache.poi.util.POILogger;
|
import org.apache.poi.util.POILogger;
|
||||||
import org.w3.x2000.x09.xmldsig.ObjectType;
|
import org.w3c.dom.Document;
|
||||||
import org.w3.x2000.x09.xmldsig.SignatureType;
|
import org.w3c.dom.Element;
|
||||||
import org.w3c.dom.Node;
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signature Facet implementation that adds ds:KeyInfo to the XML signature.
|
* Signature Facet implementation that adds ds:KeyInfo to the XML signature.
|
||||||
@ -84,34 +87,27 @@ public class KeyInfoSignatureFacet implements SignatureFacet {
|
|||||||
this.includeKeyValue = includeKeyValue;
|
this.includeKeyValue = includeKeyValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void postSign(SignatureType signatureElement,
|
@Override
|
||||||
List<X509Certificate> signingCertificateChain) {
|
public void postSign(Document document, List<X509Certificate> signingCertificateChain)
|
||||||
|
throws MarshalException {
|
||||||
LOG.log(POILogger.DEBUG, "postSign");
|
LOG.log(POILogger.DEBUG, "postSign");
|
||||||
|
|
||||||
List<ObjectType> objList = signatureElement.getObjectList();
|
NodeList nl = document.getElementsByTagNameNS(XmlDSigNS, "Object");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure we insert right after the ds:SignatureValue element, just
|
* Make sure we insert right after the ds:SignatureValue element, just
|
||||||
* before the first ds:Object element.
|
* before the first ds:Object element.
|
||||||
*/
|
*/
|
||||||
Node nextSibling = (objList.isEmpty()) ? null : objList.get(0).getDomNode();
|
Node nextSibling = (nl.getLength() == 0) ? null : nl.item(0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Construct the ds:KeyInfo element using JSR 105.
|
* Construct the ds:KeyInfo element using JSR 105.
|
||||||
*/
|
*/
|
||||||
String providerName = System.getProperty("jsr105Provider", "org.jcp.xml.dsig.internal.dom.XMLDSigRI");
|
KeyInfoFactory keyInfoFactory = SignatureInfo.getKeyInfoFactory();
|
||||||
Provider xmlDSigProv;
|
List<Object> x509DataObjects = new ArrayList<Object>();
|
||||||
try {
|
|
||||||
xmlDSigProv = (Provider) Class.forName(providerName).newInstance();
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("JRE doesn't support default xml signature provider - set jsr105Provider system property!", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyInfoFactory keyInfoFactory = KeyInfoFactory.getInstance("DOM", xmlDSigProv);
|
|
||||||
List<Object> x509DataObjects = new LinkedList<Object>();
|
|
||||||
X509Certificate signingCertificate = signingCertificateChain.get(0);
|
X509Certificate signingCertificate = signingCertificateChain.get(0);
|
||||||
|
|
||||||
List<Object> keyInfoContent = new LinkedList<Object>();
|
List<Object> keyInfoContent = new ArrayList<Object>();
|
||||||
|
|
||||||
if (this.includeKeyValue) {
|
if (this.includeKeyValue) {
|
||||||
KeyValue keyValue;
|
KeyValue keyValue;
|
||||||
@ -130,24 +126,17 @@ public class KeyInfoSignatureFacet implements SignatureFacet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.includeEntireCertificateChain) {
|
if (this.includeEntireCertificateChain) {
|
||||||
for (X509Certificate certificate : signingCertificateChain) {
|
x509DataObjects.addAll(signingCertificateChain);
|
||||||
x509DataObjects.add(certificate);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
x509DataObjects.add(signingCertificate);
|
x509DataObjects.add(signingCertificate);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (false == x509DataObjects.isEmpty()) {
|
if (!x509DataObjects.isEmpty()) {
|
||||||
X509Data x509Data = keyInfoFactory.newX509Data(x509DataObjects);
|
X509Data x509Data = keyInfoFactory.newX509Data(x509DataObjects);
|
||||||
keyInfoContent.add(x509Data);
|
keyInfoContent.add(x509Data);
|
||||||
}
|
}
|
||||||
KeyInfo keyInfo = keyInfoFactory.newKeyInfo(keyInfoContent);
|
KeyInfo keyInfo = keyInfoFactory.newKeyInfo(keyInfoContent);
|
||||||
DOMKeyInfoIf domKeyInfo;
|
DOMKeyInfo domKeyInfo = (DOMKeyInfo)keyInfo;
|
||||||
try {
|
|
||||||
domKeyInfo = HorribleProxy.newProxy(DOMKeyInfoIf.class, keyInfo);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("DOMKeyInfo instance error: " + e.getMessage(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
Key key = new Key() {
|
Key key = new Key() {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
@ -165,18 +154,27 @@ public class KeyInfoSignatureFacet implements SignatureFacet {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
DOMSignContext domSignContext = new DOMSignContext(key, signatureElement.getDomNode());
|
Element n = document.getDocumentElement();
|
||||||
|
DOMSignContext domSignContext = new DOMSignContext(key, n, nextSibling);
|
||||||
DOMCryptoContext domCryptoContext = domSignContext;
|
DOMCryptoContext domCryptoContext = domSignContext;
|
||||||
String signatureNamespacePrefix = "xd";
|
domCryptoContext.putNamespacePrefix(XmlDSigNS, "xd");
|
||||||
try {
|
DOMStructure domStructure = new DOMStructure(n);
|
||||||
domKeyInfo.marshal(signatureElement.getDomNode(), nextSibling,
|
// how to set nextSibling??? - marshal is ignoring nextSibling in DOMSignContext
|
||||||
signatureNamespacePrefix, domCryptoContext);
|
domKeyInfo.marshal(domStructure, domCryptoContext);
|
||||||
} catch (MarshalException e) {
|
|
||||||
throw new RuntimeException("marshall error: " + e.getMessage(), e);
|
// move keyinfo into the right place
|
||||||
|
if (nextSibling != null) {
|
||||||
|
NodeList kiNl = document.getElementsByTagNameNS(XmlDSigNS, "KeyInfo");
|
||||||
|
if (kiNl.getLength() != 1) {
|
||||||
|
throw new RuntimeException("KeyInfo wasn't set");
|
||||||
|
}
|
||||||
|
nextSibling.getParentNode().insertBefore(kiNl.item(0), nextSibling);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void preSign(XMLSignatureFactory signatureFactory,
|
@Override
|
||||||
|
public void preSign(Document document,
|
||||||
|
XMLSignatureFactory signatureFactory,
|
||||||
String signatureId,
|
String signatureId,
|
||||||
List<X509Certificate> signingCertificateChain,
|
List<X509Certificate> signingCertificateChain,
|
||||||
List<Reference> references,
|
List<Reference> references,
|
||||||
@ -187,7 +185,7 @@ public class KeyInfoSignatureFacet implements SignatureFacet {
|
|||||||
|
|
||||||
public Map<String,String> getNamespacePrefixMapping() {
|
public Map<String,String> getNamespacePrefixMapping() {
|
||||||
Map<String,String> map = new HashMap<String,String>();
|
Map<String,String> map = new HashMap<String,String>();
|
||||||
// map.put("xd", "http://www.w3.org/2000/09/xmldsig#");
|
// map.put("xd", XmlDSigNS);
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
|
|
||||||
package org.apache.poi.poifs.crypt.dsig.facets;
|
package org.apache.poi.poifs.crypt.dsig.facets;
|
||||||
|
|
||||||
|
import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlDSigNS;
|
||||||
|
import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlNS;
|
||||||
import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.setPrefix;
|
import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.setPrefix;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -38,7 +40,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -71,15 +72,13 @@ import org.apache.poi.poifs.crypt.HashAlgorithm;
|
|||||||
import org.apache.poi.poifs.crypt.dsig.services.RelationshipTransformService;
|
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.RelationshipTransformService.RelationshipTransformParameterSpec;
|
||||||
import org.apache.poi.poifs.crypt.dsig.services.XmlSignatureService;
|
import org.apache.poi.poifs.crypt.dsig.services.XmlSignatureService;
|
||||||
import org.apache.poi.poifs.crypt.dsig.spi.Constants;
|
|
||||||
import org.apache.poi.util.POILogFactory;
|
import org.apache.poi.util.POILogFactory;
|
||||||
import org.apache.poi.util.POILogger;
|
import org.apache.poi.util.POILogger;
|
||||||
import org.apache.xmlbeans.XmlException;
|
import org.apache.xmlbeans.XmlException;
|
||||||
import org.openxmlformats.schemas.xpackage.x2006.digitalSignature.CTSignatureTime;
|
import org.openxmlformats.schemas.xpackage.x2006.digitalSignature.CTSignatureTime;
|
||||||
import org.openxmlformats.schemas.xpackage.x2006.digitalSignature.SignatureTimeDocument;
|
import org.openxmlformats.schemas.xpackage.x2006.digitalSignature.SignatureTimeDocument;
|
||||||
import org.w3.x2000.x09.xmldsig.SignatureType;
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
import org.w3c.dom.Node;
|
|
||||||
|
|
||||||
import com.microsoft.schemas.office.x2006.digsig.CTSignatureInfoV1;
|
import com.microsoft.schemas.office.x2006.digsig.CTSignatureInfoV1;
|
||||||
import com.microsoft.schemas.office.x2006.digsig.SignatureInfoV1Document;
|
import com.microsoft.schemas.office.x2006.digsig.SignatureInfoV1Document;
|
||||||
@ -112,50 +111,43 @@ public class OOXMLSignatureFacet implements SignatureFacet {
|
|||||||
this.hashAlgo = (hashAlgo == null ? HashAlgorithm.sha1 : hashAlgo);
|
this.hashAlgo = (hashAlgo == null ? HashAlgorithm.sha1 : hashAlgo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void preSign(XMLSignatureFactory signatureFactory,
|
@Override
|
||||||
|
public void preSign(Document document,
|
||||||
|
XMLSignatureFactory signatureFactory,
|
||||||
String signatureId,
|
String signatureId,
|
||||||
List<X509Certificate> signingCertificateChain,
|
List<X509Certificate> signingCertificateChain,
|
||||||
List<Reference> references, List<XMLObject> objects)
|
List<Reference> references, List<XMLObject> objects)
|
||||||
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
|
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, IOException, URISyntaxException, XmlException {
|
||||||
LOG.log(POILogger.DEBUG, "pre sign");
|
LOG.log(POILogger.DEBUG, "pre sign");
|
||||||
addManifestObject(signatureFactory, signatureId, references, objects);
|
addManifestObject(document, signatureFactory, signatureId, references, objects);
|
||||||
addSignatureInfo(signatureFactory, signatureId, references, objects);
|
addSignatureInfo(document, signatureFactory, signatureId, references, objects);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addManifestObject(XMLSignatureFactory signatureFactory,
|
private void addManifestObject(Document document,
|
||||||
|
XMLSignatureFactory signatureFactory,
|
||||||
String signatureId, List<Reference> references,
|
String signatureId, List<Reference> references,
|
||||||
List<XMLObject> objects) throws NoSuchAlgorithmException,
|
List<XMLObject> objects) throws NoSuchAlgorithmException,
|
||||||
InvalidAlgorithmParameterException {
|
InvalidAlgorithmParameterException, IOException, URISyntaxException, XmlException {
|
||||||
Manifest manifest = constructManifest(signatureFactory);
|
|
||||||
|
List<Reference> manifestReferences = new ArrayList<Reference>();
|
||||||
|
addManifestReferences(signatureFactory, manifestReferences);
|
||||||
|
Manifest manifest = signatureFactory.newManifest(manifestReferences);
|
||||||
|
|
||||||
String objectId = "idPackageObject"; // really has to be this value.
|
String objectId = "idPackageObject"; // really has to be this value.
|
||||||
List<XMLStructure> objectContent = new LinkedList<XMLStructure>();
|
List<XMLStructure> objectContent = new ArrayList<XMLStructure>();
|
||||||
objectContent.add(manifest);
|
objectContent.add(manifest);
|
||||||
|
|
||||||
addSignatureTime(signatureFactory, signatureId, objectContent);
|
addSignatureTime(document, signatureFactory, signatureId, objectContent);
|
||||||
|
|
||||||
objects.add(signatureFactory.newXMLObject(objectContent, objectId,
|
XMLObject xo = signatureFactory.newXMLObject(objectContent, objectId, null, null);
|
||||||
null, null));
|
objects.add(xo);
|
||||||
|
|
||||||
DigestMethod digestMethod = signatureFactory.newDigestMethod(this.hashAlgo.xmlSignUri, null);
|
DigestMethod digestMethod = signatureFactory.newDigestMethod(this.hashAlgo.xmlSignUri, null);
|
||||||
Reference reference = signatureFactory.newReference("#" + objectId,
|
Reference reference = signatureFactory.newReference
|
||||||
digestMethod, null, "http://www.w3.org/2000/09/xmldsig#Object",
|
("#" + objectId, digestMethod, null, XmlDSigNS+"Object", null);
|
||||||
null);
|
|
||||||
references.add(reference);
|
references.add(reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Manifest constructManifest(XMLSignatureFactory signatureFactory)
|
|
||||||
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
|
|
||||||
List<Reference> manifestReferences = new ArrayList<Reference>();
|
|
||||||
|
|
||||||
try {
|
|
||||||
addManifestReferences(signatureFactory, manifestReferences);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("error: " + e.getMessage(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return signatureFactory.newManifest(manifestReferences);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addManifestReferences(XMLSignatureFactory signatureFactory, List<Reference> manifestReferences)
|
private void addManifestReferences(XMLSignatureFactory signatureFactory, List<Reference> manifestReferences)
|
||||||
throws IOException, NoSuchAlgorithmException,
|
throws IOException, NoSuchAlgorithmException,
|
||||||
InvalidAlgorithmParameterException, URISyntaxException, XmlException {
|
InvalidAlgorithmParameterException, URISyntaxException, XmlException {
|
||||||
@ -223,7 +215,7 @@ public class OOXMLSignatureFacet implements SignatureFacet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (parameterSpec.hasSourceIds()) {
|
if (parameterSpec.hasSourceIds()) {
|
||||||
List<Transform> transforms = new LinkedList<Transform>();
|
List<Transform> transforms = new ArrayList<Transform>();
|
||||||
transforms.add(signatureFactory.newTransform(
|
transforms.add(signatureFactory.newTransform(
|
||||||
RelationshipTransformService.TRANSFORM_URI,
|
RelationshipTransformService.TRANSFORM_URI,
|
||||||
parameterSpec));
|
parameterSpec));
|
||||||
@ -239,7 +231,8 @@ public class OOXMLSignatureFacet implements SignatureFacet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void addSignatureTime(XMLSignatureFactory signatureFactory,
|
private void addSignatureTime(Document document,
|
||||||
|
XMLSignatureFactory signatureFactory,
|
||||||
String signatureId,
|
String signatureId,
|
||||||
List<XMLStructure> objectContent) {
|
List<XMLStructure> objectContent) {
|
||||||
/*
|
/*
|
||||||
@ -256,15 +249,15 @@ public class OOXMLSignatureFacet implements SignatureFacet {
|
|||||||
ctTime.setValue(nowStr);
|
ctTime.setValue(nowStr);
|
||||||
|
|
||||||
// TODO: find better method to have xmlbeans + export the prefix
|
// TODO: find better method to have xmlbeans + export the prefix
|
||||||
Node n = ctTime.getDomNode();
|
Element n = (Element)document.importNode(ctTime.getDomNode(),true);
|
||||||
setPrefix(ctTime, PackageNamespaces.DIGITAL_SIGNATURE, "mdssi");
|
setPrefix(n, PackageNamespaces.DIGITAL_SIGNATURE, "mdssi");
|
||||||
|
|
||||||
List<XMLStructure> signatureTimeContent = new LinkedList<XMLStructure>();
|
List<XMLStructure> signatureTimeContent = new ArrayList<XMLStructure>();
|
||||||
signatureTimeContent.add(new DOMStructure(n));
|
signatureTimeContent.add(new DOMStructure(n));
|
||||||
SignatureProperty signatureTimeSignatureProperty = signatureFactory
|
SignatureProperty signatureTimeSignatureProperty = signatureFactory
|
||||||
.newSignatureProperty(signatureTimeContent, "#" + signatureId,
|
.newSignatureProperty(signatureTimeContent, "#" + signatureId,
|
||||||
"idSignatureTime");
|
"idSignatureTime");
|
||||||
List<SignatureProperty> signaturePropertyContent = new LinkedList<SignatureProperty>();
|
List<SignatureProperty> signaturePropertyContent = new ArrayList<SignatureProperty>();
|
||||||
signaturePropertyContent.add(signatureTimeSignatureProperty);
|
signaturePropertyContent.add(signatureTimeSignatureProperty);
|
||||||
SignatureProperties signatureProperties = signatureFactory
|
SignatureProperties signatureProperties = signatureFactory
|
||||||
.newSignatureProperties(signaturePropertyContent,
|
.newSignatureProperties(signaturePropertyContent,
|
||||||
@ -272,43 +265,42 @@ public class OOXMLSignatureFacet implements SignatureFacet {
|
|||||||
objectContent.add(signatureProperties);
|
objectContent.add(signatureProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addSignatureInfo(XMLSignatureFactory signatureFactory,
|
private void addSignatureInfo(Document document,
|
||||||
|
XMLSignatureFactory signatureFactory,
|
||||||
String signatureId, List<Reference> references,
|
String signatureId, List<Reference> references,
|
||||||
List<XMLObject> objects) throws NoSuchAlgorithmException,
|
List<XMLObject> objects) throws NoSuchAlgorithmException,
|
||||||
InvalidAlgorithmParameterException {
|
InvalidAlgorithmParameterException {
|
||||||
List<XMLStructure> objectContent = new LinkedList<XMLStructure>();
|
List<XMLStructure> objectContent = new ArrayList<XMLStructure>();
|
||||||
|
|
||||||
SignatureInfoV1Document sigV1 = SignatureInfoV1Document.Factory.newInstance();
|
SignatureInfoV1Document sigV1 = SignatureInfoV1Document.Factory.newInstance();
|
||||||
CTSignatureInfoV1 ctSigV1 = sigV1.addNewSignatureInfoV1();
|
CTSignatureInfoV1 ctSigV1 = sigV1.addNewSignatureInfoV1();
|
||||||
ctSigV1.setManifestHashAlgorithm(hashAlgo.xmlSignUri);
|
ctSigV1.setManifestHashAlgorithm(hashAlgo.xmlSignUri);
|
||||||
Node n = ctSigV1.getDomNode();
|
Element n = (Element)document.importNode(ctSigV1.getDomNode(), true);
|
||||||
((Element)n).setAttributeNS(Constants.NamespaceSpecNS, "xmlns", "http://schemas.microsoft.com/office/2006/digsig");
|
n.setAttributeNS(XmlNS, "xmlns", "http://schemas.microsoft.com/office/2006/digsig");
|
||||||
|
|
||||||
List<XMLStructure> signatureInfoContent = new LinkedList<XMLStructure>();
|
List<XMLStructure> signatureInfoContent = new ArrayList<XMLStructure>();
|
||||||
signatureInfoContent.add(new DOMStructure(n));
|
signatureInfoContent.add(new DOMStructure(n));
|
||||||
SignatureProperty signatureInfoSignatureProperty = signatureFactory
|
SignatureProperty signatureInfoSignatureProperty = signatureFactory
|
||||||
.newSignatureProperty(signatureInfoContent, "#" + signatureId,
|
.newSignatureProperty(signatureInfoContent, "#" + signatureId,
|
||||||
"idOfficeV1Details");
|
"idOfficeV1Details");
|
||||||
|
|
||||||
List<SignatureProperty> signaturePropertyContent = new LinkedList<SignatureProperty>();
|
List<SignatureProperty> signaturePropertyContent = new ArrayList<SignatureProperty>();
|
||||||
signaturePropertyContent.add(signatureInfoSignatureProperty);
|
signaturePropertyContent.add(signatureInfoSignatureProperty);
|
||||||
SignatureProperties signatureProperties = signatureFactory
|
SignatureProperties signatureProperties = signatureFactory
|
||||||
.newSignatureProperties(signaturePropertyContent, null);
|
.newSignatureProperties(signaturePropertyContent, null);
|
||||||
objectContent.add(signatureProperties);
|
objectContent.add(signatureProperties);
|
||||||
|
|
||||||
String objectId = "idOfficeObject";
|
String objectId = "idOfficeObject";
|
||||||
objects.add(signatureFactory.newXMLObject(objectContent, objectId,
|
objects.add(signatureFactory.newXMLObject(objectContent, objectId, null, null));
|
||||||
null, null));
|
|
||||||
|
|
||||||
DigestMethod digestMethod = signatureFactory.newDigestMethod(this.hashAlgo.xmlSignUri, null);
|
DigestMethod digestMethod = signatureFactory.newDigestMethod(this.hashAlgo.xmlSignUri, null);
|
||||||
Reference reference = signatureFactory.newReference("#" + objectId,
|
Reference reference = signatureFactory.newReference
|
||||||
digestMethod, null, "http://www.w3.org/2000/09/xmldsig#Object",
|
("#" + objectId, digestMethod, null, XmlDSigNS+"Object", null);
|
||||||
null);
|
|
||||||
references.add(reference);
|
references.add(reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void postSign(SignatureType signatureElement,
|
@Override
|
||||||
List<X509Certificate> signingCertificateChain) {
|
public void postSign(Document document, List<X509Certificate> signingCertificateChain) {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,11 +34,13 @@ import javax.xml.crypto.dsig.Reference;
|
|||||||
import javax.xml.crypto.dsig.XMLObject;
|
import javax.xml.crypto.dsig.XMLObject;
|
||||||
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
||||||
|
|
||||||
import org.apache.xmlbeans.XmlObject;
|
import org.apache.xmlbeans.XmlException;
|
||||||
import org.etsi.uri.x01903.v13.QualifyingPropertiesType;
|
import org.etsi.uri.x01903.v13.QualifyingPropertiesType;
|
||||||
import org.etsi.uri.x01903.v13.UnsignedPropertiesType;
|
import org.etsi.uri.x01903.v13.UnsignedPropertiesType;
|
||||||
import org.etsi.uri.x01903.v13.UnsignedSignaturePropertiesType;
|
import org.etsi.uri.x01903.v13.UnsignedSignaturePropertiesType;
|
||||||
import org.w3.x2000.x09.xmldsig.SignatureType;
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Work-around for Office2010 to accept the XAdES-BES/EPES signature.
|
* Work-around for Office2010 to accept the XAdES-BES/EPES signature.
|
||||||
@ -51,7 +53,9 @@ import org.w3.x2000.x09.xmldsig.SignatureType;
|
|||||||
*/
|
*/
|
||||||
public class Office2010SignatureFacet implements SignatureFacet {
|
public class Office2010SignatureFacet implements SignatureFacet {
|
||||||
|
|
||||||
public void preSign(XMLSignatureFactory signatureFactory,
|
@Override
|
||||||
|
public void preSign(Document document,
|
||||||
|
XMLSignatureFactory signatureFactory,
|
||||||
String signatureId,
|
String signatureId,
|
||||||
List<X509Certificate> signingCertificateChain,
|
List<X509Certificate> signingCertificateChain,
|
||||||
List<Reference> references,
|
List<Reference> references,
|
||||||
@ -59,23 +63,18 @@ public class Office2010SignatureFacet implements SignatureFacet {
|
|||||||
) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
|
) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void postSign(SignatureType signatureElement, List<X509Certificate> signingCertificateChain) {
|
@Override
|
||||||
QualifyingPropertiesType qualProps = null;
|
public void postSign(Document document, List<X509Certificate> signingCertificateChain)
|
||||||
|
throws XmlException {
|
||||||
// check for XAdES-BES
|
// check for XAdES-BES
|
||||||
String qualPropXQuery =
|
NodeList nl = document.getElementsByTagNameNS("http://uri.etsi.org/01903/v1.3.2#", "QualifyingProperties");
|
||||||
"declare namespace xades='http://uri.etsi.org/01903/v1.3.2#'; "
|
if (nl.getLength() != 1) {
|
||||||
+ "declare namespace ds='http://www.w3.org/2000/09/xmldsig#'; "
|
|
||||||
+ "$this/ds:Object/xades:QualifyingProperties";
|
|
||||||
XmlObject xoList[] = signatureElement.selectPath(qualPropXQuery);
|
|
||||||
if (xoList.length == 1) {
|
|
||||||
qualProps = (QualifyingPropertiesType)xoList[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (qualProps == null) {
|
|
||||||
throw new IllegalArgumentException("no XAdES-BES extension present");
|
throw new IllegalArgumentException("no XAdES-BES extension present");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QualifyingPropertiesType qualProps =
|
||||||
|
QualifyingPropertiesType.Factory.parse(nl.item(0));
|
||||||
|
|
||||||
// create basic XML container structure
|
// create basic XML container structure
|
||||||
UnsignedPropertiesType unsignedProps = qualProps.getUnsignedProperties();
|
UnsignedPropertiesType unsignedProps = qualProps.getUnsignedProperties();
|
||||||
if (unsignedProps == null) {
|
if (unsignedProps == null) {
|
||||||
@ -85,6 +84,9 @@ public class Office2010SignatureFacet implements SignatureFacet {
|
|||||||
if (unsignedSigProps == null) {
|
if (unsignedSigProps == null) {
|
||||||
unsignedSigProps = unsignedProps.addNewUnsignedSignatureProperties();
|
unsignedSigProps = unsignedProps.addNewUnsignedSignatureProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node n = document.importNode(qualProps.getDomNode().getFirstChild(), true);
|
||||||
|
nl.item(0).getParentNode().replaceChild(n, nl.item(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String,String> getNamespacePrefixMapping() {
|
public Map<String,String> getNamespacePrefixMapping() {
|
||||||
|
@ -24,17 +24,21 @@
|
|||||||
|
|
||||||
package org.apache.poi.poifs.crypt.dsig.facets;
|
package org.apache.poi.poifs.crypt.dsig.facets;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.xml.crypto.MarshalException;
|
||||||
import javax.xml.crypto.dsig.Reference;
|
import javax.xml.crypto.dsig.Reference;
|
||||||
import javax.xml.crypto.dsig.XMLObject;
|
import javax.xml.crypto.dsig.XMLObject;
|
||||||
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
||||||
|
|
||||||
import org.w3.x2000.x09.xmldsig.SignatureType;
|
import org.apache.xmlbeans.XmlException;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JSR105 Signature Facet interface.
|
* JSR105 Signature Facet interface.
|
||||||
@ -60,12 +64,13 @@ public interface SignatureFacet {
|
|||||||
* @throws NoSuchAlgorithmException
|
* @throws NoSuchAlgorithmException
|
||||||
*/
|
*/
|
||||||
void preSign(
|
void preSign(
|
||||||
XMLSignatureFactory signatureFactory
|
Document document
|
||||||
|
, XMLSignatureFactory signatureFactory
|
||||||
, String signatureId
|
, String signatureId
|
||||||
, List<X509Certificate> signingCertificateChain
|
, List<X509Certificate> signingCertificateChain
|
||||||
, List<Reference> references
|
, List<Reference> references
|
||||||
, List<XMLObject> objects
|
, List<XMLObject> objects
|
||||||
) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException;
|
) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, IOException, URISyntaxException, XmlException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is being invoked by the XML signature service engine during
|
* This method is being invoked by the XML signature service engine during
|
||||||
@ -76,8 +81,9 @@ public interface SignatureFacet {
|
|||||||
* @param signingCertificateChain
|
* @param signingCertificateChain
|
||||||
*/
|
*/
|
||||||
void postSign(
|
void postSign(
|
||||||
SignatureType signatureElement
|
Document document
|
||||||
, List<X509Certificate> signingCertificateChain);
|
, List<X509Certificate> signingCertificateChain
|
||||||
|
) throws MarshalException, XmlException;
|
||||||
|
|
||||||
Map<String,String> getNamespacePrefixMapping();
|
Map<String,String> getNamespacePrefixMapping();
|
||||||
}
|
}
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
package org.apache.poi.poifs.crypt.dsig.facets;
|
package org.apache.poi.poifs.crypt.dsig.facets;
|
||||||
|
|
||||||
|
import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlNS;
|
||||||
import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.setPrefix;
|
import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.setPrefix;
|
||||||
|
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
@ -31,10 +32,10 @@ import java.security.MessageDigest;
|
|||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.cert.CertificateEncodingException;
|
import java.security.cert.CertificateEncodingException;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
@ -52,7 +53,7 @@ import javax.xml.crypto.dsig.spec.TransformParameterSpec;
|
|||||||
import org.apache.poi.poifs.crypt.CryptoFunctions;
|
import org.apache.poi.poifs.crypt.CryptoFunctions;
|
||||||
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
||||||
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
|
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
|
||||||
import org.apache.poi.poifs.crypt.dsig.spi.Constants;
|
import org.apache.poi.poifs.crypt.dsig.services.XmlSignatureService;
|
||||||
import org.apache.poi.util.POILogFactory;
|
import org.apache.poi.util.POILogFactory;
|
||||||
import org.apache.poi.util.POILogger;
|
import org.apache.poi.util.POILogger;
|
||||||
import org.apache.xmlbeans.XmlString;
|
import org.apache.xmlbeans.XmlString;
|
||||||
@ -74,8 +75,8 @@ import org.etsi.uri.x01903.v13.SignedPropertiesType;
|
|||||||
import org.etsi.uri.x01903.v13.SignedSignaturePropertiesType;
|
import org.etsi.uri.x01903.v13.SignedSignaturePropertiesType;
|
||||||
import org.etsi.uri.x01903.v13.SignerRoleType;
|
import org.etsi.uri.x01903.v13.SignerRoleType;
|
||||||
import org.w3.x2000.x09.xmldsig.DigestMethodType;
|
import org.w3.x2000.x09.xmldsig.DigestMethodType;
|
||||||
import org.w3.x2000.x09.xmldsig.SignatureType;
|
|
||||||
import org.w3.x2000.x09.xmldsig.X509IssuerSerialType;
|
import org.w3.x2000.x09.xmldsig.X509IssuerSerialType;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -133,12 +134,14 @@ public class XAdESSignatureFacet implements SignatureFacet {
|
|||||||
this.dataObjectFormatMimeTypes = new HashMap<String, String>();
|
this.dataObjectFormatMimeTypes = new HashMap<String, String>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void postSign(SignatureType signatureElement,
|
@Override
|
||||||
List<X509Certificate> signingCertificateChain) {
|
public void postSign(Document document, List<X509Certificate> signingCertificateChain) {
|
||||||
LOG.log(POILogger.DEBUG, "postSign");
|
LOG.log(POILogger.DEBUG, "postSign");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void preSign(XMLSignatureFactory signatureFactory,
|
@Override
|
||||||
|
public void preSign(Document document,
|
||||||
|
XMLSignatureFactory signatureFactory,
|
||||||
String signatureId,
|
String signatureId,
|
||||||
List<X509Certificate> signingCertificateChain,
|
List<X509Certificate> signingCertificateChain,
|
||||||
List<Reference> references, List<XMLObject> objects)
|
List<Reference> references, List<XMLObject> objects)
|
||||||
@ -152,10 +155,8 @@ public class XAdESSignatureFacet implements SignatureFacet {
|
|||||||
|
|
||||||
// SignedProperties
|
// SignedProperties
|
||||||
SignedPropertiesType signedProperties = qualifyingProperties.addNewSignedProperties();
|
SignedPropertiesType signedProperties = qualifyingProperties.addNewSignedProperties();
|
||||||
String signedPropertiesId;
|
String signedPropertiesId = this.idSignedProperties;
|
||||||
if (null != this.idSignedProperties) {
|
if (this.idSignedProperties == null) {
|
||||||
signedPropertiesId = this.idSignedProperties;
|
|
||||||
} else {
|
|
||||||
signedPropertiesId = signatureId + "-xades";
|
signedPropertiesId = signatureId + "-xades";
|
||||||
}
|
}
|
||||||
signedProperties.setId(signedPropertiesId);
|
signedProperties.setId(signedPropertiesId);
|
||||||
@ -243,17 +244,18 @@ public class XAdESSignatureFacet implements SignatureFacet {
|
|||||||
// ((Element)qualifyingProperties.getSignedProperties().getDomNode()).setIdAttribute("Id", true);
|
// ((Element)qualifyingProperties.getSignedProperties().getDomNode()).setIdAttribute("Id", true);
|
||||||
|
|
||||||
// add XAdES ds:Object
|
// add XAdES ds:Object
|
||||||
List<XMLStructure> xadesObjectContent = new LinkedList<XMLStructure>();
|
List<XMLStructure> xadesObjectContent = new ArrayList<XMLStructure>();
|
||||||
Element qualDocEl = (Element)qualifyingProperties.getDomNode();
|
Element qualDocEl = (Element)document.importNode(qualifyingProperties.getDomNode(), true);
|
||||||
qualDocEl.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:xd", "http://uri.etsi.org/01903/v1.3.2#");
|
XmlSignatureService.registerIdAttribute(qualDocEl.getElementsByTagName("SignedProperties"));
|
||||||
setPrefix(qualifyingProperties, "http://uri.etsi.org/01903/v1.3.2#", "xd");
|
qualDocEl.setAttributeNS(XmlNS, "xmlns:xd", "http://uri.etsi.org/01903/v1.3.2#");
|
||||||
|
setPrefix(qualDocEl, "http://uri.etsi.org/01903/v1.3.2#", "xd");
|
||||||
xadesObjectContent.add(new DOMStructure(qualDocEl));
|
xadesObjectContent.add(new DOMStructure(qualDocEl));
|
||||||
XMLObject xadesObject = signatureFactory.newXMLObject(xadesObjectContent, null, null, null);
|
XMLObject xadesObject = signatureFactory.newXMLObject(xadesObjectContent, null, null, null);
|
||||||
objects.add(xadesObject);
|
objects.add(xadesObject);
|
||||||
|
|
||||||
// add XAdES ds:Reference
|
// add XAdES ds:Reference
|
||||||
DigestMethod digestMethod = signatureFactory.newDigestMethod(hashAlgo.xmlSignUri, null);
|
DigestMethod digestMethod = signatureFactory.newDigestMethod(hashAlgo.xmlSignUri, null);
|
||||||
List<Transform> transforms = new LinkedList<Transform>();
|
List<Transform> transforms = new ArrayList<Transform>();
|
||||||
Transform exclusiveTransform = signatureFactory
|
Transform exclusiveTransform = signatureFactory
|
||||||
.newTransform(CanonicalizationMethod.INCLUSIVE,
|
.newTransform(CanonicalizationMethod.INCLUSIVE,
|
||||||
(TransformParameterSpec) null);
|
(TransformParameterSpec) null);
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
package org.apache.poi.poifs.crypt.dsig.facets;
|
package org.apache.poi.poifs.crypt.dsig.facets;
|
||||||
|
|
||||||
import static org.apache.poi.poifs.crypt.dsig.HorribleProxy.newProxy;
|
import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlDSigNS;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
@ -37,9 +37,9 @@ import java.security.cert.CertificateException;
|
|||||||
import java.security.cert.CertificateFactory;
|
import java.security.cert.CertificateFactory;
|
||||||
import java.security.cert.X509CRL;
|
import java.security.cert.X509CRL;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@ -50,26 +50,24 @@ import javax.xml.crypto.dsig.XMLObject;
|
|||||||
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
||||||
|
|
||||||
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ASN1InputStreamIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ASN1IntegerIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ASN1OctetStringIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.BasicOCSPRespIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.CanonicalizerIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DERTaggedObjectIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.InitIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.OCSPRespIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.RespIDIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ResponderIDIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.X509ExtensionsIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.X509NameIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxy;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
|
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
|
||||||
import org.apache.poi.poifs.crypt.dsig.services.RevocationData;
|
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.RevocationDataService;
|
||||||
import org.apache.poi.poifs.crypt.dsig.services.TimeStampService;
|
import org.apache.poi.poifs.crypt.dsig.services.TimeStampService;
|
||||||
import org.apache.poi.util.POILogFactory;
|
import org.apache.poi.util.POILogFactory;
|
||||||
import org.apache.poi.util.POILogger;
|
import org.apache.poi.util.POILogger;
|
||||||
import org.apache.xmlbeans.XmlObject;
|
import org.apache.xml.security.c14n.Canonicalizer;
|
||||||
|
import org.apache.xmlbeans.XmlException;
|
||||||
|
import org.bouncycastle.asn1.ASN1InputStream;
|
||||||
|
import org.bouncycastle.asn1.ASN1Integer;
|
||||||
|
import org.bouncycastle.asn1.ASN1OctetString;
|
||||||
|
import org.bouncycastle.asn1.DERTaggedObject;
|
||||||
|
import org.bouncycastle.asn1.ocsp.ResponderID;
|
||||||
|
import org.bouncycastle.asn1.x500.X500Name;
|
||||||
|
import org.bouncycastle.asn1.x509.Extension;
|
||||||
|
import org.bouncycastle.cert.ocsp.BasicOCSPResp;
|
||||||
|
import org.bouncycastle.cert.ocsp.OCSPResp;
|
||||||
|
import org.bouncycastle.cert.ocsp.RespID;
|
||||||
import org.etsi.uri.x01903.v13.CRLIdentifierType;
|
import org.etsi.uri.x01903.v13.CRLIdentifierType;
|
||||||
import org.etsi.uri.x01903.v13.CRLRefType;
|
import org.etsi.uri.x01903.v13.CRLRefType;
|
||||||
import org.etsi.uri.x01903.v13.CRLRefsType;
|
import org.etsi.uri.x01903.v13.CRLRefsType;
|
||||||
@ -93,9 +91,9 @@ import org.etsi.uri.x01903.v13.UnsignedSignaturePropertiesType;
|
|||||||
import org.etsi.uri.x01903.v13.XAdESTimeStampType;
|
import org.etsi.uri.x01903.v13.XAdESTimeStampType;
|
||||||
import org.etsi.uri.x01903.v14.ValidationDataType;
|
import org.etsi.uri.x01903.v14.ValidationDataType;
|
||||||
import org.w3.x2000.x09.xmldsig.CanonicalizationMethodType;
|
import org.w3.x2000.x09.xmldsig.CanonicalizationMethodType;
|
||||||
import org.w3.x2000.x09.xmldsig.SignatureType;
|
import org.w3c.dom.Document;
|
||||||
import org.w3.x2000.x09.xmldsig.SignatureValueType;
|
|
||||||
import org.w3c.dom.Node;
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* XAdES-X-L v1.4.1 signature facet. This signature facet implementation will
|
* XAdES-X-L v1.4.1 signature facet. This signature facet implementation will
|
||||||
@ -129,14 +127,6 @@ public class XAdESXLSignatureFacet implements SignatureFacet {
|
|||||||
|
|
||||||
private final HashAlgorithm hashAlgo;
|
private final HashAlgorithm hashAlgo;
|
||||||
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
HorribleProxy.createProxy(InitIf.class, "init");
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("Can't initialize JDK xml signature classes - feature unsupported by the this JDK?!", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience constructor.
|
* Convenience constructor.
|
||||||
*
|
*
|
||||||
@ -184,21 +174,19 @@ public class XAdESXLSignatureFacet implements SignatureFacet {
|
|||||||
this.c14nAlgoId = c14nAlgoId;
|
this.c14nAlgoId = c14nAlgoId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void postSign(SignatureType signatureElement,
|
@Override
|
||||||
List<X509Certificate> signingCertificateChain) {
|
public void postSign(Document document,
|
||||||
|
List<X509Certificate> signingCertificateChain
|
||||||
|
) throws XmlException {
|
||||||
LOG.log(POILogger.DEBUG, "XAdES-X-L post sign phase");
|
LOG.log(POILogger.DEBUG, "XAdES-X-L post sign phase");
|
||||||
|
|
||||||
QualifyingPropertiesType qualProps = null;
|
QualifyingPropertiesType qualProps = null;
|
||||||
String qualPropXQuery =
|
|
||||||
"declare namespace xades='http://uri.etsi.org/01903/v1.3.2#'; "
|
// check for XAdES-BES
|
||||||
+ "declare namespace ds='http://www.w3.org/2000/09/xmldsig#'; "
|
NodeList qualNl = document.getElementsByTagNameNS("http://uri.etsi.org/01903/v1.3.2#", "QualifyingProperties");
|
||||||
+ "$this/ds:Object/xades:QualifyingProperties";
|
if (qualNl.getLength() == 1) {
|
||||||
XmlObject xoList[] = signatureElement.selectPath(qualPropXQuery);
|
qualProps = QualifyingPropertiesType.Factory.parse(qualNl.item(0));
|
||||||
if (xoList.length == 1) {
|
} else {
|
||||||
qualProps = (QualifyingPropertiesType)xoList[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (qualProps == null) {
|
|
||||||
throw new IllegalArgumentException("no XAdES-BES extension present");
|
throw new IllegalArgumentException("no XAdES-BES extension present");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,14 +202,15 @@ public class XAdESXLSignatureFacet implements SignatureFacet {
|
|||||||
|
|
||||||
|
|
||||||
// create the XAdES-T time-stamp
|
// create the XAdES-T time-stamp
|
||||||
SignatureValueType svt = signatureElement.getSignatureValue();
|
NodeList nlSigVal = document.getElementsByTagNameNS(XmlDSigNS, "SignatureValue");
|
||||||
|
if (nlSigVal.getLength() != 1) {
|
||||||
|
throw new IllegalArgumentException("SignatureValue is not set.");
|
||||||
|
}
|
||||||
|
|
||||||
RevocationData tsaRevocationDataXadesT = new RevocationData();
|
RevocationData tsaRevocationDataXadesT = new RevocationData();
|
||||||
LOG.log(POILogger.DEBUG, "creating XAdES-T time-stamp");
|
LOG.log(POILogger.DEBUG, "creating XAdES-T time-stamp");
|
||||||
XAdESTimeStampType signatureTimeStamp = createXAdESTimeStamp(
|
XAdESTimeStampType signatureTimeStamp = createXAdESTimeStamp(
|
||||||
Collections.singletonList(svt.getDomNode()),
|
Collections.singletonList(nlSigVal.item(0)), tsaRevocationDataXadesT, this.c14nAlgoId, this.timeStampService);
|
||||||
tsaRevocationDataXadesT, this.c14nAlgoId,
|
|
||||||
this.timeStampService);
|
|
||||||
|
|
||||||
// marshal the XAdES-T extension
|
// marshal the XAdES-T extension
|
||||||
unsignedSigProps.addNewSignatureTimeStamp().set(signatureTimeStamp);
|
unsignedSigProps.addNewSignatureTimeStamp().set(signatureTimeStamp);
|
||||||
@ -298,9 +287,9 @@ public class XAdESXLSignatureFacet implements SignatureFacet {
|
|||||||
|
|
||||||
OCSPIdentifierType ocspIdentifier = ocspRef.addNewOCSPIdentifier();
|
OCSPIdentifierType ocspIdentifier = ocspRef.addNewOCSPIdentifier();
|
||||||
|
|
||||||
OCSPRespIf ocspResp = HorribleProxy.newProxy(OCSPRespIf.class, ocsp);
|
OCSPResp ocspResp = new OCSPResp(ocsp);
|
||||||
|
|
||||||
BasicOCSPRespIf basicOcspResp = ocspResp.getResponseObject();
|
BasicOCSPResp basicOcspResp = (BasicOCSPResp)ocspResp.getResponseObject();
|
||||||
|
|
||||||
Calendar cal = Calendar.getInstance();
|
Calendar cal = Calendar.getInstance();
|
||||||
cal.setTime(basicOcspResp.getProducedAt());
|
cal.setTime(basicOcspResp.getProducedAt());
|
||||||
@ -308,16 +297,16 @@ public class XAdESXLSignatureFacet implements SignatureFacet {
|
|||||||
|
|
||||||
ResponderIDType responderId = ocspIdentifier.addNewResponderID();
|
ResponderIDType responderId = ocspIdentifier.addNewResponderID();
|
||||||
|
|
||||||
RespIDIf respId = basicOcspResp.getResponderId();
|
RespID respId = basicOcspResp.getResponderId();
|
||||||
ResponderIDIf ocspResponderId = respId.toASN1Object();
|
ResponderID ocspResponderId = respId.toASN1Object();
|
||||||
DERTaggedObjectIf derTaggedObject = ocspResponderId.toASN1Object();
|
DERTaggedObject derTaggedObject = (DERTaggedObject)ocspResponderId.toASN1Primitive();
|
||||||
if (2 == derTaggedObject.getTagNo()) {
|
if (2 == derTaggedObject.getTagNo()) {
|
||||||
ASN1OctetStringIf keyHashOctetString = derTaggedObject.getObject$String();
|
ASN1OctetString keyHashOctetString = (ASN1OctetString)derTaggedObject.getObject();
|
||||||
byte key[] = keyHashOctetString.getOctets();
|
byte key[] = keyHashOctetString.getOctets();
|
||||||
responderId.setByKey(key);
|
responderId.setByKey(key);
|
||||||
} else {
|
} else {
|
||||||
X509NameIf name = HorribleProxy.createProxy(X509NameIf.class, "getInstance", derTaggedObject.getObject$Object());
|
X500Name name = X500Name.getInstance(derTaggedObject.getObject());
|
||||||
String nameStr = name.toString$delegate();
|
String nameStr = name.toString();
|
||||||
responderId.setByName(nameStr);
|
responderId.setByName(nameStr);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -327,13 +316,10 @@ public class XAdESXLSignatureFacet implements SignatureFacet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// marshal XAdES-C
|
// marshal XAdES-C
|
||||||
|
|
||||||
// XAdES-X Type 1 timestamp
|
// XAdES-X Type 1 timestamp
|
||||||
|
List<Node> timeStampNodesXadesX1 = new ArrayList<Node>();
|
||||||
|
timeStampNodesXadesX1.add(nlSigVal.item(0));
|
||||||
|
|
||||||
List<Node> timeStampNodesXadesX1 = new LinkedList<Node>();
|
|
||||||
timeStampNodesXadesX1.add(signatureElement.getDomNode());
|
|
||||||
timeStampNodesXadesX1.add(signatureTimeStamp.getDomNode());
|
timeStampNodesXadesX1.add(signatureTimeStamp.getDomNode());
|
||||||
timeStampNodesXadesX1.add(completeCertificateRefs.getDomNode());
|
timeStampNodesXadesX1.add(completeCertificateRefs.getDomNode());
|
||||||
timeStampNodesXadesX1.add(completeRevocationRefs.getDomNode());
|
timeStampNodesXadesX1.add(completeRevocationRefs.getDomNode());
|
||||||
@ -365,6 +351,8 @@ public class XAdESXLSignatureFacet implements SignatureFacet {
|
|||||||
createRevocationValues(revocationValues, revocationData);
|
createRevocationValues(revocationValues, revocationData);
|
||||||
|
|
||||||
// marshal XAdES-X-L
|
// marshal XAdES-X-L
|
||||||
|
Node n = document.importNode(qualProps.getDomNode().getFirstChild(), true);
|
||||||
|
qualNl.item(0).getParentNode().replaceChild(n, qualNl.item(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] getC14nValue(List<Node> nodeList, String c14nAlgoId) {
|
public static byte[] getC14nValue(List<Node> nodeList, String c14nAlgoId) {
|
||||||
@ -375,7 +363,7 @@ public class XAdESXLSignatureFacet implements SignatureFacet {
|
|||||||
* Re-initialize the c14n else the namespaces will get cached
|
* Re-initialize the c14n else the namespaces will get cached
|
||||||
* and will be missing from the c14n resulting nodes.
|
* and will be missing from the c14n resulting nodes.
|
||||||
*/
|
*/
|
||||||
CanonicalizerIf c14n = HorribleProxy.createProxy(CanonicalizerIf.class, "getInstance", c14nAlgoId);
|
Canonicalizer c14n = Canonicalizer.getInstance(c14nAlgoId);
|
||||||
c14nValue.write(c14n.canonicalizeSubtree(node));
|
c14nValue.write(c14n.canonicalizeSubtree(node));
|
||||||
}
|
}
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
@ -386,7 +374,9 @@ public class XAdESXLSignatureFacet implements SignatureFacet {
|
|||||||
return c14nValue.toByteArray();
|
return c14nValue.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void preSign(XMLSignatureFactory signatureFactory,
|
@Override
|
||||||
|
public void preSign(Document document,
|
||||||
|
XMLSignatureFactory signatureFactory,
|
||||||
String signatureId,
|
String signatureId,
|
||||||
List<X509Certificate> signingCertificateChain,
|
List<X509Certificate> signingCertificateChain,
|
||||||
List<Reference> references, List<XMLObject> objects)
|
List<Reference> references, List<XMLObject> objects)
|
||||||
@ -396,17 +386,17 @@ public class XAdESXLSignatureFacet implements SignatureFacet {
|
|||||||
|
|
||||||
private BigInteger getCrlNumber(X509CRL crl) {
|
private BigInteger getCrlNumber(X509CRL crl) {
|
||||||
try {
|
try {
|
||||||
X509ExtensionsIf x509ext = newProxy(X509ExtensionsIf.class);
|
byte[] crlNumberExtensionValue = crl.getExtensionValue(Extension.cRLNumber.getId());
|
||||||
byte[] crlNumberExtensionValue = crl.getExtensionValue(x509ext.CRLNumber().getId());
|
|
||||||
if (null == crlNumberExtensionValue) {
|
if (null == crlNumberExtensionValue) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASN1InputStreamIf asn1InputStream = HorribleProxy.newProxy(ASN1InputStreamIf.class, crlNumberExtensionValue);
|
@SuppressWarnings("resource")
|
||||||
ASN1OctetStringIf octetString = asn1InputStream.readObject$ASNString();
|
ASN1InputStream asn1InputStream = new ASN1InputStream(crlNumberExtensionValue);
|
||||||
|
ASN1OctetString octetString = (ASN1OctetString)asn1InputStream.readObject();
|
||||||
byte[] octets = octetString.getOctets();
|
byte[] octets = octetString.getOctets();
|
||||||
asn1InputStream = HorribleProxy.newProxy(ASN1InputStreamIf.class, octets);
|
asn1InputStream = new ASN1InputStream(octets);
|
||||||
ASN1IntegerIf integer = asn1InputStream.readObject$Integer();
|
ASN1Integer integer = (ASN1Integer)asn1InputStream.readObject();
|
||||||
BigInteger crlNumber = integer.getPositiveValue();
|
BigInteger crlNumber = integer.getPositiveValue();
|
||||||
return crlNumber;
|
return crlNumber;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -33,9 +33,9 @@ import java.security.InvalidAlgorithmParameterException;
|
|||||||
import java.security.Provider;
|
import java.security.Provider;
|
||||||
import java.security.Security;
|
import java.security.Security;
|
||||||
import java.security.spec.AlgorithmParameterSpec;
|
import java.security.spec.AlgorithmParameterSpec;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.xml.crypto.Data;
|
import javax.xml.crypto.Data;
|
||||||
@ -85,7 +85,7 @@ public class RelationshipTransformService extends TransformService {
|
|||||||
* Relationship Transform parameter specification class.
|
* Relationship Transform parameter specification class.
|
||||||
*/
|
*/
|
||||||
public static class RelationshipTransformParameterSpec implements TransformParameterSpec {
|
public static class RelationshipTransformParameterSpec implements TransformParameterSpec {
|
||||||
List<String> sourceIds = new LinkedList<String>();
|
List<String> sourceIds = new ArrayList<String>();
|
||||||
public void addRelationshipReference(String relationshipId) {
|
public void addRelationshipReference(String relationshipId) {
|
||||||
sourceIds.add(relationshipId);
|
sourceIds.add(relationshipId);
|
||||||
}
|
}
|
||||||
@ -98,7 +98,7 @@ public class RelationshipTransformService extends TransformService {
|
|||||||
public RelationshipTransformService() {
|
public RelationshipTransformService() {
|
||||||
super();
|
super();
|
||||||
LOG.log(POILogger.DEBUG, "constructor");
|
LOG.log(POILogger.DEBUG, "constructor");
|
||||||
this.sourceIds = new LinkedList<String>();
|
this.sourceIds = new ArrayList<String>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,7 +26,7 @@ package org.apache.poi.poifs.crypt.dsig.services;
|
|||||||
|
|
||||||
import java.security.cert.CRLException;
|
import java.security.cert.CRLException;
|
||||||
import java.security.cert.X509CRL;
|
import java.security.cert.X509CRL;
|
||||||
import java.util.LinkedList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,8 +45,8 @@ public class RevocationData {
|
|||||||
* Default constructor.
|
* Default constructor.
|
||||||
*/
|
*/
|
||||||
public RevocationData() {
|
public RevocationData() {
|
||||||
this.crls = new LinkedList<byte[]>();
|
this.crls = new ArrayList<byte[]>();
|
||||||
this.ocsps = new LinkedList<byte[]>();
|
this.ocsps = new ArrayList<byte[]>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,16 +26,18 @@ package org.apache.poi.poifs.crypt.dsig.services;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.PrivateKey;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.CertificateSecurityException;
|
import javax.xml.crypto.MarshalException;
|
||||||
import org.apache.poi.poifs.crypt.dsig.ExpiredCertificateSecurityException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
import org.apache.poi.poifs.crypt.dsig.RevokedCertificateSecurityException;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.TrustCertificateSecurityException;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.spi.AddressDTO;
|
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.DigestInfo;
|
||||||
import org.apache.poi.poifs.crypt.dsig.spi.IdentityDTO;
|
import org.apache.poi.poifs.crypt.dsig.spi.IdentityDTO;
|
||||||
|
import org.apache.xmlbeans.XmlException;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for signature service component.
|
* Interface for signature service component.
|
||||||
@ -79,7 +81,8 @@ public interface SignatureService {
|
|||||||
* @return the digest to be signed.
|
* @return the digest to be signed.
|
||||||
* @throws NoSuchAlgorithmException
|
* @throws NoSuchAlgorithmException
|
||||||
*/
|
*/
|
||||||
DigestInfo preSign(List<DigestInfo> digestInfos,
|
DigestInfo preSign(Document document, List<DigestInfo> digestInfos,
|
||||||
|
PrivateKey privateKey,
|
||||||
List<X509Certificate> signingCertificateChain,
|
List<X509Certificate> signingCertificateChain,
|
||||||
IdentityDTO identity, AddressDTO address, byte[] photo)
|
IdentityDTO identity, AddressDTO address, byte[] photo)
|
||||||
throws NoSuchAlgorithmException;
|
throws NoSuchAlgorithmException;
|
||||||
@ -92,10 +95,7 @@ public interface SignatureService {
|
|||||||
* @param signingCertificateChain
|
* @param signingCertificateChain
|
||||||
* the optional chain of signing certificates.
|
* the optional chain of signing certificates.
|
||||||
*/
|
*/
|
||||||
void postSign(byte[] signatureValue,
|
void postSign(Document document, byte[] signatureValue,
|
||||||
List<X509Certificate> signingCertificateChain)
|
List<X509Certificate> signingCertificateChain)
|
||||||
throws ExpiredCertificateSecurityException,
|
throws IOException, MarshalException, ParserConfigurationException, XmlException;
|
||||||
RevokedCertificateSecurityException,
|
|
||||||
TrustCertificateSecurityException, CertificateSecurityException,
|
|
||||||
SecurityException, IOException;
|
|
||||||
}
|
}
|
||||||
|
@ -24,10 +24,6 @@
|
|||||||
|
|
||||||
package org.apache.poi.poifs.crypt.dsig.services;
|
package org.apache.poi.poifs.crypt.dsig.services;
|
||||||
|
|
||||||
import static org.apache.poi.poifs.crypt.dsig.HorribleProxy.createProxy;
|
|
||||||
import static org.apache.poi.poifs.crypt.dsig.HorribleProxy.newProxy;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
@ -38,39 +34,37 @@ import java.net.URL;
|
|||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.security.cert.Certificate;
|
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.security.auth.x500.X500Principal;
|
|
||||||
import javax.xml.bind.DatatypeConverter;
|
import javax.xml.bind.DatatypeConverter;
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.Hex;
|
import org.apache.commons.codec.binary.Hex;
|
||||||
import org.apache.poi.poifs.crypt.CryptoFunctions;
|
import org.apache.poi.poifs.crypt.CryptoFunctions;
|
||||||
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ASN1InputStreamIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ASN1OctetStringIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.AuthorityKeyIdentifierIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.BcDigestCalculatorProviderIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.BcRSASignerInfoVerifierBuilderIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DEROctetStringIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DefaultDigestAlgorithmIdentifierFinderIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.PKIFailureInfoIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.SignerIdIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.SignerInformationVerifierIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.SubjectKeyIdentifierIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.TimeStampRequestGeneratorIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.TimeStampRequestIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.TimeStampResponseIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.TimeStampTokenIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.X509CertificateHolderIf;
|
|
||||||
import org.apache.poi.util.IOUtils;
|
import org.apache.poi.util.IOUtils;
|
||||||
import org.apache.poi.util.POILogFactory;
|
import org.apache.poi.util.POILogFactory;
|
||||||
import org.apache.poi.util.POILogger;
|
import org.apache.poi.util.POILogger;
|
||||||
|
import org.bouncycastle.asn1.cmp.PKIFailureInfo;
|
||||||
|
import org.bouncycastle.asn1.x500.X500Name;
|
||||||
|
import org.bouncycastle.cert.X509CertificateHolder;
|
||||||
|
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
|
||||||
|
import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
|
||||||
|
import org.bouncycastle.cms.DefaultCMSSignatureAlgorithmNameGenerator;
|
||||||
|
import org.bouncycastle.cms.SignerId;
|
||||||
|
import org.bouncycastle.cms.SignerInformationVerifier;
|
||||||
|
import org.bouncycastle.cms.bc.BcRSASignerInfoVerifierBuilder;
|
||||||
|
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
|
||||||
|
import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
|
||||||
|
import org.bouncycastle.operator.bc.BcDigestCalculatorProvider;
|
||||||
|
import org.bouncycastle.tsp.TimeStampRequest;
|
||||||
|
import org.bouncycastle.tsp.TimeStampRequestGenerator;
|
||||||
|
import org.bouncycastle.tsp.TimeStampResponse;
|
||||||
|
import org.bouncycastle.tsp.TimeStampToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A TSP time-stamp service implementation.
|
* A TSP time-stamp service implementation.
|
||||||
@ -108,6 +102,10 @@ public class TSPTimeStampService implements TimeStampService {
|
|||||||
|
|
||||||
private String digestAlgoOid;
|
private String digestAlgoOid;
|
||||||
|
|
||||||
|
private String requestContentType = "application/timestamp-query;charset=ISO-8859-1";
|
||||||
|
|
||||||
|
private String responseContentType = "application/timestamp-reply";
|
||||||
|
|
||||||
public TSPTimeStampService(String tspServiceUrl,
|
public TSPTimeStampService(String tspServiceUrl,
|
||||||
TimeStampServiceValidator validator) {
|
TimeStampServiceValidator validator) {
|
||||||
this(tspServiceUrl, validator, null, null);
|
this(tspServiceUrl, validator, null, null);
|
||||||
@ -234,12 +232,12 @@ public class TSPTimeStampService implements TimeStampService {
|
|||||||
|
|
||||||
// generate the TSP request
|
// generate the TSP request
|
||||||
BigInteger nonce = new BigInteger(128, new SecureRandom());
|
BigInteger nonce = new BigInteger(128, new SecureRandom());
|
||||||
TimeStampRequestGeneratorIf requestGenerator = newProxy(TimeStampRequestGeneratorIf.class);
|
TimeStampRequestGenerator requestGenerator = new TimeStampRequestGenerator();
|
||||||
requestGenerator.setCertReq(true);
|
requestGenerator.setCertReq(true);
|
||||||
if (null != this.requestPolicy) {
|
if (null != this.requestPolicy) {
|
||||||
requestGenerator.setReqPolicy(this.requestPolicy);
|
requestGenerator.setReqPolicy(this.requestPolicy);
|
||||||
}
|
}
|
||||||
TimeStampRequestIf request = requestGenerator.generate(this.digestAlgoOid, digest, nonce);
|
TimeStampRequest request = requestGenerator.generate(this.digestAlgoOid, digest, nonce);
|
||||||
byte[] encodedRequest = request.getEncoded();
|
byte[] encodedRequest = request.getEncoded();
|
||||||
|
|
||||||
// create the HTTP POST request
|
// create the HTTP POST request
|
||||||
@ -256,8 +254,7 @@ public class TSPTimeStampService implements TimeStampService {
|
|||||||
|
|
||||||
huc.setDoOutput(true); // also sets method to POST.
|
huc.setDoOutput(true); // also sets method to POST.
|
||||||
huc.setRequestProperty("User-Agent", this.userAgent);
|
huc.setRequestProperty("User-Agent", this.userAgent);
|
||||||
// "application/timestamp-query;charset=ISO-8859-1"
|
huc.setRequestProperty("Content-Type", requestContentType);
|
||||||
huc.setRequestProperty("Content-Type", "application/timestamp-request");
|
|
||||||
|
|
||||||
OutputStream hucOut = huc.getOutputStream();
|
OutputStream hucOut = huc.getOutputStream();
|
||||||
hucOut.write(encodedRequest);
|
hucOut.write(encodedRequest);
|
||||||
@ -281,8 +278,7 @@ public class TSPTimeStampService implements TimeStampService {
|
|||||||
IOUtils.copy(huc.getInputStream(), bos);
|
IOUtils.copy(huc.getInputStream(), bos);
|
||||||
LOG.log(POILogger.DEBUG, "response content: ", bos.toString());
|
LOG.log(POILogger.DEBUG, "response content: ", bos.toString());
|
||||||
|
|
||||||
// "application/timestamp-reply"
|
if (!contentType.startsWith(responseContentType)) {
|
||||||
if (!contentType.startsWith("application/timestamp-response")) {
|
|
||||||
throw new RuntimeException("invalid Content-Type: " + contentType);
|
throw new RuntimeException("invalid Content-Type: " + contentType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,13 +287,13 @@ public class TSPTimeStampService implements TimeStampService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TSP response parsing and validation
|
// TSP response parsing and validation
|
||||||
TimeStampResponseIf timeStampResponse = newProxy(TimeStampResponseIf.class, bos.toByteArray());
|
TimeStampResponse timeStampResponse = new TimeStampResponse(bos.toByteArray());
|
||||||
timeStampResponse.validate(request);
|
timeStampResponse.validate(request);
|
||||||
|
|
||||||
if (0 != timeStampResponse.getStatus()) {
|
if (0 != timeStampResponse.getStatus()) {
|
||||||
LOG.log(POILogger.DEBUG, "status: " + timeStampResponse.getStatus());
|
LOG.log(POILogger.DEBUG, "status: " + timeStampResponse.getStatus());
|
||||||
LOG.log(POILogger.DEBUG, "status string: " + timeStampResponse.getStatusString());
|
LOG.log(POILogger.DEBUG, "status string: " + timeStampResponse.getStatusString());
|
||||||
PKIFailureInfoIf failInfo = timeStampResponse.getFailInfo();
|
PKIFailureInfo failInfo = timeStampResponse.getFailInfo();
|
||||||
if (null != failInfo) {
|
if (null != failInfo) {
|
||||||
LOG.log(POILogger.DEBUG, "fail info int value: " + failInfo.intValue());
|
LOG.log(POILogger.DEBUG, "fail info int value: " + failInfo.intValue());
|
||||||
if (/*PKIFailureInfo.unacceptedPolicy*/(1 << 8) == failInfo.intValue()) {
|
if (/*PKIFailureInfo.unacceptedPolicy*/(1 << 8) == failInfo.intValue()) {
|
||||||
@ -307,30 +303,29 @@ public class TSPTimeStampService implements TimeStampService {
|
|||||||
throw new RuntimeException("timestamp response status != 0: "
|
throw new RuntimeException("timestamp response status != 0: "
|
||||||
+ timeStampResponse.getStatus());
|
+ timeStampResponse.getStatus());
|
||||||
}
|
}
|
||||||
TimeStampTokenIf timeStampToken = timeStampResponse.getTimeStampToken();
|
TimeStampToken timeStampToken = timeStampResponse.getTimeStampToken();
|
||||||
SignerIdIf signerId = timeStampToken.getSID();
|
SignerId signerId = timeStampToken.getSID();
|
||||||
BigInteger signerCertSerialNumber = signerId.getSerialNumber();
|
BigInteger signerCertSerialNumber = signerId.getSerialNumber();
|
||||||
X500Principal signerCertIssuer = signerId.getIssuer();
|
X500Name signerCertIssuer = signerId.getIssuer();
|
||||||
LOG.log(POILogger.DEBUG, "signer cert serial number: " + signerCertSerialNumber);
|
LOG.log(POILogger.DEBUG, "signer cert serial number: " + signerCertSerialNumber);
|
||||||
LOG.log(POILogger.DEBUG, "signer cert issuer: " + signerCertIssuer);
|
LOG.log(POILogger.DEBUG, "signer cert issuer: " + signerCertIssuer);
|
||||||
|
|
||||||
// TSP signer certificates retrieval
|
// TSP signer certificates retrieval
|
||||||
Collection<Certificate> certificates = timeStampToken.getCertificates().getMatches(null);
|
Collection<X509CertificateHolder> certificates = timeStampToken.getCertificates().getMatches(null);
|
||||||
|
JcaX509ExtensionUtils utils = new JcaX509ExtensionUtils();
|
||||||
|
|
||||||
X509Certificate signerCert = null;
|
X509CertificateHolder signerCert = null;
|
||||||
Map<String, X509Certificate> certificateMap = new HashMap<String, X509Certificate>();
|
Map<String, X509CertificateHolder> certificateMap = new HashMap<String, X509CertificateHolder>();
|
||||||
for (Certificate certificate : certificates) {
|
for (X509CertificateHolder certificate : certificates) {
|
||||||
X509Certificate x509Certificate = (X509Certificate) certificate;
|
if (signerCertIssuer.equals(certificate.getIssuer())
|
||||||
if (signerCertIssuer.equals(x509Certificate
|
&& signerCertSerialNumber.equals(certificate.getSerialNumber())) {
|
||||||
.getIssuerX500Principal())
|
signerCert = certificate;
|
||||||
&& signerCertSerialNumber.equals(x509Certificate
|
|
||||||
.getSerialNumber())) {
|
|
||||||
signerCert = x509Certificate;
|
|
||||||
}
|
}
|
||||||
String ski = Hex.encodeHexString(getSubjectKeyId(x509Certificate));
|
byte skiBytes[] = utils.createSubjectKeyIdentifier(certificate.getSubjectPublicKeyInfo()).getKeyIdentifier();
|
||||||
certificateMap.put(ski, x509Certificate);
|
String ski = Hex.encodeHexString(skiBytes);
|
||||||
|
certificateMap.put(ski, certificate);
|
||||||
LOG.log(POILogger.DEBUG, "embedded certificate: "
|
LOG.log(POILogger.DEBUG, "embedded certificate: "
|
||||||
+ x509Certificate.getSubjectX500Principal() + "; SKI="
|
+ certificate.getSubject() + "; SKI="
|
||||||
+ ski);
|
+ ski);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,26 +334,29 @@ public class TSPTimeStampService implements TimeStampService {
|
|||||||
throw new RuntimeException(
|
throw new RuntimeException(
|
||||||
"TSP response token has no signer certificate");
|
"TSP response token has no signer certificate");
|
||||||
}
|
}
|
||||||
List<X509Certificate> tspCertificateChain = new LinkedList<X509Certificate>();
|
List<X509Certificate> tspCertificateChain = new ArrayList<X509Certificate>();
|
||||||
X509Certificate certificate = signerCert;
|
JcaX509CertificateConverter x509converter = new JcaX509CertificateConverter();
|
||||||
|
x509converter.setProvider("BC");
|
||||||
|
X509CertificateHolder certificate = signerCert;
|
||||||
do {
|
do {
|
||||||
LOG.log(POILogger.DEBUG, "adding to certificate chain: "
|
LOG.log(POILogger.DEBUG, "adding to certificate chain: " + certificate.getSubject());
|
||||||
+ certificate.getSubjectX500Principal());
|
tspCertificateChain.add(x509converter.getCertificate(certificate));
|
||||||
tspCertificateChain.add(certificate);
|
if (certificate.getSubject().equals(certificate.getIssuer())) {
|
||||||
if (certificate.getSubjectX500Principal().equals(
|
|
||||||
certificate.getIssuerX500Principal())) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
String aki = Hex.encodeHexString(getAuthorityKeyId(certificate));
|
byte akiBytes[] = utils.createAuthorityKeyIdentifier(certificate.getSubjectPublicKeyInfo()).getKeyIdentifier();
|
||||||
|
String aki = Hex.encodeHexString(akiBytes);
|
||||||
certificate = certificateMap.get(aki);
|
certificate = certificateMap.get(aki);
|
||||||
} while (null != certificate);
|
} while (null != certificate);
|
||||||
|
|
||||||
// verify TSP signer signature
|
// verify TSP signer signature
|
||||||
X509CertificateHolderIf holder = newProxy(X509CertificateHolderIf.class, tspCertificateChain.get(0).getEncoded());
|
X509CertificateHolder holder = new X509CertificateHolder(tspCertificateChain.get(0).getEncoded());
|
||||||
DefaultDigestAlgorithmIdentifierFinderIf finder = newProxy(DefaultDigestAlgorithmIdentifierFinderIf.class);
|
DefaultCMSSignatureAlgorithmNameGenerator nameGen = new DefaultCMSSignatureAlgorithmNameGenerator();
|
||||||
BcDigestCalculatorProviderIf calculator = newProxy(BcDigestCalculatorProviderIf.class);
|
DefaultSignatureAlgorithmIdentifierFinder sigAlgoFinder = new DefaultSignatureAlgorithmIdentifierFinder();
|
||||||
BcRSASignerInfoVerifierBuilderIf verifierBuilder = newProxy(BcRSASignerInfoVerifierBuilderIf.class, finder, calculator);
|
DefaultDigestAlgorithmIdentifierFinder hashAlgoFinder = new DefaultDigestAlgorithmIdentifierFinder();
|
||||||
SignerInformationVerifierIf verifier = verifierBuilder.build(holder);
|
BcDigestCalculatorProvider calculator = new BcDigestCalculatorProvider();
|
||||||
|
BcRSASignerInfoVerifierBuilder verifierBuilder = new BcRSASignerInfoVerifierBuilder(nameGen, sigAlgoFinder, hashAlgoFinder, calculator);
|
||||||
|
SignerInformationVerifier verifier = verifierBuilder.build(holder);
|
||||||
|
|
||||||
timeStampToken.validate(verifier);
|
timeStampToken.validate(verifier);
|
||||||
|
|
||||||
@ -372,29 +370,19 @@ public class TSPTimeStampService implements TimeStampService {
|
|||||||
return timestamp;
|
return timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] getSubjectKeyId(X509Certificate cert) throws Exception {
|
/**
|
||||||
// X509Extensions.SubjectKeyIdentifier.getId()
|
* usually the request content type is "application/timestamp-query;charset=ISO-8859-1",
|
||||||
byte[] extvalue = cert.getExtensionValue("2.5.29.14");
|
* but some timestamp server use a different content type
|
||||||
if (extvalue == null) return null;
|
*/
|
||||||
|
public void setRequestContentType(String requestContentType) {
|
||||||
ASN1InputStreamIf keyCntStream = newProxy(ASN1InputStreamIf.class, new ByteArrayInputStream(extvalue));
|
this.requestContentType = requestContentType;
|
||||||
ASN1OctetStringIf cntStr = createProxy(ASN1OctetStringIf.class, "getInstance", keyCntStream.readObject$Object());
|
|
||||||
ASN1InputStreamIf keyIdStream = newProxy(ASN1InputStreamIf.class, new ByteArrayInputStream(cntStr.getOctets()));
|
|
||||||
SubjectKeyIdentifierIf keyId = createProxy(SubjectKeyIdentifierIf.class, "getInstance", keyIdStream.readObject$Object());
|
|
||||||
|
|
||||||
return keyId.getKeyIdentifier();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] getAuthorityKeyId(X509Certificate cert) throws Exception {
|
/**
|
||||||
// X509Extensions.AuthorityKeyIdentifier.getId()
|
* usually the response content type is "application/timestamp-reply",
|
||||||
byte[] extvalue = cert.getExtensionValue("2.5.29.35");
|
* but some timestamp server use a different content type
|
||||||
if (extvalue == null) return null;
|
*/
|
||||||
|
public void setResponseContentType(String responseContentType) {
|
||||||
ASN1InputStreamIf keyCntStream = newProxy(ASN1InputStreamIf.class, new ByteArrayInputStream(extvalue));
|
this.responseContentType = responseContentType;
|
||||||
DEROctetStringIf cntStr = keyCntStream.readObject$DERString();
|
|
||||||
ASN1InputStreamIf keyIdStream = newProxy(ASN1InputStreamIf.class, new ByteArrayInputStream(cntStr.getOctets()));
|
|
||||||
AuthorityKeyIdentifierIf keyId = newProxy(AuthorityKeyIdentifierIf.class, keyIdStream.readObject$Sequence());
|
|
||||||
|
|
||||||
return keyId.getKeyIdentifier();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -24,20 +24,25 @@
|
|||||||
|
|
||||||
package org.apache.poi.poifs.crypt.dsig.services;
|
package org.apache.poi.poifs.crypt.dsig.services;
|
||||||
|
|
||||||
|
import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlDSigNS;
|
||||||
|
import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlNS;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.Key;
|
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.NoSuchProviderException;
|
import java.security.NoSuchProviderException;
|
||||||
|
import java.security.PrivateKey;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@ -45,7 +50,6 @@ import java.util.UUID;
|
|||||||
import javax.xml.crypto.MarshalException;
|
import javax.xml.crypto.MarshalException;
|
||||||
import javax.xml.crypto.URIDereferencer;
|
import javax.xml.crypto.URIDereferencer;
|
||||||
import javax.xml.crypto.XMLStructure;
|
import javax.xml.crypto.XMLStructure;
|
||||||
import javax.xml.crypto.dom.DOMCryptoContext;
|
|
||||||
import javax.xml.crypto.dsig.CanonicalizationMethod;
|
import javax.xml.crypto.dsig.CanonicalizationMethod;
|
||||||
import javax.xml.crypto.dsig.DigestMethod;
|
import javax.xml.crypto.dsig.DigestMethod;
|
||||||
import javax.xml.crypto.dsig.Manifest;
|
import javax.xml.crypto.dsig.Manifest;
|
||||||
@ -57,11 +61,12 @@ import javax.xml.crypto.dsig.XMLSignContext;
|
|||||||
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
||||||
import javax.xml.crypto.dsig.dom.DOMSignContext;
|
import javax.xml.crypto.dsig.dom.DOMSignContext;
|
||||||
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
|
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
import javax.xml.transform.TransformerException;
|
import javax.xml.transform.TransformerException;
|
||||||
import javax.xml.transform.TransformerFactoryConfigurationError;
|
import javax.xml.transform.TransformerFactoryConfigurationError;
|
||||||
|
|
||||||
|
import org.apache.jcp.xml.dsig.internal.dom.DOMReference;
|
||||||
|
import org.apache.jcp.xml.dsig.internal.dom.DOMSignedInfo;
|
||||||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
||||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||||
import org.apache.poi.openxml4j.opc.PackageNamespaces;
|
import org.apache.poi.openxml4j.opc.PackageNamespaces;
|
||||||
@ -74,11 +79,6 @@ import org.apache.poi.openxml4j.opc.PackagingURIHelper;
|
|||||||
import org.apache.poi.openxml4j.opc.TargetMode;
|
import org.apache.poi.openxml4j.opc.TargetMode;
|
||||||
import org.apache.poi.poifs.crypt.CryptoFunctions;
|
import org.apache.poi.poifs.crypt.CryptoFunctions;
|
||||||
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DOMReferenceIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DOMSignedInfoIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DOMXMLSignatureIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.XMLSignatureIf;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxy;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.OOXMLURIDereferencer;
|
import org.apache.poi.poifs.crypt.dsig.OOXMLURIDereferencer;
|
||||||
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
|
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.KeyInfoSignatureFacet;
|
||||||
@ -87,19 +87,22 @@ 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.SignatureFacet;
|
||||||
import org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet;
|
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.AddressDTO;
|
||||||
import org.apache.poi.poifs.crypt.dsig.spi.Constants;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo;
|
import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo;
|
||||||
import org.apache.poi.poifs.crypt.dsig.spi.IdentityDTO;
|
import org.apache.poi.poifs.crypt.dsig.spi.IdentityDTO;
|
||||||
import org.apache.poi.util.POILogFactory;
|
import org.apache.poi.util.POILogFactory;
|
||||||
import org.apache.poi.util.POILogger;
|
import org.apache.poi.util.POILogger;
|
||||||
|
import org.apache.xml.security.signature.XMLSignature;
|
||||||
|
import org.apache.xml.security.utils.Base64;
|
||||||
import org.apache.xmlbeans.XmlException;
|
import org.apache.xmlbeans.XmlException;
|
||||||
import org.apache.xmlbeans.XmlOptions;
|
import org.apache.xmlbeans.XmlOptions;
|
||||||
import org.w3.x2000.x09.xmldsig.SignatureDocument;
|
import org.w3.x2000.x09.xmldsig.SignatureDocument;
|
||||||
import org.w3.x2000.x09.xmldsig.SignatureType;
|
|
||||||
import org.w3.x2000.x09.xmldsig.SignatureValueType;
|
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
import org.w3c.dom.NodeList;
|
import org.w3c.dom.NodeList;
|
||||||
|
import org.w3c.dom.events.Event;
|
||||||
|
import org.w3c.dom.events.EventListener;
|
||||||
|
import org.w3c.dom.events.EventTarget;
|
||||||
|
import org.w3c.dom.events.MutationEvent;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
|
||||||
@ -115,18 +118,18 @@ public class XmlSignatureService implements SignatureService {
|
|||||||
private String signatureId = "idPackageSignature";
|
private String signatureId = "idPackageSignature";
|
||||||
private final HashAlgorithm hashAlgo;
|
private final HashAlgorithm hashAlgo;
|
||||||
private final OPCPackage opcPackage;
|
private final OPCPackage opcPackage;
|
||||||
private SignatureDocument sigDoc;
|
// private SignatureDocument sigDoc;
|
||||||
private XAdESSignatureFacet xadesSignatureFacet;
|
private XAdESSignatureFacet xadesSignatureFacet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main constructor.
|
* Main constructor.
|
||||||
*/
|
*/
|
||||||
public XmlSignatureService(HashAlgorithm digestAlgo, OPCPackage opcPackage) {
|
public XmlSignatureService(HashAlgorithm digestAlgo, OPCPackage opcPackage) {
|
||||||
this.signatureFacets = new LinkedList<SignatureFacet>();
|
this.signatureFacets = new ArrayList<SignatureFacet>();
|
||||||
this.signatureNamespacePrefix = null;
|
this.signatureNamespacePrefix = null;
|
||||||
this.hashAlgo = digestAlgo;
|
this.hashAlgo = digestAlgo;
|
||||||
this.opcPackage = opcPackage;
|
this.opcPackage = opcPackage;
|
||||||
this.sigDoc = null;
|
// this.sigDoc = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initFacets(Date clock) {
|
public void initFacets(Date clock) {
|
||||||
@ -228,19 +231,20 @@ public class XmlSignatureService implements SignatureService {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
// protected abstract OutputStream getSignedDocumentOutputStream();
|
// protected abstract OutputStream getSignedDocumentOutputStream();
|
||||||
|
@Override
|
||||||
public DigestInfo preSign(List<DigestInfo> digestInfos,
|
public DigestInfo preSign(Document document, List<DigestInfo> digestInfos,
|
||||||
|
PrivateKey key,
|
||||||
List<X509Certificate> signingCertificateChain,
|
List<X509Certificate> signingCertificateChain,
|
||||||
IdentityDTO identity, AddressDTO address, byte[] photo)
|
IdentityDTO identity, AddressDTO address, byte[] photo)
|
||||||
throws NoSuchAlgorithmException {
|
throws NoSuchAlgorithmException {
|
||||||
SignatureInfo.initXmlProvider();
|
SignatureInfo.initXmlProvider();
|
||||||
|
|
||||||
LOG.log(POILogger.DEBUG, "preSign");
|
LOG.log(POILogger.DEBUG, "preSign");
|
||||||
HashAlgorithm hashAlgo = getSignatureDigestAlgorithm();
|
HashAlgorithm hashAlgo = getSignatureDigestAlgorithm();
|
||||||
|
|
||||||
byte[] digestValue;
|
byte[] digestValue;
|
||||||
try {
|
try {
|
||||||
digestValue = getXmlSignatureDigestValue(hashAlgo, digestInfos, signingCertificateChain);
|
digestValue = getXmlSignatureDigestValue(document, hashAlgo, digestInfos, key, signingCertificateChain);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException("XML signature error: " + e.getMessage(), e);
|
throw new RuntimeException("XML signature error: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
@ -249,78 +253,74 @@ public class XmlSignatureService implements SignatureService {
|
|||||||
return new DigestInfo(digestValue, hashAlgo, description);
|
return new DigestInfo(digestValue, hashAlgo, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void postSign(byte[] signatureValue, List<X509Certificate> signingCertificateChain)
|
@Override
|
||||||
throws IOException {
|
public void postSign(Document document, byte[] signatureValue, List<X509Certificate> signingCertificateChain)
|
||||||
|
throws IOException, MarshalException, ParserConfigurationException, XmlException {
|
||||||
LOG.log(POILogger.DEBUG, "postSign");
|
LOG.log(POILogger.DEBUG, "postSign");
|
||||||
SignatureInfo.initXmlProvider();
|
SignatureInfo.initXmlProvider();
|
||||||
|
|
||||||
/*
|
|
||||||
* Retrieve the intermediate XML signature document from the temporary
|
|
||||||
* data storage.
|
|
||||||
*/
|
|
||||||
SignatureType sigType = sigDoc.getSignature();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check ds:Signature node.
|
* Check ds:Signature node.
|
||||||
*/
|
*/
|
||||||
if (!signatureId.equals(sigType.getId())) {
|
if (!signatureId.equals(document.getDocumentElement().getAttribute("Id"))) {
|
||||||
throw new RuntimeException("ds:Signature not found for @Id: " + signatureId);
|
throw new RuntimeException("ds:Signature not found for @Id: " + signatureId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Insert signature value into the ds:SignatureValue element
|
* Insert signature value into the ds:SignatureValue element
|
||||||
*/
|
*/
|
||||||
SignatureValueType sigVal = sigType.getSignatureValue();
|
NodeList sigValNl = document.getElementsByTagNameNS(XmlDSigNS, "SignatureValue");
|
||||||
sigVal.setByteArrayValue(signatureValue);
|
if (sigValNl.getLength() != 1) {
|
||||||
|
throw new RuntimeException("preSign has to be called before postSign");
|
||||||
|
}
|
||||||
|
sigValNl.item(0).setTextContent(Base64.encode(signatureValue));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allow signature facets to inject their own stuff.
|
* Allow signature facets to inject their own stuff.
|
||||||
*/
|
*/
|
||||||
for (SignatureFacet signatureFacet : this.signatureFacets) {
|
for (SignatureFacet signatureFacet : this.signatureFacets) {
|
||||||
signatureFacet.postSign(sigType, signingCertificateChain);
|
signatureFacet.postSign(document, signingCertificateChain);
|
||||||
}
|
}
|
||||||
|
|
||||||
writeDocument();
|
writeDocument(document);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private byte[] getXmlSignatureDigestValue(HashAlgorithm hashAlgo,
|
private byte[] getXmlSignatureDigestValue(Document document, HashAlgorithm hashAlgo,
|
||||||
List<DigestInfo> digestInfos,
|
List<DigestInfo> digestInfos,
|
||||||
|
PrivateKey privateKey,
|
||||||
List<X509Certificate> signingCertificateChain)
|
List<X509Certificate> signingCertificateChain)
|
||||||
throws ParserConfigurationException, NoSuchAlgorithmException,
|
throws ParserConfigurationException, NoSuchAlgorithmException,
|
||||||
InvalidAlgorithmParameterException, MarshalException,
|
InvalidAlgorithmParameterException, MarshalException,
|
||||||
javax.xml.crypto.dsig.XMLSignatureException,
|
javax.xml.crypto.dsig.XMLSignatureException,
|
||||||
TransformerFactoryConfigurationError, TransformerException,
|
TransformerFactoryConfigurationError, TransformerException,
|
||||||
IOException, SAXException, NoSuchProviderException, XmlException {
|
IOException, SAXException, NoSuchProviderException, XmlException, URISyntaxException {
|
||||||
/*
|
|
||||||
* DOM Document construction.
|
|
||||||
*/
|
|
||||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
|
||||||
dbf.setNamespaceAware(true);
|
|
||||||
Document doc = dbf.newDocumentBuilder().newDocument();
|
|
||||||
|
|
||||||
/*
|
// it's necessary to explicitly set the mdssi namespace, but the sign() method has no
|
||||||
* Signature context construction.
|
// normal way to interfere with, so we need to add the namespace under the hand ...
|
||||||
*/
|
final EventTarget et = (EventTarget)document;
|
||||||
Key key = new Key() {
|
EventListener myModificationListener = new EventListener() {
|
||||||
private static final long serialVersionUID = 1L;
|
@Override
|
||||||
|
public void handleEvent(Event e) {
|
||||||
public String getAlgorithm() {
|
if (e instanceof MutationEvent) {
|
||||||
return null;
|
MutationEvent mutEvt = (MutationEvent)e;
|
||||||
}
|
if (mutEvt.getTarget() instanceof Element) {
|
||||||
|
Element el = (Element)mutEvt.getTarget();
|
||||||
public byte[] getEncoded() {
|
if ("idPackageObject".equals(el.getAttribute("Id"))) {
|
||||||
return null;
|
et.removeEventListener("DOMSubtreeModified", this, false);
|
||||||
}
|
el.setAttributeNS(XmlNS, "xmlns:mdssi", PackageNamespaces.DIGITAL_SIGNATURE);
|
||||||
|
}
|
||||||
public String getFormat() {
|
}
|
||||||
return null;
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// As of JDK 7, can't use sigDoc here directly, because the
|
et.addEventListener("DOMSubtreeModified", myModificationListener, false);
|
||||||
// setAttributeID will be called and it's not implemented in xmlbeans
|
|
||||||
XMLSignContext xmlSignContext = new DOMSignContext(key, doc);
|
/*
|
||||||
|
* Signature context construction.
|
||||||
|
*/
|
||||||
|
XMLSignContext xmlSignContext = new DOMSignContext(privateKey, document);
|
||||||
URIDereferencer uriDereferencer = getURIDereferencer();
|
URIDereferencer uriDereferencer = getURIDereferencer();
|
||||||
if (null != uriDereferencer) {
|
if (null != uriDereferencer) {
|
||||||
xmlSignContext.setURIDereferencer(uriDereferencer);
|
xmlSignContext.setURIDereferencer(uriDereferencer);
|
||||||
@ -334,40 +334,34 @@ public class XmlSignatureService implements SignatureService {
|
|||||||
/*
|
/*
|
||||||
* OOo doesn't like ds namespaces so per default prefixing is off.
|
* OOo doesn't like ds namespaces so per default prefixing is off.
|
||||||
*/
|
*/
|
||||||
xmlSignContext.putNamespacePrefix(
|
xmlSignContext.putNamespacePrefix(XmlDSigNS, this.signatureNamespacePrefix);
|
||||||
javax.xml.crypto.dsig.XMLSignature.XMLNS,
|
|
||||||
this.signatureNamespacePrefix);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
XMLSignatureFactory signatureFactory = XMLSignatureFactory.getInstance("DOM", "XMLDSig");
|
XMLSignatureFactory signatureFactory = SignatureInfo.getSignatureFactory();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add ds:References that come from signing client local files.
|
* Add ds:References that come from signing client local files.
|
||||||
*/
|
*/
|
||||||
List<Reference> references = new LinkedList<Reference>();
|
List<Reference> references = new ArrayList<Reference>();
|
||||||
addDigestInfosAsReferences(digestInfos, signatureFactory, references);
|
addDigestInfosAsReferences(digestInfos, signatureFactory, references);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Invoke the signature facets.
|
* Invoke the signature facets.
|
||||||
*/
|
*/
|
||||||
String localSignatureId;
|
String localSignatureId = this.signatureId;
|
||||||
if (null == this.signatureId) {
|
if (localSignatureId == null) {
|
||||||
localSignatureId = "xmldsig-" + UUID.randomUUID().toString();
|
localSignatureId = "xmldsig-" + UUID.randomUUID().toString();
|
||||||
} else {
|
|
||||||
localSignatureId = this.signatureId;
|
|
||||||
}
|
}
|
||||||
List<XMLObject> objects = new LinkedList<XMLObject>();
|
List<XMLObject> objects = new ArrayList<XMLObject>();
|
||||||
for (SignatureFacet signatureFacet : this.signatureFacets) {
|
for (SignatureFacet signatureFacet : this.signatureFacets) {
|
||||||
LOG.log(POILogger.DEBUG, "invoking signature facet: "
|
LOG.log(POILogger.DEBUG, "invoking signature facet: " + signatureFacet.getClass().getSimpleName());
|
||||||
+ signatureFacet.getClass().getSimpleName());
|
signatureFacet.preSign(document, signatureFactory, localSignatureId, signingCertificateChain, references, objects);
|
||||||
signatureFacet.preSign(signatureFactory, localSignatureId, signingCertificateChain, references, objects);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ds:SignedInfo
|
* ds:SignedInfo
|
||||||
*/
|
*/
|
||||||
SignatureMethod signatureMethod = signatureFactory.newSignatureMethod(
|
SignatureMethod signatureMethod = signatureFactory.newSignatureMethod(getSignatureMethod(hashAlgo), null);
|
||||||
getSignatureMethod(hashAlgo), null);
|
|
||||||
CanonicalizationMethod canonicalizationMethod = signatureFactory
|
CanonicalizationMethod canonicalizationMethod = signatureFactory
|
||||||
.newCanonicalizationMethod(getCanonicalizationMethod(),
|
.newCanonicalizationMethod(getCanonicalizationMethod(),
|
||||||
(C14NMethodParameterSpec) null);
|
(C14NMethodParameterSpec) null);
|
||||||
@ -385,20 +379,12 @@ public class XmlSignatureService implements SignatureService {
|
|||||||
/*
|
/*
|
||||||
* ds:Signature Marshalling.
|
* ds:Signature Marshalling.
|
||||||
*/
|
*/
|
||||||
DOMXMLSignatureIf domXmlSignature;
|
xmlSignContext.setDefaultNamespacePrefix(this.signatureNamespacePrefix);
|
||||||
try {
|
// xmlSignContext.putNamespacePrefix(PackageNamespaces.DIGITAL_SIGNATURE, "mdssi");
|
||||||
domXmlSignature = HorribleProxy.newProxy(DOMXMLSignatureIf.class, xmlSignature);
|
xmlSignature.sign(xmlSignContext);
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("DomXmlSignature instance error: " + e.getMessage(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
domXmlSignature.marshal(doc, this.signatureNamespacePrefix, (DOMCryptoContext) xmlSignContext);
|
|
||||||
|
|
||||||
registerIds(doc);
|
registerIds(document);
|
||||||
Element el = doc.getElementById("idPackageObject");
|
// document.getElementById("idPackageObject").setAttributeNS(XmlNS, "xmlns:mdssi", PackageNamespaces.DIGITAL_SIGNATURE);
|
||||||
if (el != null) {
|
|
||||||
el.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:mdssi", PackageNamespaces.DIGITAL_SIGNATURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -415,12 +401,7 @@ public class XmlSignatureService implements SignatureService {
|
|||||||
for (Reference manifestReference : manifestReferences) {
|
for (Reference manifestReference : manifestReferences) {
|
||||||
if (manifestReference.getDigestValue() != null) continue;
|
if (manifestReference.getDigestValue() != null) continue;
|
||||||
|
|
||||||
DOMReferenceIf manifestDOMReference;
|
DOMReference manifestDOMReference = (DOMReference)manifestReference;
|
||||||
try {
|
|
||||||
manifestDOMReference = HorribleProxy.newProxy(DOMReferenceIf.class, manifestReference);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("DOMReference instance error: " + e.getMessage(), e);
|
|
||||||
}
|
|
||||||
manifestDOMReference.digest(xmlSignContext);
|
manifestDOMReference.digest(xmlSignContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -431,12 +412,7 @@ public class XmlSignatureService implements SignatureService {
|
|||||||
*/
|
*/
|
||||||
List<Reference> signedInfoReferences = signedInfo.getReferences();
|
List<Reference> signedInfoReferences = signedInfo.getReferences();
|
||||||
for (Reference signedInfoReference : signedInfoReferences) {
|
for (Reference signedInfoReference : signedInfoReferences) {
|
||||||
DOMReferenceIf domReference;
|
DOMReference domReference = (DOMReference)signedInfoReference;
|
||||||
try {
|
|
||||||
domReference = HorribleProxy.newProxy(DOMReferenceIf.class, signedInfoReference);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("DOMReference instance error: " + e.getMessage(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ds:Reference with external digest value
|
// ds:Reference with external digest value
|
||||||
if (domReference.getDigestValue() != null) continue;
|
if (domReference.getDigestValue() != null) continue;
|
||||||
@ -447,20 +423,11 @@ public class XmlSignatureService implements SignatureService {
|
|||||||
/*
|
/*
|
||||||
* Calculation of XML signature digest value.
|
* Calculation of XML signature digest value.
|
||||||
*/
|
*/
|
||||||
DOMSignedInfoIf domSignedInfo;
|
DOMSignedInfo domSignedInfo = (DOMSignedInfo)signedInfo;
|
||||||
try {
|
|
||||||
domSignedInfo = HorribleProxy.newProxy(DOMSignedInfoIf.class, signedInfo);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("DOMSignedInfo instance error: " + e.getMessage(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
|
ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
|
||||||
domSignedInfo.canonicalize(xmlSignContext, dataStream);
|
domSignedInfo.canonicalize(xmlSignContext, dataStream);
|
||||||
byte[] octets = dataStream.toByteArray();
|
byte[] octets = dataStream.toByteArray();
|
||||||
|
|
||||||
sigDoc = SignatureDocument.Factory.parse(doc.getDocumentElement());
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO: we could be using DigestOutputStream here to optimize memory
|
* TODO: we could be using DigestOutputStream here to optimize memory
|
||||||
* usage.
|
* usage.
|
||||||
@ -478,13 +445,13 @@ public class XmlSignatureService implements SignatureService {
|
|||||||
* @param doc
|
* @param doc
|
||||||
*/
|
*/
|
||||||
public void registerIds(Document doc) {
|
public void registerIds(Document doc) {
|
||||||
NodeList nl = doc.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "Object");
|
NodeList nl = doc.getElementsByTagNameNS(XmlDSigNS, "Object");
|
||||||
registerIdAttribute(nl);
|
registerIdAttribute(nl);
|
||||||
nl = doc.getElementsByTagNameNS("http://uri.etsi.org/01903/v1.3.2#", "SignedProperties");
|
nl = doc.getElementsByTagNameNS("http://uri.etsi.org/01903/v1.3.2#", "SignedProperties");
|
||||||
registerIdAttribute(nl);
|
registerIdAttribute(nl);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void registerIdAttribute(NodeList nl) {
|
public static void registerIdAttribute(NodeList nl) {
|
||||||
for (int i=0; i<nl.getLength(); i++) {
|
for (int i=0; i<nl.getLength(); i++) {
|
||||||
Element el = (Element)nl.item(i);
|
Element el = (Element)nl.item(i);
|
||||||
if (el.hasAttribute("Id")) {
|
if (el.hasAttribute("Id")) {
|
||||||
@ -493,12 +460,9 @@ public class XmlSignatureService implements SignatureService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addDigestInfosAsReferences(List<DigestInfo> digestInfos,
|
private void addDigestInfosAsReferences(List<DigestInfo> digestInfos, XMLSignatureFactory signatureFactory, List<Reference> references)
|
||||||
XMLSignatureFactory signatureFactory, List<Reference> references)
|
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, MalformedURLException {
|
||||||
throws NoSuchAlgorithmException,
|
for (DigestInfo digestInfo : safe(digestInfos)) {
|
||||||
InvalidAlgorithmParameterException, MalformedURLException {
|
|
||||||
if (digestInfos == null) return;
|
|
||||||
for (DigestInfo digestInfo : digestInfos) {
|
|
||||||
byte[] documentDigestValue = digestInfo.digestValue;
|
byte[] documentDigestValue = digestInfo.digestValue;
|
||||||
|
|
||||||
DigestMethod digestMethod = signatureFactory.newDigestMethod(
|
DigestMethod digestMethod = signatureFactory.newDigestMethod(
|
||||||
@ -517,19 +481,12 @@ public class XmlSignatureService implements SignatureService {
|
|||||||
throw new RuntimeException("digest algo is null");
|
throw new RuntimeException("digest algo is null");
|
||||||
}
|
}
|
||||||
|
|
||||||
XMLSignatureIf XmlSignature;
|
|
||||||
try {
|
|
||||||
XmlSignature = HorribleProxy.newProxy(XMLSignatureIf.class);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("JDK doesn't support XmlSignature", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (hashAlgo) {
|
switch (hashAlgo) {
|
||||||
case sha1: return XmlSignature.ALGO_ID_SIGNATURE_RSA_SHA1();
|
case sha1: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;
|
||||||
case sha256: return XmlSignature.ALGO_ID_SIGNATURE_RSA_SHA256();
|
case sha256: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256;
|
||||||
case sha384: return XmlSignature.ALGO_ID_SIGNATURE_RSA_SHA384();
|
case sha384: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA384;
|
||||||
case sha512: return XmlSignature.ALGO_ID_SIGNATURE_RSA_SHA512();
|
case sha512: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512;
|
||||||
case ripemd160: return XmlSignature.ALGO_ID_MAC_HMAC_RIPEMD160();
|
case ripemd160: return XMLSignature.ALGO_ID_MAC_HMAC_RIPEMD160;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -549,15 +506,11 @@ public class XmlSignatureService implements SignatureService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SignatureDocument getSignatureDocument() {
|
|
||||||
return sigDoc;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getCanonicalizationMethod() {
|
protected String getCanonicalizationMethod() {
|
||||||
return CanonicalizationMethod.INCLUSIVE;
|
return CanonicalizationMethod.INCLUSIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void writeDocument() throws IOException {
|
protected void writeDocument(Document document) throws IOException, XmlException {
|
||||||
XmlOptions xo = new XmlOptions();
|
XmlOptions xo = new XmlOptions();
|
||||||
Map<String,String> namespaceMap = new HashMap<String,String>();
|
Map<String,String> namespaceMap = new HashMap<String,String>();
|
||||||
for (SignatureFacet sf : this.signatureFacets) {
|
for (SignatureFacet sf : this.signatureFacets) {
|
||||||
@ -594,6 +547,7 @@ public class XmlSignatureService implements SignatureService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OutputStream os = sigPart.getOutputStream();
|
OutputStream os = sigPart.getOutputStream();
|
||||||
|
SignatureDocument sigDoc = SignatureDocument.Factory.parse(document);
|
||||||
sigDoc.save(os, xo);
|
sigDoc.save(os, xo);
|
||||||
os.close();
|
os.close();
|
||||||
|
|
||||||
@ -612,4 +566,9 @@ public class XmlSignatureService implements SignatureService {
|
|||||||
|
|
||||||
sigsPart.addRelationship(sigPartName, TargetMode.INTERNAL, PackageRelationshipTypes.DIGITAL_SIGNATURE);
|
sigsPart.addRelationship(sigPartName, TargetMode.INTERNAL, PackageRelationshipTypes.DIGITAL_SIGNATURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T> List<T> safe(List<T> other) {
|
||||||
|
return other == null ? Collections.EMPTY_LIST : other;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
/* ====================================================================
|
|
||||||
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.dsig.spi;
|
|
||||||
|
|
||||||
public interface Constants {
|
|
||||||
String NamespaceSpecNS = "http://www.w3.org/2000/xmlns/";
|
|
||||||
String SignatureSpecNS = "http://www.w3.org/2000/09/xmldsig#";
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user