package org.limewire.security;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.limewire.security.SecureMessage.Status;
/**
* An abstract base class to verify a {@link SecureMessage}. The
* callback, a {@link SecureMessageCallback} receives notification if the
* message is verified.
*/
public abstract class Verifier implements Runnable {
private static final Log LOG = LogFactory.getLog(Verifier.class);
private SecureMessage message;
private SecureMessageCallback callback;
public Verifier(SecureMessage message, SecureMessageCallback callback) {
this.message = message;
this.callback = callback;
}
/**
* Returns the <code>PublicKey</code> that is used to verify the signature.
*/
public abstract PublicKey getPublicKey();
/**
* Returns the algorithm of the signature.
*/
public abstract String getAlgorithm();
/**
* Returns the <code>SecureMessage</code>.
*/
public SecureMessage getSecureMessage() {
return message;
}
/**
* Returns the <code>SecureMessageCallback</code>.
*/
public SecureMessageCallback getSecureMessageCallback() {
return callback;
}
/** Does the verification. */
public void run() {
SecureMessage message = getSecureMessage();
SecureMessageCallback callback = getSecureMessageCallback();
PublicKey pubKey = getPublicKey();
String algorithm = getAlgorithm();
if(pubKey == null) {
LOG.warn("Cannot verify message without a public key.");
message.setSecureStatus(Status.INSECURE);
callback.handleSecureMessage(message, false);
return;
}
byte[] signature = message.getSecureSignature();
if(signature == null) {
LOG.warn("Cannot verify message without a signature.");
message.setSecureStatus(Status.INSECURE);
callback.handleSecureMessage(message, false);
return;
}
try {
Signature verifier = Signature.getInstance(algorithm);
verifier.initVerify(pubKey);
message.updateSignatureWithSecuredBytes(verifier);
if(verifier.verify(signature)) {
message.setSecureStatus(Status.SECURE);
callback.handleSecureMessage(message, true);
return;
}
// fallthrough on not secure & failures to set failed.
} catch (NoSuchAlgorithmException nsax) {
LOG.error("No alg.", nsax);
} catch (InvalidKeyException ikx) {
LOG.error("Invalid key", ikx);
} catch (SignatureException sx) {
LOG.error("Bad sig", sx);
} catch (ClassCastException ccx) {
LOG.error("bad cast", ccx);
}
message.setSecureStatus(Status.FAILED);
callback.handleSecureMessage(message, false);
}
}