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:
parent
bc400ad94a
commit
a16db327fd
@ -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) {
|
||||||
@ -627,7 +877,21 @@ 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user