mirror of https://github.com/apache/poi.git
#64186 - Decrease usage of ThreadLocals in XML Signature API
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1874671 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
3691704678
commit
b04379bc4c
|
@ -18,9 +18,9 @@
|
|||
/* ====================================================================
|
||||
This product contains an ASLv2 licensed version of the OOXML signer
|
||||
package from the eID Applet project
|
||||
http://code.google.com/p/eid-applet/source/browse/trunk/README.txt
|
||||
http://code.google.com/p/eid-applet/source/browse/trunk/README.txt
|
||||
Copyright (C) 2008-2014 FedICT.
|
||||
================================================================= */
|
||||
================================================================= */
|
||||
|
||||
package org.apache.poi.poifs.crypt.dsig;
|
||||
|
||||
|
@ -42,33 +42,29 @@ import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
|||
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||
import org.apache.poi.openxml4j.opc.PackagePartName;
|
||||
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
|
||||
import org.apache.poi.poifs.crypt.dsig.SignatureConfig.SignatureConfigurable;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
|
||||
/**
|
||||
* JSR105 URI dereferencer for Office Open XML documents.
|
||||
*/
|
||||
public class OOXMLURIDereferencer implements URIDereferencer, SignatureConfigurable {
|
||||
public class OOXMLURIDereferencer implements URIDereferencer {
|
||||
|
||||
private static final POILogger LOG = POILogFactory.getLogger(OOXMLURIDereferencer.class);
|
||||
|
||||
private SignatureConfig signatureConfig;
|
||||
private SignatureInfo signatureInfo;
|
||||
private URIDereferencer baseUriDereferencer;
|
||||
|
||||
public void setSignatureConfig(SignatureConfig signatureConfig) {
|
||||
this.signatureConfig = signatureConfig;
|
||||
public void setSignatureInfo(SignatureInfo signatureInfo) {
|
||||
this.signatureInfo = signatureInfo;
|
||||
baseUriDereferencer = signatureInfo.getSignatureFactory().getURIDereferencer();
|
||||
}
|
||||
|
||||
public Data dereference(URIReference uriReference, XMLCryptoContext context) throws URIReferenceException {
|
||||
if (baseUriDereferencer == null) {
|
||||
baseUriDereferencer = signatureConfig.getSignatureFactory().getURIDereferencer();
|
||||
if (uriReference == null) {
|
||||
throw new NullPointerException("URIReference cannot be null - call setSignatureInfo(...) before");
|
||||
}
|
||||
|
||||
if (null == uriReference) {
|
||||
throw new NullPointerException("URIReference cannot be null");
|
||||
}
|
||||
if (null == context) {
|
||||
if (context == null) {
|
||||
throw new NullPointerException("XMLCryptoContext cannot be null");
|
||||
}
|
||||
|
||||
|
@ -82,7 +78,7 @@ public class OOXMLURIDereferencer implements URIDereferencer, SignatureConfigura
|
|||
PackagePart part = findPart(uri);
|
||||
if (part == null) {
|
||||
LOG.log(POILogger.DEBUG, "cannot resolve, delegating to base DOM URI dereferencer", uri);
|
||||
return this.baseUriDereferencer.dereference(uriReference, context);
|
||||
return baseUriDereferencer.dereference(uriReference, context);
|
||||
}
|
||||
|
||||
InputStream dataStream;
|
||||
|
@ -116,15 +112,14 @@ public class OOXMLURIDereferencer implements URIDereferencer, SignatureConfigura
|
|||
LOG.log(POILogger.DEBUG, "illegal part name (expected)", uri);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
PackagePartName ppn;
|
||||
try {
|
||||
ppn = PackagingURIHelper.createPartName(path);
|
||||
return signatureInfo.getOpcPackage().getPart(ppn);
|
||||
} catch (InvalidFormatException e) {
|
||||
LOG.log(POILogger.WARN, "illegal part name (not expected)", uri);
|
||||
return null;
|
||||
}
|
||||
|
||||
return signatureConfig.getOpcPackage().getPart(ppn);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,12 +27,15 @@ import java.text.DateFormat;
|
|||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.xml.crypto.URIDereferencer;
|
||||
import javax.xml.crypto.dsig.CanonicalizationMethod;
|
||||
|
@ -53,11 +56,12 @@ 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.Internal;
|
||||
import org.apache.poi.util.LocaleUtil;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
import org.apache.poi.util.Removal;
|
||||
import org.apache.xml.security.signature.XMLSignature;
|
||||
import org.w3c.dom.events.EventListener;
|
||||
|
||||
/**
|
||||
* This class bundles the configuration options used for the existing
|
||||
|
@ -73,11 +77,16 @@ public class SignatureConfig {
|
|||
private static final POILogger LOG = POILogFactory.getLogger(SignatureConfig.class);
|
||||
private static final String DigestMethod_SHA224 = "http://www.w3.org/2001/04/xmldsig-more#sha224";
|
||||
private static final String DigestMethod_SHA384 = "http://www.w3.org/2001/04/xmldsig-more#sha384";
|
||||
private static final String XMLSEC_SANTUARIO = "org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI";
|
||||
private static final String XMLSEC_JDK = "org.jcp.xml.dsig.internal.dom.XMLDSigRI";
|
||||
|
||||
private static final List<Supplier<SignatureFacet>> DEFAULT_FACETS = Arrays.asList(
|
||||
OOXMLSignatureFacet::new,
|
||||
KeyInfoSignatureFacet::new,
|
||||
XAdESSignatureFacet::new,
|
||||
Office2010SignatureFacet::new
|
||||
);
|
||||
|
||||
public interface SignatureConfigurable {
|
||||
void setSignatureConfig(SignatureConfig signatureConfig);
|
||||
}
|
||||
|
||||
private ThreadLocal<OPCPackage> opcPackage = new ThreadLocal<>();
|
||||
private ThreadLocal<XMLSignatureFactory> signatureFactory = new ThreadLocal<>();
|
||||
|
@ -94,7 +103,7 @@ public class SignatureConfig {
|
|||
* the optional signature policy service used for XAdES-EPES.
|
||||
*/
|
||||
private SignaturePolicyService signaturePolicyService;
|
||||
private URIDereferencer uriDereferencer;
|
||||
private URIDereferencer uriDereferencer = new OOXMLURIDereferencer();
|
||||
private String canonicalizationMethod = CanonicalizationMethod.INCLUSIVE;
|
||||
|
||||
private boolean includeEntireCertificateChain = true;
|
||||
|
@ -161,7 +170,7 @@ public class SignatureConfig {
|
|||
* with certain namespaces, so this EventListener is used to interfere
|
||||
* with the marshalling process.
|
||||
*/
|
||||
private EventListener signatureMarshalListener;
|
||||
private SignatureMarshalListener signatureMarshalListener = new SignatureMarshalDefaultListener();
|
||||
|
||||
/**
|
||||
* Map of namespace uris to prefix
|
||||
|
@ -181,61 +190,11 @@ public class SignatureConfig {
|
|||
*/
|
||||
private boolean allowMultipleSignatures = false;
|
||||
|
||||
|
||||
/**
|
||||
* 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 (opcPackage == null) {
|
||||
throw new EncryptedDocumentException("opcPackage is null");
|
||||
}
|
||||
if (uriDereferencer == null) {
|
||||
uriDereferencer = new OOXMLURIDereferencer();
|
||||
}
|
||||
if (uriDereferencer instanceof SignatureConfigurable) {
|
||||
((SignatureConfigurable)uriDereferencer).setSignatureConfig(this);
|
||||
}
|
||||
if (namespacePrefixes.isEmpty()) {
|
||||
/*
|
||||
* OOo doesn't like ds namespaces so per default prefixing is off.
|
||||
*/
|
||||
// namespacePrefixes.put(XML_DIGSIG_NS, "");
|
||||
namespacePrefixes.put(OO_DIGSIG_NS, "mdssi");
|
||||
namespacePrefixes.put(XADES_132_NS, "xd");
|
||||
}
|
||||
|
||||
if (onlyValidation) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (signatureMarshalListener == null) {
|
||||
signatureMarshalListener = new SignatureMarshalListener();
|
||||
}
|
||||
|
||||
if (signatureMarshalListener instanceof SignatureConfigurable) {
|
||||
((SignatureConfigurable)signatureMarshalListener).setSignatureConfig(this);
|
||||
}
|
||||
|
||||
if (tspService != null) {
|
||||
tspService.setSignatureConfig(this);
|
||||
}
|
||||
|
||||
if (signatureFacets.isEmpty()) {
|
||||
addSignatureFacet(new OOXMLSignatureFacet());
|
||||
addSignatureFacet(new KeyInfoSignatureFacet());
|
||||
addSignatureFacet(new XAdESSignatureFacet());
|
||||
addSignatureFacet(new Office2010SignatureFacet());
|
||||
}
|
||||
|
||||
for (SignatureFacet sf : signatureFacets) {
|
||||
sf.setSignatureConfig(this);
|
||||
}
|
||||
public SignatureConfig() {
|
||||
// OOo doesn't like ds namespaces so per default prefixing is off.
|
||||
// namespacePrefixes.put(XML_DIGSIG_NS, "");
|
||||
namespacePrefixes.put(OO_DIGSIG_NS, "mdssi");
|
||||
namespacePrefixes.put(XADES_132_NS, "xd");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -249,7 +208,11 @@ public class SignatureConfig {
|
|||
* @return the list of facets, may be empty when the config object is not initialized
|
||||
*/
|
||||
public List<SignatureFacet> getSignatureFacets() {
|
||||
return signatureFacets;
|
||||
if (signatureFacets.isEmpty()) {
|
||||
return DEFAULT_FACETS.stream().map(Supplier::get).collect(Collectors.toList());
|
||||
} else {
|
||||
return signatureFacets;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -275,14 +238,22 @@ public class SignatureConfig {
|
|||
|
||||
/**
|
||||
* @return the opc package to be used by this thread, stored as thread-local
|
||||
*
|
||||
* @deprecated in POI 4.1.3 - use {@link SignatureInfo#setOpcPackage(OPCPackage)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
@Removal(version = "5.0.0")
|
||||
public OPCPackage getOpcPackage() {
|
||||
return opcPackage.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param opcPackage the opc package to be handled by this thread, stored as thread-local
|
||||
*
|
||||
* @deprecated in POI 4.1.3 - use {@link SignatureInfo#setOpcPackage(OPCPackage)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
@Removal(version = "5.0.0")
|
||||
public void setOpcPackage(OPCPackage opcPackage) {
|
||||
this.opcPackage.set(opcPackage);
|
||||
}
|
||||
|
@ -378,14 +349,22 @@ public class SignatureConfig {
|
|||
|
||||
/**
|
||||
* @return the dereferencer used for Reference/@URI attributes, defaults to {@link OOXMLURIDereferencer}
|
||||
*
|
||||
* @deprecated in POI 4.1.3 - use {@link SignatureInfo#getUriDereferencer()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
@Removal(version = "5.0.0")
|
||||
public URIDereferencer getUriDereferencer() {
|
||||
return uriDereferencer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param uriDereferencer the dereferencer used for Reference/@URI attributes
|
||||
*
|
||||
* @deprecated in POI 4.1.3 - use {@link SignatureInfo#setUriDereferencer(URIDereferencer)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
@Removal(version = "5.0.0")
|
||||
public void setUriDereferencer(URIDereferencer uriDereferencer) {
|
||||
this.uriDereferencer = uriDereferencer;
|
||||
}
|
||||
|
@ -753,11 +732,10 @@ public class SignatureConfig {
|
|||
|
||||
|
||||
/**
|
||||
* @return the event listener which is active while xml structure for
|
||||
* the signature is created.
|
||||
* @return the event listener which is active while xml structure for the signature is created.
|
||||
* Defaults to {@link SignatureMarshalListener}
|
||||
*/
|
||||
public EventListener getSignatureMarshalListener() {
|
||||
public SignatureMarshalListener getSignatureMarshalListener() {
|
||||
return signatureMarshalListener;
|
||||
}
|
||||
|
||||
|
@ -765,7 +743,7 @@ public class SignatureConfig {
|
|||
* @param signatureMarshalListener the event listener watching the xml structure
|
||||
* generation for the signature
|
||||
*/
|
||||
public void setSignatureMarshalListener(EventListener signatureMarshalListener) {
|
||||
public void setSignatureMarshalListener(SignatureMarshalListener signatureMarshalListener) {
|
||||
this.signatureMarshalListener = signatureMarshalListener;
|
||||
}
|
||||
|
||||
|
@ -898,85 +876,91 @@ public class SignatureConfig {
|
|||
|
||||
/**
|
||||
* @param signatureFactory the xml signature factory, saved as thread-local
|
||||
*
|
||||
* @deprecated in POI 4.1.3 - use {@link SignatureInfo#setSignatureFactory(XMLSignatureFactory)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Removal(version = "5.0.0")
|
||||
public void setSignatureFactory(XMLSignatureFactory signatureFactory) {
|
||||
this.signatureFactory.set(signatureFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the xml signature factory (thread-local)
|
||||
*
|
||||
* @deprecated in POI 4.1.3 - will be handled by SignatureInfo internally
|
||||
*/
|
||||
@Deprecated
|
||||
@Removal(version = "5.0.0")
|
||||
public XMLSignatureFactory getSignatureFactory() {
|
||||
XMLSignatureFactory sigFac = signatureFactory.get();
|
||||
if (sigFac == null) {
|
||||
sigFac = XMLSignatureFactory.getInstance("DOM", getProvider());
|
||||
setSignatureFactory(sigFac);
|
||||
}
|
||||
return sigFac;
|
||||
return signatureFactory.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param keyInfoFactory the key factory, saved as thread-local
|
||||
*
|
||||
* @deprecated in POI 4.1.3 - use {@link SignatureInfo#setKeyInfoFactory(KeyInfoFactory)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Removal(version = "5.0.0")
|
||||
public void setKeyInfoFactory(KeyInfoFactory keyInfoFactory) {
|
||||
this.keyInfoFactory.set(keyInfoFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the key factory (thread-local)
|
||||
*
|
||||
* @deprecated in POI 4.1.3 - will be handled by SignatureInfo internally
|
||||
*/
|
||||
@Deprecated
|
||||
@Removal(version = "5.0.0")
|
||||
public KeyInfoFactory getKeyInfoFactory() {
|
||||
KeyInfoFactory keyFac = keyInfoFactory.get();
|
||||
if (keyFac == null) {
|
||||
keyFac = KeyInfoFactory.getInstance("DOM", getProvider());
|
||||
setKeyInfoFactory(keyFac);
|
||||
}
|
||||
return keyFac;
|
||||
return keyInfoFactory.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method tests the existence of xml signature provider in the following order:
|
||||
* <ul>
|
||||
* Helper method to set provider
|
||||
* @param provider the provider
|
||||
* @deprecated in POI 4.1.3 - use {@link SignatureInfo#setProvider(Provider)}
|
||||
*/
|
||||
@Internal
|
||||
@Deprecated
|
||||
@Removal(version = "5.0.0")
|
||||
public void setProvider(Provider provider) {
|
||||
this.provider.set(provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the cached provider or null if not set before
|
||||
*
|
||||
* @deprecated in POI 4.1.3 - will be handled by SignatureInfo internally
|
||||
*/
|
||||
@Deprecated
|
||||
@Removal(version = "5.0.0")
|
||||
public Provider getProvider() {
|
||||
return provider.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the possible classes for XMLSEC.
|
||||
* The order is
|
||||
* <ol>
|
||||
* <li>the class pointed to by the system property "jsr105Provider"</li>
|
||||
* <li>the Santuario xmlsec provider</li>
|
||||
* <li>the JDK xmlsec provider</li>
|
||||
* </ul>
|
||||
* </ol>
|
||||
*
|
||||
* For signing the classes are linked against the Santuario xmlsec, so this might
|
||||
* only work for validation (not tested).
|
||||
*
|
||||
* @return the xml dsig provider
|
||||
* @return a list of possible XMLSEC provider class names
|
||||
*/
|
||||
public Provider getProvider() {
|
||||
Provider prov = provider.get();
|
||||
if (prov == null) {
|
||||
String[] dsigProviderNames = {
|
||||
System.getProperty("jsr105Provider"),
|
||||
// Santuario xmlsec
|
||||
"org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI",
|
||||
// JDK xmlsec
|
||||
"org.jcp.xml.dsig.internal.dom.XMLDSigRI"
|
||||
};
|
||||
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;
|
||||
public static String[] getProviderNames() {
|
||||
// need to check every time, as the system property might have been changed in the meantime
|
||||
String sysProp = System.getProperty("jsr105Provider");
|
||||
return (sysProp == null || "".equals(sysProp))
|
||||
? new String[]{XMLSEC_SANTUARIO, XMLSEC_JDK}
|
||||
: new String[]{sysProp, XMLSEC_SANTUARIO, XMLSEC_JDK};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the cannonicalization method for XAdES-XL signing.
|
||||
* Defaults to <code>EXCLUSIVE</code>
|
||||
|
|
|
@ -31,6 +31,7 @@ import java.io.IOException;
|
|||
import java.io.OutputStream;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.Provider;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
|
@ -38,6 +39,8 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.xml.crypto.MarshalException;
|
||||
import javax.xml.crypto.URIDereferencer;
|
||||
|
@ -52,6 +55,7 @@ import javax.xml.crypto.dsig.XMLObject;
|
|||
import javax.xml.crypto.dsig.XMLSignatureException;
|
||||
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
||||
import javax.xml.crypto.dsig.dom.DOMSignContext;
|
||||
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
|
||||
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
|
||||
|
||||
import org.apache.jcp.xml.dsig.internal.dom.DOMReference;
|
||||
|
@ -70,7 +74,6 @@ import org.apache.poi.openxml4j.opc.PackagingURIHelper;
|
|||
import org.apache.poi.openxml4j.opc.TargetMode;
|
||||
import org.apache.poi.poifs.crypt.CryptoFunctions;
|
||||
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
||||
import org.apache.poi.poifs.crypt.dsig.SignatureConfig.SignatureConfigurable;
|
||||
import org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet;
|
||||
import org.apache.poi.poifs.crypt.dsig.services.RelationshipTransformService;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
|
@ -84,6 +87,7 @@ import org.w3c.dom.Element;
|
|||
import org.w3c.dom.NodeList;
|
||||
import org.w3c.dom.events.EventListener;
|
||||
import org.w3c.dom.events.EventTarget;
|
||||
import org.w3c.dom.events.MutationEvent;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -153,20 +157,16 @@ import org.w3c.dom.events.EventTarget;
|
|||
* <li>and slf4j-api (tested against 1.7.30)</li>
|
||||
* </ul>
|
||||
*/
|
||||
public class SignatureInfo implements SignatureConfigurable {
|
||||
public class SignatureInfo {
|
||||
|
||||
private static final POILogger LOG = POILogFactory.getLogger(SignatureInfo.class);
|
||||
private static boolean isInitialized;
|
||||
|
||||
private SignatureConfig signatureConfig;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor initializes xml signature environment, if it hasn't been initialized before
|
||||
*/
|
||||
public SignatureInfo() {
|
||||
initXmlProvider();
|
||||
}
|
||||
private OPCPackage opcPackage;
|
||||
private Provider provider;
|
||||
private XMLSignatureFactory signatureFactory;
|
||||
private KeyInfoFactory keyInfoFactory;
|
||||
private URIDereferencer uriDereferencer;
|
||||
|
||||
/**
|
||||
* @return the signature config
|
||||
|
@ -178,30 +178,45 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||
/**
|
||||
* @param signatureConfig the signature config, needs to be set before a SignatureInfo object is used
|
||||
*/
|
||||
@Override
|
||||
public void setSignatureConfig(SignatureConfig signatureConfig) {
|
||||
this.signatureConfig = signatureConfig;
|
||||
}
|
||||
|
||||
public void setOpcPackage(OPCPackage opcPackage) {
|
||||
this.opcPackage = opcPackage;
|
||||
}
|
||||
|
||||
public OPCPackage getOpcPackage() {
|
||||
return opcPackage;
|
||||
}
|
||||
|
||||
public URIDereferencer getUriDereferencer() {
|
||||
return uriDereferencer;
|
||||
}
|
||||
|
||||
public void setUriDereferencer(URIDereferencer uriDereferencer) {
|
||||
this.uriDereferencer = uriDereferencer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true, if first signature part is valid
|
||||
*/
|
||||
public boolean verifySignature() {
|
||||
initXmlProvider();
|
||||
// http://www.oracle.com/technetwork/articles/javase/dig-signature-api-140772.html
|
||||
for (SignaturePart sp : getSignatureParts()){
|
||||
// only validate first part
|
||||
return sp.validate();
|
||||
}
|
||||
return false;
|
||||
// only validate first part
|
||||
Iterator<SignaturePart> iter = getSignatureParts().iterator();
|
||||
return iter.hasNext() && iter.next().validate();
|
||||
}
|
||||
|
||||
/**
|
||||
* add the xml signature to the document
|
||||
*
|
||||
* @throws XMLSignatureException
|
||||
* @throws MarshalException
|
||||
* @throws XMLSignatureException if the signature can't be calculated
|
||||
* @throws MarshalException if the document can't be serialized
|
||||
*/
|
||||
public void confirmSignature() throws XMLSignatureException, MarshalException {
|
||||
initXmlProvider();
|
||||
final Document document = DocumentHelper.createDocument();
|
||||
final DOMSignContext xmlSignContext = createXMLSignContext(document);
|
||||
|
||||
|
@ -223,6 +238,7 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||
* @return the initialized signature context
|
||||
*/
|
||||
public DOMSignContext createXMLSignContext(final Document document) {
|
||||
initXmlProvider();
|
||||
return new DOMSignContext(signatureConfig.getKey(), document);
|
||||
}
|
||||
|
||||
|
@ -231,10 +247,10 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||
* Sign (encrypt) the digest with the private key.
|
||||
* Currently only rsa is supported.
|
||||
*
|
||||
* @param digest the hashed input
|
||||
* @return the encrypted hash
|
||||
*/
|
||||
public String signDigest(final DOMSignContext xmlSignContext, final DOMSignedInfo signedInfo) {
|
||||
initXmlProvider();
|
||||
final PrivateKey key = signatureConfig.getKey();
|
||||
final HashAlgorithm algo = signatureConfig.getDigestAlgo();
|
||||
|
||||
|
@ -243,12 +259,12 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||
|
||||
|
||||
if (algo.hashSize*4/3 > BASE64DEFAULTLENGTH && !XMLUtils.ignoreLineBreaks()) {
|
||||
throw new EncryptedDocumentException("The hash size of the choosen hash algorithm ("+algo+" = "+algo.hashSize+" bytes), "+
|
||||
throw new EncryptedDocumentException("The hash size of the chosen hash algorithm ("+algo+" = "+algo.hashSize+" bytes), "+
|
||||
"will motivate XmlSec to add linebreaks to the generated digest, which results in an invalid signature (... at least "+
|
||||
"for Office) - please persuade it otherwise by adding '-Dorg.apache.xml.security.ignoreLineBreaks=true' to the JVM "+
|
||||
"system properties.");
|
||||
}
|
||||
|
||||
|
||||
try (final DigestOutputStream dos = getDigestStream(algo, key)) {
|
||||
dos.init();
|
||||
|
||||
|
@ -277,78 +293,61 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||
* the parts can be validated independently.
|
||||
*/
|
||||
public Iterable<SignaturePart> getSignatureParts() {
|
||||
signatureConfig.init(true);
|
||||
return new Iterable<SignaturePart>() {
|
||||
@Override
|
||||
public Iterator<SignaturePart> iterator() {
|
||||
return new Iterator<SignaturePart>() {
|
||||
OPCPackage pkg = signatureConfig.getOpcPackage();
|
||||
Iterator<PackageRelationship> sigOrigRels =
|
||||
pkg.getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN).iterator();
|
||||
Iterator<PackageRelationship> sigRels;
|
||||
PackagePart sigPart;
|
||||
initXmlProvider();
|
||||
return SignaturePartIterator::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
while (sigRels == null || !sigRels.hasNext()) {
|
||||
if (!sigOrigRels.hasNext()) {
|
||||
return false;
|
||||
}
|
||||
sigPart = pkg.getPart(sigOrigRels.next());
|
||||
LOG.log(POILogger.DEBUG, "Digital Signature Origin part", sigPart);
|
||||
try {
|
||||
sigRels = sigPart.getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE).iterator();
|
||||
} catch (InvalidFormatException e) {
|
||||
LOG.log(POILogger.WARN, "Reference to signature is invalid.", e);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private final class SignaturePartIterator implements Iterator<SignaturePart> {
|
||||
Iterator<PackageRelationship> sigOrigRels;
|
||||
private Iterator<PackageRelationship> sigRels;
|
||||
private PackagePart sigPart;
|
||||
|
||||
@Override
|
||||
public SignaturePart next() {
|
||||
PackagePart sigRelPart = null;
|
||||
do {
|
||||
try {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
sigRelPart = sigPart.getRelatedPart(sigRels.next());
|
||||
LOG.log(POILogger.DEBUG, "XML Signature part", sigRelPart);
|
||||
} catch (InvalidFormatException e) {
|
||||
LOG.log(POILogger.WARN, "Reference to signature is invalid.", e);
|
||||
}
|
||||
} while (sigRelPart == null);
|
||||
return new SignaturePart(sigRelPart, signatureConfig);
|
||||
}
|
||||
private SignaturePartIterator() {
|
||||
sigOrigRels = opcPackage.getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN).iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
while (sigRels == null || !sigRels.hasNext()) {
|
||||
if (!sigOrigRels.hasNext()) {
|
||||
return false;
|
||||
}
|
||||
sigPart = opcPackage.getPart(sigOrigRels.next());
|
||||
LOG.log(POILogger.DEBUG, "Digital Signature Origin part", sigPart);
|
||||
try {
|
||||
sigRels = sigPart.getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE).iterator();
|
||||
} catch (InvalidFormatException e) {
|
||||
LOG.log(POILogger.WARN, "Reference to signature is invalid.", e);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the xml signing environment and the bouncycastle provider
|
||||
*/
|
||||
protected static synchronized void initXmlProvider() {
|
||||
if (isInitialized) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
isInitialized = true;
|
||||
|
||||
try {
|
||||
Init.init();
|
||||
RelationshipTransformService.registerDsigProvider();
|
||||
CryptoFunctions.registerBouncyCastle();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Xml & BouncyCastle-Provider initialization failed", e);
|
||||
@Override
|
||||
public SignaturePart next() {
|
||||
PackagePart sigRelPart = null;
|
||||
do {
|
||||
try {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
sigRelPart = sigPart.getRelatedPart(sigRels.next());
|
||||
LOG.log(POILogger.DEBUG, "XML Signature part", sigRelPart);
|
||||
} catch (InvalidFormatException e) {
|
||||
LOG.log(POILogger.WARN, "Reference to signature is invalid.", e);
|
||||
}
|
||||
} while (sigRelPart == null);
|
||||
return new SignaturePart(sigRelPart, SignatureInfo.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Helper method for adding informations before the signing.
|
||||
* Normally {@link #confirmSignature()} is sufficient to be used.
|
||||
|
@ -356,35 +355,18 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||
@SuppressWarnings("unchecked")
|
||||
public DOMSignedInfo preSign(final DOMSignContext xmlSignContext)
|
||||
throws XMLSignatureException, MarshalException {
|
||||
signatureConfig.init(false);
|
||||
|
||||
final Document document = (Document)xmlSignContext.getParent();
|
||||
|
||||
// it's necessary to explicitly set the mdssi namespace, but the sign() method has no
|
||||
// normal way to interfere with, so we need to add the namespace under the hand ...
|
||||
EventTarget target = (EventTarget)document;
|
||||
EventListener creationListener = signatureConfig.getSignatureMarshalListener();
|
||||
if (creationListener != null) {
|
||||
if (creationListener instanceof SignatureMarshalListener) {
|
||||
((SignatureMarshalListener)creationListener).setEventTarget(target);
|
||||
}
|
||||
SignatureMarshalListener.setListener(target, creationListener, true);
|
||||
}
|
||||
registerEventListener(document);
|
||||
|
||||
/*
|
||||
* Signature context construction.
|
||||
*/
|
||||
URIDereferencer uriDereferencer = signatureConfig.getUriDereferencer();
|
||||
if (null != uriDereferencer) {
|
||||
// Signature context construction.
|
||||
if (uriDereferencer != null) {
|
||||
xmlSignContext.setURIDereferencer(uriDereferencer);
|
||||
}
|
||||
|
||||
signatureConfig.getNamespacePrefixes().forEach(xmlSignContext::putNamespacePrefix);
|
||||
|
||||
xmlSignContext.setDefaultNamespacePrefix("");
|
||||
// signatureConfig.getNamespacePrefixes().get(XML_DIGSIG_NS));
|
||||
|
||||
XMLSignatureFactory signatureFactory = signatureConfig.getSignatureFactory();
|
||||
|
||||
/*
|
||||
* Add ds:References that come from signing client local files.
|
||||
|
@ -397,7 +379,7 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||
List<XMLObject> objects = new ArrayList<>();
|
||||
for (SignatureFacet signatureFacet : signatureConfig.getSignatureFacets()) {
|
||||
LOG.log(POILogger.DEBUG, "invoking signature facet: " + signatureFacet.getClass().getSimpleName());
|
||||
signatureFacet.preSign(document, references, objects);
|
||||
signatureFacet.preSign(this, document, references, objects);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -471,6 +453,35 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||
return (DOMSignedInfo)signedInfo;
|
||||
}
|
||||
|
||||
// it's necessary to explicitly set the mdssi namespace, but the sign() method has no
|
||||
// normal way to interfere with, so we need to add the namespace under the hand ...
|
||||
protected void registerEventListener(Document document) {
|
||||
final SignatureMarshalListener sml = signatureConfig.getSignatureMarshalListener();
|
||||
if (sml == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
EventTarget target = (EventTarget)document;
|
||||
|
||||
final EventListener[] el = { null };
|
||||
el[0] = (e) -> {
|
||||
if (!(e instanceof MutationEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
MutationEvent mutEvt = (MutationEvent) e;
|
||||
EventTarget et = mutEvt.getTarget();
|
||||
if (!(et instanceof Element)) {
|
||||
return;
|
||||
}
|
||||
|
||||
sml.handleElement(this, (Element) et, target, el[0]);
|
||||
};
|
||||
|
||||
SignatureMarshalListener.setListener(target, el[0], true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper method for adding informations after the signing.
|
||||
* Normally {@link #confirmSignature()} is sufficient to be used.
|
||||
|
@ -492,7 +503,7 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||
/*
|
||||
* Insert signature value into the ds:SignatureValue element
|
||||
*/
|
||||
final Element signatureNode = getDsigElement(document, "SignatureValue");
|
||||
final Element signatureNode = getDsigElement(document, "SignatureValue");
|
||||
if (signatureNode == null) {
|
||||
throw new RuntimeException("preSign has to be called before postSign");
|
||||
}
|
||||
|
@ -502,7 +513,7 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||
* Allow signature facets to inject their own stuff.
|
||||
*/
|
||||
for (SignatureFacet signatureFacet : signatureConfig.getSignatureFacets()) {
|
||||
signatureFacet.postSign(document);
|
||||
signatureFacet.postSign(this, document);
|
||||
}
|
||||
|
||||
writeDocument(document);
|
||||
|
@ -512,7 +523,7 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||
* Write XML signature into the OPC package
|
||||
*
|
||||
* @param document the xml signature document
|
||||
* @throws MarshalException
|
||||
* @throws MarshalException if the document can't be serialized
|
||||
*/
|
||||
protected void writeDocument(Document document) throws MarshalException {
|
||||
XmlOptions xo = new XmlOptions();
|
||||
|
@ -527,23 +538,21 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||
* Copy the original OOXML content to the signed OOXML package. During
|
||||
* copying some files need to changed.
|
||||
*/
|
||||
OPCPackage pkg = signatureConfig.getOpcPackage();
|
||||
|
||||
try {
|
||||
// <Default Extension="sigs" ContentType="application/vnd.openxmlformats-package.digital-signature-origin"/>
|
||||
final DSigRelation originDesc = DSigRelation.ORIGIN_SIGS;
|
||||
PackagePartName originPartName = PackagingURIHelper.createPartName(originDesc.getFileName(0));
|
||||
|
||||
PackagePart originPart = pkg.getPart(originPartName);
|
||||
PackagePart originPart = opcPackage.getPart(originPartName);
|
||||
if (originPart == null) {
|
||||
// touch empty marker file
|
||||
originPart = pkg.createPart(originPartName, originDesc.getContentType());
|
||||
pkg.addRelationship(originPartName, TargetMode.INTERNAL, originDesc.getRelation());
|
||||
originPart = opcPackage.createPart(originPartName, originDesc.getContentType());
|
||||
opcPackage.addRelationship(originPartName, TargetMode.INTERNAL, originDesc.getRelation());
|
||||
}
|
||||
|
||||
// <Override PartName="/_xmlsignatures/sig1.xml" ContentType="application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml"/>
|
||||
final DSigRelation sigDesc = DSigRelation.SIG;
|
||||
int nextSigIdx = pkg.getUnusedPartIndex(sigDesc.getDefaultFileName());
|
||||
int nextSigIdx = opcPackage.getUnusedPartIndex(sigDesc.getDefaultFileName());
|
||||
|
||||
if (!signatureConfig.isAllowMultipleSignatures()) {
|
||||
PackageRelationshipCollection prc = originPart.getRelationshipsByType(sigDesc.getRelation());
|
||||
|
@ -558,16 +567,16 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||
}
|
||||
}
|
||||
|
||||
pkg.removePart(pkg.getPart(pn));
|
||||
opcPackage.removePart(opcPackage.getPart(pn));
|
||||
}
|
||||
nextSigIdx = 1;
|
||||
}
|
||||
|
||||
|
||||
PackagePartName sigPartName = PackagingURIHelper.createPartName(sigDesc.getFileName(nextSigIdx));
|
||||
PackagePart sigPart = pkg.getPart(sigPartName);
|
||||
PackagePart sigPart = opcPackage.getPart(sigPartName);
|
||||
if (sigPart == null) {
|
||||
sigPart = pkg.createPart(sigPartName, sigDesc.getContentType());
|
||||
sigPart = opcPackage.createPart(sigPartName, sigDesc.getContentType());
|
||||
originPart.addRelationship(sigPartName, TargetMode.INTERNAL, sigDesc.getRelation());
|
||||
} else {
|
||||
sigPart.clear();
|
||||
|
@ -590,7 +599,123 @@ public class SignatureInfo implements SignatureConfigurable {
|
|||
}
|
||||
|
||||
LOG.log(POILogger.WARN, "Signature element '"+localName+"' was "+(sigValNl.getLength() == 0 ? "not found" : "multiple times"));
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setProvider(Provider provider) {
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
public void setSignatureFactory(XMLSignatureFactory signatureFactory) {
|
||||
this.signatureFactory = signatureFactory;
|
||||
}
|
||||
|
||||
public XMLSignatureFactory getSignatureFactory() {
|
||||
return signatureFactory;
|
||||
}
|
||||
|
||||
public void setKeyInfoFactory(KeyInfoFactory keyInfoFactory) {
|
||||
this.keyInfoFactory = keyInfoFactory;
|
||||
}
|
||||
|
||||
public KeyInfoFactory getKeyInfoFactory() {
|
||||
return keyInfoFactory;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the xml signing environment and the bouncycastle provider
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
protected void initXmlProvider() {
|
||||
if (opcPackage == null) {
|
||||
opcPackage = signatureConfig.getOpcPackage();
|
||||
}
|
||||
if (provider == null) {
|
||||
provider = signatureConfig.getProvider();
|
||||
if (provider == null) {
|
||||
provider = XmlProviderInitSingleton.getInstance().findProvider();
|
||||
}
|
||||
}
|
||||
if (signatureFactory == null) {
|
||||
signatureFactory = signatureConfig.getSignatureFactory();
|
||||
if (signatureFactory == null) {
|
||||
signatureFactory = XMLSignatureFactory.getInstance("DOM", provider);
|
||||
}
|
||||
}
|
||||
if (keyInfoFactory == null) {
|
||||
keyInfoFactory = signatureConfig.getKeyInfoFactory();
|
||||
if (keyInfoFactory == null) {
|
||||
keyInfoFactory = KeyInfoFactory.getInstance("DOM", provider);
|
||||
}
|
||||
}
|
||||
if (uriDereferencer == null) {
|
||||
uriDereferencer = signatureConfig.getUriDereferencer();
|
||||
if (uriDereferencer == null) {
|
||||
uriDereferencer = new OOXMLURIDereferencer();
|
||||
}
|
||||
}
|
||||
if (uriDereferencer instanceof OOXMLURIDereferencer) {
|
||||
((OOXMLURIDereferencer)uriDereferencer).setSignatureInfo(this);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class XmlProviderInitSingleton {
|
||||
|
||||
// Bill Pugh Singleton
|
||||
private static class SingletonHelper {
|
||||
private static final XmlProviderInitSingleton INSTANCE = new XmlProviderInitSingleton();
|
||||
}
|
||||
|
||||
public static XmlProviderInitSingleton getInstance(){
|
||||
return SingletonHelper.INSTANCE;
|
||||
}
|
||||
|
||||
private XmlProviderInitSingleton() {
|
||||
try {
|
||||
Init.init();
|
||||
RelationshipTransformService.registerDsigProvider();
|
||||
CryptoFunctions.registerBouncyCastle();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Xml & BouncyCastle-Provider initialization failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method tests the existence of xml signature provider in the following order:
|
||||
* <ul>
|
||||
* <li>the class pointed to by the system property "jsr105Provider"</li>
|
||||
* <li>the Santuario xmlsec provider</li>
|
||||
* <li>the JDK xmlsec provider</li>
|
||||
* </ul>
|
||||
*
|
||||
* For signing the classes are linked against the Santuario xmlsec, so this might
|
||||
* only work for validation (not tested).
|
||||
*
|
||||
* @return the xml dsig provider
|
||||
*/
|
||||
public Provider findProvider() {
|
||||
return
|
||||
Stream.of(SignatureConfig.getProviderNames())
|
||||
.map(this::getProvider)
|
||||
.filter(Objects::nonNull).findFirst()
|
||||
.orElseThrow(this::providerNotFound);
|
||||
}
|
||||
|
||||
private Provider getProvider(String className) {
|
||||
try {
|
||||
return (Provider)Class.forName(className).newInstance();
|
||||
} catch (Exception e) {
|
||||
LOG.log(POILogger.DEBUG, "XMLDsig-Provider '"+className+"' can't be found - trying next.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private RuntimeException providerNotFound() {
|
||||
return new RuntimeException("JRE doesn't support default xml signature provider - set jsr105Provider system property!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.poifs.crypt.dsig;
|
||||
|
||||
import static org.apache.poi.poifs.crypt.dsig.SignatureMarshalListener.setListener;
|
||||
import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.OO_DIGSIG_NS;
|
||||
import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.XML_NS;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.w3c.dom.events.EventListener;
|
||||
import org.w3c.dom.events.EventTarget;
|
||||
|
||||
/**
|
||||
* This listener class is used, to modify the to be digested xml document,
|
||||
* e.g. to register id attributes or set prefixes for registered namespaces
|
||||
*/
|
||||
public class SignatureMarshalDefaultListener implements SignatureMarshalListener {
|
||||
@Override
|
||||
public void handleElement(SignatureInfo signatureInfo, Element el, EventTarget target, EventListener parentListener) {
|
||||
if (el.hasAttribute("Id")) {
|
||||
el.setIdAttribute("Id", true);
|
||||
}
|
||||
|
||||
setListener(target, parentListener, false);
|
||||
if (OO_DIGSIG_NS.equals(el.getNamespaceURI())) {
|
||||
String parentNS = el.getParentNode().getNamespaceURI();
|
||||
if (!OO_DIGSIG_NS.equals(parentNS) && !el.hasAttributeNS(XML_NS, "mdssi")) {
|
||||
el.setAttributeNS(XML_NS, "xmlns:mdssi", OO_DIGSIG_NS);
|
||||
}
|
||||
}
|
||||
setPrefix(signatureInfo, el);
|
||||
setListener(target, parentListener, true);
|
||||
}
|
||||
|
||||
protected static void setPrefix(SignatureInfo signatureInfo, Node el) {
|
||||
String prefix = signatureInfo.getSignatureConfig().getNamespacePrefixes().get(el.getNamespaceURI());
|
||||
if (prefix != null && el.getPrefix() == null) {
|
||||
el.setPrefix(prefix);
|
||||
}
|
||||
|
||||
NodeList nl = el.getChildNodes();
|
||||
for (int i=0; i<nl.getLength(); i++) {
|
||||
setPrefix(signatureInfo, nl.item(i));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,85 +17,25 @@
|
|||
|
||||
package org.apache.poi.poifs.crypt.dsig;
|
||||
|
||||
import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.OO_DIGSIG_NS;
|
||||
import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.XML_NS;
|
||||
|
||||
import org.apache.poi.poifs.crypt.dsig.SignatureConfig.SignatureConfigurable;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.w3c.dom.events.Event;
|
||||
import org.w3c.dom.events.EventListener;
|
||||
import org.w3c.dom.events.EventTarget;
|
||||
import org.w3c.dom.events.MutationEvent;
|
||||
|
||||
/**
|
||||
* This listener class is used, to modify the to be digested xml document,
|
||||
* This listener interface is used, to modify the to be digested xml document,
|
||||
* e.g. to register id attributes or set prefixes for registered namespaces
|
||||
*/
|
||||
public class SignatureMarshalListener implements EventListener, SignatureConfigurable {
|
||||
ThreadLocal<EventTarget> target = new ThreadLocal<>();
|
||||
SignatureConfig signatureConfig;
|
||||
public void setEventTarget(EventTarget target) {
|
||||
this.target.set(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEvent(Event e) {
|
||||
if (!(e instanceof MutationEvent)) {
|
||||
return;
|
||||
}
|
||||
MutationEvent mutEvt = (MutationEvent)e;
|
||||
EventTarget et = mutEvt.getTarget();
|
||||
if (!(et instanceof Element)) {
|
||||
return;
|
||||
}
|
||||
handleElement((Element)et);
|
||||
}
|
||||
|
||||
public void handleElement(Element el) {
|
||||
EventTarget target = this.target.get();
|
||||
|
||||
if (el.hasAttribute("Id")) {
|
||||
el.setIdAttribute("Id", true);
|
||||
}
|
||||
|
||||
setListener(target, this, false);
|
||||
if (OO_DIGSIG_NS.equals(el.getNamespaceURI())) {
|
||||
String parentNS = el.getParentNode().getNamespaceURI();
|
||||
if (!OO_DIGSIG_NS.equals(parentNS) && !el.hasAttributeNS(XML_NS, "mdssi")) {
|
||||
el.setAttributeNS(XML_NS, "xmlns:mdssi", OO_DIGSIG_NS);
|
||||
}
|
||||
}
|
||||
setPrefix(el);
|
||||
setListener(target, this, true);
|
||||
}
|
||||
public interface SignatureMarshalListener {
|
||||
void handleElement(SignatureInfo signatureInfo, Element el, EventTarget target, EventListener parentListener);
|
||||
|
||||
// helper method to keep it in one place
|
||||
public static void setListener(EventTarget target, EventListener listener, boolean enabled) {
|
||||
String type = "DOMSubtreeModified";
|
||||
boolean useCapture = false;
|
||||
static void setListener(EventTarget target, EventListener listener, boolean enabled) {
|
||||
final String type = "DOMSubtreeModified";
|
||||
final boolean DONT_USE_CAPTURE = false;
|
||||
if (enabled) {
|
||||
target.addEventListener(type, listener, useCapture);
|
||||
target.addEventListener(type, listener, DONT_USE_CAPTURE);
|
||||
} else {
|
||||
target.removeEventListener(type, listener, useCapture);
|
||||
target.removeEventListener(type, listener, DONT_USE_CAPTURE);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setPrefix(Node el) {
|
||||
String prefix = signatureConfig.getNamespacePrefixes().get(el.getNamespaceURI());
|
||||
if (prefix != null && el.getPrefix() == null) {
|
||||
el.setPrefix(prefix);
|
||||
}
|
||||
|
||||
NodeList nl = el.getChildNodes();
|
||||
for (int i=0; i<nl.getLength(); i++) {
|
||||
setPrefix(nl.item(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSignatureConfig(SignatureConfig signatureConfig) {
|
||||
this.signatureConfig = signatureConfig;
|
||||
}
|
||||
}
|
|
@ -30,6 +30,7 @@ import java.util.Map;
|
|||
import java.util.function.Consumer;
|
||||
|
||||
import javax.xml.crypto.MarshalException;
|
||||
import javax.xml.crypto.URIDereferencer;
|
||||
import javax.xml.crypto.dsig.XMLSignature;
|
||||
import javax.xml.crypto.dsig.XMLSignatureException;
|
||||
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
||||
|
@ -54,40 +55,40 @@ import org.xml.sax.SAXException;
|
|||
|
||||
public class SignaturePart {
|
||||
private static final POILogger LOG = POILogFactory.getLogger(SignaturePart.class);
|
||||
private static final String XMLSEC_VALIDATE_MANIFEST = "org.jcp.xml.dsig.validateManifests";
|
||||
private static final String XMLSEC_VALIDATE_MANIFEST = "org.jcp.xml.dsig.validateManifests";
|
||||
|
||||
|
||||
|
||||
private final PackagePart signaturePart;
|
||||
private final SignatureConfig signatureConfig;
|
||||
private final SignatureInfo signatureInfo;
|
||||
private X509Certificate signer;
|
||||
private List<X509Certificate> certChain;
|
||||
|
||||
/* package */ SignaturePart(final PackagePart signaturePart, final SignatureConfig signatureConfig) {
|
||||
|
||||
/* package */ SignaturePart(final PackagePart signaturePart, final SignatureInfo signatureInfo) {
|
||||
this.signaturePart = signaturePart;
|
||||
this.signatureConfig = signatureConfig;
|
||||
this.signatureInfo = signatureInfo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the package part containing the signature
|
||||
*/
|
||||
public PackagePart getPackagePart() {
|
||||
return signaturePart;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the signer certificate
|
||||
*/
|
||||
public X509Certificate getSigner() {
|
||||
return signer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the certificate chain of the signer
|
||||
*/
|
||||
public List<X509Certificate> getCertChain() {
|
||||
return certChain;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper method for examining the xml signature
|
||||
*
|
||||
|
@ -102,7 +103,7 @@ public class SignaturePart {
|
|||
|
||||
/**
|
||||
* @return true, when the xml signature is valid, false otherwise
|
||||
*
|
||||
*
|
||||
* @throws EncryptedDocumentException if the signature can't be extracted or if its malformed
|
||||
*/
|
||||
public boolean validate() {
|
||||
|
@ -117,14 +118,16 @@ public class SignaturePart {
|
|||
for (int i=0; i<length; i++) {
|
||||
((Element)nl.item(i)).setIdAttribute("Id", true);
|
||||
}
|
||||
|
||||
|
||||
DOMValidateContext domValidateContext = new DOMValidateContext(keySelector, doc);
|
||||
domValidateContext.setProperty(XMLSEC_VALIDATE_MANIFEST, Boolean.TRUE);
|
||||
domValidateContext.setURIDereferencer(signatureConfig.getUriDereferencer());
|
||||
|
||||
XMLSignatureFactory xmlSignatureFactory = signatureConfig.getSignatureFactory();
|
||||
URIDereferencer uriDereferencer = signatureInfo.getUriDereferencer();
|
||||
domValidateContext.setURIDereferencer(uriDereferencer);
|
||||
|
||||
XMLSignatureFactory xmlSignatureFactory = signatureInfo.getSignatureFactory();
|
||||
XMLSignature xmlSignature = xmlSignatureFactory.unmarshalXMLSignature(domValidateContext);
|
||||
|
||||
|
||||
boolean valid = xmlSignature.validate(domValidateContext);
|
||||
|
||||
if (valid) {
|
||||
|
@ -132,7 +135,7 @@ public class SignaturePart {
|
|||
certChain = keySelector.getCertChain();
|
||||
extractConfig(doc, xmlSignature);
|
||||
}
|
||||
|
||||
|
||||
return valid;
|
||||
} catch (IOException e) {
|
||||
String s = "error in reading document";
|
||||
|
@ -158,6 +161,7 @@ public class SignaturePart {
|
|||
}
|
||||
|
||||
private void extractConfig(final Document doc, final XMLSignature xmlSignature) throws XPathExpressionException {
|
||||
SignatureConfig signatureConfig = signatureInfo.getSignatureConfig();
|
||||
if (!signatureConfig.isUpdateConfigOnValidate()) {
|
||||
return;
|
||||
}
|
||||
|
@ -168,7 +172,7 @@ public class SignaturePart {
|
|||
final XPath xpath = XPathHelper.getFactory().newXPath();
|
||||
xpath.setNamespaceContext(new XPathNSContext());
|
||||
|
||||
final Map<String,Consumer<String>> m = new HashMap();
|
||||
final Map<String,Consumer<String>> m = new HashMap<>();
|
||||
m.put("//mdssi:SignatureTime/mdssi:Value", signatureConfig::setExecutionTime);
|
||||
m.put("//xd:ClaimedRole", signatureConfig::setXadesRole);
|
||||
m.put("//dsss:SignatureComments", signatureConfig::setSignatureDescription);
|
||||
|
@ -185,7 +189,7 @@ public class SignaturePart {
|
|||
final Map<String,String> nsMap = new HashMap<>();
|
||||
|
||||
{
|
||||
signatureConfig.getNamespacePrefixes().forEach((k,v) -> nsMap.put(v,k));
|
||||
signatureInfo.getSignatureConfig().getNamespacePrefixes().forEach((k,v) -> nsMap.put(v,k));
|
||||
nsMap.put("dsss", MS_DIGSIG_NS);
|
||||
nsMap.put("ds", XML_DIGSIG_NS);
|
||||
}
|
||||
|
@ -193,6 +197,8 @@ public class SignaturePart {
|
|||
public String getNamespaceURI(String prefix) {
|
||||
return nsMap.get(prefix);
|
||||
}
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public Iterator getPrefixes(String val) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -18,12 +18,15 @@
|
|||
/* ====================================================================
|
||||
This product contains an ASLv2 licensed version of the OOXML signer
|
||||
package from the eID Applet project
|
||||
http://code.google.com/p/eid-applet/source/browse/trunk/README.txt
|
||||
http://code.google.com/p/eid-applet/source/browse/trunk/README.txt
|
||||
Copyright (C) 2008-2014 FedICT.
|
||||
================================================================= */
|
||||
================================================================= */
|
||||
|
||||
package org.apache.poi.poifs.crypt.dsig.facets;
|
||||
|
||||
import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacetHelper.newReference;
|
||||
import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacetHelper.newTransform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -33,28 +36,29 @@ import javax.xml.crypto.dsig.Transform;
|
|||
import javax.xml.crypto.dsig.XMLObject;
|
||||
import javax.xml.crypto.dsig.XMLSignatureException;
|
||||
|
||||
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
/**
|
||||
* Signature Facet implementation to create enveloped signatures.
|
||||
*
|
||||
*
|
||||
* @author Frank Cornelis
|
||||
*
|
||||
*/
|
||||
public class EnvelopedSignatureFacet extends SignatureFacet {
|
||||
public class EnvelopedSignatureFacet implements SignatureFacet {
|
||||
|
||||
@Override
|
||||
public void preSign(Document document
|
||||
public void preSign(SignatureInfo signatureInfo
|
||||
, Document document
|
||||
, List<Reference> references
|
||||
, List<XMLObject> objects)
|
||||
throws XMLSignatureException {
|
||||
List<Transform> transforms = new ArrayList<>();
|
||||
Transform envelopedTransform = newTransform(CanonicalizationMethod.ENVELOPED);
|
||||
Transform envelopedTransform = newTransform(signatureInfo, CanonicalizationMethod.ENVELOPED);
|
||||
transforms.add(envelopedTransform);
|
||||
Transform exclusiveTransform = newTransform(CanonicalizationMethod.EXCLUSIVE);
|
||||
Transform exclusiveTransform = newTransform(signatureInfo, CanonicalizationMethod.EXCLUSIVE);
|
||||
transforms.add(exclusiveTransform);
|
||||
|
||||
Reference reference = newReference("", transforms, null, null, null);
|
||||
Reference reference = newReference(signatureInfo, "", transforms, null, null, null);
|
||||
references.add(reference);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
/* ====================================================================
|
||||
This product contains an ASLv2 licensed version of the OOXML signer
|
||||
package from the eID Applet project
|
||||
http://code.google.com/p/eid-applet/source/browse/trunk/README.txt
|
||||
http://code.google.com/p/eid-applet/source/browse/trunk/README.txt
|
||||
Copyright (C) 2008-2014 FedICT.
|
||||
================================================================= */
|
||||
================================================================= */
|
||||
|
||||
package org.apache.poi.poifs.crypt.dsig.facets;
|
||||
|
||||
|
@ -29,7 +29,6 @@ import java.security.KeyException;
|
|||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.crypto.MarshalException;
|
||||
import javax.xml.crypto.XMLStructure;
|
||||
|
@ -41,6 +40,8 @@ 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;
|
||||
|
@ -50,21 +51,20 @@ import org.w3c.dom.NodeList;
|
|||
|
||||
/**
|
||||
* Signature Facet implementation that adds ds:KeyInfo to the XML signature.
|
||||
*
|
||||
*
|
||||
* @author Frank Cornelis
|
||||
*
|
||||
*/
|
||||
public class KeyInfoSignatureFacet extends SignatureFacet {
|
||||
public class KeyInfoSignatureFacet implements SignatureFacet {
|
||||
|
||||
private static final POILogger LOG = POILogFactory.getLogger(KeyInfoSignatureFacet.class);
|
||||
|
||||
|
||||
@Override
|
||||
public void postSign(Document document)
|
||||
public void postSign(SignatureInfo signatureInfo, Document document)
|
||||
throws MarshalException {
|
||||
LOG.log(POILogger.DEBUG, "postSign");
|
||||
|
||||
NodeList nl = document.getElementsByTagNameNS(XML_DIGSIG_NS, "Object");
|
||||
|
||||
|
||||
/*
|
||||
* Make sure we insert right after the ds:SignatureValue element, just
|
||||
* before the first ds:Object element.
|
||||
|
@ -74,8 +74,9 @@ public class KeyInfoSignatureFacet extends SignatureFacet {
|
|||
/*
|
||||
* Construct the ds:KeyInfo element using JSR 105.
|
||||
*/
|
||||
KeyInfoFactory keyInfoFactory = signatureConfig.getKeyInfoFactory();
|
||||
KeyInfoFactory keyInfoFactory = signatureInfo.getKeyInfoFactory();
|
||||
List<Object> x509DataObjects = new ArrayList<>();
|
||||
SignatureConfig signatureConfig = signatureInfo.getSignatureConfig();
|
||||
X509Certificate signingCertificate = signatureConfig.getSigningCertificateChain().get(0);
|
||||
|
||||
List<XMLStructure> keyInfoContent = new ArrayList<>();
|
||||
|
@ -107,7 +108,7 @@ public class KeyInfoSignatureFacet extends SignatureFacet {
|
|||
keyInfoContent.add(x509Data);
|
||||
}
|
||||
KeyInfo keyInfo = keyInfoFactory.newKeyInfo(keyInfoContent);
|
||||
DOMKeyInfo domKeyInfo = (DOMKeyInfo)keyInfo;
|
||||
DOMKeyInfo domKeyInfo = (DOMKeyInfo)keyInfo;
|
||||
|
||||
Key key = new Key() {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -133,7 +134,7 @@ public class KeyInfoSignatureFacet extends SignatureFacet {
|
|||
|
||||
DOMStructure domStructure = new DOMStructure(n);
|
||||
domKeyInfo.marshal(domStructure, domSignContext);
|
||||
|
||||
|
||||
// move keyinfo into the right place
|
||||
if (nextSibling != null) {
|
||||
NodeList kiNl = document.getElementsByTagNameNS(XML_DIGSIG_NS, "KeyInfo");
|
||||
|
|
|
@ -24,20 +24,21 @@
|
|||
|
||||
package org.apache.poi.poifs.crypt.dsig.facets;
|
||||
|
||||
import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacetHelper.newReference;
|
||||
import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacetHelper.newTransform;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.crypto.URIReference;
|
||||
import javax.xml.crypto.XMLStructure;
|
||||
import javax.xml.crypto.dom.DOMStructure;
|
||||
import javax.xml.crypto.dsig.CanonicalizationMethod;
|
||||
|
@ -48,7 +49,10 @@ import javax.xml.crypto.dsig.SignatureProperty;
|
|||
import javax.xml.crypto.dsig.Transform;
|
||||
import javax.xml.crypto.dsig.XMLObject;
|
||||
import javax.xml.crypto.dsig.XMLSignatureException;
|
||||
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
||||
|
||||
import com.microsoft.schemas.office.x2006.digsig.CTSignatureInfoV1;
|
||||
import com.microsoft.schemas.office.x2006.digsig.SignatureInfoV1Document;
|
||||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
||||
import org.apache.poi.openxml4j.opc.ContentTypes;
|
||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||
|
@ -58,9 +62,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.SignatureInfo;
|
||||
import org.apache.poi.poifs.crypt.dsig.services.RelationshipTransformService;
|
||||
import org.apache.poi.poifs.crypt.dsig.services.RelationshipTransformService.RelationshipTransformParameterSpec;
|
||||
import org.apache.poi.util.LocaleUtil;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
import org.openxmlformats.schemas.xpackage.x2006.digitalSignature.CTSignatureTime;
|
||||
|
@ -68,58 +73,58 @@ import org.openxmlformats.schemas.xpackage.x2006.digitalSignature.SignatureTimeD
|
|||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import com.microsoft.schemas.office.x2006.digsig.CTSignatureInfoV1;
|
||||
import com.microsoft.schemas.office.x2006.digsig.SignatureInfoV1Document;
|
||||
|
||||
/**
|
||||
* Office OpenXML Signature Facet implementation.
|
||||
*
|
||||
* @see <a href="http://msdn.microsoft.com/en-us/library/cc313071.aspx">[MS-OFFCRYPTO]: Office Document Cryptography Structure</a>
|
||||
*/
|
||||
public class OOXMLSignatureFacet extends SignatureFacet {
|
||||
public class OOXMLSignatureFacet implements SignatureFacet {
|
||||
|
||||
private static final POILogger LOG = POILogFactory.getLogger(OOXMLSignatureFacet.class);
|
||||
private static final String ID_PACKAGE_OBJECT = "idPackageObject";
|
||||
|
||||
@Override
|
||||
public void preSign(
|
||||
Document document
|
||||
SignatureInfo signatureInfo
|
||||
, Document document
|
||||
, List<Reference> references
|
||||
, List<XMLObject> objects)
|
||||
throws XMLSignatureException {
|
||||
LOG.log(POILogger.DEBUG, "pre sign");
|
||||
addManifestObject(document, references, objects);
|
||||
addSignatureInfo(document, references, objects);
|
||||
addManifestObject(signatureInfo, document, references, objects);
|
||||
addSignatureInfo(signatureInfo, document, references, objects);
|
||||
}
|
||||
|
||||
protected void addManifestObject(
|
||||
Document document
|
||||
SignatureInfo signatureInfo
|
||||
, Document document
|
||||
, List<Reference> references
|
||||
, List<XMLObject> objects)
|
||||
throws XMLSignatureException {
|
||||
|
||||
final XMLSignatureFactory sigFac = signatureInfo.getSignatureFactory();
|
||||
|
||||
List<Reference> manifestReferences = new ArrayList<>();
|
||||
addManifestReferences(manifestReferences);
|
||||
Manifest manifest = getSignatureFactory().newManifest(manifestReferences);
|
||||
addManifestReferences(signatureInfo, manifestReferences);
|
||||
Manifest manifest = sigFac.newManifest(manifestReferences);
|
||||
|
||||
List<XMLStructure> objectContent = new ArrayList<>();
|
||||
objectContent.add(manifest);
|
||||
|
||||
addSignatureTime(document, objectContent);
|
||||
addSignatureTime(signatureInfo, document, objectContent);
|
||||
|
||||
XMLObject xo = getSignatureFactory().newXMLObject(objectContent, ID_PACKAGE_OBJECT, null, null);
|
||||
XMLObject xo = sigFac.newXMLObject(objectContent, ID_PACKAGE_OBJECT, null, null);
|
||||
objects.add(xo);
|
||||
|
||||
Reference reference = newReference("#"+ID_PACKAGE_OBJECT, null, XML_DIGSIG_NS+"Object", null, null);
|
||||
Reference reference = newReference(signatureInfo, "#"+ID_PACKAGE_OBJECT, null, XML_DIGSIG_NS+"Object", null, null);
|
||||
references.add(reference);
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
protected void addManifestReferences(List<Reference> manifestReferences)
|
||||
protected void addManifestReferences(SignatureInfo signatureInfo, List<Reference> manifestReferences)
|
||||
throws XMLSignatureException {
|
||||
|
||||
OPCPackage ooxml = signatureConfig.getOpcPackage();
|
||||
List<PackagePart> relsEntryNames = ooxml.getPartsByContentType(ContentTypes.RELATIONSHIPS_PART);
|
||||
OPCPackage opcPackage = signatureInfo.getOpcPackage();
|
||||
List<PackagePart> relsEntryNames = opcPackage.getPartsByContentType(ContentTypes.RELATIONSHIPS_PART);
|
||||
|
||||
Set<String> digestedPartNames = new HashSet<>();
|
||||
for (PackagePart pp : relsEntryNames) {
|
||||
|
@ -127,7 +132,7 @@ public class OOXMLSignatureFacet extends SignatureFacet {
|
|||
|
||||
PackageRelationshipCollection prc;
|
||||
try {
|
||||
prc = new PackageRelationshipCollection(ooxml);
|
||||
prc = new PackageRelationshipCollection(opcPackage);
|
||||
prc.parseRelationshipsPart(pp);
|
||||
} catch (InvalidFormatException e) {
|
||||
throw new XMLSignatureException("Invalid relationship descriptor: "+pp.getPartName().getName(), e);
|
||||
|
@ -163,7 +168,7 @@ public class OOXMLSignatureFacet extends SignatureFacet {
|
|||
String contentType;
|
||||
try {
|
||||
PackagePartName relName = PackagingURIHelper.createPartName(partName);
|
||||
PackagePart pp2 = ooxml.getPart(relName);
|
||||
PackagePart pp2 = opcPackage.getPart(relName);
|
||||
contentType = pp2.getContentType();
|
||||
} catch (InvalidFormatException e) {
|
||||
throw new XMLSignatureException(e);
|
||||
|
@ -176,26 +181,22 @@ public class OOXMLSignatureFacet extends SignatureFacet {
|
|||
}
|
||||
|
||||
String uri = partName + "?ContentType=" + contentType;
|
||||
Reference reference = newReference(uri, null, null, null, null);
|
||||
Reference reference = newReference(signatureInfo, uri, null, null, null, null);
|
||||
manifestReferences.add(reference);
|
||||
}
|
||||
|
||||
if (parameterSpec.hasSourceIds()) {
|
||||
List<Transform> transforms = new ArrayList<>();
|
||||
transforms.add(newTransform(RelationshipTransformService.TRANSFORM_URI, parameterSpec));
|
||||
transforms.add(newTransform(CanonicalizationMethod.INCLUSIVE));
|
||||
transforms.add(newTransform(signatureInfo, RelationshipTransformService.TRANSFORM_URI, parameterSpec));
|
||||
transforms.add(newTransform(signatureInfo, CanonicalizationMethod.INCLUSIVE));
|
||||
String uri = normalizePartName(pp.getPartName().getURI(), baseUri)
|
||||
+ "?ContentType=application/vnd.openxmlformats-package.relationships+xml";
|
||||
Reference reference = newReference(uri, transforms, null, null, null);
|
||||
Reference reference = newReference(signatureInfo, uri, transforms, null, null, null);
|
||||
manifestReferences.add(reference);
|
||||
}
|
||||
}
|
||||
|
||||
manifestReferences.sort(new Comparator<Reference>() {
|
||||
public int compare(Reference o1, Reference o2) {
|
||||
return o1.getURI().compareTo(o2.getURI());
|
||||
}
|
||||
});
|
||||
|
||||
manifestReferences.sort(Comparator.comparing(URIReference::getURI));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -217,7 +218,9 @@ public class OOXMLSignatureFacet extends SignatureFacet {
|
|||
}
|
||||
|
||||
|
||||
protected void addSignatureTime(Document document, List<XMLStructure> objectContent) {
|
||||
protected void addSignatureTime(SignatureInfo signatureInfo, Document document, List<XMLStructure> objectContent) {
|
||||
SignatureConfig signatureConfig = signatureInfo.getSignatureConfig();
|
||||
XMLSignatureFactory sigFac = signatureInfo.getSignatureFactory();
|
||||
/*
|
||||
* SignatureTime
|
||||
*/
|
||||
|
@ -230,20 +233,25 @@ public class OOXMLSignatureFacet extends SignatureFacet {
|
|||
Element n = (Element)document.importNode(ctTime.getDomNode(),true);
|
||||
List<XMLStructure> signatureTimeContent = new ArrayList<>();
|
||||
signatureTimeContent.add(new DOMStructure(n));
|
||||
SignatureProperty signatureTimeSignatureProperty = getSignatureFactory()
|
||||
SignatureProperty signatureTimeSignatureProperty = sigFac
|
||||
.newSignatureProperty(signatureTimeContent, "#" + signatureConfig.getPackageSignatureId(),
|
||||
"idSignatureTime");
|
||||
List<SignatureProperty> signaturePropertyContent = new ArrayList<>();
|
||||
signaturePropertyContent.add(signatureTimeSignatureProperty);
|
||||
SignatureProperties signatureProperties = getSignatureFactory()
|
||||
SignatureProperties signatureProperties = sigFac
|
||||
.newSignatureProperties(signaturePropertyContent, null);
|
||||
objectContent.add(signatureProperties);
|
||||
}
|
||||
|
||||
protected void addSignatureInfo(Document document,
|
||||
List<Reference> references,
|
||||
List<XMLObject> objects)
|
||||
protected void addSignatureInfo(
|
||||
SignatureInfo signatureInfo
|
||||
, Document document
|
||||
, List<Reference> references
|
||||
, List<XMLObject> objects)
|
||||
throws XMLSignatureException {
|
||||
SignatureConfig signatureConfig = signatureInfo.getSignatureConfig();
|
||||
XMLSignatureFactory sigFac = signatureInfo.getSignatureFactory();
|
||||
|
||||
List<XMLStructure> objectContent = new ArrayList<>();
|
||||
|
||||
SignatureInfoV1Document sigV1 = SignatureInfoV1Document.Factory.newInstance();
|
||||
|
@ -259,20 +267,20 @@ public class OOXMLSignatureFacet extends SignatureFacet {
|
|||
|
||||
List<XMLStructure> signatureInfoContent = new ArrayList<>();
|
||||
signatureInfoContent.add(new DOMStructure(n));
|
||||
SignatureProperty signatureInfoSignatureProperty = getSignatureFactory()
|
||||
SignatureProperty signatureInfoSignatureProperty = sigFac
|
||||
.newSignatureProperty(signatureInfoContent, "#" + signatureConfig.getPackageSignatureId(),
|
||||
"idOfficeV1Details");
|
||||
|
||||
List<SignatureProperty> signaturePropertyContent = new ArrayList<>();
|
||||
signaturePropertyContent.add(signatureInfoSignatureProperty);
|
||||
SignatureProperties signatureProperties = getSignatureFactory()
|
||||
SignatureProperties signatureProperties = sigFac
|
||||
.newSignatureProperties(signaturePropertyContent, null);
|
||||
objectContent.add(signatureProperties);
|
||||
|
||||
String objectId = "idOfficeObject";
|
||||
objects.add(getSignatureFactory().newXMLObject(objectContent, objectId, null, null));
|
||||
objects.add(sigFac.newXMLObject(objectContent, objectId, null, null));
|
||||
|
||||
Reference reference = newReference("#" + objectId, null, XML_DIGSIG_NS+"Object", null, null);
|
||||
Reference reference = newReference(signatureInfo, "#" + objectId, null, XML_DIGSIG_NS+"Object", null, null);
|
||||
references.add(reference);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
/* ====================================================================
|
||||
This product contains an ASLv2 licensed version of the OOXML signer
|
||||
package from the eID Applet project
|
||||
http://code.google.com/p/eid-applet/source/browse/trunk/README.txt
|
||||
http://code.google.com/p/eid-applet/source/browse/trunk/README.txt
|
||||
Copyright (C) 2008-2014 FedICT.
|
||||
================================================================= */
|
||||
================================================================= */
|
||||
|
||||
package org.apache.poi.poifs.crypt.dsig.facets;
|
||||
|
||||
|
@ -28,6 +28,7 @@ import static org.apache.poi.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
|
|||
|
||||
import javax.xml.crypto.MarshalException;
|
||||
|
||||
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
|
||||
import org.apache.xmlbeans.XmlException;
|
||||
import org.etsi.uri.x01903.v13.QualifyingPropertiesType;
|
||||
import org.etsi.uri.x01903.v13.UnsignedPropertiesType;
|
||||
|
@ -38,17 +39,15 @@ import org.w3c.dom.NodeList;
|
|||
|
||||
/**
|
||||
* Work-around for Office2010 to accept the XAdES-BES/EPES signature.
|
||||
*
|
||||
* xades:UnsignedProperties/xades:UnsignedSignatureProperties needs to be
|
||||
* present.
|
||||
*
|
||||
*
|
||||
* xades:UnsignedProperties/xades:UnsignedSignatureProperties needs to be present.
|
||||
*
|
||||
* @author Frank Cornelis
|
||||
*
|
||||
*/
|
||||
public class Office2010SignatureFacet extends SignatureFacet {
|
||||
public class Office2010SignatureFacet implements SignatureFacet {
|
||||
|
||||
@Override
|
||||
public void postSign(Document document)
|
||||
public void postSign(SignatureInfo signatureInfo, Document document)
|
||||
throws MarshalException {
|
||||
// check for XAdES-BES
|
||||
NodeList nl = document.getElementsByTagNameNS(XADES_132_NS, "QualifyingProperties");
|
||||
|
@ -62,7 +61,7 @@ public class Office2010SignatureFacet extends SignatureFacet {
|
|||
} catch (XmlException e) {
|
||||
throw new MarshalException(e);
|
||||
}
|
||||
|
||||
|
||||
// create basic XML container structure
|
||||
UnsignedPropertiesType unsignedProps = qualProps.getUnsignedProperties();
|
||||
if (unsignedProps == null) {
|
||||
|
@ -72,7 +71,7 @@ public class Office2010SignatureFacet extends SignatureFacet {
|
|||
if (unsignedSigProps == null) {
|
||||
/* unsignedSigProps = */ unsignedProps.addNewUnsignedSignatureProperties();
|
||||
}
|
||||
|
||||
|
||||
Node n = document.importNode(qualProps.getDomNode().getFirstChild(), true);
|
||||
nl.item(0).getParentNode().replaceChild(n, nl.item(0));
|
||||
}
|
||||
|
|
|
@ -18,70 +18,57 @@
|
|||
/* ====================================================================
|
||||
This product contains an ASLv2 licensed version of the OOXML signer
|
||||
package from the eID Applet project
|
||||
http://code.google.com/p/eid-applet/source/browse/trunk/README.txt
|
||||
http://code.google.com/p/eid-applet/source/browse/trunk/README.txt
|
||||
Copyright (C) 2008-2014 FedICT.
|
||||
================================================================= */
|
||||
================================================================= */
|
||||
|
||||
package org.apache.poi.poifs.crypt.dsig.facets;
|
||||
|
||||
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.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
/**
|
||||
* JSR105 Signature Facet base class.
|
||||
*/
|
||||
public abstract class SignatureFacet implements SignatureConfigurable {
|
||||
@Internal
|
||||
public interface SignatureFacet {
|
||||
|
||||
private static final POILogger LOG = POILogFactory.getLogger(SignatureFacet.class);
|
||||
|
||||
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;
|
||||
|
||||
@Override
|
||||
public void setSignatureConfig(SignatureConfig signatureConfig) {
|
||||
this.signatureConfig = signatureConfig;
|
||||
}
|
||||
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#";
|
||||
|
||||
/**
|
||||
* This method is being invoked by the XML signature service engine during
|
||||
* pre-sign phase. Via this method a signature facet implementation can add
|
||||
* signature facets to an XML signature.
|
||||
*
|
||||
*
|
||||
* @param signatureInfo the signature info object holding the OPCPackage and other document related data
|
||||
* @param document the signature document to be used for imports
|
||||
* @param references list of reference definitions
|
||||
* @param objects objects to be signed/included in the signature document
|
||||
* @throws XMLSignatureException
|
||||
*/
|
||||
public void preSign(
|
||||
Document document
|
||||
default void preSign(
|
||||
SignatureInfo signatureInfo
|
||||
, Document document
|
||||
, List<Reference> references
|
||||
, List<XMLObject> objects
|
||||
) throws XMLSignatureException {
|
||||
// empty
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -89,62 +76,12 @@ public abstract class SignatureFacet implements SignatureConfigurable {
|
|||
* the post-sign phase. Via this method a signature facet can extend the XML
|
||||
* signatures with for example key information.
|
||||
*
|
||||
* @param signatureInfo the signature info object holding the OPCPackage and other document related data
|
||||
* @param document the signature document to be modified
|
||||
* @throws MarshalException
|
||||
*/
|
||||
public void postSign(Document document) throws MarshalException {
|
||||
// empty
|
||||
default void postSign(SignatureInfo signatureInfo, Document document) throws MarshalException {
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.poifs.crypt.dsig.facets;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.crypto.dsig.DigestMethod;
|
||||
import javax.xml.crypto.dsig.Reference;
|
||||
import javax.xml.crypto.dsig.Transform;
|
||||
import javax.xml.crypto.dsig.XMLSignatureException;
|
||||
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
||||
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
|
||||
|
||||
import org.apache.poi.poifs.crypt.dsig.SignatureConfig;
|
||||
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
|
||||
import org.apache.poi.util.Internal;
|
||||
|
||||
@Internal
|
||||
final class SignatureFacetHelper {
|
||||
private SignatureFacetHelper() {}
|
||||
|
||||
static Transform newTransform(SignatureInfo signatureInfo, String canonicalizationMethod) throws XMLSignatureException {
|
||||
return newTransform(signatureInfo, canonicalizationMethod, null);
|
||||
}
|
||||
|
||||
static Transform newTransform(SignatureInfo signatureInfo, String canonicalizationMethod, TransformParameterSpec paramSpec)
|
||||
throws XMLSignatureException {
|
||||
try {
|
||||
return signatureInfo.getSignatureFactory().newTransform(canonicalizationMethod, paramSpec);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new XMLSignatureException("unknown canonicalization method: "+canonicalizationMethod, e);
|
||||
}
|
||||
}
|
||||
|
||||
static Reference newReference(
|
||||
SignatureInfo signatureInfo
|
||||
, String uri
|
||||
, List<Transform> transforms
|
||||
, String type
|
||||
, String id
|
||||
, byte[] digestValue)
|
||||
throws XMLSignatureException {
|
||||
// the references appear in the package signature or the package object
|
||||
// so we can use the default digest algorithm
|
||||
SignatureConfig signatureConfig = signatureInfo.getSignatureConfig();
|
||||
String digestMethodUri = signatureConfig.getDigestMethodUri();
|
||||
XMLSignatureFactory sigFac = signatureInfo.getSignatureFactory();
|
||||
DigestMethod digestMethod;
|
||||
try {
|
||||
digestMethod = sigFac.newDigestMethod(digestMethodUri, null);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new XMLSignatureException("unknown digest method uri: "+digestMethodUri, e);
|
||||
}
|
||||
|
||||
return (digestValue == null)
|
||||
? sigFac.newReference(uri, digestMethod, transforms, type, id)
|
||||
: sigFac.newReference(uri, digestMethod, transforms, type, id, digestValue);
|
||||
}
|
||||
}
|
|
@ -18,13 +18,15 @@
|
|||
/* ====================================================================
|
||||
This product contains an ASLv2 licensed version of the OOXML signer
|
||||
package from the eID Applet project
|
||||
http://code.google.com/p/eid-applet/source/browse/trunk/README.txt
|
||||
http://code.google.com/p/eid-applet/source/browse/trunk/README.txt
|
||||
Copyright (C) 2008-2014 FedICT.
|
||||
================================================================= */
|
||||
================================================================= */
|
||||
|
||||
package org.apache.poi.poifs.crypt.dsig.facets;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacetHelper.newReference;
|
||||
import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacetHelper.newTransform;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
|
@ -48,6 +50,7 @@ import javax.xml.crypto.dsig.XMLSignatureException;
|
|||
import org.apache.poi.poifs.crypt.CryptoFunctions;
|
||||
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
||||
import org.apache.poi.poifs.crypt.dsig.SignatureConfig;
|
||||
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
|
||||
import org.apache.poi.poifs.crypt.dsig.services.SignaturePolicyService;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
|
@ -77,36 +80,39 @@ import org.w3c.dom.Node;
|
|||
* XAdES Signature Facet. Implements XAdES v1.4.1 which is compatible with XAdES
|
||||
* v1.3.2. The implemented XAdES format is XAdES-BES/EPES. It's up to another
|
||||
* part of the signature service to upgrade the XAdES-BES to a XAdES-X-L.
|
||||
*
|
||||
*
|
||||
* This implementation has been tested against an implementation that
|
||||
* participated multiple ETSI XAdES plugtests.
|
||||
*
|
||||
*
|
||||
* @author Frank Cornelis
|
||||
* @see <a href="http://en.wikipedia.org/wiki/XAdES">XAdES</a>
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class XAdESSignatureFacet extends SignatureFacet {
|
||||
public class XAdESSignatureFacet implements SignatureFacet {
|
||||
|
||||
private static final POILogger LOG = POILogFactory.getLogger(XAdESSignatureFacet.class);
|
||||
|
||||
private static final String XADES_TYPE = "http://uri.etsi.org/01903#SignedProperties";
|
||||
|
||||
|
||||
private final Map<String, String> dataObjectFormatMimeTypes = new HashMap<>();
|
||||
|
||||
|
||||
@Override
|
||||
public void preSign(
|
||||
Document document
|
||||
SignatureInfo signatureInfo
|
||||
, Document document
|
||||
, List<Reference> references
|
||||
, List<XMLObject> objects)
|
||||
throws XMLSignatureException {
|
||||
LOG.log(POILogger.DEBUG, "preSign");
|
||||
|
||||
SignatureConfig signatureConfig = signatureInfo.getSignatureConfig();
|
||||
|
||||
// QualifyingProperties
|
||||
QualifyingPropertiesDocument qualDoc = QualifyingPropertiesDocument.Factory.newInstance();
|
||||
QualifyingPropertiesType qualifyingProperties = qualDoc.addNewQualifyingProperties();
|
||||
qualifyingProperties.setTarget("#" + signatureConfig.getPackageSignatureId());
|
||||
|
||||
|
||||
// SignedProperties
|
||||
SignedPropertiesType signedProperties = qualifyingProperties.addNewSignedProperties();
|
||||
signedProperties.setId(signatureConfig.getXadesSignatureId());
|
||||
|
@ -115,35 +121,37 @@ public class XAdESSignatureFacet extends SignatureFacet {
|
|||
SignedSignaturePropertiesType signedSignatureProperties = signedProperties.addNewSignedSignatureProperties();
|
||||
|
||||
// SigningTime
|
||||
addSigningTime(signedSignatureProperties);
|
||||
addSigningTime(signatureInfo, signedSignatureProperties);
|
||||
|
||||
// SigningCertificate
|
||||
addCertificate(signedSignatureProperties);
|
||||
addCertificate(signatureInfo, signedSignatureProperties);
|
||||
|
||||
// ClaimedRole
|
||||
addXadesRole(signedSignatureProperties);
|
||||
addXadesRole(signatureInfo, signedSignatureProperties);
|
||||
|
||||
// XAdES-EPES
|
||||
addPolicy(signedSignatureProperties);
|
||||
addPolicy(signatureInfo, signedSignatureProperties);
|
||||
|
||||
// DataObjectFormat
|
||||
addMimeTypes(signedProperties);
|
||||
|
||||
// add XAdES ds:Object
|
||||
objects.add(addXadesObject(document, qualifyingProperties));
|
||||
objects.add(addXadesObject(signatureInfo, document, qualifyingProperties));
|
||||
|
||||
// add XAdES ds:Reference
|
||||
references.add(addXadesReference());
|
||||
references.add(addXadesReference(signatureInfo));
|
||||
}
|
||||
|
||||
private void addSigningTime(SignedSignaturePropertiesType signedSignatureProperties) {
|
||||
private void addSigningTime(SignatureInfo signatureInfo, SignedSignaturePropertiesType signedSignatureProperties) {
|
||||
SignatureConfig signatureConfig = signatureInfo.getSignatureConfig();
|
||||
Calendar xmlGregorianCalendar = Calendar.getInstance(TimeZone.getTimeZone("Z"), Locale.ROOT);
|
||||
xmlGregorianCalendar.setTime(signatureConfig.getExecutionTime());
|
||||
xmlGregorianCalendar.clear(Calendar.MILLISECOND);
|
||||
signedSignatureProperties.setSigningTime(xmlGregorianCalendar);
|
||||
}
|
||||
|
||||
private void addCertificate(SignedSignaturePropertiesType signedSignatureProperties) {
|
||||
private void addCertificate(SignatureInfo signatureInfo, SignedSignaturePropertiesType signedSignatureProperties) {
|
||||
SignatureConfig signatureConfig = signatureInfo.getSignatureConfig();
|
||||
List<X509Certificate> chain = signatureConfig.getSigningCertificateChain();
|
||||
if (chain == null || chain.isEmpty()) {
|
||||
throw new RuntimeException("no signing certificate chain available");
|
||||
|
@ -153,7 +161,8 @@ public class XAdESSignatureFacet extends SignatureFacet {
|
|||
setCertID(certId, signatureConfig, signatureConfig.isXadesIssuerNameNoReverseOrder(), chain.get(0));
|
||||
}
|
||||
|
||||
private void addXadesRole(SignedSignaturePropertiesType signedSignatureProperties) {
|
||||
private void addXadesRole(SignatureInfo signatureInfo, SignedSignaturePropertiesType signedSignatureProperties) {
|
||||
SignatureConfig signatureConfig = signatureInfo.getSignatureConfig();
|
||||
String role = signatureConfig.getXadesRole();
|
||||
if (role == null || role.isEmpty()) {
|
||||
return;
|
||||
|
@ -168,7 +177,8 @@ public class XAdESSignatureFacet extends SignatureFacet {
|
|||
insertXChild(claimedRole, roleString);
|
||||
}
|
||||
|
||||
private void addPolicy(SignedSignaturePropertiesType signedSignatureProperties) {
|
||||
private void addPolicy(SignatureInfo signatureInfo, SignedSignaturePropertiesType signedSignatureProperties) {
|
||||
SignatureConfig signatureConfig = signatureInfo.getSignatureConfig();
|
||||
SignaturePolicyService policyService = signatureConfig.getSignaturePolicyService();
|
||||
if (policyService == null) {
|
||||
if (signatureConfig.isXadesSignaturePolicyImplied()) {
|
||||
|
@ -221,22 +231,23 @@ public class XAdESSignatureFacet extends SignatureFacet {
|
|||
});
|
||||
}
|
||||
|
||||
private XMLObject addXadesObject(Document document, QualifyingPropertiesType qualifyingProperties) {
|
||||
private XMLObject addXadesObject(SignatureInfo signatureInfo, Document document, QualifyingPropertiesType qualifyingProperties) {
|
||||
Node qualDocElSrc = qualifyingProperties.getDomNode();
|
||||
Node qualDocEl = document.importNode(qualDocElSrc, true);
|
||||
List<XMLStructure> xadesObjectContent = Arrays.asList(new DOMStructure(qualDocEl));
|
||||
return getSignatureFactory().newXMLObject(xadesObjectContent, null, null, null);
|
||||
return signatureInfo.getSignatureFactory().newXMLObject(xadesObjectContent, null, null, null);
|
||||
}
|
||||
|
||||
private Reference addXadesReference() throws XMLSignatureException {
|
||||
List<Transform> transforms = singletonList(newTransform(CanonicalizationMethod.INCLUSIVE));
|
||||
return newReference("#"+signatureConfig.getXadesSignatureId(), transforms, XADES_TYPE, null, null);
|
||||
private Reference addXadesReference(SignatureInfo signatureInfo) throws XMLSignatureException {
|
||||
SignatureConfig signatureConfig = signatureInfo.getSignatureConfig();
|
||||
List<Transform> transforms = singletonList(newTransform(signatureInfo, CanonicalizationMethod.INCLUSIVE));
|
||||
return newReference(signatureInfo, "#"+signatureConfig.getXadesSignatureId(), transforms, XADES_TYPE, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives back the JAXB DigestAlgAndValue data structure.
|
||||
*
|
||||
* @param digestAlgAndValue the parent for the new digest element
|
||||
* @param digestAlgAndValue the parent for the new digest element
|
||||
* @param data the data to be digested
|
||||
* @param digestAlgo the digest algorithm
|
||||
*/
|
||||
|
@ -246,7 +257,7 @@ public class XAdESSignatureFacet extends SignatureFacet {
|
|||
HashAlgorithm digestAlgo) {
|
||||
DigestMethodType digestMethod = digestAlgAndValue.addNewDigestMethod();
|
||||
digestMethod.setAlgorithm(SignatureConfig.getDigestMethodUri(digestAlgo));
|
||||
|
||||
|
||||
MessageDigest messageDigest = CryptoFunctions.getMessageDigest(digestAlgo);
|
||||
byte[] digestValue = messageDigest.digest(data);
|
||||
digestAlgAndValue.setDigestValue(digestValue);
|
||||
|
@ -264,7 +275,7 @@ public class XAdESSignatureFacet extends SignatureFacet {
|
|||
* Make sure the DN is encoded using the same order as present
|
||||
* within the certificate. This is an Office2010 work-around.
|
||||
* Should be reverted back.
|
||||
*
|
||||
*
|
||||
* XXX: not correct according to RFC 4514.
|
||||
*/
|
||||
// TODO: check if issuerName is different on getTBSCertificate
|
||||
|
@ -283,14 +294,14 @@ public class XAdESSignatureFacet extends SignatureFacet {
|
|||
throw new RuntimeException("certificate encoding error: "
|
||||
+ e.getMessage(), e);
|
||||
}
|
||||
DigestAlgAndValueType certDigest = certId.addNewCertDigest();
|
||||
DigestAlgAndValueType certDigest = certId.addNewCertDigest();
|
||||
setDigestAlgAndValue(certDigest, encodedCertificate, signatureConfig.getXadesDigestAlgo());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a mime-type for the given ds:Reference (referred via its @URI). This
|
||||
* information is added via the xades:DataObjectFormat element.
|
||||
*
|
||||
*
|
||||
* @param dsReferenceUri
|
||||
* @param mimetype
|
||||
*/
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
/* ====================================================================
|
||||
This product contains an ASLv2 licensed version of the OOXML signer
|
||||
package from the eID Applet project
|
||||
http://code.google.com/p/eid-applet/source/browse/trunk/README.txt
|
||||
http://code.google.com/p/eid-applet/source/browse/trunk/README.txt
|
||||
Copyright (C) 2008-2014 FedICT.
|
||||
================================================================= */
|
||||
================================================================= */
|
||||
|
||||
package org.apache.poi.poifs.crypt.dsig.facets;
|
||||
|
||||
|
@ -47,6 +47,8 @@ import java.util.UUID;
|
|||
|
||||
import javax.xml.crypto.MarshalException;
|
||||
|
||||
import org.apache.poi.poifs.crypt.dsig.SignatureConfig;
|
||||
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
|
||||
import org.apache.poi.poifs.crypt.dsig.services.RevocationData;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
|
@ -73,18 +75,18 @@ import org.w3c.dom.NodeList;
|
|||
/**
|
||||
* XAdES-X-L v1.4.1 signature facet. This signature facet implementation will
|
||||
* upgrade a given XAdES-BES/EPES signature to XAdES-X-L.
|
||||
*
|
||||
*
|
||||
* We don't inherit from XAdESSignatureFacet as we also want to be able to use
|
||||
* this facet out of the context of a signature creation. This signature facet
|
||||
* assumes that the signature is already XAdES-BES/EPES compliant.
|
||||
*
|
||||
*
|
||||
* This implementation has been tested against an implementation that
|
||||
* participated multiple ETSI XAdES plugtests.
|
||||
*
|
||||
*
|
||||
* @author Frank Cornelis
|
||||
* @see XAdESSignatureFacet
|
||||
*/
|
||||
public class XAdESXLSignatureFacet extends SignatureFacet {
|
||||
public class XAdESXLSignatureFacet implements SignatureFacet {
|
||||
|
||||
private static final POILogger LOG = POILogFactory.getLogger(XAdESXLSignatureFacet.class);
|
||||
|
||||
|
@ -99,9 +101,11 @@ public class XAdESXLSignatureFacet extends SignatureFacet {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void postSign(Document document) throws MarshalException {
|
||||
public void postSign(SignatureInfo signatureInfo, Document document) throws MarshalException {
|
||||
LOG.log(POILogger.DEBUG, "XAdES-X-L post sign phase");
|
||||
|
||||
SignatureConfig signatureConfig = signatureInfo.getSignatureConfig();
|
||||
|
||||
QualifyingPropertiesDocument qualDoc = null;
|
||||
QualifyingPropertiesType qualProps = null;
|
||||
|
||||
|
@ -127,18 +131,18 @@ public class XAdESXLSignatureFacet extends SignatureFacet {
|
|||
if (unsignedSigProps == null) {
|
||||
unsignedSigProps = unsignedProps.addNewUnsignedSignatureProperties();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// create the XAdES-T time-stamp
|
||||
NodeList nlSigVal = document.getElementsByTagNameNS(XML_DIGSIG_NS, "SignatureValue");
|
||||
if (nlSigVal.getLength() != 1) {
|
||||
throw new IllegalArgumentException("SignatureValue is not set.");
|
||||
}
|
||||
|
||||
|
||||
RevocationData tsaRevocationDataXadesT = new RevocationData();
|
||||
LOG.log(POILogger.DEBUG, "creating XAdES-T time-stamp");
|
||||
XAdESTimeStampType signatureTimeStamp = createXAdESTimeStamp
|
||||
(Collections.singletonList(nlSigVal.item(0)), tsaRevocationDataXadesT);
|
||||
(signatureInfo, Collections.singletonList(nlSigVal.item(0)), tsaRevocationDataXadesT);
|
||||
|
||||
// marshal the XAdES-T extension
|
||||
unsignedSigProps.addNewSignatureTimeStamp().set(signatureTimeStamp);
|
||||
|
@ -158,7 +162,7 @@ public class XAdESXLSignatureFacet extends SignatureFacet {
|
|||
}
|
||||
|
||||
// XAdES-C: complete certificate refs
|
||||
CompleteCertificateRefsType completeCertificateRefs =
|
||||
CompleteCertificateRefsType completeCertificateRefs =
|
||||
unsignedSigProps.addNewCompleteCertificateRefs();
|
||||
|
||||
CertIDListType certIdList = completeCertificateRefs.addNewCertRefs();
|
||||
|
@ -176,7 +180,7 @@ public class XAdESXLSignatureFacet extends SignatureFacet {
|
|||
}
|
||||
|
||||
// XAdES-C: complete revocation refs
|
||||
CompleteRevocationRefsType completeRevocationRefs =
|
||||
CompleteRevocationRefsType completeRevocationRefs =
|
||||
unsignedSigProps.addNewCompleteRevocationRefs();
|
||||
RevocationData revocationData = signatureConfig.getRevocationDataService()
|
||||
.getRevocationData(certChain);
|
||||
|
@ -212,22 +216,22 @@ public class XAdESXLSignatureFacet extends SignatureFacet {
|
|||
for (byte[] ocsp : revocationData.getOCSPs()) {
|
||||
try {
|
||||
OCSPRefType ocspRef = ocspRefs.addNewOCSPRef();
|
||||
|
||||
|
||||
DigestAlgAndValueType digestAlgAndValue = ocspRef.addNewDigestAlgAndValue();
|
||||
XAdESSignatureFacet.setDigestAlgAndValue(digestAlgAndValue, ocsp, signatureConfig.getDigestAlgo());
|
||||
|
||||
|
||||
OCSPIdentifierType ocspIdentifier = ocspRef.addNewOCSPIdentifier();
|
||||
|
||||
|
||||
OCSPResp ocspResp = new OCSPResp(ocsp);
|
||||
|
||||
|
||||
BasicOCSPResp basicOcspResp = (BasicOCSPResp)ocspResp.getResponseObject();
|
||||
|
||||
|
||||
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Z"), Locale.ROOT);
|
||||
cal.setTime(basicOcspResp.getProducedAt());
|
||||
ocspIdentifier.setProducedAt(cal);
|
||||
|
||||
|
||||
ResponderIDType responderId = ocspIdentifier.addNewResponderID();
|
||||
|
||||
|
||||
RespID respId = basicOcspResp.getResponderId();
|
||||
ResponderID ocspResponderId = respId.toASN1Primitive();
|
||||
DERTaggedObject derTaggedObject = (DERTaggedObject)ocspResponderId.toASN1Primitive();
|
||||
|
@ -247,7 +251,7 @@ public class XAdESXLSignatureFacet extends SignatureFacet {
|
|||
}
|
||||
|
||||
// marshal XAdES-C
|
||||
|
||||
|
||||
// XAdES-X Type 1 timestamp
|
||||
List<Node> timeStampNodesXadesX1 = new ArrayList<>();
|
||||
timeStampNodesXadesX1.add(nlSigVal.item(0));
|
||||
|
@ -258,7 +262,7 @@ public class XAdESXLSignatureFacet extends SignatureFacet {
|
|||
RevocationData tsaRevocationDataXadesX1 = new RevocationData();
|
||||
LOG.log(POILogger.DEBUG, "creating XAdES-X time-stamp");
|
||||
XAdESTimeStampType timeStampXadesX1 = createXAdESTimeStamp
|
||||
(timeStampNodesXadesX1, tsaRevocationDataXadesX1);
|
||||
(signatureInfo, timeStampNodesXadesX1, tsaRevocationDataXadesX1);
|
||||
if (tsaRevocationDataXadesX1.hasRevocationDataEntries()) {
|
||||
ValidationDataType timeStampXadesX1ValidationData = createValidationData(tsaRevocationDataXadesX1);
|
||||
insertXChild(unsignedSigProps, timeStampXadesX1ValidationData);
|
||||
|
@ -277,7 +281,7 @@ public class XAdESXLSignatureFacet extends SignatureFacet {
|
|||
throw new RuntimeException("certificate encoding error: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RevocationValuesType revocationValues = unsignedSigProps.addNewRevocationValues();
|
||||
createRevocationValues(revocationValues, revocationData);
|
||||
|
||||
|
@ -330,18 +334,21 @@ public class XAdESXLSignatureFacet extends SignatureFacet {
|
|||
}
|
||||
|
||||
private XAdESTimeStampType createXAdESTimeStamp(
|
||||
SignatureInfo signatureInfo,
|
||||
List<Node> nodeList,
|
||||
RevocationData revocationData) {
|
||||
SignatureConfig signatureConfig = signatureInfo.getSignatureConfig();
|
||||
byte[] c14nSignatureValueElement = getC14nValue(nodeList, signatureConfig.getXadesCanonicalizationMethod());
|
||||
|
||||
return createXAdESTimeStamp(c14nSignatureValueElement, revocationData);
|
||||
return createXAdESTimeStamp(signatureInfo, c14nSignatureValueElement, revocationData);
|
||||
}
|
||||
|
||||
private XAdESTimeStampType createXAdESTimeStamp(byte[] data, RevocationData revocationData) {
|
||||
private XAdESTimeStampType createXAdESTimeStamp(SignatureInfo signatureInfo, byte[] data, RevocationData revocationData) {
|
||||
SignatureConfig signatureConfig = signatureInfo.getSignatureConfig();
|
||||
// create the time-stamp
|
||||
byte[] timeStampToken;
|
||||
try {
|
||||
timeStampToken = signatureConfig.getTspService().timeStamp(data, revocationData);
|
||||
timeStampToken = signatureConfig.getTspService().timeStamp(signatureInfo, data, revocationData);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("error while creating a time-stamp: "
|
||||
+ e.getMessage(), e);
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
/* ====================================================================
|
||||
This product contains an ASLv2 licensed version of the OOXML signer
|
||||
package from the eID Applet project
|
||||
http://code.google.com/p/eid-applet/source/browse/trunk/README.txt
|
||||
http://code.google.com/p/eid-applet/source/browse/trunk/README.txt
|
||||
Copyright (C) 2008-2014 FedICT.
|
||||
================================================================= */
|
||||
================================================================= */
|
||||
|
||||
package org.apache.poi.poifs.crypt.dsig.services;
|
||||
|
||||
|
@ -47,6 +47,7 @@ import java.util.Map;
|
|||
import org.apache.poi.poifs.crypt.CryptoFunctions;
|
||||
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
||||
import org.apache.poi.poifs.crypt.dsig.SignatureConfig;
|
||||
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
|
@ -72,16 +73,14 @@ import org.bouncycastle.tsp.TimeStampToken;
|
|||
|
||||
/**
|
||||
* A TSP time-stamp service implementation.
|
||||
*
|
||||
*
|
||||
* @author Frank Cornelis
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class TSPTimeStampService implements TimeStampService {
|
||||
|
||||
private static final POILogger LOG = POILogFactory.getLogger(TSPTimeStampService.class);
|
||||
|
||||
private SignatureConfig signatureConfig;
|
||||
|
||||
/**
|
||||
* Maps the digest algorithm to corresponding OID value.
|
||||
*/
|
||||
|
@ -97,8 +96,9 @@ public class TSPTimeStampService implements TimeStampService {
|
|||
}
|
||||
|
||||
@SuppressWarnings({"unchecked","squid:S2647"})
|
||||
public byte[] timeStamp(byte[] data, RevocationData revocationData)
|
||||
throws Exception {
|
||||
public byte[] timeStamp(SignatureInfo signatureInfo, byte[] data, RevocationData revocationData) throws Exception {
|
||||
SignatureConfig signatureConfig = signatureInfo.getSignatureConfig();
|
||||
|
||||
// digest the message
|
||||
MessageDigest messageDigest = CryptoFunctions.getMessageDigest(signatureConfig.getTspDigestAlgo());
|
||||
byte[] digest = messageDigest.digest(data);
|
||||
|
@ -170,7 +170,7 @@ public class TSPTimeStampService implements TimeStampService {
|
|||
huc.disconnect();
|
||||
}
|
||||
|
||||
if (!contentType.startsWith(signatureConfig.isTspOldProtocol()
|
||||
if (!contentType.startsWith(signatureConfig.isTspOldProtocol()
|
||||
? "application/timestamp-response"
|
||||
: "application/timestamp-reply"
|
||||
)) {
|
||||
|
@ -178,7 +178,7 @@ public class TSPTimeStampService implements TimeStampService {
|
|||
// dump the first few bytes
|
||||
": " + HexDump.dump(bos.toByteArray(), 0, 0, 200));
|
||||
}
|
||||
|
||||
|
||||
if (bos.size() == 0) {
|
||||
throw new RuntimeException("Content-Length is zero");
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ public class TSPTimeStampService implements TimeStampService {
|
|||
|
||||
// TSP signer certificates retrieval
|
||||
Collection<X509CertificateHolder> certificates = timeStampToken.getCertificates().getMatches(null);
|
||||
|
||||
|
||||
X509CertificateHolder signerCert = null;
|
||||
Map<X500Name, X509CertificateHolder> certificateMap = new HashMap<>();
|
||||
for (X509CertificateHolder certificate : certificates) {
|
||||
|
@ -245,7 +245,7 @@ public class TSPTimeStampService implements TimeStampService {
|
|||
BcDigestCalculatorProvider calculator = new BcDigestCalculatorProvider();
|
||||
BcRSASignerInfoVerifierBuilder verifierBuilder = new BcRSASignerInfoVerifierBuilder(nameGen, sigAlgoFinder, hashAlgoFinder, calculator);
|
||||
SignerInformationVerifier verifier = verifierBuilder.build(holder);
|
||||
|
||||
|
||||
timeStampToken.validate(verifier);
|
||||
|
||||
// verify TSP signer certificate
|
||||
|
@ -258,8 +258,4 @@ public class TSPTimeStampService implements TimeStampService {
|
|||
|
||||
return timeStampToken.getEncoded();
|
||||
}
|
||||
|
||||
public void setSignatureConfig(SignatureConfig signatureConfig) {
|
||||
this.signatureConfig = signatureConfig;
|
||||
}
|
||||
}
|
|
@ -18,28 +18,26 @@
|
|||
/* ====================================================================
|
||||
This product contains an ASLv2 licensed version of the OOXML signer
|
||||
package from the eID Applet project
|
||||
http://code.google.com/p/eid-applet/source/browse/trunk/README.txt
|
||||
http://code.google.com/p/eid-applet/source/browse/trunk/README.txt
|
||||
Copyright (C) 2008-2014 FedICT.
|
||||
================================================================= */
|
||||
================================================================= */
|
||||
|
||||
package org.apache.poi.poifs.crypt.dsig.services;
|
||||
|
||||
import org.apache.poi.poifs.crypt.dsig.SignatureConfig.SignatureConfigurable;
|
||||
|
||||
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
|
||||
|
||||
/**
|
||||
* Interface for a time-stamp service.
|
||||
*
|
||||
*
|
||||
* @author Frank Cornelis
|
||||
*
|
||||
*/
|
||||
public interface TimeStampService extends SignatureConfigurable {
|
||||
public interface TimeStampService {
|
||||
|
||||
/**
|
||||
* Gives back the encoded time-stamp token for the given array of data
|
||||
* bytes. We assume that the time-stamp token itself contains its full
|
||||
* certificate chain required for proper validation.
|
||||
*
|
||||
*
|
||||
* @param data
|
||||
* the data to be time-stamped.
|
||||
* @param revocationData
|
||||
|
@ -49,6 +47,5 @@ public interface TimeStampService extends SignatureConfigurable {
|
|||
* @throws Exception
|
||||
* in case something went wrong.
|
||||
*/
|
||||
byte[] timeStamp(byte[] data, RevocationData revocationData)
|
||||
throws Exception;
|
||||
byte[] timeStamp(SignatureInfo signatureInfo, byte[] data, RevocationData revocationData) throws Exception;
|
||||
}
|
||||
|
|
|
@ -104,27 +104,18 @@ import org.apache.poi.xssf.streaming.SXSSFWorkbook;
|
|||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.apache.xmlbeans.SystemProperties;
|
||||
import org.apache.xmlbeans.XmlObject;
|
||||
import org.bouncycastle.asn1.DERIA5String;
|
||||
import org.bouncycastle.asn1.DEROctetString;
|
||||
import org.bouncycastle.asn1.DERSequence;
|
||||
import org.bouncycastle.asn1.ocsp.OCSPObjectIdentifiers;
|
||||
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
|
||||
import org.bouncycastle.asn1.x500.X500Name;
|
||||
import org.bouncycastle.asn1.x509.AuthorityInformationAccess;
|
||||
import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
|
||||
import org.bouncycastle.asn1.x509.BasicConstraints;
|
||||
import org.bouncycastle.asn1.x509.CRLNumber;
|
||||
import org.bouncycastle.asn1.x509.CRLReason;
|
||||
import org.bouncycastle.asn1.x509.DistributionPoint;
|
||||
import org.bouncycastle.asn1.x509.DistributionPointName;
|
||||
import org.bouncycastle.asn1.x509.Extension;
|
||||
import org.bouncycastle.asn1.x509.Extensions;
|
||||
import org.bouncycastle.asn1.x509.GeneralName;
|
||||
import org.bouncycastle.asn1.x509.GeneralNames;
|
||||
import org.bouncycastle.asn1.x509.KeyUsage;
|
||||
import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
|
||||
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
|
||||
import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
|
||||
import org.bouncycastle.cert.X509CRLHolder;
|
||||
import org.bouncycastle.cert.X509CertificateHolder;
|
||||
import org.bouncycastle.cert.X509ExtensionUtils;
|
||||
|
@ -141,7 +132,6 @@ import org.bouncycastle.cert.ocsp.OCSPReqBuilder;
|
|||
import org.bouncycastle.cert.ocsp.OCSPResp;
|
||||
import org.bouncycastle.cert.ocsp.OCSPRespBuilder;
|
||||
import org.bouncycastle.cert.ocsp.Req;
|
||||
import org.bouncycastle.cert.ocsp.RevokedStatus;
|
||||
import org.bouncycastle.crypto.params.RSAKeyParameters;
|
||||
import org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory;
|
||||
import org.bouncycastle.openssl.PEMParser;
|
||||
|
@ -196,7 +186,7 @@ public class TestSignatureInfo {
|
|||
String additionalJar = System.getProperty("additionaljar");
|
||||
//System.out.println("Having: " + additionalJar);
|
||||
Assume.assumeTrue("Not running TestSignatureInfo because we are testing with additionaljar set to " + additionalJar,
|
||||
additionalJar == null || additionalJar.trim().length() == 0);
|
||||
additionalJar == null || additionalJar.trim().length() == 0);
|
||||
|
||||
System.setProperty("org.apache.xml.security.ignoreLineBreaks", "true");
|
||||
|
||||
|
@ -207,98 +197,97 @@ public class TestSignatureInfo {
|
|||
@Ignore("This test is very sensitive, it breaks with every little change to the produced XML")
|
||||
@Test
|
||||
public void bug61182() throws Exception {
|
||||
String pfxInput =
|
||||
"H4sIAAAAAAAAAFXTfzzTeRwH8P2uGRmG6hKSmJh9a2HsuPy60VnHCEU6v86sieZH2Jr2qFl+s+ZHJ5tfUcfKb4uho/OjiFq1qTv5ceFyp0PqEK"+
|
||||
"fH4+66++Pz+Dwer9fj8f7r9cRzEd4QMBTPRWxDIM14ZN47NfAWsJgL34Bx4at4Lvwdngvd9b8KqgbjQpGbMXzzgRGovytVFTBEzIXU47kQCd4U"+
|
||||
"ofJPvHl8JwyTjRS55hbKoor3UJLDE1i/PcPKCBAIDATjQlKiK67XjVYdcnkZgD2txroiAUb8W9dtn57DvTsbM+3wIsdocXDEN7TdPKgaSl+tU1"+
|
||||
"xq9oqiB5yMaZCPho8uUEbFU9U6u3N7lEMLTJGeA0RfX+5FMRrpXPFrbrlJ8uNUCE2H247P28Ckyfqlsy32yeKg/HTbH5JpqUDNw2B32+SaiRw7"+
|
||||
"ofRMePUpaAoK7KYgmd5ZIc0rLLYjJBfOWCb28xlrGhbpJvdToFdqt5PXVjEz5YOJ6g7W0fskuKW9/iZP0yLEVpR9XkkHmb6tfpcE8YwCdWNCan"+
|
||||
"LvAsco25JdF1j2/FLAMVU79HdOex07main90dy40511OZtTGZ+TdVd3lKZ7D3clEg9hLESHwSNnZ6239X4yLM4xYSElQ/hqSbwdmiozYG9PhF2"+
|
||||
"Zf0XaZnxzTK0Iot+rJ3kYoxWTLE8DR9leV62Ywbtlg4mapYOxb3lT7fQ1x4EQ44flh2oFWSPLR8LMbsc6jzJsV6OZ3TrODjHEdw9W+8OD32vd8"+
|
||||
"XQ6iCaIHcrSOn6qS0TKLr786234eeSAhvAQbEsVn7vrvc/487Be/O2e/+5Y5zRq2zAtz6pfcNyraJNDqMW1inNkgJ3t3VESbZ3pNzyl3KHILs0"+
|
||||
"51dY6msDYSlWhw40TglXxj9rw95O6gFWIuN012W/vhS50jpKXcao4gc1aLaXtJXxirbRkpZ/0e7a0pD6TDa7+GxEdEEML3VGo9udD5YUKhU3y7"+
|
||||
"SzWAgN6WIEIglq7LilvCjqIVLIfg8CvVGL9f5iSsCDf5hef4vMxbyvcjINuy06gZu+iPYOWNxjfrwKGYzoqqotK2aywgYVrPMh0JovfkDuN95n"+
|
||||
"MdVlYHbN1Mnn4TxAwuv+u3AkBlDZvRUUCwoDMUGxeMNPhTaAgWl60xhhBgCBaEMgAACReMAav7n3x598IDYJ9GxGXRAwaPOT/kfO/1AgPqLQkp"+
|
||||
"MiIVaHthnUS4v2y32e2BjdMPyIImUTBW3cV3R5tjVQm0MOm+D2C5+bBW9vHLjLR4lun4toQiY3Ls/v4bES/OJ4EmpZk5xhL9i5ClofYZNEsxFn"+
|
||||
"An/q821Tg+Cq9Er4XYGQe8ogjjLJ2b7dUsJ3auFQFNUJF7Ke7yUL2EeYYxl6vz5l4q5u8704mRbFts1E1eWMp6WIy91GPrsVlRGvtuNERfrjfE"+
|
||||
"YtzUI3Flcv65zJUbUBEzUnTS0fEYso2XyToAl8kb251mUY2o2lJzv5dp/1htmcjeeP2MjxC+3S45ljx7jd52Pv9XAat+ryiauFOF7YgztkoWWD"+
|
||||
"h62tplPH1bzDV+d0NLdaE5AfVJ09HuUYTFS+iggtvT5Euyk+unj4N2XvzW91n+GNjtgWfKOHmkinUPvYRh70Jv+wlPJrVaT8mL7GxJLqDC9jbv"+
|
||||
"Gznoiae6es+wQejnk3XjU366MrK/zXxngBYj9J6NnXc9mMiTFLX8WqQ8iTelTAFs2NJzPoDzrBUz4JFIEOa6Dja6dULc68g1jFDTeEHZyra7RZ"+
|
||||
"2ElqGDEqcNRo3SNX6feMy9EF1GOyZK0Sa87KwjKw8aM68dpsIYjfLcTXaZ6atg0BKfMnl6axeUGEaIFSP7rzj9wjzumRbG3jgUVp2lX5AK/tsO"+
|
||||
"7R4TQX/9/H6RiN34c9KldmPZZGANXzzTajZS9mR2OSvlJ+F4AgSko4htrMAKFTBu51/5SWNsO1vlRaaG48ZRJ+8PzuHQMdvS36gNpRPi7jhF1S"+
|
||||
"H3B2ycI4y0VURv6SrqJNUY/X645ZFJQ+eBO+ptG7o8axf1dcqh2beiQk+GRTeZ37LVeUlaeo9vl1/+8tyBfyT2v5lFC5E19WdKIyCuZe7r99Px"+
|
||||
"D/Od4Qj0TA92+DQnbCQTCMy/wwse9O4gsEebkkpPIP5GBV3Q0YBsj75XE0uSFQ1tCZSW8bNa9MUJZ/nPBfExohHlgGAAA=";
|
||||
final String pfxInput =
|
||||
"H4sIAAAAAAAAAFXTfzzTeRwH8P2uGRmG6hKSmJh9a2HsuPy60VnHCEU6v86sieZH2Jr2qFl+s+ZHJ5tfUcfKb4uho/OjiFq1qTv5ceFyp0PqEK"+
|
||||
"fH4+66++Pz+Dwer9fj8f7r9cRzEd4QMBTPRWxDIM14ZN47NfAWsJgL34Bx4at4Lvwdngvd9b8KqgbjQpGbMXzzgRGovytVFTBEzIXU47kQCd4U"+
|
||||
"ofJPvHl8JwyTjRS55hbKoor3UJLDE1i/PcPKCBAIDATjQlKiK67XjVYdcnkZgD2txroiAUb8W9dtn57DvTsbM+3wIsdocXDEN7TdPKgaSl+tU1"+
|
||||
"xq9oqiB5yMaZCPho8uUEbFU9U6u3N7lEMLTJGeA0RfX+5FMRrpXPFrbrlJ8uNUCE2H247P28Ckyfqlsy32yeKg/HTbH5JpqUDNw2B32+SaiRw7"+
|
||||
"ofRMePUpaAoK7KYgmd5ZIc0rLLYjJBfOWCb28xlrGhbpJvdToFdqt5PXVjEz5YOJ6g7W0fskuKW9/iZP0yLEVpR9XkkHmb6tfpcE8YwCdWNCan"+
|
||||
"LvAsco25JdF1j2/FLAMVU79HdOex07main90dy40511OZtTGZ+TdVd3lKZ7D3clEg9hLESHwSNnZ6239X4yLM4xYSElQ/hqSbwdmiozYG9PhF2"+
|
||||
"Zf0XaZnxzTK0Iot+rJ3kYoxWTLE8DR9leV62Ywbtlg4mapYOxb3lT7fQ1x4EQ44flh2oFWSPLR8LMbsc6jzJsV6OZ3TrODjHEdw9W+8OD32vd8"+
|
||||
"XQ6iCaIHcrSOn6qS0TKLr786234eeSAhvAQbEsVn7vrvc/487Be/O2e/+5Y5zRq2zAtz6pfcNyraJNDqMW1inNkgJ3t3VESbZ3pNzyl3KHILs0"+
|
||||
"51dY6msDYSlWhw40TglXxj9rw95O6gFWIuN012W/vhS50jpKXcao4gc1aLaXtJXxirbRkpZ/0e7a0pD6TDa7+GxEdEEML3VGo9udD5YUKhU3y7"+
|
||||
"SzWAgN6WIEIglq7LilvCjqIVLIfg8CvVGL9f5iSsCDf5hef4vMxbyvcjINuy06gZu+iPYOWNxjfrwKGYzoqqotK2aywgYVrPMh0JovfkDuN95n"+
|
||||
"MdVlYHbN1Mnn4TxAwuv+u3AkBlDZvRUUCwoDMUGxeMNPhTaAgWl60xhhBgCBaEMgAACReMAav7n3x598IDYJ9GxGXRAwaPOT/kfO/1AgPqLQkp"+
|
||||
"MiIVaHthnUS4v2y32e2BjdMPyIImUTBW3cV3R5tjVQm0MOm+D2C5+bBW9vHLjLR4lun4toQiY3Ls/v4bES/OJ4EmpZk5xhL9i5ClofYZNEsxFn"+
|
||||
"An/q821Tg+Cq9Er4XYGQe8ogjjLJ2b7dUsJ3auFQFNUJF7Ke7yUL2EeYYxl6vz5l4q5u8704mRbFts1E1eWMp6WIy91GPrsVlRGvtuNERfrjfE"+
|
||||
"YtzUI3Flcv65zJUbUBEzUnTS0fEYso2XyToAl8kb251mUY2o2lJzv5dp/1htmcjeeP2MjxC+3S45ljx7jd52Pv9XAat+ryiauFOF7YgztkoWWD"+
|
||||
"h62tplPH1bzDV+d0NLdaE5AfVJ09HuUYTFS+iggtvT5Euyk+unj4N2XvzW91n+GNjtgWfKOHmkinUPvYRh70Jv+wlPJrVaT8mL7GxJLqDC9jbv"+
|
||||
"Gznoiae6es+wQejnk3XjU366MrK/zXxngBYj9J6NnXc9mMiTFLX8WqQ8iTelTAFs2NJzPoDzrBUz4JFIEOa6Dja6dULc68g1jFDTeEHZyra7RZ"+
|
||||
"2ElqGDEqcNRo3SNX6feMy9EF1GOyZK0Sa87KwjKw8aM68dpsIYjfLcTXaZ6atg0BKfMnl6axeUGEaIFSP7rzj9wjzumRbG3jgUVp2lX5AK/tsO"+
|
||||
"7R4TQX/9/H6RiN34c9KldmPZZGANXzzTajZS9mR2OSvlJ+F4AgSko4htrMAKFTBu51/5SWNsO1vlRaaG48ZRJ+8PzuHQMdvS36gNpRPi7jhF1S"+
|
||||
"H3B2ycI4y0VURv6SrqJNUY/X645ZFJQ+eBO+ptG7o8axf1dcqh2beiQk+GRTeZ37LVeUlaeo9vl1/+8tyBfyT2v5lFC5E19WdKIyCuZe7r99Px"+
|
||||
"D/Od4Qj0TA92+DQnbCQTCMy/wwse9O4gsEebkkpPIP5GBV3Q0YBsj75XE0uSFQ1tCZSW8bNa9MUJZ/nPBfExohHlgGAAA=";
|
||||
|
||||
// Unix
|
||||
final String unixSignExp =
|
||||
"QkqTFQZjXagjRAoOWKpAGa8AR0rKqkSfBtfSWqtjBmTgyjarn+t2POHkpySIpheHAbg+90GKSH88ACMtPHbG7q" +
|
||||
"FL4gtgAD9Kjew6j16j0IRBwy145UlPrSLFMfF7YF7UlU1k1LBkIlRJ6Fv4MAJl6XspuzZOZIUmHZrWrdxycUQ=";
|
||||
|
||||
// Windows
|
||||
final String winSignExp =
|
||||
"GmAlL7+bT1r3FsMHJOp3pKg8betblYieZTjhMIrPZPRBbSzjO7KsYRGNtr0aOE3qr8xzyYJN6/8QdF5X7pUEUc" +
|
||||
"2m8ctrm7s5o2vZTkAqk9ENJGDjBPXX7TnuVOiVeL1cJdtjHC2QpjtRwkFR+B54G6b1OXLOFuQpP3vqR3+/XXE=";
|
||||
|
||||
// Mac
|
||||
final String macSignExp =
|
||||
"NZedY/LNTYU4nAUEUhIOg5+fKdgVtzRXKmdD3v+47E7Mb84oeiUGv9cCEE91DU3StF/JFIhjOJqavOzKnCsNcz" +
|
||||
"NJ4j/inggUl1OJUsicqIGQnA7E8vzWnN1kf5lINgJLv+0PyrrX9sQZbItzxUpgqyOFYcD0trid+31nRt4wtaA=";
|
||||
|
||||
|
||||
|
||||
Calendar cal = LocaleUtil.getLocaleCalendar(LocaleUtil.TIMEZONE_UTC);
|
||||
cal.clear();
|
||||
cal.setTimeZone(LocaleUtil.TIMEZONE_UTC);
|
||||
cal.set(2017, Calendar.JULY, 1);
|
||||
|
||||
SignatureConfig signatureConfig = prepareConfig("test", "CN=Test", pfxInput);
|
||||
SignatureConfig signatureConfig = prepareConfig(pfxInput);
|
||||
signatureConfig.setExecutionTime(cal.getTime());
|
||||
|
||||
SignatureInfo si = new SignatureInfo();
|
||||
si.setSignatureConfig(signatureConfig);
|
||||
|
||||
XSSFWorkbook wb1 = new XSSFWorkbook();
|
||||
wb1.createSheet().createRow(1).createCell(1).setCellValue("Test");
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream(100000);
|
||||
wb1.write(bos);
|
||||
wb1.close();
|
||||
|
||||
OPCPackage pkg1 = OPCPackage.open(new ByteArrayInputStream(bos.toByteArray()));
|
||||
|
||||
signatureConfig.setOpcPackage(pkg1);
|
||||
si.confirmSignature();
|
||||
assertTrue(si.verifySignature());
|
||||
bos.reset();
|
||||
pkg1.save(bos);
|
||||
pkg1.close();
|
||||
|
||||
XSSFWorkbook wb2 = new XSSFWorkbook(new ByteArrayInputStream(bos.toByteArray()));
|
||||
assertEquals("Test", wb2.getSheetAt(0).getRow(1).getCell(1).getStringCellValue());
|
||||
OPCPackage pkg2 = wb2.getPackage();
|
||||
signatureConfig.setOpcPackage(pkg2);
|
||||
assertTrue(si.verifySignature());
|
||||
|
||||
// xmlbeans adds line-breaks depending on the system setting, so we get different
|
||||
// test results on Unix/Mac/Windows
|
||||
// if the xml documents eventually change, this test needs to be run with the
|
||||
// separator set to the various system configurations
|
||||
String sep = SystemProperties.getProperty( "line.separator" );
|
||||
String signExp;
|
||||
assumeTrue("Hashes only known for Windows/Unix/Mac", sep == null || "\n".equals(sep) || "\r\n".equals(sep) || "\r".equals(sep));
|
||||
if (sep == null || "\n".equals(sep)) {
|
||||
// Unix
|
||||
signExp =
|
||||
"QkqTFQZjXagjRAoOWKpAGa8AR0rKqkSfBtfSWqtjBmTgyjarn+t2POHkpySIpheHAbg+90GKSH88ACMtPHbG7q"+
|
||||
"FL4gtgAD9Kjew6j16j0IRBwy145UlPrSLFMfF7YF7UlU1k1LBkIlRJ6Fv4MAJl6XspuzZOZIUmHZrWrdxycUQ=";
|
||||
} else if ("\r\n".equals(sep)){
|
||||
// Windows
|
||||
signExp =
|
||||
"GmAlL7+bT1r3FsMHJOp3pKg8betblYieZTjhMIrPZPRBbSzjO7KsYRGNtr0aOE3qr8xzyYJN6/8QdF5X7pUEUc"+
|
||||
"2m8ctrm7s5o2vZTkAqk9ENJGDjBPXX7TnuVOiVeL1cJdtjHC2QpjtRwkFR+B54G6b1OXLOFuQpP3vqR3+/XXE=";
|
||||
} else {
|
||||
// Mac
|
||||
signExp =
|
||||
"NZedY/LNTYU4nAUEUhIOg5+fKdgVtzRXKmdD3v+47E7Mb84oeiUGv9cCEE91DU3StF/JFIhjOJqavOzKnCsNcz"+
|
||||
"NJ4j/inggUl1OJUsicqIGQnA7E8vzWnN1kf5lINgJLv+0PyrrX9sQZbItzxUpgqyOFYcD0trid+31nRt4wtaA=";
|
||||
try (XSSFWorkbook wb1 = new XSSFWorkbook()) {
|
||||
wb1.createSheet().createRow(1).createCell(1).setCellValue("Test");
|
||||
wb1.write(bos);
|
||||
}
|
||||
|
||||
String signAct = si.getSignatureParts().iterator().next().
|
||||
getSignatureDocument().getSignature().getSignatureValue().getStringValue();
|
||||
assertEquals(signExp, signAct);
|
||||
try (OPCPackage pkg1 = OPCPackage.open(new ByteArrayInputStream(bos.toByteArray()))) {
|
||||
si.setOpcPackage(pkg1);
|
||||
si.confirmSignature();
|
||||
assertTrue(si.verifySignature());
|
||||
bos.reset();
|
||||
pkg1.save(bos);
|
||||
}
|
||||
|
||||
pkg2.close();
|
||||
wb2.close();
|
||||
try (XSSFWorkbook wb2 = new XSSFWorkbook(new ByteArrayInputStream(bos.toByteArray()))) {
|
||||
assertEquals("Test", wb2.getSheetAt(0).getRow(1).getCell(1).getStringCellValue());
|
||||
OPCPackage pkg2 = wb2.getPackage();
|
||||
si.setOpcPackage(pkg2);
|
||||
assertTrue(si.verifySignature());
|
||||
|
||||
// xmlbeans adds line-breaks depending on the system setting, so we get different
|
||||
// test results on Unix/Mac/Windows
|
||||
// if the xml documents eventually change, this test needs to be run with the
|
||||
// separator set to the various system configurations
|
||||
String sep = SystemProperties.getProperty("line.separator");
|
||||
String signExp;
|
||||
assumeTrue("Hashes only known for Windows/Unix/Mac", sep == null || "\n".equals(sep) || "\r\n".equals(sep) || "\r".equals(sep));
|
||||
signExp = (sep == null || "\n".equals(sep)) ? unixSignExp : ("\r\n".equals(sep)) ? winSignExp : macSignExp;
|
||||
|
||||
String signAct = si.getSignatureParts().iterator().next().
|
||||
getSignatureDocument().getSignature().getSignatureValue().getStringValue();
|
||||
assertEquals(signExp, signAct);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void office2007prettyPrintedRels() throws Exception {
|
||||
try (OPCPackage pkg = OPCPackage.open(testdata.getFile("office2007prettyPrintedRels.docx"), PackageAccess.READ)) {
|
||||
SignatureConfig sic = new SignatureConfig();
|
||||
sic.setOpcPackage(pkg);
|
||||
SignatureInfo si = new SignatureInfo();
|
||||
si.setOpcPackage(pkg);
|
||||
si.setSignatureConfig(sic);
|
||||
boolean isValid = si.verifySignature();
|
||||
assertTrue(isValid);
|
||||
|
@ -315,19 +304,19 @@ public class TestSignatureInfo {
|
|||
};
|
||||
|
||||
for (String testFile : testFiles) {
|
||||
OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ);
|
||||
SignatureConfig sic = new SignatureConfig();
|
||||
sic.setOpcPackage(pkg);
|
||||
SignatureInfo si = new SignatureInfo();
|
||||
si.setSignatureConfig(sic);
|
||||
List<X509Certificate> result = new ArrayList<>();
|
||||
for (SignaturePart sp : si.getSignatureParts()) {
|
||||
if (sp.validate()) {
|
||||
result.add(sp.getSigner());
|
||||
try (OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ)) {
|
||||
SignatureConfig sic = new SignatureConfig();
|
||||
SignatureInfo si = new SignatureInfo();
|
||||
si.setOpcPackage(pkg);
|
||||
si.setSignatureConfig(sic);
|
||||
for (SignaturePart sp : si.getSignatureParts()) {
|
||||
if (sp.validate()) {
|
||||
result.add(sp.getSigner());
|
||||
}
|
||||
}
|
||||
pkg.revert();
|
||||
}
|
||||
pkg.revert();
|
||||
pkg.close();
|
||||
assertNotNull(result);
|
||||
assertTrue(result.isEmpty());
|
||||
}
|
||||
|
@ -345,14 +334,14 @@ public class TestSignatureInfo {
|
|||
"ms-office-2010-signed.pptx",
|
||||
"ms-office-2010-signed.xlsx",
|
||||
"Office2010-SP1-XAdES-X-L.docx",
|
||||
"signed.docx",
|
||||
"signed.docx"
|
||||
};
|
||||
|
||||
for (String testFile : testFiles) {
|
||||
try (OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ)) {
|
||||
SignatureConfig sic = new SignatureConfig();
|
||||
sic.setOpcPackage(pkg);
|
||||
SignatureInfo si = new SignatureInfo();
|
||||
si.setOpcPackage(pkg);
|
||||
si.setSignatureConfig(sic);
|
||||
List<X509Certificate> result = new ArrayList<>();
|
||||
for (SignaturePart sp : si.getSignatureParts()) {
|
||||
|
@ -378,8 +367,8 @@ public class TestSignatureInfo {
|
|||
String testFile = "hello-world-signed-twice.docx";
|
||||
try (OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ)) {
|
||||
SignatureConfig sic = new SignatureConfig();
|
||||
sic.setOpcPackage(pkg);
|
||||
SignatureInfo si = new SignatureInfo();
|
||||
si.setOpcPackage(pkg);
|
||||
si.setSignatureConfig(sic);
|
||||
List<X509Certificate> result = new ArrayList<>();
|
||||
for (SignaturePart sp : si.getSignatureParts()) {
|
||||
|
@ -404,9 +393,9 @@ public class TestSignatureInfo {
|
|||
@Test
|
||||
public void testSignSpreadsheet() throws Exception {
|
||||
String testFile = "hello-world-unsigned.xlsx";
|
||||
OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE);
|
||||
sign(pkg, "Test", "CN=Test", 1);
|
||||
pkg.close();
|
||||
try (OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE)) {
|
||||
sign(pkg);
|
||||
}
|
||||
}
|
||||
|
||||
private static class CommitableWorkbook extends XSSFWorkbook {
|
||||
|
@ -423,7 +412,7 @@ public class TestSignatureInfo {
|
|||
// sign & validate
|
||||
String testFile = "hello-world-unsigned.xlsx";
|
||||
try (OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE)) {
|
||||
sign(pkg, "Test", "CN=Test", 1);
|
||||
sign(pkg);
|
||||
|
||||
// manipulate
|
||||
try (CommitableWorkbook wb = new CommitableWorkbook(pkg)) {
|
||||
|
@ -436,8 +425,8 @@ public class TestSignatureInfo {
|
|||
|
||||
// validate
|
||||
SignatureConfig sic = new SignatureConfig();
|
||||
sic.setOpcPackage(pkg);
|
||||
SignatureInfo si = new SignatureInfo();
|
||||
si.setOpcPackage(pkg);
|
||||
si.setSignatureConfig(sic);
|
||||
boolean b = si.verifySignature();
|
||||
assertFalse("signature should be broken", b);
|
||||
|
@ -449,14 +438,14 @@ public class TestSignatureInfo {
|
|||
|
||||
@Test
|
||||
public void testSignSpreadsheetWithSignatureInfo() throws Exception {
|
||||
initKeyPair("Test", "CN=Test");
|
||||
initKeyPair();
|
||||
String testFile = "hello-world-unsigned.xlsx";
|
||||
try (OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE)) {
|
||||
SignatureConfig sic = new SignatureConfig();
|
||||
sic.setOpcPackage(pkg);
|
||||
sic.setKey(keyPair.getPrivate());
|
||||
sic.setSigningCertificateChain(Collections.singletonList(x509));
|
||||
SignatureInfo si = new SignatureInfo();
|
||||
si.setOpcPackage(pkg);
|
||||
si.setSignatureConfig(sic);
|
||||
// hash > sha1 doesn't work in excel viewer ...
|
||||
si.confirmSignature();
|
||||
|
@ -481,12 +470,11 @@ public class TestSignatureInfo {
|
|||
|
||||
try (OPCPackage pkg = OPCPackage.open(copy(sigCopy), PackageAccess.READ_WRITE)) {
|
||||
|
||||
initKeyPair("Test", "CN=Test");
|
||||
initKeyPair();
|
||||
final X509CRL crl = generateCrl(x509, keyPair.getPrivate());
|
||||
|
||||
// setup
|
||||
SignatureConfig signatureConfig = new SignatureConfig();
|
||||
signatureConfig.setOpcPackage(pkg);
|
||||
signatureConfig.setKey(keyPair.getPrivate());
|
||||
|
||||
/*
|
||||
|
@ -529,17 +517,9 @@ public class TestSignatureInfo {
|
|||
}
|
||||
|
||||
if (mockTsp) {
|
||||
TimeStampService tspService = new TimeStampService() {
|
||||
@Override
|
||||
public byte[] timeStamp(byte[] data, RevocationData revocationData) {
|
||||
revocationData.addCRL(crl);
|
||||
return "time-stamp-token".getBytes(LocaleUtil.CHARSET_1252);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSignatureConfig(SignatureConfig config) {
|
||||
// empty on purpose
|
||||
}
|
||||
TimeStampService tspService = (signatureInfo, data, revocationData) -> {
|
||||
revocationData.addCRL(crl);
|
||||
return "time-stamp-token".getBytes(LocaleUtil.CHARSET_1252);
|
||||
};
|
||||
signatureConfig.setTspService(tspService);
|
||||
} else {
|
||||
|
@ -555,8 +535,7 @@ public class TestSignatureInfo {
|
|||
|
||||
final RevocationData revocationData = new RevocationData();
|
||||
revocationData.addCRL(crl);
|
||||
OCSPResp ocspResp = createOcspResp(x509, false,
|
||||
x509, x509, keyPair.getPrivate(), "SHA1withRSA", cal.getTimeInMillis());
|
||||
OCSPResp ocspResp = createOcspResp(x509, x509, x509, keyPair.getPrivate(), cal.getTimeInMillis());
|
||||
revocationData.addOCSP(ocspResp.getEncoded());
|
||||
|
||||
RevocationDataService revocationDataService = revocationChain -> revocationData;
|
||||
|
@ -564,33 +543,31 @@ public class TestSignatureInfo {
|
|||
|
||||
// operate
|
||||
SignatureInfo si = new SignatureInfo();
|
||||
si.setOpcPackage(pkg);
|
||||
si.setSignatureConfig(signatureConfig);
|
||||
try {
|
||||
si.confirmSignature();
|
||||
} catch (RuntimeException e) {
|
||||
pkg.close();
|
||||
// only allow a ConnectException because of timeout, we see this in Jenkins from time to time...
|
||||
if (e.getCause() == null) {
|
||||
throw e;
|
||||
}
|
||||
if ((e.getCause() instanceof ConnectException) || (e.getCause() instanceof SocketTimeoutException)) {
|
||||
Assume.assumeFalse("Only allowing ConnectException with 'timed out' as message here, but had: " + e,
|
||||
e.getCause().getMessage().contains("timed out"));
|
||||
e.getCause().getMessage().contains("timed out"));
|
||||
} else if (e.getCause() instanceof IOException) {
|
||||
Assume.assumeFalse("Only allowing IOException with 'Error contacting TSP server' as message here, but had: " + e,
|
||||
e.getCause().getMessage().contains("Error contacting TSP server"));
|
||||
e.getCause().getMessage().contains("Error contacting TSP server"));
|
||||
} else if (e.getCause() instanceof RuntimeException) {
|
||||
Assume.assumeFalse("Only allowing RuntimeException with 'This site is cur' as message here, but had: " + e,
|
||||
e.getCause().getMessage().contains("This site is cur"));
|
||||
e.getCause().getMessage().contains("This site is cur"));
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
// verify
|
||||
Iterator<SignaturePart> spIter = si.getSignatureParts().iterator();
|
||||
assertTrue("Had: " + si.getSignatureConfig().getOpcPackage().
|
||||
getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN),
|
||||
spIter.hasNext());
|
||||
assertTrue("Had: " + pkg.getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN), spIter.hasNext());
|
||||
SignaturePart sp = spIter.next();
|
||||
boolean valid = sp.validate();
|
||||
assertTrue(valid);
|
||||
|
@ -627,10 +604,10 @@ public class TestSignatureInfo {
|
|||
|
||||
try (OPCPackage pkg = OPCPackage.open(new ByteArrayInputStream(bos.toByteArray()))) {
|
||||
SignatureConfig signatureConfig = new SignatureConfig();
|
||||
signatureConfig.setOpcPackage(pkg);
|
||||
signatureConfig.setUpdateConfigOnValidate(true);
|
||||
|
||||
SignatureInfo si = new SignatureInfo();
|
||||
si.setOpcPackage(pkg);
|
||||
si.setSignatureConfig(signatureConfig);
|
||||
|
||||
assertTrue(si.verifySignature());
|
||||
|
@ -667,13 +644,7 @@ public class TestSignatureInfo {
|
|||
conn.connect();
|
||||
|
||||
if (fireRequest) {
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = conn.getInputStream();
|
||||
} finally {
|
||||
IOUtils.closeQuietly(is);
|
||||
}
|
||||
|
||||
conn.getInputStream().close();
|
||||
}
|
||||
/* if connecting is possible we return true here */
|
||||
return null;
|
||||
|
@ -692,9 +663,9 @@ public class TestSignatureInfo {
|
|||
public void testCertChain() throws Exception {
|
||||
KeyStore keystore = KeyStore.getInstance("PKCS12");
|
||||
String password = "test";
|
||||
InputStream is = testdata.openResourceAsStream("chaintest.pfx");
|
||||
keystore.load(is, password.toCharArray());
|
||||
is.close();
|
||||
try (InputStream is = testdata.openResourceAsStream("chaintest.pfx")) {
|
||||
keystore.load(is, password.toCharArray());
|
||||
}
|
||||
|
||||
Key key = keystore.getKey("poitest", password.toCharArray());
|
||||
Certificate[] chainList = keystore.getCertificateChain("poitest");
|
||||
|
@ -714,9 +685,9 @@ public class TestSignatureInfo {
|
|||
Calendar oldCal = LocaleUtil.getLocaleCalendar(2007, 7, 1);
|
||||
signatureConfig.setExecutionTime(oldCal.getTime());
|
||||
signatureConfig.setDigestAlgo(HashAlgorithm.sha1);
|
||||
signatureConfig.setOpcPackage(pkg);
|
||||
|
||||
SignatureInfo si = new SignatureInfo();
|
||||
si.setOpcPackage(pkg);
|
||||
si.setSignatureConfig(signatureConfig);
|
||||
|
||||
si.confirmSignature();
|
||||
|
@ -735,7 +706,7 @@ public class TestSignatureInfo {
|
|||
@Test
|
||||
public void testNonSha1() throws Exception {
|
||||
String testFile = "hello-world-unsigned.xlsx";
|
||||
initKeyPair("Test", "CN=Test");
|
||||
initKeyPair();
|
||||
|
||||
SignatureConfig signatureConfig = new SignatureConfig();
|
||||
signatureConfig.setKey(keyPair.getPrivate());
|
||||
|
@ -745,13 +716,10 @@ public class TestSignatureInfo {
|
|||
, HashAlgorithm.sha384, HashAlgorithm.sha512, HashAlgorithm.ripemd160};
|
||||
|
||||
for (HashAlgorithm ha : testAlgo) {
|
||||
OPCPackage pkg = null;
|
||||
try {
|
||||
signatureConfig.setDigestAlgo(ha);
|
||||
pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE);
|
||||
signatureConfig.setOpcPackage(pkg);
|
||||
|
||||
signatureConfig.setDigestAlgo(ha);
|
||||
try (OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE)) {
|
||||
SignatureInfo si = new SignatureInfo();
|
||||
si.setOpcPackage(pkg);
|
||||
si.setSignatureConfig(signatureConfig);
|
||||
|
||||
si.confirmSignature();
|
||||
|
@ -759,10 +727,6 @@ public class TestSignatureInfo {
|
|||
assertTrue("Signature not correctly calculated for " + ha, b);
|
||||
} catch (EncryptedDocumentException e) {
|
||||
Assume.assumeTrue(e.getMessage().startsWith("Export Restrictions"));
|
||||
} finally {
|
||||
if (pkg != null) {
|
||||
pkg.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -776,20 +740,18 @@ public class TestSignatureInfo {
|
|||
wb1.removeSheetAt(0);
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
wb1.write(os);
|
||||
wb1.close();
|
||||
try (OPCPackage pkg = OPCPackage.open(new ByteArrayInputStream(os.toByteArray()))) {
|
||||
|
||||
initKeyPair("Test", "CN=Test");
|
||||
try (OPCPackage pkg = OPCPackage.open(new ByteArrayInputStream(os.toByteArray()))) {
|
||||
initKeyPair();
|
||||
SignatureConfig signatureConfig = new SignatureConfig();
|
||||
signatureConfig.setKey(keyPair.getPrivate());
|
||||
signatureConfig.setSigningCertificateChain(Collections.singletonList(x509));
|
||||
signatureConfig.setOpcPackage(pkg);
|
||||
|
||||
SignatureInfo si = new SignatureInfo();
|
||||
si.setOpcPackage(pkg);
|
||||
si.setSignatureConfig(signatureConfig);
|
||||
si.confirmSignature();
|
||||
assertTrue("invalid signature", si.verifySignature());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -833,8 +795,8 @@ public class TestSignatureInfo {
|
|||
private void verifyPkg63011(File tpl, boolean multi) throws InvalidFormatException, IOException {
|
||||
try (OPCPackage pkg = OPCPackage.open(tpl, PackageAccess.READ)) {
|
||||
SignatureConfig sic = new SignatureConfig();
|
||||
sic.setOpcPackage(pkg);
|
||||
SignatureInfo si = new SignatureInfo();
|
||||
si.setOpcPackage(pkg);
|
||||
si.setSignatureConfig(sic);
|
||||
List<X509Certificate> result = new ArrayList<>();
|
||||
for (SignaturePart sp : si.getSignatureParts()) {
|
||||
|
@ -860,7 +822,7 @@ public class TestSignatureInfo {
|
|||
}
|
||||
|
||||
private void signPkg63011(OPCPackage pkg, String pemFile, boolean multi)
|
||||
throws IOException, CertificateException, XMLSignatureException, MarshalException {
|
||||
throws IOException, CertificateException, XMLSignatureException, MarshalException {
|
||||
assertNotNull(pkg);
|
||||
initKeyFromPEM(testdata.getFile(pemFile));
|
||||
|
||||
|
@ -869,9 +831,9 @@ public class TestSignatureInfo {
|
|||
config.setSigningCertificateChain(Collections.singletonList(x509));
|
||||
config.setExecutionTime(cal.getTime());
|
||||
config.setAllowMultipleSignatures(multi);
|
||||
config.setOpcPackage(pkg);
|
||||
|
||||
SignatureInfo si = new SignatureInfo();
|
||||
si.setOpcPackage(pkg);
|
||||
si.setSignatureConfig(config);
|
||||
si.confirmSignature();
|
||||
}
|
||||
|
@ -881,9 +843,9 @@ public class TestSignatureInfo {
|
|||
SignatureConfig sic = new SignatureConfig();
|
||||
final File file = testdata.getFile("PPT2016withComment.pptx");
|
||||
try (final OPCPackage pkg = OPCPackage.open(file, PackageAccess.READ)) {
|
||||
sic.setOpcPackage(pkg);
|
||||
sic.setUpdateConfigOnValidate(true);
|
||||
SignatureInfo si = new SignatureInfo();
|
||||
si.setOpcPackage(pkg);
|
||||
si.setSignatureConfig(sic);
|
||||
assertTrue(si.verifySignature());
|
||||
}
|
||||
|
@ -897,8 +859,8 @@ public class TestSignatureInfo {
|
|||
assertEquals(CanonicalizationMethod.INCLUSIVE, sic.getCanonicalizationMethod());
|
||||
}
|
||||
|
||||
private SignatureConfig prepareConfig(String alias, String signerDn, String pfxInput) throws Exception {
|
||||
initKeyPair(alias, signerDn, pfxInput);
|
||||
private SignatureConfig prepareConfig(String pfxInput) throws Exception {
|
||||
initKeyPair(pfxInput);
|
||||
|
||||
SignatureConfig signatureConfig = new SignatureConfig();
|
||||
signatureConfig.setKey(keyPair.getPrivate());
|
||||
|
@ -909,11 +871,13 @@ public class TestSignatureInfo {
|
|||
return signatureConfig;
|
||||
}
|
||||
|
||||
private void sign(OPCPackage pkgCopy, String alias, String signerDn, int signerCount) throws Exception {
|
||||
SignatureConfig signatureConfig = prepareConfig(alias, signerDn, null);
|
||||
signatureConfig.setOpcPackage(pkgCopy);
|
||||
private void sign(OPCPackage pkgCopy) throws Exception {
|
||||
int signerCount = 1;
|
||||
|
||||
SignatureConfig signatureConfig = prepareConfig(null);
|
||||
|
||||
SignatureInfo si = new SignatureInfo();
|
||||
si.setOpcPackage(pkgCopy);
|
||||
si.setSignatureConfig(signatureConfig);
|
||||
|
||||
final Document document = DocumentHelper.createDocument();
|
||||
|
@ -933,7 +897,7 @@ public class TestSignatureInfo {
|
|||
si.postSign(xmlSignContext, signatureValue);
|
||||
|
||||
// verify: signature
|
||||
si.getSignatureConfig().setOpcPackage(pkgCopy);
|
||||
si.setOpcPackage(pkgCopy);
|
||||
List<X509Certificate> result = new ArrayList<>();
|
||||
for (SignaturePart sp : si.getSignatureParts()) {
|
||||
if (sp.validate()) {
|
||||
|
@ -943,24 +907,25 @@ public class TestSignatureInfo {
|
|||
assertEquals(signerCount, result.size());
|
||||
}
|
||||
|
||||
private void initKeyPair(String alias, String subjectDN) throws Exception {
|
||||
initKeyPair(alias, subjectDN, null);
|
||||
private void initKeyPair() throws Exception {
|
||||
initKeyPair(null);
|
||||
}
|
||||
|
||||
private void initKeyPair(String alias, String subjectDN, String pfxInput) throws Exception {
|
||||
private void initKeyPair(String pfxInput) throws Exception {
|
||||
final String alias = "Test";
|
||||
final char[] password = "test".toCharArray();
|
||||
File file = new File("build/test.pfx");
|
||||
|
||||
KeyStore keystore = KeyStore.getInstance("PKCS12");
|
||||
|
||||
if (pfxInput != null) {
|
||||
InputStream fis = new ByteArrayInputStream(RawDataUtil.decompress(pfxInput));
|
||||
keystore.load(fis, password);
|
||||
fis.close();
|
||||
try (InputStream fis = new ByteArrayInputStream(RawDataUtil.decompress(pfxInput))) {
|
||||
keystore.load(fis, password);
|
||||
}
|
||||
} else if (file.exists()) {
|
||||
InputStream fis = new FileInputStream(file);
|
||||
keystore.load(fis, password);
|
||||
fis.close();
|
||||
try (InputStream fis = new FileInputStream(file)) {
|
||||
keystore.load(fis, password);
|
||||
}
|
||||
} else {
|
||||
keystore.load(null, password);
|
||||
}
|
||||
|
@ -977,15 +942,14 @@ public class TestSignatureInfo {
|
|||
Date notAfter = cal2.getTime();
|
||||
KeyUsage keyUsage = new KeyUsage(KeyUsage.digitalSignature);
|
||||
|
||||
x509 = generateCertificate(keyPair.getPublic(), subjectDN
|
||||
, notBefore, notAfter, null, keyPair.getPrivate(), true, 0, null, null, keyUsage);
|
||||
x509 = generateCertificate(keyPair.getPublic(), notBefore, notAfter, keyPair.getPrivate(), keyUsage);
|
||||
|
||||
keystore.setKeyEntry(alias, keyPair.getPrivate(), password, new Certificate[]{x509});
|
||||
|
||||
if (pfxInput == null) {
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
keystore.store(fos, password);
|
||||
fos.close();
|
||||
try (FileOutputStream fos = new FileOutputStream(file)) {
|
||||
keystore.store(fos, password);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1038,24 +1002,18 @@ public class TestSignatureInfo {
|
|||
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
|
||||
SecureRandom random = new SecureRandom();
|
||||
keyPairGenerator.initialize(new RSAKeyGenParameterSpec(1024,
|
||||
RSAKeyGenParameterSpec.F4), random);
|
||||
RSAKeyGenParameterSpec.F4), random);
|
||||
return keyPairGenerator.generateKeyPair();
|
||||
}
|
||||
|
||||
private static X509Certificate generateCertificate(PublicKey subjectPublicKey,
|
||||
String subjectDn, Date notBefore, Date notAfter,
|
||||
X509Certificate issuerCertificate, PrivateKey issuerPrivateKey,
|
||||
boolean caFlag, int pathLength, String crlUri, String ocspUri,
|
||||
KeyUsage keyUsage)
|
||||
throws IOException, OperatorCreationException, CertificateException
|
||||
{
|
||||
String signatureAlgorithm = "SHA1withRSA";
|
||||
X500Name issuerName;
|
||||
if (issuerCertificate != null) {
|
||||
issuerName = new X509CertificateHolder(issuerCertificate.getEncoded()).getIssuer();
|
||||
} else {
|
||||
issuerName = new X500Name(subjectDn);
|
||||
}
|
||||
Date notBefore, Date notAfter,
|
||||
PrivateKey issuerPrivateKey,
|
||||
KeyUsage keyUsage)
|
||||
throws IOException, OperatorCreationException, CertificateException {
|
||||
final String signatureAlgorithm = "SHA1withRSA";
|
||||
final String subjectDn = "CN=Test";
|
||||
X500Name issuerName = new X500Name(subjectDn);
|
||||
|
||||
RSAPublicKey rsaPubKey = (RSAPublicKey)subjectPublicKey;
|
||||
RSAKeyParameters rsaSpec = new RSAKeyParameters(false, rsaPubKey.getModulus(), rsaPubKey.getPublicExponent());
|
||||
|
@ -1077,47 +1035,13 @@ public class TestSignatureInfo {
|
|||
|
||||
X509ExtensionUtils exUtils = new X509ExtensionUtils(digestCalc);
|
||||
SubjectKeyIdentifier subKeyId = exUtils.createSubjectKeyIdentifier(subjectPublicKeyInfo);
|
||||
AuthorityKeyIdentifier autKeyId = (issuerCertificate != null)
|
||||
? exUtils.createAuthorityKeyIdentifier(new X509CertificateHolder(issuerCertificate.getEncoded()))
|
||||
: exUtils.createAuthorityKeyIdentifier(subjectPublicKeyInfo);
|
||||
AuthorityKeyIdentifier autKeyId = exUtils.createAuthorityKeyIdentifier(subjectPublicKeyInfo);
|
||||
|
||||
certificateGenerator.addExtension(Extension.subjectKeyIdentifier, false, subKeyId);
|
||||
certificateGenerator.addExtension(Extension.authorityKeyIdentifier, false, autKeyId);
|
||||
|
||||
if (caFlag) {
|
||||
BasicConstraints bc;
|
||||
|
||||
if (-1 == pathLength) {
|
||||
bc = new BasicConstraints(true);
|
||||
} else {
|
||||
bc = new BasicConstraints(pathLength);
|
||||
}
|
||||
certificateGenerator.addExtension(Extension.basicConstraints, false, bc);
|
||||
}
|
||||
|
||||
if (null != crlUri) {
|
||||
int uri = GeneralName.uniformResourceIdentifier;
|
||||
DERIA5String crlUriDer = new DERIA5String(crlUri);
|
||||
GeneralName gn = new GeneralName(uri, crlUriDer);
|
||||
|
||||
DERSequence gnDer = new DERSequence(gn);
|
||||
GeneralNames gns = GeneralNames.getInstance(gnDer);
|
||||
|
||||
DistributionPointName dpn = new DistributionPointName(0, gns);
|
||||
DistributionPoint distp = new DistributionPoint(dpn, null, null);
|
||||
DERSequence distpDer = new DERSequence(distp);
|
||||
certificateGenerator.addExtension(Extension.cRLDistributionPoints, false, distpDer);
|
||||
}
|
||||
|
||||
if (null != ocspUri) {
|
||||
int uri = GeneralName.uniformResourceIdentifier;
|
||||
GeneralName ocspName = new GeneralName(uri, ocspUri);
|
||||
|
||||
AuthorityInformationAccess authorityInformationAccess =
|
||||
new AuthorityInformationAccess(X509ObjectIdentifiers.ocspAccessMethod, ocspName);
|
||||
|
||||
certificateGenerator.addExtension(Extension.authorityInfoAccess, false, authorityInformationAccess);
|
||||
}
|
||||
BasicConstraints bc = new BasicConstraints(0);
|
||||
certificateGenerator.addExtension(Extension.basicConstraints, false, bc);
|
||||
|
||||
if (null != keyUsage) {
|
||||
certificateGenerator.addExtension(Extension.keyUsage, true, keyUsage);
|
||||
|
@ -1158,10 +1082,10 @@ public class TestSignatureInfo {
|
|||
}
|
||||
|
||||
private static OCSPResp createOcspResp(X509Certificate certificate,
|
||||
boolean revoked, X509Certificate issuerCertificate,
|
||||
X509Certificate ocspResponderCertificate,
|
||||
PrivateKey ocspResponderPrivateKey, String signatureAlgorithm,
|
||||
long nonceTimeinMillis)
|
||||
X509Certificate issuerCertificate,
|
||||
X509Certificate ocspResponderCertificate,
|
||||
PrivateKey ocspResponderPrivateKey,
|
||||
long nonceTimeinMillis)
|
||||
throws Exception {
|
||||
DigestCalculator digestCalc = new JcaDigestCalculatorProviderBuilder()
|
||||
.setProvider("BC").build().get(CertificateID.HASH_SHA1);
|
||||
|
@ -1192,9 +1116,6 @@ public class TestSignatureInfo {
|
|||
for (Req ocspRequest : requestList) {
|
||||
CertificateID certificateID = ocspRequest.getCertID();
|
||||
CertificateStatus certificateStatus = CertificateStatus.GOOD;
|
||||
if (revoked) {
|
||||
certificateStatus = new RevokedStatus(new Date(), CRLReason.privilegeWithdrawn);
|
||||
}
|
||||
basicOCSPRespBuilder.addResponse(certificateID, certificateStatus);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue