git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1629332 13f79535-47bb-0310-9956-ffa450edef68pull/11/head
@@ -34,7 +34,6 @@ import javax.xml.crypto.URIDereferencer; | |||
import javax.xml.crypto.URIReference; | |||
import javax.xml.crypto.URIReferenceException; | |||
import javax.xml.crypto.XMLCryptoContext; | |||
import javax.xml.crypto.dsig.XMLSignatureFactory; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
@@ -54,16 +53,15 @@ public class OOXMLURIDereferencer implements URIDereferencer, SignatureConfigura | |||
private SignatureConfig signatureConfig; | |||
private URIDereferencer baseUriDereferencer; | |||
public OOXMLURIDereferencer() { | |||
XMLSignatureFactory xmlSignatureFactory = SignatureInfo.getSignatureFactory(); | |||
this.baseUriDereferencer = xmlSignatureFactory.getURIDereferencer(); | |||
} | |||
public void setSignatureConfig(SignatureConfig signatureConfig) { | |||
this.signatureConfig = signatureConfig; | |||
} | |||
public Data dereference(URIReference uriReference, XMLCryptoContext context) throws URIReferenceException { | |||
if (baseUriDereferencer == null) { | |||
baseUriDereferencer = signatureConfig.getSignatureFactory().getURIDereferencer(); | |||
} | |||
if (null == uriReference) { | |||
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 java.security.PrivateKey; | |||
import java.security.Provider; | |||
import java.security.cert.X509Certificate; | |||
import java.util.ArrayList; | |||
import java.util.Date; | |||
@@ -32,6 +33,8 @@ import java.util.UUID; | |||
import javax.xml.crypto.URIDereferencer; | |||
import javax.xml.crypto.dsig.CanonicalizationMethod; | |||
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.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.TimeStampService; | |||
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; | |||
/** | |||
* This class bundles the configuration options used for the existing | |||
* 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) | |||
*/ | |||
public class SignatureConfig { | |||
private static final POILogger LOG = POILogFactory.getLogger(SignatureConfig.class); | |||
public static interface SignatureConfigurable { | |||
void setSignatureConfig(SignatureConfig signatureConfig); | |||
} | |||
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 HashAlgorithm digestAlgo = HashAlgorithm.sha1; | |||
@@ -72,7 +82,7 @@ public class SignatureConfig { | |||
* the optional signature policy service used for XAdES-EPES. | |||
*/ | |||
private SignaturePolicyService signaturePolicyService; | |||
private URIDereferencer uriDereferencer = new OOXMLURIDereferencer(); | |||
private URIDereferencer uriDereferencer = null; | |||
private String canonicalizationMethod = CanonicalizationMethod.INCLUSIVE; | |||
private boolean includeEntireCertificateChain = true; | |||
@@ -146,13 +156,22 @@ public class SignatureConfig { | |||
*/ | |||
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) { | |||
if (uriDereferencer == null) { | |||
throw new EncryptedDocumentException("uriDereferencer is null"); | |||
} | |||
if (opcPackage == null) { | |||
throw new EncryptedDocumentException("opcPackage is null"); | |||
} | |||
if (uriDereferencer == null) { | |||
uriDereferencer = new OOXMLURIDereferencer(); | |||
} | |||
if (uriDereferencer instanceof SignatureConfigurable) { | |||
((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() { | |||
return signatureFacets; | |||
} | |||
/** | |||
* @param signatureFacets the new list of facets | |||
*/ | |||
public void setSignatureFacets(List<SignatureFacet> signatureFacets) { | |||
this.signatureFacets = signatureFacets; | |||
} | |||
/** | |||
* @return the main digest algorithm, defaults to sha-1 | |||
*/ | |||
public HashAlgorithm getDigestAlgo() { | |||
return digestAlgo; | |||
} | |||
/** | |||
* @param digestAlgo the main digest algorithm | |||
*/ | |||
public void setDigestAlgo(HashAlgorithm digestAlgo) { | |||
this.digestAlgo = digestAlgo; | |||
} | |||
/** | |||
* @return the opc package to be used by this thread, stored as thread-local | |||
*/ | |||
public OPCPackage getOpcPackage() { | |||
return opcPackage.get(); | |||
} | |||
/** | |||
* @param opcPackage the opc package to be handled by this thread, stored as thread-local | |||
*/ | |||
public void setOpcPackage(OPCPackage opcPackage) { | |||
this.opcPackage.set(opcPackage); | |||
} | |||
/** | |||
* @return the private key | |||
*/ | |||
public PrivateKey getKey() { | |||
return key; | |||
} | |||
/** | |||
* @param key the private key | |||
*/ | |||
public void setKey(PrivateKey key) { | |||
this.key = key; | |||
} | |||
/** | |||
* @return the certificate chain, index 0 is usually the certificate matching | |||
* the private key | |||
*/ | |||
public List<X509Certificate> getSigningCertificateChain() { | |||
return signingCertificateChain; | |||
} | |||
/** | |||
* @param signingCertificateChain the certificate chain, index 0 should be | |||
* the certificate matching the private key | |||
*/ | |||
public void setSigningCertificateChain( | |||
List<X509Certificate> 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() { | |||
return executionTime; | |||
} | |||
/** | |||
* @param executionTime sets the time at which the document ought to be signed | |||
*/ | |||
public void setExecutionTime(Date executionTime) { | |||
this.executionTime = executionTime; | |||
} | |||
/** | |||
* @return the service to be used for XAdES-EPES properties. There's no default implementation | |||
*/ | |||
public SignaturePolicyService getSignaturePolicyService() { | |||
return signaturePolicyService; | |||
} | |||
/** | |||
* @param signaturePolicyService the service to be used for XAdES-EPES properties | |||
*/ | |||
public void setSignaturePolicyService(SignaturePolicyService signaturePolicyService) { | |||
this.signaturePolicyService = signaturePolicyService; | |||
} | |||
/** | |||
* @return the dereferencer used for Reference/@URI attributes, defaults to {@link OOXMLURIDereferencer} | |||
*/ | |||
public URIDereferencer getUriDereferencer() { | |||
return uriDereferencer; | |||
} | |||
/** | |||
* @param uriDereferencer the dereferencer used for Reference/@URI attributes | |||
*/ | |||
public void setUriDereferencer(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() { | |||
return signatureDescription; | |||
} | |||
/** | |||
* @param signatureDescription the human-readable description of | |||
* what the citizen will be signing. | |||
*/ | |||
public void setSignatureDescription(String signatureDescription) { | |||
this.signatureDescription = signatureDescription; | |||
} | |||
/** | |||
* @return the default canonicalization method, defaults to INCLUSIVE | |||
*/ | |||
public String getCanonicalizationMethod() { | |||
return canonicalizationMethod; | |||
} | |||
/** | |||
* @param canonicalizationMethod the default canonicalization method | |||
*/ | |||
public void setCanonicalizationMethod(String 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.IOException; | |||
import java.io.OutputStream; | |||
import java.net.URISyntaxException; | |||
import java.security.InvalidAlgorithmParameterException; | |||
import java.security.GeneralSecurityException; | |||
import java.security.MessageDigest; | |||
import java.security.NoSuchAlgorithmException; | |||
import java.security.NoSuchProviderException; | |||
import java.security.Provider; | |||
import java.security.cert.X509Certificate; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
@@ -50,7 +46,6 @@ import javax.xml.crypto.MarshalException; | |||
import javax.xml.crypto.URIDereferencer; | |||
import javax.xml.crypto.XMLStructure; | |||
import javax.xml.crypto.dsig.CanonicalizationMethod; | |||
import javax.xml.crypto.dsig.DigestMethod; | |||
import javax.xml.crypto.dsig.Manifest; | |||
import javax.xml.crypto.dsig.Reference; | |||
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.dom.DOMSignContext; | |||
import javax.xml.crypto.dsig.dom.DOMValidateContext; | |||
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory; | |||
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.XPathConstants; | |||
import javax.xml.xpath.XPathFactory; | |||
@@ -103,7 +94,6 @@ import org.w3c.dom.Element; | |||
import org.w3c.dom.NodeList; | |||
import org.w3c.dom.events.EventListener; | |||
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.setKey(keyPair.getPrivate()); | |||
* signatureConfig.setSigningCertificateChain(Collections.singletonList(x509)); | |||
* OPCPackage pkg = OPCPackage.open(..., PackageAccess.READ); | |||
* OPCPackage pkg = OPCPackage.open(..., PackageAccess.READ_WRITE); | |||
* signatureConfig.setOpcPackage(pkg); | |||
* | |||
* // 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.setURIDereferencer(signatureConfig.getUriDereferencer()); | |||
XMLSignatureFactory xmlSignatureFactory = getSignatureFactory(); | |||
XMLSignatureFactory xmlSignatureFactory = signatureConfig.getSignatureFactory(); | |||
XMLSignature xmlSignature = xmlSignatureFactory.unmarshalXMLSignature(domValidateContext); | |||
boolean valid = xmlSignature.validate(domValidateContext); | |||
@@ -258,8 +248,7 @@ public class SignatureInfo implements SignatureConfigurable { | |||
return false; | |||
} | |||
public void confirmSignature() | |||
throws NoSuchAlgorithmException, IOException, MarshalException, ParserConfigurationException, XmlException, InvalidAlgorithmParameterException, NoSuchProviderException, XMLSignatureException, TransformerFactoryConfigurationError, TransformerException, SAXException, URISyntaxException { | |||
public void confirmSignature() throws XMLSignatureException, MarshalException { | |||
Document document = DocumentHelper.createDocument(); | |||
// 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() { | |||
if (isInitialized) return; | |||
isInitialized = true; | |||
@@ -381,11 +343,7 @@ public class SignatureInfo implements SignatureConfigurable { | |||
*/ | |||
@SuppressWarnings("unchecked") | |||
public DigestInfo preSign(Document document, List<DigestInfo> digestInfos) | |||
throws ParserConfigurationException, NoSuchAlgorithmException, | |||
InvalidAlgorithmParameterException, MarshalException, | |||
javax.xml.crypto.dsig.XMLSignatureException, | |||
TransformerFactoryConfigurationError, TransformerException, | |||
IOException, SAXException, NoSuchProviderException, XmlException, URISyntaxException { | |||
throws XMLSignatureException, MarshalException { | |||
signatureConfig.init(false); | |||
// 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)); | |||
XMLSignatureFactory signatureFactory = SignatureInfo.getSignatureFactory(); | |||
XMLSignatureFactory signatureFactory = signatureConfig.getSignatureFactory(); | |||
/* | |||
* Add ds:References that come from signing client local files. | |||
@@ -422,13 +380,9 @@ public class SignatureInfo implements SignatureConfigurable { | |||
for (DigestInfo digestInfo : safe(digestInfos)) { | |||
byte[] documentDigestValue = digestInfo.digestValue; | |||
DigestMethod digestMethod = signatureFactory.newDigestMethod | |||
(signatureConfig.getDigestMethodUri(), null); | |||
String uri = new File(digestInfo.description).getName(); | |||
Reference reference = signatureFactory.newReference | |||
(uri, digestMethod, null, null, null, documentDigestValue); | |||
Reference reference = SignatureFacet.newReference | |||
(uri, null, null, null, documentDigestValue, signatureConfig); | |||
references.add(reference); | |||
} | |||
@@ -438,19 +392,24 @@ public class SignatureInfo implements SignatureConfigurable { | |||
List<XMLObject> objects = new ArrayList<XMLObject>(); | |||
for (SignatureFacet signatureFacet : signatureConfig.getSignatureFacets()) { | |||
LOG.log(POILogger.DEBUG, "invoking signature facet: " + signatureFacet.getClass().getSimpleName()); | |||
signatureFacet.preSign(document, signatureFactory, references, objects); | |||
signatureFacet.preSign(document, references, objects); | |||
} | |||
/* | |||
* ds:SignedInfo | |||
*/ | |||
SignatureMethod signatureMethod = signatureFactory.newSignatureMethod | |||
(signatureConfig.getSignatureMethod(), null); | |||
CanonicalizationMethod canonicalizationMethod = signatureFactory | |||
.newCanonicalizationMethod(signatureConfig.getCanonicalizationMethod(), | |||
(C14NMethodParameterSpec) null); | |||
SignedInfo signedInfo = signatureFactory.newSignedInfo( | |||
canonicalizationMethod, signatureMethod, references); | |||
SignedInfo signedInfo; | |||
try { | |||
SignatureMethod signatureMethod = signatureFactory.newSignatureMethod | |||
(signatureConfig.getSignatureMethod(), null); | |||
CanonicalizationMethod canonicalizationMethod = signatureFactory | |||
.newCanonicalizationMethod(signatureConfig.getCanonicalizationMethod(), | |||
(C14NMethodParameterSpec) null); | |||
signedInfo = signatureFactory.newSignedInfo( | |||
canonicalizationMethod, signatureMethod, references); | |||
} catch (GeneralSecurityException e) { | |||
throw new XMLSignatureException(e); | |||
} | |||
/* | |||
* JSR105 ds:Signature creation | |||
@@ -524,7 +483,7 @@ public class SignatureInfo implements SignatureConfigurable { | |||
* Normally {@link #confirmSignature()} is sufficient to be used. | |||
*/ | |||
public void postSign(Document document, byte[] signatureValue) | |||
throws IOException, MarshalException, ParserConfigurationException, XmlException { | |||
throws MarshalException { | |||
LOG.log(POILogger.DEBUG, "postSign"); | |||
/* | |||
@@ -554,7 +513,7 @@ public class SignatureInfo implements SignatureConfigurable { | |||
writeDocument(document); | |||
} | |||
protected void writeDocument(Document document) throws IOException, XmlException { | |||
protected void writeDocument(Document document) throws MarshalException { | |||
XmlOptions xo = new XmlOptions(); | |||
Map<String,String> namespaceMap = new HashMap<String,String>(); | |||
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"/> | |||
sigsPartName = PackagingURIHelper.createPartName("/_xmlsignatures/origin.sigs"); | |||
} catch (InvalidFormatException e) { | |||
throw new IOException(e); | |||
throw new MarshalException(e); | |||
} | |||
PackagePart sigPart = pkg.getPart(sigPartName); | |||
@@ -586,10 +545,14 @@ public class SignatureInfo implements SignatureConfigurable { | |||
sigPart = pkg.createPart(sigPartName, ContentTypes.DIGITAL_SIGNATURE_XML_SIGNATURE_PART); | |||
} | |||
OutputStream os = sigPart.getOutputStream(); | |||
SignatureDocument sigDoc = SignatureDocument.Factory.parse(document); | |||
sigDoc.save(os, xo); | |||
os.close(); | |||
try { | |||
OutputStream os = sigPart.getOutputStream(); | |||
SignatureDocument sigDoc = SignatureDocument.Factory.parse(document); | |||
sigDoc.save(os, xo); | |||
os.close(); | |||
} catch (Exception e) { | |||
throw new MarshalException("Unable to write signature document", e); | |||
} | |||
PackagePart sigsPart = pkg.getPart(sigsPartName); | |||
if (sigsPart == null) { |
@@ -24,20 +24,15 @@ | |||
package org.apache.poi.poifs.crypt.dsig.facets; | |||
import java.security.InvalidAlgorithmParameterException; | |||
import java.security.NoSuchAlgorithmException; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import javax.xml.crypto.dsig.CanonicalizationMethod; | |||
import javax.xml.crypto.dsig.DigestMethod; | |||
import javax.xml.crypto.dsig.Reference; | |||
import javax.xml.crypto.dsig.Transform; | |||
import javax.xml.crypto.dsig.XMLObject; | |||
import javax.xml.crypto.dsig.XMLSignatureFactory; | |||
import javax.xml.crypto.dsig.spec.TransformParameterSpec; | |||
import javax.xml.crypto.dsig.XMLSignatureException; | |||
import org.apache.poi.poifs.crypt.dsig.SignatureConfig; | |||
import org.w3c.dom.Document; | |||
/** | |||
@@ -46,39 +41,20 @@ import org.w3c.dom.Document; | |||
* @author Frank Cornelis | |||
* | |||
*/ | |||
public class EnvelopedSignatureFacet implements SignatureFacet { | |||
private SignatureConfig signatureConfig; | |||
public void setSignatureConfig(SignatureConfig signatureConfig) { | |||
this.signatureConfig = signatureConfig; | |||
} | |||
@Override | |||
public void postSign(Document document) { | |||
// empty | |||
} | |||
public class EnvelopedSignatureFacet extends SignatureFacet { | |||
@Override | |||
public void preSign(Document document | |||
, XMLSignatureFactory signatureFactory | |||
, List<Reference> references | |||
, List<XMLObject> objects) | |||
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { | |||
DigestMethod digestMethod = signatureFactory.newDigestMethod | |||
(signatureConfig.getDigestMethodUri(), null); | |||
throws XMLSignatureException { | |||
List<Transform> transforms = new ArrayList<Transform>(); | |||
Transform envelopedTransform = signatureFactory.newTransform | |||
(CanonicalizationMethod.ENVELOPED, (TransformParameterSpec) null); | |||
Transform envelopedTransform = newTransform(CanonicalizationMethod.ENVELOPED); | |||
transforms.add(envelopedTransform); | |||
Transform exclusiveTransform = signatureFactory.newTransform | |||
(CanonicalizationMethod.EXCLUSIVE, (TransformParameterSpec) null); | |||
Transform exclusiveTransform = newTransform(CanonicalizationMethod.EXCLUSIVE); | |||
transforms.add(exclusiveTransform); | |||
Reference reference = signatureFactory.newReference("", digestMethod, | |||
transforms, null, null); | |||
Reference reference = newReference("", transforms, null, null, null); | |||
references.add(reference); | |||
} | |||
} |
@@ -24,10 +24,8 @@ | |||
package org.apache.poi.poifs.crypt.dsig.facets; | |||
import java.security.InvalidAlgorithmParameterException; | |||
import java.security.Key; | |||
import java.security.KeyException; | |||
import java.security.NoSuchAlgorithmException; | |||
import java.security.cert.X509Certificate; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
@@ -35,9 +33,6 @@ import java.util.Map; | |||
import javax.xml.crypto.MarshalException; | |||
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.keyinfo.KeyInfo; | |||
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 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.POILogger; | |||
import org.w3c.dom.Document; | |||
@@ -60,16 +53,10 @@ import org.w3c.dom.NodeList; | |||
* @author Frank Cornelis | |||
* | |||
*/ | |||
public class KeyInfoSignatureFacet implements SignatureFacet { | |||
public class KeyInfoSignatureFacet extends SignatureFacet { | |||
private static final POILogger LOG = POILogFactory.getLogger(KeyInfoSignatureFacet.class); | |||
SignatureConfig signatureConfig; | |||
public void setSignatureConfig(SignatureConfig signatureConfig) { | |||
this.signatureConfig = signatureConfig; | |||
} | |||
@Override | |||
public void postSign(Document document) | |||
throws MarshalException { | |||
@@ -86,7 +73,7 @@ public class KeyInfoSignatureFacet implements SignatureFacet { | |||
/* | |||
* Construct the ds:KeyInfo element using JSR 105. | |||
*/ | |||
KeyInfoFactory keyInfoFactory = SignatureInfo.getKeyInfoFactory(); | |||
KeyInfoFactory keyInfoFactory = signatureConfig.getKeyInfoFactory(); | |||
List<Object> x509DataObjects = new ArrayList<Object>(); | |||
X509Certificate signingCertificate = signatureConfig.getSigningCertificateChain().get(0); | |||
@@ -104,8 +91,8 @@ public class KeyInfoSignatureFacet implements SignatureFacet { | |||
if (signatureConfig.isIncludeIssuerSerial()) { | |||
x509DataObjects.add(keyInfoFactory.newX509IssuerSerial( | |||
signingCertificate.getIssuerX500Principal().toString(), | |||
signingCertificate.getSerialNumber())); | |||
signingCertificate.getIssuerX500Principal().toString(), | |||
signingCertificate.getSerialNumber())); | |||
} | |||
if (signatureConfig.isIncludeEntireCertificateChain()) { | |||
@@ -155,14 +142,4 @@ public class KeyInfoSignatureFacet implements SignatureFacet { | |||
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; | |||
import java.io.IOException; | |||
import java.net.URI; | |||
import java.net.URISyntaxException; | |||
import java.security.InvalidAlgorithmParameterException; | |||
import java.security.NoSuchAlgorithmException; | |||
import java.text.DateFormat; | |||
import java.text.SimpleDateFormat; | |||
import java.util.ArrayList; | |||
@@ -41,15 +38,13 @@ import javax.xml.XMLConstants; | |||
import javax.xml.crypto.XMLStructure; | |||
import javax.xml.crypto.dom.DOMStructure; | |||
import javax.xml.crypto.dsig.CanonicalizationMethod; | |||
import javax.xml.crypto.dsig.DigestMethod; | |||
import javax.xml.crypto.dsig.Manifest; | |||
import javax.xml.crypto.dsig.Reference; | |||
import javax.xml.crypto.dsig.SignatureProperties; | |||
import javax.xml.crypto.dsig.SignatureProperty; | |||
import javax.xml.crypto.dsig.Transform; | |||
import javax.xml.crypto.dsig.XMLObject; | |||
import javax.xml.crypto.dsig.XMLSignatureFactory; | |||
import javax.xml.crypto.dsig.spec.TransformParameterSpec; | |||
import javax.xml.crypto.dsig.XMLSignatureException; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
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.PackagingURIHelper; | |||
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.RelationshipTransformParameterSpec; | |||
import org.apache.poi.util.POILogFactory; | |||
import org.apache.poi.util.POILogger; | |||
import org.apache.xmlbeans.XmlException; | |||
import org.openxmlformats.schemas.xpackage.x2006.digitalSignature.CTSignatureTime; | |||
import org.openxmlformats.schemas.xpackage.x2006.digitalSignature.SignatureTimeDocument; | |||
import org.w3c.dom.Document; | |||
@@ -80,64 +73,50 @@ import com.microsoft.schemas.office.x2006.digsig.SignatureInfoV1Document; | |||
* @author fcorneli | |||
* @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 SignatureConfig signatureConfig; | |||
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, IOException, URISyntaxException, XmlException { | |||
throws XMLSignatureException { | |||
LOG.log(POILogger.DEBUG, "pre sign"); | |||
addManifestObject(document, signatureFactory, references, objects); | |||
addSignatureInfo(document, signatureFactory, references, objects); | |||
addManifestObject(document, references, objects); | |||
addSignatureInfo(document, references, objects); | |||
} | |||
protected void addManifestObject( | |||
Document document | |||
, XMLSignatureFactory signatureFactory | |||
, List<Reference> references | |||
, List<XMLObject> objects) | |||
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, IOException, URISyntaxException, XmlException { | |||
throws XMLSignatureException { | |||
List<Reference> manifestReferences = new ArrayList<Reference>(); | |||
addManifestReferences(signatureFactory, manifestReferences); | |||
Manifest manifest = signatureFactory.newManifest(manifestReferences); | |||
addManifestReferences(manifestReferences); | |||
Manifest manifest = getSignatureFactory().newManifest(manifestReferences); | |||
String objectId = "idPackageObject"; // really has to be this value. | |||
List<XMLStructure> objectContent = new ArrayList<XMLStructure>(); | |||
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); | |||
DigestMethod digestMethod = signatureFactory.newDigestMethod | |||
(signatureConfig.getDigestMethodUri(), null); | |||
Reference reference = signatureFactory.newReference | |||
("#" + objectId, digestMethod, null, XML_DIGSIG_NS+"Object", null); | |||
Reference reference = newReference("#" + objectId, null, XML_DIGSIG_NS+"Object", null, null); | |||
references.add(reference); | |||
} | |||
protected void addManifestReferences | |||
(XMLSignatureFactory signatureFactory, List<Reference> manifestReferences) | |||
throws IOException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, URISyntaxException, XmlException { | |||
protected void addManifestReferences(List<Reference> manifestReferences) | |||
throws XMLSignatureException { | |||
OPCPackage ooxml = signatureConfig.getOpcPackage(); | |||
List<PackagePart> relsEntryNames = ooxml.getPartsByContentType(ContentTypes.RELATIONSHIPS_PART); | |||
DigestMethod digestMethod = signatureFactory.newDigestMethod | |||
(signatureConfig.getDigestMethodUri(), null); | |||
Set<String> digestedPartNames = new HashSet<String>(); | |||
for (PackagePart pp : relsEntryNames) { | |||
String baseUri = pp.getPartName().getName().replaceFirst("(.*)/_rels/.*", "$1"); | |||
@@ -147,7 +126,7 @@ public class OOXMLSignatureFacet implements SignatureFacet { | |||
prc = new PackageRelationshipCollection(ooxml); | |||
prc.parseRelationshipsPart(pp); | |||
} 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(); | |||
@@ -169,8 +148,12 @@ public class OOXMLSignatureFacet implements SignatureFacet { | |||
// TODO: find a better way ... | |||
String partName = baseUri + relationship.getTargetURI().toString(); | |||
partName = new URI(partName).normalize().getPath().replace('\\', '/'); | |||
LOG.log(POILogger.DEBUG, "part name: " + partName); | |||
try { | |||
partName = new URI(partName).normalize().getPath().replace('\\', '/'); | |||
LOG.log(POILogger.DEBUG, "part name: " + partName); | |||
} catch (URISyntaxException e) { | |||
throw new XMLSignatureException(e); | |||
} | |||
String contentType; | |||
try { | |||
@@ -178,7 +161,7 @@ public class OOXMLSignatureFacet implements SignatureFacet { | |||
PackagePart pp2 = ooxml.getPart(relName); | |||
contentType = pp2.getContentType(); | |||
} catch (InvalidFormatException e) { | |||
throw new IOException(e); | |||
throw new XMLSignatureException(e); | |||
} | |||
if (relationshipType.endsWith("customXml") | |||
@@ -190,7 +173,7 @@ public class OOXMLSignatureFacet implements SignatureFacet { | |||
if (!digestedPartNames.contains(partName)) { | |||
// We only digest a part once. | |||
String uri = partName + "?ContentType=" + contentType; | |||
Reference reference = signatureFactory.newReference(uri, digestMethod); | |||
Reference reference = newReference(uri, null, null, null, null); | |||
manifestReferences.add(reference); | |||
digestedPartNames.add(partName); | |||
} | |||
@@ -198,25 +181,18 @@ public class OOXMLSignatureFacet implements SignatureFacet { | |||
if (parameterSpec.hasSourceIds()) { | |||
List<Transform> transforms = new ArrayList<Transform>(); | |||
transforms.add(signatureFactory.newTransform( | |||
RelationshipTransformService.TRANSFORM_URI, | |||
parameterSpec)); | |||
transforms.add(signatureFactory.newTransform( | |||
CanonicalizationMethod.INCLUSIVE, | |||
(TransformParameterSpec) null)); | |||
transforms.add(newTransform(RelationshipTransformService.TRANSFORM_URI, parameterSpec)); | |||
transforms.add(newTransform(CanonicalizationMethod.INCLUSIVE)); | |||
String uri = pp.getPartName().getName() | |||
+ "?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); | |||
} | |||
} | |||
} | |||
protected void addSignatureTime( | |||
Document document | |||
, XMLSignatureFactory signatureFactory | |||
, List<XMLStructure> objectContent) { | |||
protected void addSignatureTime(Document document, List<XMLStructure> objectContent) { | |||
/* | |||
* SignatureTime | |||
*/ | |||
@@ -233,22 +209,21 @@ public class OOXMLSignatureFacet implements SignatureFacet { | |||
Element n = (Element)document.importNode(ctTime.getDomNode(),true); | |||
List<XMLStructure> signatureTimeContent = new ArrayList<XMLStructure>(); | |||
signatureTimeContent.add(new DOMStructure(n)); | |||
SignatureProperty signatureTimeSignatureProperty = signatureFactory | |||
SignatureProperty signatureTimeSignatureProperty = getSignatureFactory() | |||
.newSignatureProperty(signatureTimeContent, "#" + signatureConfig.getPackageSignatureId(), | |||
"idSignatureTime"); | |||
List<SignatureProperty> signaturePropertyContent = new ArrayList<SignatureProperty>(); | |||
signaturePropertyContent.add(signatureTimeSignatureProperty); | |||
SignatureProperties signatureProperties = signatureFactory | |||
SignatureProperties signatureProperties = getSignatureFactory() | |||
.newSignatureProperties(signaturePropertyContent, | |||
"id-signature-time-" + signatureConfig.getExecutionTime()); | |||
objectContent.add(signatureProperties); | |||
} | |||
protected void addSignatureInfo(Document document, | |||
XMLSignatureFactory signatureFactory, | |||
List<Reference> references, | |||
List<XMLObject> objects) | |||
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { | |||
throws XMLSignatureException { | |||
List<XMLStructure> objectContent = new ArrayList<XMLStructure>(); | |||
SignatureInfoV1Document sigV1 = SignatureInfoV1Document.Factory.newInstance(); | |||
@@ -259,31 +234,23 @@ public class OOXMLSignatureFacet implements SignatureFacet { | |||
List<XMLStructure> signatureInfoContent = new ArrayList<XMLStructure>(); | |||
signatureInfoContent.add(new DOMStructure(n)); | |||
SignatureProperty signatureInfoSignatureProperty = signatureFactory | |||
SignatureProperty signatureInfoSignatureProperty = getSignatureFactory() | |||
.newSignatureProperty(signatureInfoContent, "#" + signatureConfig.getPackageSignatureId(), | |||
"idOfficeV1Details"); | |||
List<SignatureProperty> signaturePropertyContent = new ArrayList<SignatureProperty>(); | |||
signaturePropertyContent.add(signatureInfoSignatureProperty); | |||
SignatureProperties signatureProperties = signatureFactory | |||
SignatureProperties signatureProperties = getSignatureFactory() | |||
.newSignatureProperties(signaturePropertyContent, null); | |||
objectContent.add(signatureProperties); | |||
String objectId = "idOfficeObject"; | |||
objects.add(signatureFactory.newXMLObject(objectContent, objectId, null, null)); | |||
objects.add(getSignatureFactory().newXMLObject(objectContent, objectId, null, null)); | |||
DigestMethod digestMethod = signatureFactory.newDigestMethod | |||
(signatureConfig.getDigestMethodUri(), null); | |||
Reference reference = signatureFactory.newReference | |||
("#" + objectId, digestMethod, null, XML_DIGSIG_NS+"Object", null); | |||
Reference reference = newReference("#" + objectId, null, XML_DIGSIG_NS+"Object", null, null); | |||
references.add(reference); | |||
} | |||
@Override | |||
public void postSign(Document document) { | |||
// empty | |||
} | |||
protected static String getRelationshipReferenceURI(String zipEntryName) { | |||
return "/" | |||
+ zipEntryName |
@@ -24,15 +24,8 @@ | |||
package org.apache.poi.poifs.crypt.dsig.facets; | |||
import java.security.InvalidAlgorithmParameterException; | |||
import java.security.NoSuchAlgorithmException; | |||
import java.util.List; | |||
import javax.xml.crypto.MarshalException; | |||
import javax.xml.crypto.dsig.Reference; | |||
import javax.xml.crypto.dsig.XMLObject; | |||
import javax.xml.crypto.dsig.XMLSignatureFactory; | |||
import org.apache.poi.poifs.crypt.dsig.SignatureConfig; | |||
import org.apache.xmlbeans.XmlException; | |||
import org.etsi.uri.x01903.v13.QualifyingPropertiesType; | |||
import org.etsi.uri.x01903.v13.UnsignedPropertiesType; | |||
@@ -50,32 +43,23 @@ import org.w3c.dom.NodeList; | |||
* @author Frank Cornelis | |||
* | |||
*/ | |||
public class Office2010SignatureFacet implements 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 { | |||
} | |||
public class Office2010SignatureFacet extends SignatureFacet { | |||
@Override | |||
public void postSign(Document document) | |||
throws XmlException { | |||
throws MarshalException { | |||
// check for XAdES-BES | |||
NodeList nl = document.getElementsByTagNameNS(XADES_132_NS, "QualifyingProperties"); | |||
if (nl.getLength() != 1) { | |||
throw new IllegalArgumentException("no XAdES-BES extension present"); | |||
throw new MarshalException("no XAdES-BES extension present"); | |||
} | |||
QualifyingPropertiesType qualProps = | |||
QualifyingPropertiesType.Factory.parse(nl.item(0)); | |||
QualifyingPropertiesType qualProps; | |||
try { | |||
qualProps = QualifyingPropertiesType.Factory.parse(nl.item(0)); | |||
} catch (XmlException e) { | |||
throw new MarshalException(e); | |||
} | |||
// create basic XML container structure | |||
UnsignedPropertiesType unsignedProps = qualProps.getUnsignedProperties(); |
@@ -24,39 +24,43 @@ | |||
package org.apache.poi.poifs.crypt.dsig.facets; | |||
import java.io.IOException; | |||
import java.net.URISyntaxException; | |||
import java.security.InvalidAlgorithmParameterException; | |||
import java.security.NoSuchAlgorithmException; | |||
import java.security.GeneralSecurityException; | |||
import java.util.List; | |||
import javax.xml.XMLConstants; | |||
import javax.xml.crypto.MarshalException; | |||
import javax.xml.crypto.dsig.DigestMethod; | |||
import javax.xml.crypto.dsig.Reference; | |||
import javax.xml.crypto.dsig.Transform; | |||
import javax.xml.crypto.dsig.XMLObject; | |||
import javax.xml.crypto.dsig.XMLSignature; | |||
import javax.xml.crypto.dsig.XMLSignatureException; | |||
import javax.xml.crypto.dsig.XMLSignatureFactory; | |||
import javax.xml.crypto.dsig.spec.TransformParameterSpec; | |||
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.xmlbeans.XmlException; | |||
import org.w3c.dom.Document; | |||
/** | |||
* JSR105 Signature Facet interface. | |||
* | |||
* @author Frank Cornelis | |||
* | |||
* JSR105 Signature Facet base class. | |||
*/ | |||
public interface SignatureFacet extends SignatureConfigurable { | |||
public abstract class SignatureFacet implements SignatureConfigurable { | |||
String XML_NS = XMLConstants.XMLNS_ATTRIBUTE_NS_URI; | |||
String XML_DIGSIG_NS = XMLSignature.XMLNS; | |||
String OO_DIGSIG_NS = PackageNamespaces.DIGITAL_SIGNATURE; | |||
String MS_DIGSIG_NS = "http://schemas.microsoft.com/office/2006/digsig"; | |||
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 XML_NS = XMLConstants.XMLNS_ATTRIBUTE_NS_URI; | |||
public static final String XML_DIGSIG_NS = XMLSignature.XMLNS; | |||
public static final String OO_DIGSIG_NS = PackageNamespaces.DIGITAL_SIGNATURE; | |||
public static final String MS_DIGSIG_NS = "http://schemas.microsoft.com/office/2006/digsig"; | |||
public static final String XADES_132_NS = "http://uri.etsi.org/01903/v1.3.2#"; | |||
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 | |||
@@ -64,21 +68,17 @@ public interface SignatureFacet extends SignatureConfigurable { | |||
* signature facets to an XML signature. | |||
* | |||
* @param document the signature document to be used for imports | |||
* @param signatureFactory the signature factory | |||
* @param references list of reference definitions | |||
* @param objects objects to be signed/included in the signature document | |||
* @throws NoSuchAlgorithmException | |||
* @throws InvalidAlgorithmParameterException | |||
* @throws IOException | |||
* @throws URISyntaxException | |||
* @throws XmlException | |||
* @throws XMLSignatureException | |||
*/ | |||
void preSign( | |||
public void preSign( | |||
Document document | |||
, XMLSignatureFactory signatureFactory | |||
, List<Reference> references | |||
, List<XMLObject> objects | |||
) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, IOException, URISyntaxException, XmlException; | |||
) throws XMLSignatureException { | |||
// empty | |||
} | |||
/** | |||
* 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 | |||
* @throws MarshalException | |||
* @throws XmlException | |||
*/ | |||
void postSign( | |||
Document document | |||
) throws MarshalException, XmlException; | |||
public void postSign(Document document) throws MarshalException { | |||
// empty | |||
} | |||
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; | |||
import java.security.InvalidAlgorithmParameterException; | |||
import java.security.MessageDigest; | |||
import java.security.NoSuchAlgorithmException; | |||
import java.security.cert.CertificateEncodingException; | |||
import java.security.cert.X509Certificate; | |||
import java.util.ArrayList; | |||
@@ -39,12 +37,10 @@ import java.util.TimeZone; | |||
import javax.xml.crypto.XMLStructure; | |||
import javax.xml.crypto.dom.DOMStructure; | |||
import javax.xml.crypto.dsig.CanonicalizationMethod; | |||
import javax.xml.crypto.dsig.DigestMethod; | |||
import javax.xml.crypto.dsig.Reference; | |||
import javax.xml.crypto.dsig.Transform; | |||
import javax.xml.crypto.dsig.XMLObject; | |||
import javax.xml.crypto.dsig.XMLSignatureFactory; | |||
import javax.xml.crypto.dsig.spec.TransformParameterSpec; | |||
import javax.xml.crypto.dsig.XMLSignatureException; | |||
import org.apache.poi.poifs.crypt.CryptoFunctions; | |||
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> | |||
* | |||
*/ | |||
public class XAdESSignatureFacet implements SignatureFacet { | |||
public class XAdESSignatureFacet extends SignatureFacet { | |||
private static final POILogger LOG = POILogFactory.getLogger(XAdESSignatureFacet.class); | |||
private static final String XADES_TYPE = "http://uri.etsi.org/01903#SignedProperties"; | |||
private SignatureConfig signatureConfig; | |||
private Map<String, String> dataObjectFormatMimeTypes = new HashMap<String, String>(); | |||
public void setSignatureConfig(SignatureConfig signatureConfig) { | |||
this.signatureConfig = signatureConfig; | |||
} | |||
@Override | |||
public void postSign(Document document) { | |||
LOG.log(POILogger.DEBUG, "postSign"); | |||
} | |||
@Override | |||
public void preSign(Document document, | |||
XMLSignatureFactory signatureFactory, | |||
List<Reference> references, List<XMLObject> objects) | |||
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { | |||
public void preSign( | |||
Document document | |||
, List<Reference> references | |||
, List<XMLObject> objects) | |||
throws XMLSignatureException { | |||
LOG.log(POILogger.DEBUG, "preSign"); | |||
// QualifyingProperties | |||
@@ -209,18 +196,15 @@ public class XAdESSignatureFacet implements SignatureFacet { | |||
Element qualDocElSrc = (Element)qualifyingProperties.getDomNode(); | |||
Element qualDocEl = (Element)document.importNode(qualDocElSrc, true); | |||
xadesObjectContent.add(new DOMStructure(qualDocEl)); | |||
XMLObject xadesObject = signatureFactory.newXMLObject(xadesObjectContent, null, null, null); | |||
XMLObject xadesObject = getSignatureFactory().newXMLObject(xadesObjectContent, null, null, null); | |||
objects.add(xadesObject); | |||
// add XAdES ds:Reference | |||
DigestMethod digestMethod = signatureFactory.newDigestMethod(signatureConfig.getDigestMethodUri(), null); | |||
List<Transform> transforms = new ArrayList<Transform>(); | |||
Transform exclusiveTransform = signatureFactory | |||
.newTransform(CanonicalizationMethod.INCLUSIVE, | |||
(TransformParameterSpec) null); | |||
Transform exclusiveTransform = newTransform(CanonicalizationMethod.INCLUSIVE); | |||
transforms.add(exclusiveTransform); | |||
Reference reference = signatureFactory.newReference | |||
("#"+signatureConfig.getXadesSignatureId(), digestMethod, transforms, XADES_TYPE, null); | |||
Reference reference = newReference | |||
("#"+signatureConfig.getXadesSignatureId(), transforms, XADES_TYPE, null, null); | |||
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.ByteArrayOutputStream; | |||
import java.math.BigInteger; | |||
import java.security.InvalidAlgorithmParameterException; | |||
import java.security.NoSuchAlgorithmException; | |||
import java.security.cert.CRLException; | |||
import java.security.cert.CertificateEncodingException; | |||
import java.security.cert.CertificateException; | |||
@@ -43,12 +41,9 @@ import java.util.Collections; | |||
import java.util.List; | |||
import java.util.UUID; | |||
import javax.xml.crypto.MarshalException; | |||
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.util.POILogFactory; | |||
import org.apache.poi.util.POILogger; | |||
@@ -106,20 +101,14 @@ import org.w3c.dom.NodeList; | |||
* @author Frank Cornelis | |||
* @see XAdESSignatureFacet | |||
*/ | |||
public class XAdESXLSignatureFacet implements SignatureFacet { | |||
public class XAdESXLSignatureFacet extends SignatureFacet { | |||
private static final POILogger LOG = POILogFactory.getLogger(XAdESXLSignatureFacet.class); | |||
private SignatureConfig signatureConfig; | |||
private String c14nAlgoId = CanonicalizationMethod.EXCLUSIVE; | |||
private final CertificateFactory certificateFactory; | |||
public void setSignatureConfig(SignatureConfig signatureConfig) { | |||
this.signatureConfig = signatureConfig; | |||
} | |||
public XAdESXLSignatureFacet() { | |||
try { | |||
this.certificateFactory = CertificateFactory.getInstance("X.509"); | |||
@@ -133,7 +122,7 @@ public class XAdESXLSignatureFacet implements SignatureFacet { | |||
} | |||
@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"); | |||
QualifyingPropertiesDocument qualDoc = null; | |||
@@ -142,10 +131,14 @@ public class XAdESXLSignatureFacet implements SignatureFacet { | |||
// check for XAdES-BES | |||
NodeList qualNl = document.getElementsByTagNameNS(XADES_132_NS, "QualifyingProperties"); | |||
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(); | |||
} else { | |||
throw new IllegalArgumentException("no XAdES-BES extension present"); | |||
throw new MarshalException("no XAdES-BES extension present"); | |||
} | |||
// create basic XML container structure | |||
@@ -335,14 +328,6 @@ public class XAdESXLSignatureFacet implements SignatureFacet { | |||
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) { | |||
try { | |||
byte[] crlNumberExtensionValue = crl.getExtensionValue(Extension.cRLNumber.getId()); |