/*
* Created on Oct 15, 2004
*
*/
package hk.hku.cecid.ebms.pkg;
import hk.hku.cecid.ebms.pkg.pki.CertResolver;
import java.io.IOException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.Iterator;
import javax.net.ssl.X509TrustManager;
import javax.xml.soap.SOAPException;
/**
* @author Donahue Sze
*
*/
public class SignatureHandler {
private static Object signLock = new Object();
private static Object verifyLock = new Object();
private EbxmlMessage message;
private String username;
private char[] password;
private String keyStoreLocation;
private PublicKey publicKey;
private CertResolver certResolver;
public SignatureHandler(EbxmlMessage message, String username, char[] password, String keyStoreLocation, X509TrustManager trustman) throws SignatureException {
this.message = message;
this.username = username;
this.password = password;
this.keyStoreLocation = keyStoreLocation;
try {
certResolver = new KeyStoreCertResolver(trustman);
} catch (Exception e) {
throw new SignatureException("Unable to create signature handler",
e);
}
}
public SignatureHandler(EbxmlMessage message, final Certificate cert) throws SignatureException {
this.message = message;
this.certResolver = new CertResolver() {
public Certificate[] resolve(Object obj) {
return new Certificate[] { cert };
}
};
}
/**
* Sign this <code>EbxmlMessage</code> with XML signature
*
* @throws SOAPException
* @throws SignatureException
*/
public void sign() throws SOAPException, SignatureException {
sign(null);
}
/**
* Sign this <code>EbxmlMessage</code> with XML signature
*
* @param algorithm
* Specifies the algorithm used to generate the digital
* signature. Refer to <a href=
* "http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/#sec-AlgID">
* XML-Signature Syntax and Processing: Algorithm Identifiers and
* Implementation Requirements </a> for details.
* @throws SOAPException
* @throws SignatureException
*/
public void sign(String algorithm) throws SOAPException, SignatureException {
sign(null, null, false);
}
/**
* Sign this <code>EbxmlMessage</code> with XML signature
*
* @param algorithm
* Specifies the algorithm used to generate the digital
* signature. Refer to <a href=
* "http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/#sec-AlgID">
* XML-Signature Syntax and Processing: Algorithm Identifiers and
* Implementation Requirements </a> for details.
* @param signEnvelopeOnly
* whether it should sign the envelope only, without signing the
* payload.
* @param digestAlgorithm
* Description of the Parameter
* @throws SOAPException
* @throws SignatureException
*/
public void sign(String algorithm, String digestAlgorithm,
boolean signEnvelopeOnly) throws SOAPException, SignatureException {
synchronized (signLock) {
Signature signature = Signature.newInstance(message);
signature.sign(username, password, keyStoreLocation, algorithm,
digestAlgorithm, signEnvelopeOnly);
message.getHeaderContainer().addExtensionElement(signature);
}
}
/**
* Verify the message using trusted keystore.
*
* @return true if the digital signature is valid; false otherwise.
* @throws SOAPException
* @throws SignatureException
*/
public boolean verify() throws SOAPException, SignatureException {
synchronized (verifyLock) {
boolean result = true;
Iterator i = message.getHeaderContainer().getSignatures();
if (i.hasNext()) {
while (i.hasNext()) {
Signature sig = (Signature) i.next();
Signature signature = Signature.newInstance(message,
sig.soapEnvelope, sig.getSOAPElement());
result = result
&& signature.verify(password, keyStoreLocation,
certResolver, message.getDatasource());
}
} else {
throw new SignatureException("No <"
+ Signature.NAMESPACE_PREFIX_DS + ":"
+ Signature.ELEMENT_SIGNATURE
+ "> element is found to be verified!");
}
return result;
}
}
public boolean verifyByPublicKey() throws SOAPException, SignatureException {
synchronized (verifyLock) {
boolean result = true;
Iterator i = message.getHeaderContainer().getSignatures();
if (i.hasNext()) {
while (i.hasNext()) {
Signature sig = (Signature) i.next();
Signature signature = Signature.newInstance(message,
sig.soapEnvelope, sig.getSOAPElement());
//result = result && signature.verify(publicKey);
result = result
&& signature.verify(null, null, certResolver,
message.getDatasource());
}
} else {
throw new SignatureException("No <"
+ Signature.NAMESPACE_PREFIX_DS + ":"
+ Signature.ELEMENT_SIGNATURE
+ "> element is found to be verified!");
}
return result;
}
}
private class KeyStoreCertResolver implements CertResolver {
X509TrustManager manager;
/**
* @throws IOException
* @throws CertificateException
* @throws NoSuchAlgorithmException
* @throws KeyStoreException
* @throws NoSuchProviderException
*
*/
public KeyStoreCertResolver(X509TrustManager trustman) throws NoSuchAlgorithmException,
CertificateException, IOException, KeyStoreException,
NoSuchProviderException {
manager = trustman;
}
/*
* (non-Javadoc)
*
* @see hk.hku.cecid.ebms.pkg.pki.CertResolver#resolve(java.lang.Object)
*/
public Certificate[] resolve(Object obj) {
return manager.getAcceptedIssuers();
}
}
}