xml signature: mainly javadocs - a few reorgs

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1631003 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2014-10-10 22:48:21 +00:00
parent bc400ad94a
commit a16db327fd
4 changed files with 345 additions and 26 deletions

View File

@ -51,6 +51,7 @@ import org.apache.poi.poifs.crypt.dsig.services.TimeStampService;
import org.apache.poi.poifs.crypt.dsig.services.TimeStampServiceValidator; import org.apache.poi.poifs.crypt.dsig.services.TimeStampServiceValidator;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
import org.apache.xml.security.signature.XMLSignature;
import org.w3c.dom.events.EventListener; import org.w3c.dom.events.EventListener;
/** /**
@ -122,8 +123,9 @@ public class SignatureConfig {
*/ */
private HashAlgorithm xadesDigestAlgo = null; private HashAlgorithm xadesDigestAlgo = null;
private String xadesRole = null; private String xadesRole = null;
private String xadesSignatureId = null; private String xadesSignatureId = "idSignedProperties";
private boolean xadesSignaturePolicyImplied = true; private boolean xadesSignaturePolicyImplied = true;
private String xadesCanonicalizationMethod = CanonicalizationMethod.EXCLUSIVE;
/** /**
* Work-around for Office 2010 IssuerName encoding. * Work-around for Office 2010 IssuerName encoding.
@ -198,10 +200,6 @@ public class SignatureConfig {
tspService.setSignatureConfig(this); tspService.setSignatureConfig(this);
} }
if (xadesSignatureId == null || xadesSignatureId.isEmpty()) {
xadesSignatureId = "idSignedProperties";
}
if (signatureFacets.isEmpty()) { if (signatureFacets.isEmpty()) {
addSignatureFacet(new OOXMLSignatureFacet()); addSignatureFacet(new OOXMLSignatureFacet());
addSignatureFacet(new KeyInfoSignatureFacet()); addSignatureFacet(new KeyInfoSignatureFacet());
@ -366,141 +364,358 @@ public class SignatureConfig {
public void setCanonicalizationMethod(String canonicalizationMethod) { public void setCanonicalizationMethod(String canonicalizationMethod) {
this.canonicalizationMethod = canonicalizationMethod; this.canonicalizationMethod = canonicalizationMethod;
} }
/**
* @return The signature Id attribute value used to create the XML signature.
* Defaults to "idPackageSignature"
*/
public String getPackageSignatureId() { public String getPackageSignatureId() {
return packageSignatureId; return packageSignatureId;
} }
/**
* @param packageSignatureId The signature Id attribute value used to create the XML signature.
* A <code>null</code> value will trigger an automatically generated signature Id.
*/
public void setPackageSignatureId(String packageSignatureId) { public void setPackageSignatureId(String packageSignatureId) {
this.packageSignatureId = nvl(packageSignatureId,"xmldsig-"+UUID.randomUUID()); this.packageSignatureId = nvl(packageSignatureId,"xmldsig-"+UUID.randomUUID());
} }
/**
* @return the url of the timestamp provider (TSP)
*/
public String getTspUrl() { public String getTspUrl() {
return tspUrl; return tspUrl;
} }
/**
* @param tspUrl the url of the timestamp provider (TSP)
*/
public void setTspUrl(String tspUrl) { public void setTspUrl(String tspUrl) {
this.tspUrl = tspUrl; this.tspUrl = tspUrl;
} }
/**
* @return if true, uses timestamp-request/response mimetype,
* if false, timestamp-query/reply mimetype
*/
public boolean isTspOldProtocol() { public boolean isTspOldProtocol() {
return tspOldProtocol; return tspOldProtocol;
} }
/**
* @param tspOldProtocol defines the timestamp-protocol mimetype
* @see {@link #isTspOldProtocol()}
*/
public void setTspOldProtocol(boolean tspOldProtocol) { public void setTspOldProtocol(boolean tspOldProtocol) {
this.tspOldProtocol = tspOldProtocol; this.tspOldProtocol = tspOldProtocol;
} }
/**
* @return the hash algorithm to be used for the timestamp entry.
* Defaults to the hash algorithm of the main entry
*/
public HashAlgorithm getTspDigestAlgo() { public HashAlgorithm getTspDigestAlgo() {
return nvl(tspDigestAlgo,digestAlgo); return nvl(tspDigestAlgo,digestAlgo);
} }
/**
* @param tspDigestAlgo the algorithm to be used for the timestamp entry.
* if <code>null</code>, the hash algorithm of the main entry
*/
public void setTspDigestAlgo(HashAlgorithm tspDigestAlgo) { public void setTspDigestAlgo(HashAlgorithm tspDigestAlgo) {
this.tspDigestAlgo = tspDigestAlgo; this.tspDigestAlgo = tspDigestAlgo;
} }
/**
* @return the proxy url to be used for all communications.
* Currently this affects the timestamp service
*/
public String getProxyUrl() { public String getProxyUrl() {
return proxyUrl; return proxyUrl;
} }
/**
* @param proxyUrl the proxy url to be used for all communications.
* Currently this affects the timestamp service
*/
public void setProxyUrl(String proxyUrl) { public void setProxyUrl(String proxyUrl) {
this.proxyUrl = proxyUrl; this.proxyUrl = proxyUrl;
} }
/**
* @return the timestamp service. Defaults to {@link TSPTimeStampService}
*/
public TimeStampService getTspService() { public TimeStampService getTspService() {
return tspService; return tspService;
} }
/**
* @param tspService the timestamp service
*/
public void setTspService(TimeStampService tspService) { public void setTspService(TimeStampService tspService) {
this.tspService = tspService; this.tspService = tspService;
} }
/**
* @return the user id for the timestamp service - currently only basic authorization is supported
*/
public String getTspUser() { public String getTspUser() {
return tspUser; return tspUser;
} }
/**
* @param tspUser the user id for the timestamp service - currently only basic authorization is supported
*/
public void setTspUser(String tspUser) { public void setTspUser(String tspUser) {
this.tspUser = tspUser; this.tspUser = tspUser;
} }
/**
* @return the password for the timestamp service
*/
public String getTspPass() { public String getTspPass() {
return tspPass; return tspPass;
} }
/**
* @param tspPass the password for the timestamp service
*/
public void setTspPass(String tspPass) { public void setTspPass(String tspPass) {
this.tspPass = tspPass; this.tspPass = tspPass;
} }
/**
* @return the validator for the timestamp service (certificate)
*/
public TimeStampServiceValidator getTspValidator() { public TimeStampServiceValidator getTspValidator() {
return tspValidator; return tspValidator;
} }
/**
* @param tspValidator the validator for the timestamp service (certificate)
*/
public void setTspValidator(TimeStampServiceValidator tspValidator) { public void setTspValidator(TimeStampServiceValidator tspValidator) {
this.tspValidator = tspValidator; this.tspValidator = tspValidator;
} }
/**
* @return the optional revocation data service used for XAdES-C and XAdES-X-L.
* When <code>null</code> the signature will be limited to XAdES-T only.
*/
public RevocationDataService getRevocationDataService() { public RevocationDataService getRevocationDataService() {
return revocationDataService; return revocationDataService;
} }
/**
* @param revocationDataService the optional revocation data service used for XAdES-C and XAdES-X-L.
* When <code>null</code> the signature will be limited to XAdES-T only.
*/
public void setRevocationDataService(RevocationDataService revocationDataService) { public void setRevocationDataService(RevocationDataService revocationDataService) {
this.revocationDataService = revocationDataService; this.revocationDataService = revocationDataService;
} }
/**
* @return hash algorithm used for XAdES. Defaults to the {@link #getDigestAlgo()}
*/
public HashAlgorithm getXadesDigestAlgo() { public HashAlgorithm getXadesDigestAlgo() {
return nvl(xadesDigestAlgo,digestAlgo); return nvl(xadesDigestAlgo,digestAlgo);
} }
/**
* @param xadesDigestAlgo hash algorithm used for XAdES.
* When <code>null</code>, defaults to {@link #getDigestAlgo()}
*/
public void setXadesDigestAlgo(HashAlgorithm xadesDigestAlgo) { public void setXadesDigestAlgo(HashAlgorithm xadesDigestAlgo) {
this.xadesDigestAlgo = xadesDigestAlgo; this.xadesDigestAlgo = xadesDigestAlgo;
} }
/**
* @return the user agent used for http communication (e.g. to the TSP)
*/
public String getUserAgent() { public String getUserAgent() {
return userAgent; return userAgent;
} }
/**
* @param userAgent the user agent used for http communication (e.g. to the TSP)
*/
public void setUserAgent(String userAgent) { public void setUserAgent(String userAgent) {
this.userAgent = userAgent; this.userAgent = userAgent;
} }
/**
* @return the asn.1 object id for the tsp request policy.
* Defaults to <code>1.3.6.1.4.1.13762.3</code>
*/
public String getTspRequestPolicy() { public String getTspRequestPolicy() {
return tspRequestPolicy; return tspRequestPolicy;
} }
/**
* @param tspRequestPolicy the asn.1 object id for the tsp request policy.
*/
public void setTspRequestPolicy(String tspRequestPolicy) { public void setTspRequestPolicy(String tspRequestPolicy) {
this.tspRequestPolicy = tspRequestPolicy; this.tspRequestPolicy = tspRequestPolicy;
} }
/**
* @return true, if the whole certificate chain is included in the signature.
* When false, only the signer cert will be included
*/
public boolean isIncludeEntireCertificateChain() { public boolean isIncludeEntireCertificateChain() {
return includeEntireCertificateChain; return includeEntireCertificateChain;
} }
/**
* @param includeEntireCertificateChain if true, include the whole certificate chain.
* If false, only include the signer cert
*/
public void setIncludeEntireCertificateChain(boolean includeEntireCertificateChain) { public void setIncludeEntireCertificateChain(boolean includeEntireCertificateChain) {
this.includeEntireCertificateChain = includeEntireCertificateChain; this.includeEntireCertificateChain = includeEntireCertificateChain;
} }
/**
* @return if true, issuer serial number is included
*/
public boolean isIncludeIssuerSerial() { public boolean isIncludeIssuerSerial() {
return includeIssuerSerial; return includeIssuerSerial;
} }
/**
* @param includeIssuerSerial if true, issuer serial number is included
*/
public void setIncludeIssuerSerial(boolean includeIssuerSerial) { public void setIncludeIssuerSerial(boolean includeIssuerSerial) {
this.includeIssuerSerial = includeIssuerSerial; this.includeIssuerSerial = includeIssuerSerial;
} }
/**
* @return if true, the key value of the public key (certificate) is included
*/
public boolean isIncludeKeyValue() { public boolean isIncludeKeyValue() {
return includeKeyValue; return includeKeyValue;
} }
/**
* @param includeKeyValue if true, the key value of the public key (certificate) is included
*/
public void setIncludeKeyValue(boolean includeKeyValue) { public void setIncludeKeyValue(boolean includeKeyValue) {
this.includeKeyValue = includeKeyValue; this.includeKeyValue = includeKeyValue;
} }
/**
* @return the xades role element. If <code>null</code> the claimed role element is omitted.
* Defaults to <code>null</code>
*/
public String getXadesRole() { public String getXadesRole() {
return xadesRole; return xadesRole;
} }
/**
* @param xadesRole the xades role element. If <code>null</code> the claimed role element is omitted.
*/
public void setXadesRole(String xadesRole) { public void setXadesRole(String xadesRole) {
this.xadesRole = xadesRole; this.xadesRole = xadesRole;
} }
/**
* @return the Id for the XAdES SignedProperties element.
* Defaults to <code>idSignedProperties</code>
*/
public String getXadesSignatureId() { public String getXadesSignatureId() {
return xadesSignatureId; return nvl(xadesSignatureId, "idSignedProperties");
} }
/**
* @param xadesSignatureId the Id for the XAdES SignedProperties element.
* When <code>null</code> defaults to <code>idSignedProperties</code>
*/
public void setXadesSignatureId(String xadesSignatureId) { public void setXadesSignatureId(String xadesSignatureId) {
this.xadesSignatureId = xadesSignatureId; this.xadesSignatureId = xadesSignatureId;
} }
/**
* @return when true, include the policy-implied block.
* Defaults to <code>true</code>
*/
public boolean isXadesSignaturePolicyImplied() { public boolean isXadesSignaturePolicyImplied() {
return xadesSignaturePolicyImplied; return xadesSignaturePolicyImplied;
} }
/**
* @param xadesSignaturePolicyImplied when true, include the policy-implied block
*/
public void setXadesSignaturePolicyImplied(boolean xadesSignaturePolicyImplied) { public void setXadesSignaturePolicyImplied(boolean xadesSignaturePolicyImplied) {
this.xadesSignaturePolicyImplied = xadesSignaturePolicyImplied; this.xadesSignaturePolicyImplied = xadesSignaturePolicyImplied;
} }
/**
* 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.
*
* @return when true, the issuer DN is used instead of the issuer X500 principal
*/
public boolean isXadesIssuerNameNoReverseOrder() { public boolean isXadesIssuerNameNoReverseOrder() {
return xadesIssuerNameNoReverseOrder; return xadesIssuerNameNoReverseOrder;
} }
/**
* @param xadesIssuerNameNoReverseOrder when true, the issuer DN instead of the issuer X500 prinicpal is used
*/
public void setXadesIssuerNameNoReverseOrder(boolean xadesIssuerNameNoReverseOrder) { public void setXadesIssuerNameNoReverseOrder(boolean xadesIssuerNameNoReverseOrder) {
this.xadesIssuerNameNoReverseOrder = xadesIssuerNameNoReverseOrder; this.xadesIssuerNameNoReverseOrder = xadesIssuerNameNoReverseOrder;
} }
/**
* @return the event listener which is active while xml structure for
* the signature is created.
* Defaults to {@link SignatureMarshalListener}
*/
public EventListener getSignatureMarshalListener() { public EventListener getSignatureMarshalListener() {
return signatureMarshalListener; return signatureMarshalListener;
} }
/**
* @param signatureMarshalListener the event listener watching the xml structure
* generation for the signature
*/
public void setSignatureMarshalListener(EventListener signatureMarshalListener) { public void setSignatureMarshalListener(EventListener signatureMarshalListener) {
this.signatureMarshalListener = signatureMarshalListener; this.signatureMarshalListener = signatureMarshalListener;
} }
/**
* @return the map of namespace uri (key) to prefix (value)
*/
public Map<String, String> getNamespacePrefixes() { public Map<String, String> getNamespacePrefixes() {
return namespacePrefixes; return namespacePrefixes;
} }
/**
* @param namespacePrefixes the map of namespace uri (key) to prefix (value)
*/
public void setNamespacePrefixes(Map<String, String> namespacePrefixes) { public void setNamespacePrefixes(Map<String, String> namespacePrefixes) {
this.namespacePrefixes = namespacePrefixes; this.namespacePrefixes = namespacePrefixes;
} }
/**
* helper method for null/default value handling
* @param value
* @param defaultValue
* @return if value is not null, return value otherwise defaultValue
*/
protected static <T> T nvl(T value, T defaultValue) { protected static <T> T nvl(T value, T defaultValue) {
return value == null ? defaultValue : value; return value == null ? defaultValue : value;
} }
/**
* Each digest method has its own IV (initial vector)
*
* @return the IV depending on the main digest method
*/
public byte[] getHashMagic() { public byte[] getHashMagic() {
// see https://www.ietf.org/rfc/rfc3110.txt // see https://www.ietf.org/rfc/rfc3110.txt
// RSA/SHA1 SIG Resource Records // RSA/SHA1 SIG Resource Records
@ -545,23 +760,34 @@ public class SignatureConfig {
return result; return result;
} }
public String getSignatureMethod() { /**
* @return the uri for the signature method, i.e. currently only rsa is
* supported, so it's the rsa variant of the main digest
*/
public String getSignatureMethodUri() {
switch (getDigestAlgo()) { switch (getDigestAlgo()) {
case sha1: return org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1; case sha1: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;
case sha224: return org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA224; case sha224: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA224;
case sha256: return org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256; case sha256: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256;
case sha384: return org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA384; case sha384: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA384;
case sha512: return org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512; case sha512: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512;
case ripemd160: return org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_RIPEMD160; case ripemd160: return XMLSignature.ALGO_ID_SIGNATURE_RSA_RIPEMD160;
default: throw new EncryptedDocumentException("Hash algorithm " default: throw new EncryptedDocumentException("Hash algorithm "
+getDigestAlgo()+" not supported for signing."); +getDigestAlgo()+" not supported for signing.");
} }
} }
/**
* @return the uri for the main digest
*/
public String getDigestMethodUri() { public String getDigestMethodUri() {
return getDigestMethodUri(getDigestAlgo()); return getDigestMethodUri(getDigestAlgo());
} }
/**
* @param digestAlgo the digest algo, currently only sha* and ripemd160 is supported
* @return the uri for the given digest
*/
public static String getDigestMethodUri(HashAlgorithm digestAlgo) { public static String getDigestMethodUri(HashAlgorithm digestAlgo) {
switch (digestAlgo) { switch (digestAlgo) {
case sha1: return DigestMethod.SHA1; case sha1: return DigestMethod.SHA1;
@ -575,10 +801,16 @@ public class SignatureConfig {
} }
} }
/**
* @param signatureFactory the xml signature factory, saved as thread-local
*/
public void setSignatureFactory(XMLSignatureFactory signatureFactory) { public void setSignatureFactory(XMLSignatureFactory signatureFactory) {
this.signatureFactory.set(signatureFactory); this.signatureFactory.set(signatureFactory);
} }
/**
* @return the xml signature factory (thread-local)
*/
public XMLSignatureFactory getSignatureFactory() { public XMLSignatureFactory getSignatureFactory() {
XMLSignatureFactory sigFac = signatureFactory.get(); XMLSignatureFactory sigFac = signatureFactory.get();
if (sigFac == null) { if (sigFac == null) {
@ -588,10 +820,16 @@ public class SignatureConfig {
return sigFac; return sigFac;
} }
/**
* @param keyInfoFactory the key factory, saved as thread-local
*/
public void setKeyInfoFactory(KeyInfoFactory keyInfoFactory) { public void setKeyInfoFactory(KeyInfoFactory keyInfoFactory) {
this.keyInfoFactory.set(keyInfoFactory); this.keyInfoFactory.set(keyInfoFactory);
} }
/**
* @return the key factory (thread-local)
*/
public KeyInfoFactory getKeyInfoFactory() { public KeyInfoFactory getKeyInfoFactory() {
KeyInfoFactory keyFac = keyInfoFactory.get(); KeyInfoFactory keyFac = keyInfoFactory.get();
if (keyFac == null) { if (keyFac == null) {
@ -601,7 +839,19 @@ public class SignatureConfig {
return keyFac; return keyFac;
} }
// currently classes are linked to Apache Santuario, so this might be superfluous /**
* 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 getProvider() { public Provider getProvider() {
Provider prov = provider.get(); Provider prov = provider.get();
if (prov == null) { if (prov == null) {
@ -628,6 +878,20 @@ public class SignatureConfig {
return prov; return prov;
} }
/**
* @return the cannonicalization method for XAdES-XL signing.
* Defaults to <code>EXCLUSIVE</code>
* @see {@link CanonicalizationMethod}
*/
public String getXadesCanonicalizationMethod() {
return xadesCanonicalizationMethod;
}
/**
* @param xadesCanonicalizationMethod the cannonicalization method for XAdES-XL signing
* @see {@link CanonicalizationMethod}
*/
public void setXadesCanonicalizationMethod(String xadesCanonicalizationMethod) {
this.xadesCanonicalizationMethod = xadesCanonicalizationMethod;
}
} }

View File

@ -179,23 +179,42 @@ public class SignatureInfo implements SignatureConfigurable {
this.signaturePart = signaturePart; this.signaturePart = signaturePart;
} }
/**
* @return the package part containing the signature
*/
public PackagePart getPackagePart() { public PackagePart getPackagePart() {
return signaturePart; return signaturePart;
} }
/**
* @return the signer certificate
*/
public X509Certificate getSigner() { public X509Certificate getSigner() {
return signer; return signer;
} }
/**
* @return the certificate chain of the signer
*/
public List<X509Certificate> getCertChain() { public List<X509Certificate> getCertChain() {
return certChain; return certChain;
} }
/**
* Helper method for examining the xml signature
*
* @return the xml signature document
* @throws IOException if the xml signature doesn't exist or can't be read
* @throws XmlException if the xml signature is malformed
*/
public SignatureDocument getSignatureDocument() throws IOException, XmlException { public SignatureDocument getSignatureDocument() throws IOException, XmlException {
// TODO: check for XXE // TODO: check for XXE
return SignatureDocument.Factory.parse(signaturePart.getInputStream()); return SignatureDocument.Factory.parse(signaturePart.getInputStream());
} }
/**
* @return true, when the xml signature is valid, false otherwise
*/
public boolean validate() { public boolean validate() {
KeyInfoKeySelector keySelector = new KeyInfoKeySelector(); KeyInfoKeySelector keySelector = new KeyInfoKeySelector();
try { try {
@ -227,18 +246,30 @@ public class SignatureInfo implements SignatureConfigurable {
} }
} }
/**
* Constructor initializes xml signature environment, if it hasn't been initialized before
*/
public SignatureInfo() { public SignatureInfo() {
initXmlProvider(); initXmlProvider();
} }
/**
* @return the signature config
*/
public SignatureConfig getSignatureConfig() { public SignatureConfig getSignatureConfig() {
return signatureConfig; return signatureConfig;
} }
/**
* @param signatureConfig the signature config, needs to be set before a SignatureInfo object is used
*/
public void setSignatureConfig(SignatureConfig signatureConfig) { public void setSignatureConfig(SignatureConfig signatureConfig) {
this.signatureConfig = signatureConfig; this.signatureConfig = signatureConfig;
} }
/**
* @return true, if first signature part is valid
*/
public boolean verifySignature() { public boolean verifySignature() {
// http://www.oracle.com/technetwork/articles/javase/dig-signature-api-140772.html // http://www.oracle.com/technetwork/articles/javase/dig-signature-api-140772.html
for (SignaturePart sp : getSignatureParts()){ for (SignaturePart sp : getSignatureParts()){
@ -248,6 +279,12 @@ public class SignatureInfo implements SignatureConfigurable {
return false; return false;
} }
/**
* add the xml signature to the document
*
* @throws XMLSignatureException
* @throws MarshalException
*/
public void confirmSignature() throws XMLSignatureException, MarshalException { public void confirmSignature() throws XMLSignatureException, MarshalException {
Document document = DocumentHelper.createDocument(); Document document = DocumentHelper.createDocument();
@ -261,6 +298,13 @@ public class SignatureInfo implements SignatureConfigurable {
postSign(document, signatureValue); postSign(document, signatureValue);
} }
/**
* Sign (encrypt) the digest with the private key.
* Currently only rsa is supported.
*
* @param digest the hashed input
* @return the encrypted hash
*/
public byte[] signDigest(byte digest[]) { public byte[] signDigest(byte digest[]) {
Cipher cipher = CryptoFunctions.getCipher(signatureConfig.getKey(), CipherAlgorithm.rsa Cipher cipher = CryptoFunctions.getCipher(signatureConfig.getKey(), CipherAlgorithm.rsa
, ChainingMode.ecb, null, Cipher.ENCRYPT_MODE, "PKCS1Padding"); , ChainingMode.ecb, null, Cipher.ENCRYPT_MODE, "PKCS1Padding");
@ -277,6 +321,10 @@ public class SignatureInfo implements SignatureConfigurable {
} }
} }
/**
* @return a signature part for each signature document.
* the parts can be validated independently.
*/
public Iterable<SignaturePart> getSignatureParts() { public Iterable<SignaturePart> getSignatureParts() {
signatureConfig.init(true); signatureConfig.init(true);
return new Iterable<SignaturePart>() { return new Iterable<SignaturePart>() {
@ -324,6 +372,9 @@ public class SignatureInfo implements SignatureConfigurable {
}; };
} }
/**
* Initialize the xml signing environment and the bouncycastle provider
*/
protected static synchronized void initXmlProvider() { protected static synchronized void initXmlProvider() {
if (isInitialized) return; if (isInitialized) return;
isInitialized = true; isInitialized = true;
@ -401,7 +452,7 @@ public class SignatureInfo implements SignatureConfigurable {
SignedInfo signedInfo; SignedInfo signedInfo;
try { try {
SignatureMethod signatureMethod = signatureFactory.newSignatureMethod SignatureMethod signatureMethod = signatureFactory.newSignatureMethod
(signatureConfig.getSignatureMethod(), null); (signatureConfig.getSignatureMethodUri(), null);
CanonicalizationMethod canonicalizationMethod = signatureFactory CanonicalizationMethod canonicalizationMethod = signatureFactory
.newCanonicalizationMethod(signatureConfig.getCanonicalizationMethod(), .newCanonicalizationMethod(signatureConfig.getCanonicalizationMethod(),
(C14NMethodParameterSpec) null); (C14NMethodParameterSpec) null);
@ -513,6 +564,12 @@ public class SignatureInfo implements SignatureConfigurable {
writeDocument(document); writeDocument(document);
} }
/**
* Write XML signature into the OPC package
*
* @param document the xml signature document
* @throws MarshalException
*/
protected void writeDocument(Document document) throws MarshalException { protected void writeDocument(Document document) throws MarshalException {
XmlOptions xo = new XmlOptions(); XmlOptions xo = new XmlOptions();
Map<String,String> namespaceMap = new HashMap<String,String>(); Map<String,String> namespaceMap = new HashMap<String,String>();
@ -569,6 +626,12 @@ public class SignatureInfo implements SignatureConfigurable {
sigsPart.addRelationship(sigPartName, TargetMode.INTERNAL, PackageRelationshipTypes.DIGITAL_SIGNATURE); sigsPart.addRelationship(sigPartName, TargetMode.INTERNAL, PackageRelationshipTypes.DIGITAL_SIGNATURE);
} }
/**
* Helper method for null lists, which are converted to empty lists
*
* @param other the reference to wrap, if null
* @return if other is null, an empty lists is returned, otherwise other is returned
*/
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private static <T> List<T> safe(List<T> other) { private static <T> List<T> safe(List<T> other) {
return other == null ? Collections.EMPTY_LIST : other; return other == null ? Collections.EMPTY_LIST : other;

View File

@ -56,7 +56,6 @@ public abstract class SignatureFacet implements SignatureConfigurable {
public static final String XADES_141_NS = "http://uri.etsi.org/01903/v1.4.1#"; public static final String XADES_141_NS = "http://uri.etsi.org/01903/v1.4.1#";
protected SignatureConfig signatureConfig; protected SignatureConfig signatureConfig;
protected ThreadLocal<XMLSignatureFactory> signatureFactory;
public void setSignatureConfig(SignatureConfig signatureConfig) { public void setSignatureConfig(SignatureConfig signatureConfig) {
this.signatureConfig = signatureConfig; this.signatureConfig = signatureConfig;

View File

@ -42,7 +42,6 @@ import java.util.List;
import java.util.UUID; import java.util.UUID;
import javax.xml.crypto.MarshalException; import javax.xml.crypto.MarshalException;
import javax.xml.crypto.dsig.CanonicalizationMethod;
import org.apache.poi.poifs.crypt.dsig.services.RevocationData; import org.apache.poi.poifs.crypt.dsig.services.RevocationData;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
@ -105,8 +104,6 @@ public class XAdESXLSignatureFacet extends SignatureFacet {
private static final POILogger LOG = POILogFactory.getLogger(XAdESXLSignatureFacet.class); private static final POILogger LOG = POILogFactory.getLogger(XAdESXLSignatureFacet.class);
private String c14nAlgoId = CanonicalizationMethod.EXCLUSIVE;
private final CertificateFactory certificateFactory; private final CertificateFactory certificateFactory;
public XAdESXLSignatureFacet() { public XAdESXLSignatureFacet() {
@ -117,10 +114,6 @@ public class XAdESXLSignatureFacet extends SignatureFacet {
} }
} }
public void setCanonicalizerAlgorithm(String c14nAlgoId) {
this.c14nAlgoId = c14nAlgoId;
}
@Override @Override
public void postSign(Document document) throws MarshalException { public void postSign(Document document) throws MarshalException {
LOG.log(POILogger.DEBUG, "XAdES-X-L post sign phase"); LOG.log(POILogger.DEBUG, "XAdES-X-L post sign phase");
@ -351,7 +344,7 @@ public class XAdESXLSignatureFacet extends SignatureFacet {
private XAdESTimeStampType createXAdESTimeStamp( private XAdESTimeStampType createXAdESTimeStamp(
List<Node> nodeList, List<Node> nodeList,
RevocationData revocationData) { RevocationData revocationData) {
byte[] c14nSignatureValueElement = getC14nValue(nodeList, c14nAlgoId); byte[] c14nSignatureValueElement = getC14nValue(nodeList, signatureConfig.getXadesCanonicalizationMethod());
return createXAdESTimeStamp(c14nSignatureValueElement, revocationData); return createXAdESTimeStamp(c14nSignatureValueElement, revocationData);
} }
@ -370,7 +363,7 @@ public class XAdESXLSignatureFacet extends SignatureFacet {
XAdESTimeStampType xadesTimeStamp = XAdESTimeStampType.Factory.newInstance(); XAdESTimeStampType xadesTimeStamp = XAdESTimeStampType.Factory.newInstance();
xadesTimeStamp.setId("time-stamp-" + UUID.randomUUID().toString()); xadesTimeStamp.setId("time-stamp-" + UUID.randomUUID().toString());
CanonicalizationMethodType c14nMethod = xadesTimeStamp.addNewCanonicalizationMethod(); CanonicalizationMethodType c14nMethod = xadesTimeStamp.addNewCanonicalizationMethod();
c14nMethod.setAlgorithm(c14nAlgoId); c14nMethod.setAlgorithm(signatureConfig.getXadesCanonicalizationMethod());
// embed the time-stamp // embed the time-stamp
EncapsulatedPKIDataType encapsulatedTimeStamp = xadesTimeStamp.addNewEncapsulatedTimeStamp(); EncapsulatedPKIDataType encapsulatedTimeStamp = xadesTimeStamp.addNewEncapsulatedTimeStamp();