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:
Andreas Beeker 2014-08-24 23:06:05 +00:00
parent d0cc2e4267
commit 687194fd91
13 changed files with 365 additions and 458 deletions

View File

@ -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);

View File

@ -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;
} }

View File

@ -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
} }

View File

@ -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() {

View File

@ -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();
} }

View File

@ -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);

View File

@ -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) {

View File

@ -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>();
} }
/** /**

View File

@ -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[]>();
} }
/** /**

View File

@ -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;
} }

View File

@ -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();
} }
} }

View File

@ -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;
}
} }

View File

@ -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#";
}