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:
Andreas Beeker 2014-10-03 22:24:09 +00:00
parent ab84e448ca
commit 30d72983d1
10 changed files with 356 additions and 311 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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