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