another round of refactoring, limited exception declarations, more javadocs
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1629332 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
ab84e448ca
commit
30d72983d1
@ -34,7 +34,6 @@ import javax.xml.crypto.URIDereferencer;
|
|||||||
import javax.xml.crypto.URIReference;
|
import javax.xml.crypto.URIReference;
|
||||||
import javax.xml.crypto.URIReferenceException;
|
import javax.xml.crypto.URIReferenceException;
|
||||||
import javax.xml.crypto.XMLCryptoContext;
|
import javax.xml.crypto.XMLCryptoContext;
|
||||||
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
|
||||||
|
|
||||||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
||||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||||
@ -54,16 +53,15 @@ public class OOXMLURIDereferencer implements URIDereferencer, SignatureConfigura
|
|||||||
private SignatureConfig signatureConfig;
|
private SignatureConfig signatureConfig;
|
||||||
private URIDereferencer baseUriDereferencer;
|
private URIDereferencer baseUriDereferencer;
|
||||||
|
|
||||||
public OOXMLURIDereferencer() {
|
|
||||||
XMLSignatureFactory xmlSignatureFactory = SignatureInfo.getSignatureFactory();
|
|
||||||
this.baseUriDereferencer = xmlSignatureFactory.getURIDereferencer();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSignatureConfig(SignatureConfig signatureConfig) {
|
public void setSignatureConfig(SignatureConfig signatureConfig) {
|
||||||
this.signatureConfig = signatureConfig;
|
this.signatureConfig = signatureConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Data dereference(URIReference uriReference, XMLCryptoContext context) throws URIReferenceException {
|
public Data dereference(URIReference uriReference, XMLCryptoContext context) throws URIReferenceException {
|
||||||
|
if (baseUriDereferencer == null) {
|
||||||
|
baseUriDereferencer = signatureConfig.getSignatureFactory().getURIDereferencer();
|
||||||
|
}
|
||||||
|
|
||||||
if (null == uriReference) {
|
if (null == uriReference) {
|
||||||
throw new NullPointerException("URIReference cannot be null");
|
throw new NullPointerException("URIReference cannot be null");
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.OO_DIGSIG_NS
|
|||||||
import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.XADES_132_NS;
|
import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.XADES_132_NS;
|
||||||
|
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
|
import java.security.Provider;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@ -32,6 +33,8 @@ import java.util.UUID;
|
|||||||
import javax.xml.crypto.URIDereferencer;
|
import javax.xml.crypto.URIDereferencer;
|
||||||
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.XMLSignatureFactory;
|
||||||
|
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
|
||||||
|
|
||||||
import org.apache.poi.EncryptedDocumentException;
|
import org.apache.poi.EncryptedDocumentException;
|
||||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||||
@ -46,21 +49,28 @@ import org.apache.poi.poifs.crypt.dsig.services.SignaturePolicyService;
|
|||||||
import org.apache.poi.poifs.crypt.dsig.services.TSPTimeStampService;
|
import org.apache.poi.poifs.crypt.dsig.services.TSPTimeStampService;
|
||||||
import org.apache.poi.poifs.crypt.dsig.services.TimeStampService;
|
import org.apache.poi.poifs.crypt.dsig.services.TimeStampService;
|
||||||
import org.apache.poi.poifs.crypt.dsig.services.TimeStampServiceValidator;
|
import org.apache.poi.poifs.crypt.dsig.services.TimeStampServiceValidator;
|
||||||
|
import org.apache.poi.util.POILogFactory;
|
||||||
|
import org.apache.poi.util.POILogger;
|
||||||
import org.w3c.dom.events.EventListener;
|
import org.w3c.dom.events.EventListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class bundles the configuration options used for the existing
|
* This class bundles the configuration options used for the existing
|
||||||
* signature facets.
|
* signature facets.
|
||||||
* Apart of the opc-package (thread local) most values will probably be constant, so
|
* Apart of the thread local members (e.g. opc-package) most values will probably be constant, so
|
||||||
* it might be configured centrally (e.g. by spring)
|
* it might be configured centrally (e.g. by spring)
|
||||||
*/
|
*/
|
||||||
public class SignatureConfig {
|
public class SignatureConfig {
|
||||||
|
|
||||||
|
private static final POILogger LOG = POILogFactory.getLogger(SignatureConfig.class);
|
||||||
|
|
||||||
public static interface SignatureConfigurable {
|
public static interface SignatureConfigurable {
|
||||||
void setSignatureConfig(SignatureConfig signatureConfig);
|
void setSignatureConfig(SignatureConfig signatureConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ThreadLocal<OPCPackage> opcPackage = new ThreadLocal<OPCPackage>();
|
private ThreadLocal<OPCPackage> opcPackage = new ThreadLocal<OPCPackage>();
|
||||||
|
private ThreadLocal<XMLSignatureFactory> signatureFactory = new ThreadLocal<XMLSignatureFactory>();
|
||||||
|
private ThreadLocal<KeyInfoFactory> keyInfoFactory = new ThreadLocal<KeyInfoFactory>();
|
||||||
|
private ThreadLocal<Provider> provider = new ThreadLocal<Provider>();
|
||||||
|
|
||||||
private List<SignatureFacet> signatureFacets = new ArrayList<SignatureFacet>();
|
private List<SignatureFacet> signatureFacets = new ArrayList<SignatureFacet>();
|
||||||
private HashAlgorithm digestAlgo = HashAlgorithm.sha1;
|
private HashAlgorithm digestAlgo = HashAlgorithm.sha1;
|
||||||
@ -72,7 +82,7 @@ public class SignatureConfig {
|
|||||||
* the optional signature policy service used for XAdES-EPES.
|
* the optional signature policy service used for XAdES-EPES.
|
||||||
*/
|
*/
|
||||||
private SignaturePolicyService signaturePolicyService;
|
private SignaturePolicyService signaturePolicyService;
|
||||||
private URIDereferencer uriDereferencer = new OOXMLURIDereferencer();
|
private URIDereferencer uriDereferencer = null;
|
||||||
private String canonicalizationMethod = CanonicalizationMethod.INCLUSIVE;
|
private String canonicalizationMethod = CanonicalizationMethod.INCLUSIVE;
|
||||||
|
|
||||||
private boolean includeEntireCertificateChain = true;
|
private boolean includeEntireCertificateChain = true;
|
||||||
@ -146,13 +156,22 @@ public class SignatureConfig {
|
|||||||
*/
|
*/
|
||||||
Map<String,String> namespacePrefixes = new HashMap<String,String>();
|
Map<String,String> namespacePrefixes = new HashMap<String,String>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inits and checks the config object.
|
||||||
|
* If not set previously, complex configuration properties also get
|
||||||
|
* created/initialized via this initialization call.
|
||||||
|
*
|
||||||
|
* @param onlyValidation if true, only a subset of the properties
|
||||||
|
* is initialized, which are necessary for validation. If false,
|
||||||
|
* also the other properties needed for signing are been taken care of
|
||||||
|
*/
|
||||||
protected void init(boolean onlyValidation) {
|
protected void init(boolean onlyValidation) {
|
||||||
if (uriDereferencer == null) {
|
|
||||||
throw new EncryptedDocumentException("uriDereferencer is null");
|
|
||||||
}
|
|
||||||
if (opcPackage == null) {
|
if (opcPackage == null) {
|
||||||
throw new EncryptedDocumentException("opcPackage is null");
|
throw new EncryptedDocumentException("opcPackage is null");
|
||||||
}
|
}
|
||||||
|
if (uriDereferencer == null) {
|
||||||
|
uriDereferencer = new OOXMLURIDereferencer();
|
||||||
|
}
|
||||||
if (uriDereferencer instanceof SignatureConfigurable) {
|
if (uriDereferencer instanceof SignatureConfigurable) {
|
||||||
((SignatureConfigurable)uriDereferencer).setSignatureConfig(this);
|
((SignatureConfigurable)uriDereferencer).setSignatureConfig(this);
|
||||||
}
|
}
|
||||||
@ -195,68 +214,155 @@ public class SignatureConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addSignatureFacet(SignatureFacet sf) {
|
/**
|
||||||
signatureFacets.add(sf);
|
* @param signatureFacet the signature facet is appended to facet list
|
||||||
|
*/
|
||||||
|
public void addSignatureFacet(SignatureFacet signatureFacet) {
|
||||||
|
signatureFacets.add(signatureFacet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the list of facets, may be empty when the config object is not initialized
|
||||||
|
*/
|
||||||
public List<SignatureFacet> getSignatureFacets() {
|
public List<SignatureFacet> getSignatureFacets() {
|
||||||
return signatureFacets;
|
return signatureFacets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param signatureFacets the new list of facets
|
||||||
|
*/
|
||||||
public void setSignatureFacets(List<SignatureFacet> signatureFacets) {
|
public void setSignatureFacets(List<SignatureFacet> signatureFacets) {
|
||||||
this.signatureFacets = signatureFacets;
|
this.signatureFacets = signatureFacets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the main digest algorithm, defaults to sha-1
|
||||||
|
*/
|
||||||
public HashAlgorithm getDigestAlgo() {
|
public HashAlgorithm getDigestAlgo() {
|
||||||
return digestAlgo;
|
return digestAlgo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param digestAlgo the main digest algorithm
|
||||||
|
*/
|
||||||
public void setDigestAlgo(HashAlgorithm digestAlgo) {
|
public void setDigestAlgo(HashAlgorithm digestAlgo) {
|
||||||
this.digestAlgo = digestAlgo;
|
this.digestAlgo = digestAlgo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the opc package to be used by this thread, stored as thread-local
|
||||||
|
*/
|
||||||
public OPCPackage getOpcPackage() {
|
public OPCPackage getOpcPackage() {
|
||||||
return opcPackage.get();
|
return opcPackage.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param opcPackage the opc package to be handled by this thread, stored as thread-local
|
||||||
|
*/
|
||||||
public void setOpcPackage(OPCPackage opcPackage) {
|
public void setOpcPackage(OPCPackage opcPackage) {
|
||||||
this.opcPackage.set(opcPackage);
|
this.opcPackage.set(opcPackage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the private key
|
||||||
|
*/
|
||||||
public PrivateKey getKey() {
|
public PrivateKey getKey() {
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param key the private key
|
||||||
|
*/
|
||||||
public void setKey(PrivateKey key) {
|
public void setKey(PrivateKey key) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the certificate chain, index 0 is usually the certificate matching
|
||||||
|
* the private key
|
||||||
|
*/
|
||||||
public List<X509Certificate> getSigningCertificateChain() {
|
public List<X509Certificate> getSigningCertificateChain() {
|
||||||
return signingCertificateChain;
|
return signingCertificateChain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param signingCertificateChain the certificate chain, index 0 should be
|
||||||
|
* the certificate matching the private key
|
||||||
|
*/
|
||||||
public void setSigningCertificateChain(
|
public void setSigningCertificateChain(
|
||||||
List<X509Certificate> signingCertificateChain) {
|
List<X509Certificate> signingCertificateChain) {
|
||||||
this.signingCertificateChain = signingCertificateChain;
|
this.signingCertificateChain = signingCertificateChain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the time at which the document is signed, also used for the timestamp service.
|
||||||
|
* defaults to now
|
||||||
|
*/
|
||||||
public Date getExecutionTime() {
|
public Date getExecutionTime() {
|
||||||
return executionTime;
|
return executionTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param executionTime sets the time at which the document ought to be signed
|
||||||
|
*/
|
||||||
public void setExecutionTime(Date executionTime) {
|
public void setExecutionTime(Date executionTime) {
|
||||||
this.executionTime = executionTime;
|
this.executionTime = executionTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the service to be used for XAdES-EPES properties. There's no default implementation
|
||||||
|
*/
|
||||||
public SignaturePolicyService getSignaturePolicyService() {
|
public SignaturePolicyService getSignaturePolicyService() {
|
||||||
return signaturePolicyService;
|
return signaturePolicyService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param signaturePolicyService the service to be used for XAdES-EPES properties
|
||||||
|
*/
|
||||||
public void setSignaturePolicyService(SignaturePolicyService signaturePolicyService) {
|
public void setSignaturePolicyService(SignaturePolicyService signaturePolicyService) {
|
||||||
this.signaturePolicyService = signaturePolicyService;
|
this.signaturePolicyService = signaturePolicyService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the dereferencer used for Reference/@URI attributes, defaults to {@link OOXMLURIDereferencer}
|
||||||
|
*/
|
||||||
public URIDereferencer getUriDereferencer() {
|
public URIDereferencer getUriDereferencer() {
|
||||||
return uriDereferencer;
|
return uriDereferencer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param uriDereferencer the dereferencer used for Reference/@URI attributes
|
||||||
|
*/
|
||||||
public void setUriDereferencer(URIDereferencer uriDereferencer) {
|
public void setUriDereferencer(URIDereferencer uriDereferencer) {
|
||||||
this.uriDereferencer = uriDereferencer;
|
this.uriDereferencer = uriDereferencer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Gives back the human-readable description of what the citizen
|
||||||
|
* will be signing. The default value is "Office OpenXML Document".
|
||||||
|
*/
|
||||||
public String getSignatureDescription() {
|
public String getSignatureDescription() {
|
||||||
return signatureDescription;
|
return signatureDescription;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param signatureDescription the human-readable description of
|
||||||
|
* what the citizen will be signing.
|
||||||
|
*/
|
||||||
public void setSignatureDescription(String signatureDescription) {
|
public void setSignatureDescription(String signatureDescription) {
|
||||||
this.signatureDescription = signatureDescription;
|
this.signatureDescription = signatureDescription;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the default canonicalization method, defaults to INCLUSIVE
|
||||||
|
*/
|
||||||
public String getCanonicalizationMethod() {
|
public String getCanonicalizationMethod() {
|
||||||
return canonicalizationMethod;
|
return canonicalizationMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param canonicalizationMethod the default canonicalization method
|
||||||
|
*/
|
||||||
public void setCanonicalizationMethod(String canonicalizationMethod) {
|
public void setCanonicalizationMethod(String canonicalizationMethod) {
|
||||||
this.canonicalizationMethod = canonicalizationMethod;
|
this.canonicalizationMethod = canonicalizationMethod;
|
||||||
}
|
}
|
||||||
@ -469,4 +575,59 @@ public class SignatureConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSignatureFactory(XMLSignatureFactory signatureFactory) {
|
||||||
|
this.signatureFactory.set(signatureFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
public XMLSignatureFactory getSignatureFactory() {
|
||||||
|
XMLSignatureFactory sigFac = signatureFactory.get();
|
||||||
|
if (sigFac == null) {
|
||||||
|
sigFac = XMLSignatureFactory.getInstance("DOM", getProvider());
|
||||||
|
setSignatureFactory(sigFac);
|
||||||
|
}
|
||||||
|
return sigFac;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKeyInfoFactory(KeyInfoFactory keyInfoFactory) {
|
||||||
|
this.keyInfoFactory.set(keyInfoFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeyInfoFactory getKeyInfoFactory() {
|
||||||
|
KeyInfoFactory keyFac = keyInfoFactory.get();
|
||||||
|
if (keyFac == null) {
|
||||||
|
keyFac = KeyInfoFactory.getInstance("DOM", getProvider());
|
||||||
|
setKeyInfoFactory(keyFac);
|
||||||
|
}
|
||||||
|
return keyFac;
|
||||||
|
}
|
||||||
|
|
||||||
|
// currently classes are linked to Apache Santuario, so this might be superfluous
|
||||||
|
public Provider getProvider() {
|
||||||
|
Provider prov = provider.get();
|
||||||
|
if (prov == null) {
|
||||||
|
String dsigProviderNames[] = {
|
||||||
|
System.getProperty("jsr105Provider"),
|
||||||
|
"org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI", // Santuario xmlsec
|
||||||
|
"org.jcp.xml.dsig.internal.dom.XMLDSigRI" // JDK xmlsec
|
||||||
|
};
|
||||||
|
for (String pn : dsigProviderNames) {
|
||||||
|
if (pn == null) continue;
|
||||||
|
try {
|
||||||
|
prov = (Provider)Class.forName(pn).newInstance();
|
||||||
|
break;
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.log(POILogger.DEBUG, "XMLDsig-Provider '"+pn+"' can't be found - trying next.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prov == null) {
|
||||||
|
throw new RuntimeException("JRE doesn't support default xml signature provider - set jsr105Provider system property!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return prov;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -30,12 +30,8 @@ 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.URISyntaxException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.NoSuchProviderException;
|
|
||||||
import java.security.Provider;
|
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -50,7 +46,6 @@ 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.dsig.CanonicalizationMethod;
|
import javax.xml.crypto.dsig.CanonicalizationMethod;
|
||||||
import javax.xml.crypto.dsig.DigestMethod;
|
|
||||||
import javax.xml.crypto.dsig.Manifest;
|
import javax.xml.crypto.dsig.Manifest;
|
||||||
import javax.xml.crypto.dsig.Reference;
|
import javax.xml.crypto.dsig.Reference;
|
||||||
import javax.xml.crypto.dsig.SignatureMethod;
|
import javax.xml.crypto.dsig.SignatureMethod;
|
||||||
@ -62,11 +57,7 @@ import javax.xml.crypto.dsig.XMLSignatureException;
|
|||||||
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.dom.DOMValidateContext;
|
import javax.xml.crypto.dsig.dom.DOMValidateContext;
|
||||||
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
|
|
||||||
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
|
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
|
||||||
import javax.xml.transform.TransformerException;
|
|
||||||
import javax.xml.transform.TransformerFactoryConfigurationError;
|
|
||||||
import javax.xml.xpath.XPath;
|
import javax.xml.xpath.XPath;
|
||||||
import javax.xml.xpath.XPathConstants;
|
import javax.xml.xpath.XPathConstants;
|
||||||
import javax.xml.xpath.XPathFactory;
|
import javax.xml.xpath.XPathFactory;
|
||||||
@ -103,7 +94,6 @@ import org.w3c.dom.Element;
|
|||||||
import org.w3c.dom.NodeList;
|
import org.w3c.dom.NodeList;
|
||||||
import org.w3c.dom.events.EventListener;
|
import org.w3c.dom.events.EventListener;
|
||||||
import org.w3c.dom.events.EventTarget;
|
import org.w3c.dom.events.EventTarget;
|
||||||
import org.xml.sax.SAXException;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -144,7 +134,7 @@ import org.xml.sax.SAXException;
|
|||||||
* SignatureConfig signatureConfig = new SignatureConfig();
|
* SignatureConfig signatureConfig = new SignatureConfig();
|
||||||
* signatureConfig.setKey(keyPair.getPrivate());
|
* signatureConfig.setKey(keyPair.getPrivate());
|
||||||
* signatureConfig.setSigningCertificateChain(Collections.singletonList(x509));
|
* signatureConfig.setSigningCertificateChain(Collections.singletonList(x509));
|
||||||
* OPCPackage pkg = OPCPackage.open(..., PackageAccess.READ);
|
* OPCPackage pkg = OPCPackage.open(..., PackageAccess.READ_WRITE);
|
||||||
* signatureConfig.setOpcPackage(pkg);
|
* signatureConfig.setOpcPackage(pkg);
|
||||||
*
|
*
|
||||||
* // adding the signature document to the package
|
* // adding the signature document to the package
|
||||||
@ -220,7 +210,7 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||||||
domValidateContext.setProperty("org.jcp.xml.dsig.validateManifests", Boolean.TRUE);
|
domValidateContext.setProperty("org.jcp.xml.dsig.validateManifests", Boolean.TRUE);
|
||||||
domValidateContext.setURIDereferencer(signatureConfig.getUriDereferencer());
|
domValidateContext.setURIDereferencer(signatureConfig.getUriDereferencer());
|
||||||
|
|
||||||
XMLSignatureFactory xmlSignatureFactory = getSignatureFactory();
|
XMLSignatureFactory xmlSignatureFactory = signatureConfig.getSignatureFactory();
|
||||||
XMLSignature xmlSignature = xmlSignatureFactory.unmarshalXMLSignature(domValidateContext);
|
XMLSignature xmlSignature = xmlSignatureFactory.unmarshalXMLSignature(domValidateContext);
|
||||||
boolean valid = xmlSignature.validate(domValidateContext);
|
boolean valid = xmlSignature.validate(domValidateContext);
|
||||||
|
|
||||||
@ -258,8 +248,7 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void confirmSignature()
|
public void confirmSignature() throws XMLSignatureException, MarshalException {
|
||||||
throws NoSuchAlgorithmException, IOException, MarshalException, ParserConfigurationException, XmlException, InvalidAlgorithmParameterException, NoSuchProviderException, XMLSignatureException, TransformerFactoryConfigurationError, TransformerException, SAXException, URISyntaxException {
|
|
||||||
Document document = DocumentHelper.createDocument();
|
Document document = DocumentHelper.createDocument();
|
||||||
|
|
||||||
// operate
|
// operate
|
||||||
@ -335,33 +324,6 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static XMLSignatureFactory getSignatureFactory() {
|
|
||||||
return XMLSignatureFactory.getInstance("DOM", getProvider());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static KeyInfoFactory getKeyInfoFactory() {
|
|
||||||
return KeyInfoFactory.getInstance("DOM", getProvider());
|
|
||||||
}
|
|
||||||
|
|
||||||
// currently classes are linked to Apache Santuario, so this might be superfluous
|
|
||||||
public static Provider getProvider() {
|
|
||||||
String dsigProviderNames[] = {
|
|
||||||
System.getProperty("jsr105Provider"),
|
|
||||||
"org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI", // Santuario xmlsec
|
|
||||||
"org.jcp.xml.dsig.internal.dom.XMLDSigRI" // JDK xmlsec
|
|
||||||
};
|
|
||||||
for (String pn : dsigProviderNames) {
|
|
||||||
if (pn == null) continue;
|
|
||||||
try {
|
|
||||||
return (Provider)Class.forName(pn).newInstance();
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOG.log(POILogger.DEBUG, "XMLDsig-Provider '"+pn+"' can't be found - trying next.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new RuntimeException("JRE doesn't support default xml signature provider - set jsr105Provider system property!");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static synchronized void initXmlProvider() {
|
protected static synchronized void initXmlProvider() {
|
||||||
if (isInitialized) return;
|
if (isInitialized) return;
|
||||||
isInitialized = true;
|
isInitialized = true;
|
||||||
@ -381,11 +343,7 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public DigestInfo preSign(Document document, List<DigestInfo> digestInfos)
|
public DigestInfo preSign(Document document, List<DigestInfo> digestInfos)
|
||||||
throws ParserConfigurationException, NoSuchAlgorithmException,
|
throws XMLSignatureException, MarshalException {
|
||||||
InvalidAlgorithmParameterException, MarshalException,
|
|
||||||
javax.xml.crypto.dsig.XMLSignatureException,
|
|
||||||
TransformerFactoryConfigurationError, TransformerException,
|
|
||||||
IOException, SAXException, NoSuchProviderException, XmlException, URISyntaxException {
|
|
||||||
signatureConfig.init(false);
|
signatureConfig.init(false);
|
||||||
|
|
||||||
// it's necessary to explicitly set the mdssi namespace, but the sign() method has no
|
// it's necessary to explicitly set the mdssi namespace, but the sign() method has no
|
||||||
@ -413,7 +371,7 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||||||
}
|
}
|
||||||
xmlSignContext.setDefaultNamespacePrefix(""); // signatureConfig.getNamespacePrefixes().get(XML_DIGSIG_NS));
|
xmlSignContext.setDefaultNamespacePrefix(""); // signatureConfig.getNamespacePrefixes().get(XML_DIGSIG_NS));
|
||||||
|
|
||||||
XMLSignatureFactory signatureFactory = SignatureInfo.getSignatureFactory();
|
XMLSignatureFactory signatureFactory = signatureConfig.getSignatureFactory();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add ds:References that come from signing client local files.
|
* Add ds:References that come from signing client local files.
|
||||||
@ -422,13 +380,9 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||||||
for (DigestInfo digestInfo : safe(digestInfos)) {
|
for (DigestInfo digestInfo : safe(digestInfos)) {
|
||||||
byte[] documentDigestValue = digestInfo.digestValue;
|
byte[] documentDigestValue = digestInfo.digestValue;
|
||||||
|
|
||||||
DigestMethod digestMethod = signatureFactory.newDigestMethod
|
|
||||||
(signatureConfig.getDigestMethodUri(), null);
|
|
||||||
|
|
||||||
String uri = new File(digestInfo.description).getName();
|
String uri = new File(digestInfo.description).getName();
|
||||||
|
Reference reference = SignatureFacet.newReference
|
||||||
Reference reference = signatureFactory.newReference
|
(uri, null, null, null, documentDigestValue, signatureConfig);
|
||||||
(uri, digestMethod, null, null, null, documentDigestValue);
|
|
||||||
references.add(reference);
|
references.add(reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,19 +392,24 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||||||
List<XMLObject> objects = new ArrayList<XMLObject>();
|
List<XMLObject> objects = new ArrayList<XMLObject>();
|
||||||
for (SignatureFacet signatureFacet : signatureConfig.getSignatureFacets()) {
|
for (SignatureFacet signatureFacet : signatureConfig.getSignatureFacets()) {
|
||||||
LOG.log(POILogger.DEBUG, "invoking signature facet: " + signatureFacet.getClass().getSimpleName());
|
LOG.log(POILogger.DEBUG, "invoking signature facet: " + signatureFacet.getClass().getSimpleName());
|
||||||
signatureFacet.preSign(document, signatureFactory, references, objects);
|
signatureFacet.preSign(document, references, objects);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ds:SignedInfo
|
* ds:SignedInfo
|
||||||
*/
|
*/
|
||||||
SignatureMethod signatureMethod = signatureFactory.newSignatureMethod
|
SignedInfo signedInfo;
|
||||||
(signatureConfig.getSignatureMethod(), null);
|
try {
|
||||||
CanonicalizationMethod canonicalizationMethod = signatureFactory
|
SignatureMethod signatureMethod = signatureFactory.newSignatureMethod
|
||||||
.newCanonicalizationMethod(signatureConfig.getCanonicalizationMethod(),
|
(signatureConfig.getSignatureMethod(), null);
|
||||||
(C14NMethodParameterSpec) null);
|
CanonicalizationMethod canonicalizationMethod = signatureFactory
|
||||||
SignedInfo signedInfo = signatureFactory.newSignedInfo(
|
.newCanonicalizationMethod(signatureConfig.getCanonicalizationMethod(),
|
||||||
canonicalizationMethod, signatureMethod, references);
|
(C14NMethodParameterSpec) null);
|
||||||
|
signedInfo = signatureFactory.newSignedInfo(
|
||||||
|
canonicalizationMethod, signatureMethod, references);
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
throw new XMLSignatureException(e);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* JSR105 ds:Signature creation
|
* JSR105 ds:Signature creation
|
||||||
@ -524,7 +483,7 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||||||
* Normally {@link #confirmSignature()} is sufficient to be used.
|
* Normally {@link #confirmSignature()} is sufficient to be used.
|
||||||
*/
|
*/
|
||||||
public void postSign(Document document, byte[] signatureValue)
|
public void postSign(Document document, byte[] signatureValue)
|
||||||
throws IOException, MarshalException, ParserConfigurationException, XmlException {
|
throws MarshalException {
|
||||||
LOG.log(POILogger.DEBUG, "postSign");
|
LOG.log(POILogger.DEBUG, "postSign");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -554,7 +513,7 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||||||
writeDocument(document);
|
writeDocument(document);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void writeDocument(Document document) throws IOException, XmlException {
|
protected void writeDocument(Document document) throws MarshalException {
|
||||||
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(Map.Entry<String,String> entry : signatureConfig.getNamespacePrefixes().entrySet()){
|
for(Map.Entry<String,String> entry : signatureConfig.getNamespacePrefixes().entrySet()){
|
||||||
@ -578,7 +537,7 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||||||
// <Default Extension="sigs" ContentType="application/vnd.openxmlformats-package.digital-signature-origin"/>
|
// <Default Extension="sigs" ContentType="application/vnd.openxmlformats-package.digital-signature-origin"/>
|
||||||
sigsPartName = PackagingURIHelper.createPartName("/_xmlsignatures/origin.sigs");
|
sigsPartName = PackagingURIHelper.createPartName("/_xmlsignatures/origin.sigs");
|
||||||
} catch (InvalidFormatException e) {
|
} catch (InvalidFormatException e) {
|
||||||
throw new IOException(e);
|
throw new MarshalException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
PackagePart sigPart = pkg.getPart(sigPartName);
|
PackagePart sigPart = pkg.getPart(sigPartName);
|
||||||
@ -586,10 +545,14 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||||||
sigPart = pkg.createPart(sigPartName, ContentTypes.DIGITAL_SIGNATURE_XML_SIGNATURE_PART);
|
sigPart = pkg.createPart(sigPartName, ContentTypes.DIGITAL_SIGNATURE_XML_SIGNATURE_PART);
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputStream os = sigPart.getOutputStream();
|
try {
|
||||||
SignatureDocument sigDoc = SignatureDocument.Factory.parse(document);
|
OutputStream os = sigPart.getOutputStream();
|
||||||
sigDoc.save(os, xo);
|
SignatureDocument sigDoc = SignatureDocument.Factory.parse(document);
|
||||||
os.close();
|
sigDoc.save(os, xo);
|
||||||
|
os.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new MarshalException("Unable to write signature document", e);
|
||||||
|
}
|
||||||
|
|
||||||
PackagePart sigsPart = pkg.getPart(sigsPartName);
|
PackagePart sigsPart = pkg.getPart(sigsPartName);
|
||||||
if (sigsPart == null) {
|
if (sigsPart == null) {
|
||||||
|
@ -24,20 +24,15 @@
|
|||||||
|
|
||||||
package org.apache.poi.poifs.crypt.dsig.facets;
|
package org.apache.poi.poifs.crypt.dsig.facets;
|
||||||
|
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.xml.crypto.dsig.CanonicalizationMethod;
|
import javax.xml.crypto.dsig.CanonicalizationMethod;
|
||||||
import javax.xml.crypto.dsig.DigestMethod;
|
|
||||||
import javax.xml.crypto.dsig.Reference;
|
import javax.xml.crypto.dsig.Reference;
|
||||||
import javax.xml.crypto.dsig.Transform;
|
import javax.xml.crypto.dsig.Transform;
|
||||||
import javax.xml.crypto.dsig.XMLObject;
|
import javax.xml.crypto.dsig.XMLObject;
|
||||||
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
import javax.xml.crypto.dsig.XMLSignatureException;
|
||||||
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
|
|
||||||
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.SignatureConfig;
|
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -46,39 +41,20 @@ import org.w3c.dom.Document;
|
|||||||
* @author Frank Cornelis
|
* @author Frank Cornelis
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class EnvelopedSignatureFacet implements SignatureFacet {
|
public class EnvelopedSignatureFacet extends SignatureFacet {
|
||||||
|
|
||||||
private SignatureConfig signatureConfig;
|
|
||||||
|
|
||||||
public void setSignatureConfig(SignatureConfig signatureConfig) {
|
|
||||||
this.signatureConfig = signatureConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void postSign(Document document) {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void preSign(Document document
|
public void preSign(Document document
|
||||||
, XMLSignatureFactory signatureFactory
|
|
||||||
, List<Reference> references
|
, List<Reference> references
|
||||||
, List<XMLObject> objects)
|
, List<XMLObject> objects)
|
||||||
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
|
throws XMLSignatureException {
|
||||||
DigestMethod digestMethod = signatureFactory.newDigestMethod
|
|
||||||
(signatureConfig.getDigestMethodUri(), null);
|
|
||||||
|
|
||||||
List<Transform> transforms = new ArrayList<Transform>();
|
List<Transform> transforms = new ArrayList<Transform>();
|
||||||
Transform envelopedTransform = signatureFactory.newTransform
|
Transform envelopedTransform = newTransform(CanonicalizationMethod.ENVELOPED);
|
||||||
(CanonicalizationMethod.ENVELOPED, (TransformParameterSpec) null);
|
|
||||||
transforms.add(envelopedTransform);
|
transforms.add(envelopedTransform);
|
||||||
Transform exclusiveTransform = signatureFactory.newTransform
|
Transform exclusiveTransform = newTransform(CanonicalizationMethod.EXCLUSIVE);
|
||||||
(CanonicalizationMethod.EXCLUSIVE, (TransformParameterSpec) null);
|
|
||||||
transforms.add(exclusiveTransform);
|
transforms.add(exclusiveTransform);
|
||||||
|
|
||||||
Reference reference = signatureFactory.newReference("", digestMethod,
|
Reference reference = newReference("", transforms, null, null, null);
|
||||||
transforms, null, null);
|
|
||||||
|
|
||||||
references.add(reference);
|
references.add(reference);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,10 +24,8 @@
|
|||||||
|
|
||||||
package org.apache.poi.poifs.crypt.dsig.facets;
|
package org.apache.poi.poifs.crypt.dsig.facets;
|
||||||
|
|
||||||
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.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -35,9 +33,6 @@ import java.util.Map;
|
|||||||
|
|
||||||
import javax.xml.crypto.MarshalException;
|
import javax.xml.crypto.MarshalException;
|
||||||
import javax.xml.crypto.dom.DOMStructure;
|
import javax.xml.crypto.dom.DOMStructure;
|
||||||
import javax.xml.crypto.dsig.Reference;
|
|
||||||
import javax.xml.crypto.dsig.XMLObject;
|
|
||||||
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.keyinfo.KeyInfo;
|
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
|
||||||
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
|
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
|
||||||
@ -45,8 +40,6 @@ import javax.xml.crypto.dsig.keyinfo.KeyValue;
|
|||||||
import javax.xml.crypto.dsig.keyinfo.X509Data;
|
import javax.xml.crypto.dsig.keyinfo.X509Data;
|
||||||
|
|
||||||
import org.apache.jcp.xml.dsig.internal.dom.DOMKeyInfo;
|
import org.apache.jcp.xml.dsig.internal.dom.DOMKeyInfo;
|
||||||
import org.apache.poi.poifs.crypt.dsig.SignatureConfig;
|
|
||||||
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.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
@ -60,16 +53,10 @@ import org.w3c.dom.NodeList;
|
|||||||
* @author Frank Cornelis
|
* @author Frank Cornelis
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class KeyInfoSignatureFacet implements SignatureFacet {
|
public class KeyInfoSignatureFacet extends SignatureFacet {
|
||||||
|
|
||||||
private static final POILogger LOG = POILogFactory.getLogger(KeyInfoSignatureFacet.class);
|
private static final POILogger LOG = POILogFactory.getLogger(KeyInfoSignatureFacet.class);
|
||||||
|
|
||||||
SignatureConfig signatureConfig;
|
|
||||||
|
|
||||||
public void setSignatureConfig(SignatureConfig signatureConfig) {
|
|
||||||
this.signatureConfig = signatureConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postSign(Document document)
|
public void postSign(Document document)
|
||||||
throws MarshalException {
|
throws MarshalException {
|
||||||
@ -86,7 +73,7 @@ public class KeyInfoSignatureFacet implements SignatureFacet {
|
|||||||
/*
|
/*
|
||||||
* Construct the ds:KeyInfo element using JSR 105.
|
* Construct the ds:KeyInfo element using JSR 105.
|
||||||
*/
|
*/
|
||||||
KeyInfoFactory keyInfoFactory = SignatureInfo.getKeyInfoFactory();
|
KeyInfoFactory keyInfoFactory = signatureConfig.getKeyInfoFactory();
|
||||||
List<Object> x509DataObjects = new ArrayList<Object>();
|
List<Object> x509DataObjects = new ArrayList<Object>();
|
||||||
X509Certificate signingCertificate = signatureConfig.getSigningCertificateChain().get(0);
|
X509Certificate signingCertificate = signatureConfig.getSigningCertificateChain().get(0);
|
||||||
|
|
||||||
@ -104,8 +91,8 @@ public class KeyInfoSignatureFacet implements SignatureFacet {
|
|||||||
|
|
||||||
if (signatureConfig.isIncludeIssuerSerial()) {
|
if (signatureConfig.isIncludeIssuerSerial()) {
|
||||||
x509DataObjects.add(keyInfoFactory.newX509IssuerSerial(
|
x509DataObjects.add(keyInfoFactory.newX509IssuerSerial(
|
||||||
signingCertificate.getIssuerX500Principal().toString(),
|
signingCertificate.getIssuerX500Principal().toString(),
|
||||||
signingCertificate.getSerialNumber()));
|
signingCertificate.getSerialNumber()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signatureConfig.isIncludeEntireCertificateChain()) {
|
if (signatureConfig.isIncludeEntireCertificateChain()) {
|
||||||
@ -155,14 +142,4 @@ public class KeyInfoSignatureFacet implements SignatureFacet {
|
|||||||
nextSibling.getParentNode().insertBefore(kiNl.item(0), nextSibling);
|
nextSibling.getParentNode().insertBefore(kiNl.item(0), nextSibling);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void preSign(
|
|
||||||
Document document
|
|
||||||
, XMLSignatureFactory signatureFactory
|
|
||||||
, List<Reference> references
|
|
||||||
, List<XMLObject> objects
|
|
||||||
) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -24,11 +24,8 @@
|
|||||||
|
|
||||||
package org.apache.poi.poifs.crypt.dsig.facets;
|
package org.apache.poi.poifs.crypt.dsig.facets;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -41,15 +38,13 @@ import javax.xml.XMLConstants;
|
|||||||
import javax.xml.crypto.XMLStructure;
|
import javax.xml.crypto.XMLStructure;
|
||||||
import javax.xml.crypto.dom.DOMStructure;
|
import javax.xml.crypto.dom.DOMStructure;
|
||||||
import javax.xml.crypto.dsig.CanonicalizationMethod;
|
import javax.xml.crypto.dsig.CanonicalizationMethod;
|
||||||
import javax.xml.crypto.dsig.DigestMethod;
|
|
||||||
import javax.xml.crypto.dsig.Manifest;
|
import javax.xml.crypto.dsig.Manifest;
|
||||||
import javax.xml.crypto.dsig.Reference;
|
import javax.xml.crypto.dsig.Reference;
|
||||||
import javax.xml.crypto.dsig.SignatureProperties;
|
import javax.xml.crypto.dsig.SignatureProperties;
|
||||||
import javax.xml.crypto.dsig.SignatureProperty;
|
import javax.xml.crypto.dsig.SignatureProperty;
|
||||||
import javax.xml.crypto.dsig.Transform;
|
import javax.xml.crypto.dsig.Transform;
|
||||||
import javax.xml.crypto.dsig.XMLObject;
|
import javax.xml.crypto.dsig.XMLObject;
|
||||||
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
import javax.xml.crypto.dsig.XMLSignatureException;
|
||||||
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
|
|
||||||
|
|
||||||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
||||||
import org.apache.poi.openxml4j.opc.ContentTypes;
|
import org.apache.poi.openxml4j.opc.ContentTypes;
|
||||||
@ -60,12 +55,10 @@ import org.apache.poi.openxml4j.opc.PackageRelationship;
|
|||||||
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
|
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
|
||||||
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
|
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.dsig.SignatureConfig;
|
|
||||||
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.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.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.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
@ -80,64 +73,50 @@ import com.microsoft.schemas.office.x2006.digsig.SignatureInfoV1Document;
|
|||||||
* @author fcorneli
|
* @author fcorneli
|
||||||
* @see <a href="http://msdn.microsoft.com/en-us/library/cc313071.aspx">[MS-OFFCRYPTO]: Office Document Cryptography Structure</a>
|
* @see <a href="http://msdn.microsoft.com/en-us/library/cc313071.aspx">[MS-OFFCRYPTO]: Office Document Cryptography Structure</a>
|
||||||
*/
|
*/
|
||||||
public class OOXMLSignatureFacet implements SignatureFacet {
|
public class OOXMLSignatureFacet extends SignatureFacet {
|
||||||
|
|
||||||
private static final POILogger LOG = POILogFactory.getLogger(OOXMLSignatureFacet.class);
|
private static final POILogger LOG = POILogFactory.getLogger(OOXMLSignatureFacet.class);
|
||||||
|
|
||||||
private SignatureConfig signatureConfig;
|
|
||||||
|
|
||||||
public void setSignatureConfig(SignatureConfig signatureConfig) {
|
|
||||||
this.signatureConfig = signatureConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void preSign(
|
public void preSign(
|
||||||
Document document
|
Document document
|
||||||
, XMLSignatureFactory signatureFactory
|
|
||||||
, List<Reference> references
|
, List<Reference> references
|
||||||
, List<XMLObject> objects)
|
, List<XMLObject> objects)
|
||||||
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, IOException, URISyntaxException, XmlException {
|
throws XMLSignatureException {
|
||||||
LOG.log(POILogger.DEBUG, "pre sign");
|
LOG.log(POILogger.DEBUG, "pre sign");
|
||||||
addManifestObject(document, signatureFactory, references, objects);
|
addManifestObject(document, references, objects);
|
||||||
addSignatureInfo(document, signatureFactory, references, objects);
|
addSignatureInfo(document, references, objects);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addManifestObject(
|
protected void addManifestObject(
|
||||||
Document document
|
Document document
|
||||||
, XMLSignatureFactory signatureFactory
|
|
||||||
, List<Reference> references
|
, List<Reference> references
|
||||||
, List<XMLObject> objects)
|
, List<XMLObject> objects)
|
||||||
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, IOException, URISyntaxException, XmlException {
|
throws XMLSignatureException {
|
||||||
|
|
||||||
List<Reference> manifestReferences = new ArrayList<Reference>();
|
List<Reference> manifestReferences = new ArrayList<Reference>();
|
||||||
addManifestReferences(signatureFactory, manifestReferences);
|
addManifestReferences(manifestReferences);
|
||||||
Manifest manifest = signatureFactory.newManifest(manifestReferences);
|
Manifest manifest = getSignatureFactory().newManifest(manifestReferences);
|
||||||
|
|
||||||
String objectId = "idPackageObject"; // really has to be this value.
|
String objectId = "idPackageObject"; // really has to be this value.
|
||||||
List<XMLStructure> objectContent = new ArrayList<XMLStructure>();
|
List<XMLStructure> objectContent = new ArrayList<XMLStructure>();
|
||||||
objectContent.add(manifest);
|
objectContent.add(manifest);
|
||||||
|
|
||||||
addSignatureTime(document, signatureFactory, objectContent);
|
addSignatureTime(document, objectContent);
|
||||||
|
|
||||||
XMLObject xo = signatureFactory.newXMLObject(objectContent, objectId, null, null);
|
XMLObject xo = getSignatureFactory().newXMLObject(objectContent, objectId, null, null);
|
||||||
objects.add(xo);
|
objects.add(xo);
|
||||||
|
|
||||||
DigestMethod digestMethod = signatureFactory.newDigestMethod
|
Reference reference = newReference("#" + objectId, null, XML_DIGSIG_NS+"Object", null, null);
|
||||||
(signatureConfig.getDigestMethodUri(), null);
|
|
||||||
Reference reference = signatureFactory.newReference
|
|
||||||
("#" + objectId, digestMethod, null, XML_DIGSIG_NS+"Object", null);
|
|
||||||
references.add(reference);
|
references.add(reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addManifestReferences
|
protected void addManifestReferences(List<Reference> manifestReferences)
|
||||||
(XMLSignatureFactory signatureFactory, List<Reference> manifestReferences)
|
throws XMLSignatureException {
|
||||||
throws IOException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, URISyntaxException, XmlException {
|
|
||||||
|
|
||||||
OPCPackage ooxml = signatureConfig.getOpcPackage();
|
OPCPackage ooxml = signatureConfig.getOpcPackage();
|
||||||
List<PackagePart> relsEntryNames = ooxml.getPartsByContentType(ContentTypes.RELATIONSHIPS_PART);
|
List<PackagePart> relsEntryNames = ooxml.getPartsByContentType(ContentTypes.RELATIONSHIPS_PART);
|
||||||
|
|
||||||
DigestMethod digestMethod = signatureFactory.newDigestMethod
|
|
||||||
(signatureConfig.getDigestMethodUri(), null);
|
|
||||||
Set<String> digestedPartNames = new HashSet<String>();
|
Set<String> digestedPartNames = new HashSet<String>();
|
||||||
for (PackagePart pp : relsEntryNames) {
|
for (PackagePart pp : relsEntryNames) {
|
||||||
String baseUri = pp.getPartName().getName().replaceFirst("(.*)/_rels/.*", "$1");
|
String baseUri = pp.getPartName().getName().replaceFirst("(.*)/_rels/.*", "$1");
|
||||||
@ -147,7 +126,7 @@ public class OOXMLSignatureFacet implements SignatureFacet {
|
|||||||
prc = new PackageRelationshipCollection(ooxml);
|
prc = new PackageRelationshipCollection(ooxml);
|
||||||
prc.parseRelationshipsPart(pp);
|
prc.parseRelationshipsPart(pp);
|
||||||
} catch (InvalidFormatException e) {
|
} catch (InvalidFormatException e) {
|
||||||
throw new IOException("Invalid relationship descriptor: "+pp.getPartName().getName(), e);
|
throw new XMLSignatureException("Invalid relationship descriptor: "+pp.getPartName().getName(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
RelationshipTransformParameterSpec parameterSpec = new RelationshipTransformParameterSpec();
|
RelationshipTransformParameterSpec parameterSpec = new RelationshipTransformParameterSpec();
|
||||||
@ -169,8 +148,12 @@ public class OOXMLSignatureFacet implements SignatureFacet {
|
|||||||
|
|
||||||
// TODO: find a better way ...
|
// TODO: find a better way ...
|
||||||
String partName = baseUri + relationship.getTargetURI().toString();
|
String partName = baseUri + relationship.getTargetURI().toString();
|
||||||
partName = new URI(partName).normalize().getPath().replace('\\', '/');
|
try {
|
||||||
LOG.log(POILogger.DEBUG, "part name: " + partName);
|
partName = new URI(partName).normalize().getPath().replace('\\', '/');
|
||||||
|
LOG.log(POILogger.DEBUG, "part name: " + partName);
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
throw new XMLSignatureException(e);
|
||||||
|
}
|
||||||
|
|
||||||
String contentType;
|
String contentType;
|
||||||
try {
|
try {
|
||||||
@ -178,7 +161,7 @@ public class OOXMLSignatureFacet implements SignatureFacet {
|
|||||||
PackagePart pp2 = ooxml.getPart(relName);
|
PackagePart pp2 = ooxml.getPart(relName);
|
||||||
contentType = pp2.getContentType();
|
contentType = pp2.getContentType();
|
||||||
} catch (InvalidFormatException e) {
|
} catch (InvalidFormatException e) {
|
||||||
throw new IOException(e);
|
throw new XMLSignatureException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (relationshipType.endsWith("customXml")
|
if (relationshipType.endsWith("customXml")
|
||||||
@ -190,7 +173,7 @@ public class OOXMLSignatureFacet implements SignatureFacet {
|
|||||||
if (!digestedPartNames.contains(partName)) {
|
if (!digestedPartNames.contains(partName)) {
|
||||||
// We only digest a part once.
|
// We only digest a part once.
|
||||||
String uri = partName + "?ContentType=" + contentType;
|
String uri = partName + "?ContentType=" + contentType;
|
||||||
Reference reference = signatureFactory.newReference(uri, digestMethod);
|
Reference reference = newReference(uri, null, null, null, null);
|
||||||
manifestReferences.add(reference);
|
manifestReferences.add(reference);
|
||||||
digestedPartNames.add(partName);
|
digestedPartNames.add(partName);
|
||||||
}
|
}
|
||||||
@ -198,25 +181,18 @@ public class OOXMLSignatureFacet implements SignatureFacet {
|
|||||||
|
|
||||||
if (parameterSpec.hasSourceIds()) {
|
if (parameterSpec.hasSourceIds()) {
|
||||||
List<Transform> transforms = new ArrayList<Transform>();
|
List<Transform> transforms = new ArrayList<Transform>();
|
||||||
transforms.add(signatureFactory.newTransform(
|
transforms.add(newTransform(RelationshipTransformService.TRANSFORM_URI, parameterSpec));
|
||||||
RelationshipTransformService.TRANSFORM_URI,
|
transforms.add(newTransform(CanonicalizationMethod.INCLUSIVE));
|
||||||
parameterSpec));
|
|
||||||
transforms.add(signatureFactory.newTransform(
|
|
||||||
CanonicalizationMethod.INCLUSIVE,
|
|
||||||
(TransformParameterSpec) null));
|
|
||||||
String uri = pp.getPartName().getName()
|
String uri = pp.getPartName().getName()
|
||||||
+ "?ContentType=application/vnd.openxmlformats-package.relationships+xml";
|
+ "?ContentType=application/vnd.openxmlformats-package.relationships+xml";
|
||||||
Reference reference = signatureFactory.newReference(uri, digestMethod, transforms, null, null);
|
Reference reference = newReference(uri, transforms, null, null, null);
|
||||||
manifestReferences.add(reference);
|
manifestReferences.add(reference);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void addSignatureTime(
|
protected void addSignatureTime(Document document, List<XMLStructure> objectContent) {
|
||||||
Document document
|
|
||||||
, XMLSignatureFactory signatureFactory
|
|
||||||
, List<XMLStructure> objectContent) {
|
|
||||||
/*
|
/*
|
||||||
* SignatureTime
|
* SignatureTime
|
||||||
*/
|
*/
|
||||||
@ -233,22 +209,21 @@ public class OOXMLSignatureFacet implements SignatureFacet {
|
|||||||
Element n = (Element)document.importNode(ctTime.getDomNode(),true);
|
Element n = (Element)document.importNode(ctTime.getDomNode(),true);
|
||||||
List<XMLStructure> signatureTimeContent = new ArrayList<XMLStructure>();
|
List<XMLStructure> signatureTimeContent = new ArrayList<XMLStructure>();
|
||||||
signatureTimeContent.add(new DOMStructure(n));
|
signatureTimeContent.add(new DOMStructure(n));
|
||||||
SignatureProperty signatureTimeSignatureProperty = signatureFactory
|
SignatureProperty signatureTimeSignatureProperty = getSignatureFactory()
|
||||||
.newSignatureProperty(signatureTimeContent, "#" + signatureConfig.getPackageSignatureId(),
|
.newSignatureProperty(signatureTimeContent, "#" + signatureConfig.getPackageSignatureId(),
|
||||||
"idSignatureTime");
|
"idSignatureTime");
|
||||||
List<SignatureProperty> signaturePropertyContent = new ArrayList<SignatureProperty>();
|
List<SignatureProperty> signaturePropertyContent = new ArrayList<SignatureProperty>();
|
||||||
signaturePropertyContent.add(signatureTimeSignatureProperty);
|
signaturePropertyContent.add(signatureTimeSignatureProperty);
|
||||||
SignatureProperties signatureProperties = signatureFactory
|
SignatureProperties signatureProperties = getSignatureFactory()
|
||||||
.newSignatureProperties(signaturePropertyContent,
|
.newSignatureProperties(signaturePropertyContent,
|
||||||
"id-signature-time-" + signatureConfig.getExecutionTime());
|
"id-signature-time-" + signatureConfig.getExecutionTime());
|
||||||
objectContent.add(signatureProperties);
|
objectContent.add(signatureProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addSignatureInfo(Document document,
|
protected void addSignatureInfo(Document document,
|
||||||
XMLSignatureFactory signatureFactory,
|
|
||||||
List<Reference> references,
|
List<Reference> references,
|
||||||
List<XMLObject> objects)
|
List<XMLObject> objects)
|
||||||
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
|
throws XMLSignatureException {
|
||||||
List<XMLStructure> objectContent = new ArrayList<XMLStructure>();
|
List<XMLStructure> objectContent = new ArrayList<XMLStructure>();
|
||||||
|
|
||||||
SignatureInfoV1Document sigV1 = SignatureInfoV1Document.Factory.newInstance();
|
SignatureInfoV1Document sigV1 = SignatureInfoV1Document.Factory.newInstance();
|
||||||
@ -259,31 +234,23 @@ public class OOXMLSignatureFacet implements SignatureFacet {
|
|||||||
|
|
||||||
List<XMLStructure> signatureInfoContent = new ArrayList<XMLStructure>();
|
List<XMLStructure> signatureInfoContent = new ArrayList<XMLStructure>();
|
||||||
signatureInfoContent.add(new DOMStructure(n));
|
signatureInfoContent.add(new DOMStructure(n));
|
||||||
SignatureProperty signatureInfoSignatureProperty = signatureFactory
|
SignatureProperty signatureInfoSignatureProperty = getSignatureFactory()
|
||||||
.newSignatureProperty(signatureInfoContent, "#" + signatureConfig.getPackageSignatureId(),
|
.newSignatureProperty(signatureInfoContent, "#" + signatureConfig.getPackageSignatureId(),
|
||||||
"idOfficeV1Details");
|
"idOfficeV1Details");
|
||||||
|
|
||||||
List<SignatureProperty> signaturePropertyContent = new ArrayList<SignatureProperty>();
|
List<SignatureProperty> signaturePropertyContent = new ArrayList<SignatureProperty>();
|
||||||
signaturePropertyContent.add(signatureInfoSignatureProperty);
|
signaturePropertyContent.add(signatureInfoSignatureProperty);
|
||||||
SignatureProperties signatureProperties = signatureFactory
|
SignatureProperties signatureProperties = getSignatureFactory()
|
||||||
.newSignatureProperties(signaturePropertyContent, null);
|
.newSignatureProperties(signaturePropertyContent, null);
|
||||||
objectContent.add(signatureProperties);
|
objectContent.add(signatureProperties);
|
||||||
|
|
||||||
String objectId = "idOfficeObject";
|
String objectId = "idOfficeObject";
|
||||||
objects.add(signatureFactory.newXMLObject(objectContent, objectId, null, null));
|
objects.add(getSignatureFactory().newXMLObject(objectContent, objectId, null, null));
|
||||||
|
|
||||||
DigestMethod digestMethod = signatureFactory.newDigestMethod
|
Reference reference = newReference("#" + objectId, null, XML_DIGSIG_NS+"Object", null, null);
|
||||||
(signatureConfig.getDigestMethodUri(), null);
|
|
||||||
Reference reference = signatureFactory.newReference
|
|
||||||
("#" + objectId, digestMethod, null, XML_DIGSIG_NS+"Object", null);
|
|
||||||
references.add(reference);
|
references.add(reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void postSign(Document document) {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static String getRelationshipReferenceURI(String zipEntryName) {
|
protected static String getRelationshipReferenceURI(String zipEntryName) {
|
||||||
return "/"
|
return "/"
|
||||||
+ zipEntryName
|
+ zipEntryName
|
||||||
|
@ -24,15 +24,8 @@
|
|||||||
|
|
||||||
package org.apache.poi.poifs.crypt.dsig.facets;
|
package org.apache.poi.poifs.crypt.dsig.facets;
|
||||||
|
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import javax.xml.crypto.MarshalException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.xml.crypto.dsig.Reference;
|
|
||||||
import javax.xml.crypto.dsig.XMLObject;
|
|
||||||
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
|
||||||
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.SignatureConfig;
|
|
||||||
import org.apache.xmlbeans.XmlException;
|
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;
|
||||||
@ -50,32 +43,23 @@ import org.w3c.dom.NodeList;
|
|||||||
* @author Frank Cornelis
|
* @author Frank Cornelis
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class Office2010SignatureFacet implements SignatureFacet {
|
public class Office2010SignatureFacet extends SignatureFacet {
|
||||||
|
|
||||||
public void setSignatureConfig(SignatureConfig signatureConfig) {
|
|
||||||
// this.signatureConfig = signatureConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void preSign(
|
|
||||||
Document document
|
|
||||||
, XMLSignatureFactory signatureFactory
|
|
||||||
, List<Reference> references
|
|
||||||
, List<XMLObject> objects
|
|
||||||
) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postSign(Document document)
|
public void postSign(Document document)
|
||||||
throws XmlException {
|
throws MarshalException {
|
||||||
// check for XAdES-BES
|
// check for XAdES-BES
|
||||||
NodeList nl = document.getElementsByTagNameNS(XADES_132_NS, "QualifyingProperties");
|
NodeList nl = document.getElementsByTagNameNS(XADES_132_NS, "QualifyingProperties");
|
||||||
if (nl.getLength() != 1) {
|
if (nl.getLength() != 1) {
|
||||||
throw new IllegalArgumentException("no XAdES-BES extension present");
|
throw new MarshalException("no XAdES-BES extension present");
|
||||||
}
|
}
|
||||||
|
|
||||||
QualifyingPropertiesType qualProps =
|
QualifyingPropertiesType qualProps;
|
||||||
QualifyingPropertiesType.Factory.parse(nl.item(0));
|
try {
|
||||||
|
qualProps = QualifyingPropertiesType.Factory.parse(nl.item(0));
|
||||||
|
} catch (XmlException e) {
|
||||||
|
throw new MarshalException(e);
|
||||||
|
}
|
||||||
|
|
||||||
// create basic XML container structure
|
// create basic XML container structure
|
||||||
UnsignedPropertiesType unsignedProps = qualProps.getUnsignedProperties();
|
UnsignedPropertiesType unsignedProps = qualProps.getUnsignedProperties();
|
||||||
|
@ -24,39 +24,43 @@
|
|||||||
|
|
||||||
package org.apache.poi.poifs.crypt.dsig.facets;
|
package org.apache.poi.poifs.crypt.dsig.facets;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.xml.XMLConstants;
|
import javax.xml.XMLConstants;
|
||||||
import javax.xml.crypto.MarshalException;
|
import javax.xml.crypto.MarshalException;
|
||||||
|
import javax.xml.crypto.dsig.DigestMethod;
|
||||||
import javax.xml.crypto.dsig.Reference;
|
import javax.xml.crypto.dsig.Reference;
|
||||||
|
import javax.xml.crypto.dsig.Transform;
|
||||||
import javax.xml.crypto.dsig.XMLObject;
|
import javax.xml.crypto.dsig.XMLObject;
|
||||||
import javax.xml.crypto.dsig.XMLSignature;
|
import javax.xml.crypto.dsig.XMLSignature;
|
||||||
|
import javax.xml.crypto.dsig.XMLSignatureException;
|
||||||
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
||||||
|
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
|
||||||
|
|
||||||
import org.apache.poi.openxml4j.opc.PackageNamespaces;
|
import org.apache.poi.openxml4j.opc.PackageNamespaces;
|
||||||
|
import org.apache.poi.poifs.crypt.dsig.SignatureConfig;
|
||||||
import org.apache.poi.poifs.crypt.dsig.SignatureConfig.SignatureConfigurable;
|
import org.apache.poi.poifs.crypt.dsig.SignatureConfig.SignatureConfigurable;
|
||||||
import org.apache.xmlbeans.XmlException;
|
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JSR105 Signature Facet interface.
|
* JSR105 Signature Facet base class.
|
||||||
*
|
|
||||||
* @author Frank Cornelis
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public interface SignatureFacet extends SignatureConfigurable {
|
public abstract class SignatureFacet implements SignatureConfigurable {
|
||||||
|
|
||||||
String XML_NS = XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
|
public static final String XML_NS = XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
|
||||||
String XML_DIGSIG_NS = XMLSignature.XMLNS;
|
public static final String XML_DIGSIG_NS = XMLSignature.XMLNS;
|
||||||
String OO_DIGSIG_NS = PackageNamespaces.DIGITAL_SIGNATURE;
|
public static final String OO_DIGSIG_NS = PackageNamespaces.DIGITAL_SIGNATURE;
|
||||||
String MS_DIGSIG_NS = "http://schemas.microsoft.com/office/2006/digsig";
|
public static final String MS_DIGSIG_NS = "http://schemas.microsoft.com/office/2006/digsig";
|
||||||
String XADES_132_NS = "http://uri.etsi.org/01903/v1.3.2#";
|
public static final String XADES_132_NS = "http://uri.etsi.org/01903/v1.3.2#";
|
||||||
String XADES_141_NS = "http://uri.etsi.org/01903/v1.4.1#";
|
public static final String XADES_141_NS = "http://uri.etsi.org/01903/v1.4.1#";
|
||||||
|
|
||||||
|
protected SignatureConfig signatureConfig;
|
||||||
|
protected ThreadLocal<XMLSignatureFactory> signatureFactory;
|
||||||
|
|
||||||
|
public void setSignatureConfig(SignatureConfig signatureConfig) {
|
||||||
|
this.signatureConfig = signatureConfig;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is being invoked by the XML signature service engine during
|
* This method is being invoked by the XML signature service engine during
|
||||||
@ -64,21 +68,17 @@ public interface SignatureFacet extends SignatureConfigurable {
|
|||||||
* signature facets to an XML signature.
|
* signature facets to an XML signature.
|
||||||
*
|
*
|
||||||
* @param document the signature document to be used for imports
|
* @param document the signature document to be used for imports
|
||||||
* @param signatureFactory the signature factory
|
|
||||||
* @param references list of reference definitions
|
* @param references list of reference definitions
|
||||||
* @param objects objects to be signed/included in the signature document
|
* @param objects objects to be signed/included in the signature document
|
||||||
* @throws NoSuchAlgorithmException
|
* @throws XMLSignatureException
|
||||||
* @throws InvalidAlgorithmParameterException
|
|
||||||
* @throws IOException
|
|
||||||
* @throws URISyntaxException
|
|
||||||
* @throws XmlException
|
|
||||||
*/
|
*/
|
||||||
void preSign(
|
public void preSign(
|
||||||
Document document
|
Document document
|
||||||
, XMLSignatureFactory signatureFactory
|
|
||||||
, List<Reference> references
|
, List<Reference> references
|
||||||
, List<XMLObject> objects
|
, List<XMLObject> objects
|
||||||
) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, IOException, URISyntaxException, XmlException;
|
) throws XMLSignatureException {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is being invoked by the XML signature service engine during
|
* This method is being invoked by the XML signature service engine during
|
||||||
@ -87,9 +87,59 @@ public interface SignatureFacet extends SignatureConfigurable {
|
|||||||
*
|
*
|
||||||
* @param document the signature document to be modified
|
* @param document the signature document to be modified
|
||||||
* @throws MarshalException
|
* @throws MarshalException
|
||||||
* @throws XmlException
|
|
||||||
*/
|
*/
|
||||||
void postSign(
|
public void postSign(Document document) throws MarshalException {
|
||||||
Document document
|
// empty
|
||||||
) throws MarshalException, XmlException;
|
}
|
||||||
|
|
||||||
|
protected XMLSignatureFactory getSignatureFactory() {
|
||||||
|
return signatureConfig.getSignatureFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Transform newTransform(String canonicalizationMethod) throws XMLSignatureException {
|
||||||
|
return newTransform(canonicalizationMethod, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Transform newTransform(String canonicalizationMethod, TransformParameterSpec paramSpec)
|
||||||
|
throws XMLSignatureException {
|
||||||
|
try {
|
||||||
|
return getSignatureFactory().newTransform(canonicalizationMethod, paramSpec);
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
throw new XMLSignatureException("unknown canonicalization method: "+canonicalizationMethod, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Reference newReference(String uri, List<Transform> transforms, String type, String id, byte digestValue[])
|
||||||
|
throws XMLSignatureException {
|
||||||
|
return newReference(uri, transforms, type, id, digestValue, signatureConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Reference newReference(
|
||||||
|
String uri
|
||||||
|
, List<Transform> transforms
|
||||||
|
, String type
|
||||||
|
, String id
|
||||||
|
, byte digestValue[]
|
||||||
|
, SignatureConfig signatureConfig)
|
||||||
|
throws XMLSignatureException {
|
||||||
|
// the references appear in the package signature or the package object
|
||||||
|
// so we can use the default digest algorithm
|
||||||
|
String digestMethodUri = signatureConfig.getDigestMethodUri();
|
||||||
|
XMLSignatureFactory sigFac = signatureConfig.getSignatureFactory();
|
||||||
|
DigestMethod digestMethod;
|
||||||
|
try {
|
||||||
|
digestMethod = sigFac.newDigestMethod(digestMethodUri, null);
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
throw new XMLSignatureException("unknown digest method uri: "+digestMethodUri, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
Reference reference;
|
||||||
|
if (digestValue == null) {
|
||||||
|
reference = sigFac.newReference(uri, digestMethod, transforms, type, id);
|
||||||
|
} else {
|
||||||
|
reference = sigFac.newReference(uri, digestMethod, transforms, type, id, digestValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return reference;
|
||||||
|
}
|
||||||
}
|
}
|
@ -24,9 +24,7 @@
|
|||||||
|
|
||||||
package org.apache.poi.poifs.crypt.dsig.facets;
|
package org.apache.poi.poifs.crypt.dsig.facets;
|
||||||
|
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
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.ArrayList;
|
||||||
@ -39,12 +37,10 @@ import java.util.TimeZone;
|
|||||||
import javax.xml.crypto.XMLStructure;
|
import javax.xml.crypto.XMLStructure;
|
||||||
import javax.xml.crypto.dom.DOMStructure;
|
import javax.xml.crypto.dom.DOMStructure;
|
||||||
import javax.xml.crypto.dsig.CanonicalizationMethod;
|
import javax.xml.crypto.dsig.CanonicalizationMethod;
|
||||||
import javax.xml.crypto.dsig.DigestMethod;
|
|
||||||
import javax.xml.crypto.dsig.Reference;
|
import javax.xml.crypto.dsig.Reference;
|
||||||
import javax.xml.crypto.dsig.Transform;
|
import javax.xml.crypto.dsig.Transform;
|
||||||
import javax.xml.crypto.dsig.XMLObject;
|
import javax.xml.crypto.dsig.XMLObject;
|
||||||
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
import javax.xml.crypto.dsig.XMLSignatureException;
|
||||||
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;
|
||||||
@ -89,30 +85,21 @@ import org.w3c.dom.Element;
|
|||||||
* @see <a href="http://en.wikipedia.org/wiki/XAdES">XAdES</a>
|
* @see <a href="http://en.wikipedia.org/wiki/XAdES">XAdES</a>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class XAdESSignatureFacet implements SignatureFacet {
|
public class XAdESSignatureFacet extends SignatureFacet {
|
||||||
|
|
||||||
private static final POILogger LOG = POILogFactory.getLogger(XAdESSignatureFacet.class);
|
private static final POILogger LOG = POILogFactory.getLogger(XAdESSignatureFacet.class);
|
||||||
|
|
||||||
private static final String XADES_TYPE = "http://uri.etsi.org/01903#SignedProperties";
|
private static final String XADES_TYPE = "http://uri.etsi.org/01903#SignedProperties";
|
||||||
|
|
||||||
private SignatureConfig signatureConfig;
|
|
||||||
|
|
||||||
private Map<String, String> dataObjectFormatMimeTypes = new HashMap<String, String>();
|
private Map<String, String> dataObjectFormatMimeTypes = new HashMap<String, String>();
|
||||||
|
|
||||||
public void setSignatureConfig(SignatureConfig signatureConfig) {
|
|
||||||
this.signatureConfig = signatureConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postSign(Document document) {
|
public void preSign(
|
||||||
LOG.log(POILogger.DEBUG, "postSign");
|
Document document
|
||||||
}
|
, List<Reference> references
|
||||||
|
, List<XMLObject> objects)
|
||||||
@Override
|
throws XMLSignatureException {
|
||||||
public void preSign(Document document,
|
|
||||||
XMLSignatureFactory signatureFactory,
|
|
||||||
List<Reference> references, List<XMLObject> objects)
|
|
||||||
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
|
|
||||||
LOG.log(POILogger.DEBUG, "preSign");
|
LOG.log(POILogger.DEBUG, "preSign");
|
||||||
|
|
||||||
// QualifyingProperties
|
// QualifyingProperties
|
||||||
@ -209,18 +196,15 @@ public class XAdESSignatureFacet implements SignatureFacet {
|
|||||||
Element qualDocElSrc = (Element)qualifyingProperties.getDomNode();
|
Element qualDocElSrc = (Element)qualifyingProperties.getDomNode();
|
||||||
Element qualDocEl = (Element)document.importNode(qualDocElSrc, true);
|
Element qualDocEl = (Element)document.importNode(qualDocElSrc, true);
|
||||||
xadesObjectContent.add(new DOMStructure(qualDocEl));
|
xadesObjectContent.add(new DOMStructure(qualDocEl));
|
||||||
XMLObject xadesObject = signatureFactory.newXMLObject(xadesObjectContent, null, null, null);
|
XMLObject xadesObject = getSignatureFactory().newXMLObject(xadesObjectContent, null, null, null);
|
||||||
objects.add(xadesObject);
|
objects.add(xadesObject);
|
||||||
|
|
||||||
// add XAdES ds:Reference
|
// add XAdES ds:Reference
|
||||||
DigestMethod digestMethod = signatureFactory.newDigestMethod(signatureConfig.getDigestMethodUri(), null);
|
|
||||||
List<Transform> transforms = new ArrayList<Transform>();
|
List<Transform> transforms = new ArrayList<Transform>();
|
||||||
Transform exclusiveTransform = signatureFactory
|
Transform exclusiveTransform = newTransform(CanonicalizationMethod.INCLUSIVE);
|
||||||
.newTransform(CanonicalizationMethod.INCLUSIVE,
|
|
||||||
(TransformParameterSpec) null);
|
|
||||||
transforms.add(exclusiveTransform);
|
transforms.add(exclusiveTransform);
|
||||||
Reference reference = signatureFactory.newReference
|
Reference reference = newReference
|
||||||
("#"+signatureConfig.getXadesSignatureId(), digestMethod, transforms, XADES_TYPE, null);
|
("#"+signatureConfig.getXadesSignatureId(), transforms, XADES_TYPE, null, null);
|
||||||
references.add(reference);
|
references.add(reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,8 +29,6 @@ import static org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet.insertX
|
|||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.cert.CRLException;
|
import java.security.cert.CRLException;
|
||||||
import java.security.cert.CertificateEncodingException;
|
import java.security.cert.CertificateEncodingException;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
@ -43,12 +41,9 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import javax.xml.crypto.MarshalException;
|
||||||
import javax.xml.crypto.dsig.CanonicalizationMethod;
|
import javax.xml.crypto.dsig.CanonicalizationMethod;
|
||||||
import javax.xml.crypto.dsig.Reference;
|
|
||||||
import javax.xml.crypto.dsig.XMLObject;
|
|
||||||
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
|
||||||
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.SignatureConfig;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.services.RevocationData;
|
import org.apache.poi.poifs.crypt.dsig.services.RevocationData;
|
||||||
import org.apache.poi.util.POILogFactory;
|
import org.apache.poi.util.POILogFactory;
|
||||||
import org.apache.poi.util.POILogger;
|
import org.apache.poi.util.POILogger;
|
||||||
@ -106,20 +101,14 @@ import org.w3c.dom.NodeList;
|
|||||||
* @author Frank Cornelis
|
* @author Frank Cornelis
|
||||||
* @see XAdESSignatureFacet
|
* @see XAdESSignatureFacet
|
||||||
*/
|
*/
|
||||||
public class XAdESXLSignatureFacet implements SignatureFacet {
|
public class XAdESXLSignatureFacet extends SignatureFacet {
|
||||||
|
|
||||||
private static final POILogger LOG = POILogFactory.getLogger(XAdESXLSignatureFacet.class);
|
private static final POILogger LOG = POILogFactory.getLogger(XAdESXLSignatureFacet.class);
|
||||||
|
|
||||||
private SignatureConfig signatureConfig;
|
|
||||||
|
|
||||||
private String c14nAlgoId = CanonicalizationMethod.EXCLUSIVE;
|
private String c14nAlgoId = CanonicalizationMethod.EXCLUSIVE;
|
||||||
|
|
||||||
private final CertificateFactory certificateFactory;
|
private final CertificateFactory certificateFactory;
|
||||||
|
|
||||||
public void setSignatureConfig(SignatureConfig signatureConfig) {
|
|
||||||
this.signatureConfig = signatureConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
public XAdESXLSignatureFacet() {
|
public XAdESXLSignatureFacet() {
|
||||||
try {
|
try {
|
||||||
this.certificateFactory = CertificateFactory.getInstance("X.509");
|
this.certificateFactory = CertificateFactory.getInstance("X.509");
|
||||||
@ -133,7 +122,7 @@ public class XAdESXLSignatureFacet implements SignatureFacet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postSign(Document document) throws XmlException {
|
public void postSign(Document document) throws MarshalException {
|
||||||
LOG.log(POILogger.DEBUG, "XAdES-X-L post sign phase");
|
LOG.log(POILogger.DEBUG, "XAdES-X-L post sign phase");
|
||||||
|
|
||||||
QualifyingPropertiesDocument qualDoc = null;
|
QualifyingPropertiesDocument qualDoc = null;
|
||||||
@ -142,10 +131,14 @@ public class XAdESXLSignatureFacet implements SignatureFacet {
|
|||||||
// check for XAdES-BES
|
// check for XAdES-BES
|
||||||
NodeList qualNl = document.getElementsByTagNameNS(XADES_132_NS, "QualifyingProperties");
|
NodeList qualNl = document.getElementsByTagNameNS(XADES_132_NS, "QualifyingProperties");
|
||||||
if (qualNl.getLength() == 1) {
|
if (qualNl.getLength() == 1) {
|
||||||
qualDoc = QualifyingPropertiesDocument.Factory.parse(qualNl.item(0));
|
try {
|
||||||
|
qualDoc = QualifyingPropertiesDocument.Factory.parse(qualNl.item(0));
|
||||||
|
} catch (XmlException e) {
|
||||||
|
throw new MarshalException(e);
|
||||||
|
}
|
||||||
qualProps = qualDoc.getQualifyingProperties();
|
qualProps = qualDoc.getQualifyingProperties();
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("no XAdES-BES extension present");
|
throw new MarshalException("no XAdES-BES extension present");
|
||||||
}
|
}
|
||||||
|
|
||||||
// create basic XML container structure
|
// create basic XML container structure
|
||||||
@ -335,14 +328,6 @@ public class XAdESXLSignatureFacet implements SignatureFacet {
|
|||||||
return c14nValue.toByteArray();
|
return c14nValue.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void preSign(Document document,
|
|
||||||
XMLSignatureFactory signatureFactory,
|
|
||||||
List<Reference> references, List<XMLObject> objects)
|
|
||||||
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
|
|
||||||
// nothing to do here
|
|
||||||
}
|
|
||||||
|
|
||||||
private BigInteger getCrlNumber(X509CRL crl) {
|
private BigInteger getCrlNumber(X509CRL crl) {
|
||||||
try {
|
try {
|
||||||
byte[] crlNumberExtensionValue = crl.getExtensionValue(Extension.cRLNumber.getId());
|
byte[] crlNumberExtensionValue = crl.getExtensionValue(Extension.cRLNumber.getId());
|
||||||
|
Loading…
Reference in New Issue
Block a user