package org.limewire.security; import java.io.File; import java.security.PublicKey; import java.util.concurrent.ExecutorService; import org.limewire.concurrent.ExecutorsHelper; import com.google.inject.Singleton; /** A class that verifies secure messages sequentially. */ @Singleton public class SecureMessageVerifierImpl implements SecureMessageVerifier { private final ExecutorService QUEUE; /** The public key. */ private PublicKey pubKey; /** The File the public key is stored in. */ private final File keyFile; /** The base32-encoded key */ private final String keyBase32; public SecureMessageVerifierImpl() { this(null, null, null, null); } public SecureMessageVerifierImpl(String name) { this(null, null, null, name); } public SecureMessageVerifierImpl(File keyFile) { this(keyFile, null, null, null); } public SecureMessageVerifierImpl(String keyBase32, String name) { this(null, keyBase32, null, name); } public SecureMessageVerifierImpl(File keyFile, String name) { this(keyFile, null, null, name); } public SecureMessageVerifierImpl(PublicKey pubKey, String name) { this(null, null, pubKey, name); } private SecureMessageVerifierImpl(File keyFile, String keyBase32, PublicKey pubKey, String name) { if (name == null) { QUEUE = ExecutorsHelper.newProcessingQueue("SecureMessageVerifier"); } else { QUEUE = ExecutorsHelper.newProcessingQueue(name + "-SecureMessageVerifier"); } if (pubKey == null && (keyFile == null) == (keyBase32 == null)) throw new IllegalArgumentException("must have only one source of key"); this.pubKey = pubKey; this.keyFile = keyFile; this.keyBase32 = keyBase32; } /* (non-Javadoc) * @see org.limewire.security.SecureMessageVerifier#verify(org.limewire.security.SecureMessage, org.limewire.security.SecureMessageCallback) */ public void verify(SecureMessage sm, SecureMessageCallback smc) { QUEUE.execute(new VerifierImpl(pubKey, "SHA1withDSA", sm, smc)); } /* (non-Javadoc) * @see org.limewire.security.SecureMessageVerifier#verify(java.security.PublicKey, java.lang.String, org.limewire.security.SecureMessage, org.limewire.security.SecureMessageCallback) */ public void verify(PublicKey pubKey, String algorithm, SecureMessage sm, SecureMessageCallback smc) { // To avoid ambiguous results interpret a null pubKey // as an error. A null pubKey would otherwise result // in loading core's secureMessage.key if (pubKey == null) { throw new IllegalArgumentException("PublicKey is null"); } QUEUE.execute(new VerifierImpl(pubKey, algorithm, sm, smc)); } /* (non-Javadoc) * @see org.limewire.security.SecureMessageVerifier#verify(org.limewire.security.Verifier) */ public void verify(Verifier verifier) { QUEUE.execute(verifier); } /** Initializes the public key if one isn't set. */ private void initializePublicKey() { if(pubKey == null) { pubKey = createPublicKey(); } } /** Creates the public key. */ protected PublicKey createPublicKey() { if(getKeyFile() == null && keyBase32 == null) throw new NullPointerException("no key source!!"); // prefer string-based keys if (keyBase32 != null) return SignatureVerifier.readKey(keyBase32, "DSA"); return SignatureVerifier.readKey(getKeyFile(), "DSA"); } /** Gets the file holding the key. */ protected File getKeyFile() { return keyFile; } /** Simple runnable to insert into the ProcessingQueue. */ private class VerifierImpl extends Verifier { private PublicKey pubKey; private String algorithm; VerifierImpl(PublicKey pubKey, String algorithm, SecureMessage message, SecureMessageCallback callback) { super(message, callback); this.pubKey = pubKey; this.algorithm = algorithm; } @Override public String getAlgorithm() { return algorithm; } @Override public PublicKey getPublicKey() { if(pubKey == null) { initializePublicKey(); pubKey = SecureMessageVerifierImpl.this.pubKey; } return pubKey; } } }