package com.limegroup.gnutella.messages; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Signature; import java.security.SignatureException; import java.util.Random; import junit.framework.Test; import com.limegroup.gnutella.util.BaseTestCase; public class SecureMessageVerifierTest extends BaseTestCase { private static PublicKey PUBLIC_KEY; private static PrivateKey PRIVATE_KEY; public SecureMessageVerifierTest(String name) { super(name); } public static Test suite() { return buildTestSuite(SecureMessageVerifierTest.class); } public static void main(String argv[]) { junit.textui.TestRunner.run(suite()); } /** gen some fake private/public keys so we can create messages easily. */ public static void globalSetUp() throws Exception { KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA", "SUN"); SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN"); keyGen.initialize(512, random); KeyPair pair = keyGen.generateKeyPair(); PUBLIC_KEY = pair.getPublic(); PRIVATE_KEY = pair.getPrivate(); } /** Makes sure all stuff we need to work works. */ public void testSecureUpdateMessage() throws Exception { StaticMessages.initialize(); QueryReply reply = StaticMessages.getUpdateReply(); assertTrue(reply.hasSecureData()); SecureMessageVerifier verifier = new SecureMessageVerifier(); StubSecureMessageCallback callback = new StubSecureMessageCallback(); verifier.verify(reply, callback); callback.waitForReply(); assertTrue(callback.getPassed()); assertSame(reply, callback.getSecureMessage()); assertEquals(SecureMessage.SECURE, reply.getSecureStatus()); } /** Tests a secure message we create ourselves. */ public void testSecuring() throws Exception { SecureMessage m1 = new StubSecureMessage(); SecureMessageVerifier vf = new SimpleVerifier(); StubSecureMessageCallback cb = new StubSecureMessageCallback(); vf.verify(m1, cb); cb.waitForReply(); assertEquals(m1, cb.getSecureMessage()); assertEquals(true, cb.getPassed()); assertEquals(SecureMessage.SECURE, m1.getSecureStatus()); } /** Tests a bad message doesn't secure. */ public void testFails() throws Exception { SecureMessage m1 = new StubSecureMessage() { public void updateSignatureWithSecuredBytes(Signature signature) throws SignatureException { super.updateSignatureWithSecuredBytes(signature); signature.update(new byte[100]); } }; SecureMessageVerifier vf = new SimpleVerifier(); StubSecureMessageCallback cb = new StubSecureMessageCallback(); vf.verify(m1, cb); cb.waitForReply(); assertEquals(m1, cb.getSecureMessage()); assertEquals(false, cb.getPassed()); assertEquals(SecureMessage.FAILED, m1.getSecureStatus()); } /** Tests a message with no signature. */ public void testNoSignature() throws Exception { SecureMessage m1 = new SecureMessageAdapter(); SecureMessageVerifier vf = new SimpleVerifier(); StubSecureMessageCallback cb = new StubSecureMessageCallback(); vf.verify(m1, cb); cb.waitForReply(); assertEquals(m1, cb.getSecureMessage()); assertEquals(false, cb.getPassed()); assertEquals(SecureMessage.INSECURE, m1.getSecureStatus()); } /** Tests attempting to secure with no public key. */ public void testNoPublicKey() throws Exception { SecureMessage m1 = new StubSecureMessage(); SecureMessageVerifier vf = new SecureMessageVerifier() { protected PublicKey createPublicKey() { return null; } }; StubSecureMessageCallback cb = new StubSecureMessageCallback(); vf.verify(m1, cb); cb.waitForReply(); assertEquals(m1, cb.getSecureMessage()); assertEquals(false, cb.getPassed()); assertEquals(SecureMessage.INSECURE, m1.getSecureStatus()); } /** Tests attempting to secure with a different signature. */ public void testWrongSignature() throws Exception { SecureMessage m1 = new StubSecureMessage() { public byte[] getSecureSignature() { byte[] sig = super.getSecureSignature(); sig[0]++; return sig; } }; SecureMessageVerifier vf = new SimpleVerifier(); StubSecureMessageCallback cb = new StubSecureMessageCallback(); vf.verify(m1, cb); cb.waitForReply(); assertEquals(m1, cb.getSecureMessage()); assertEquals(false, cb.getPassed()); assertEquals(SecureMessage.FAILED, m1.getSecureStatus()); } /** Verifier that'll use our fake public key. */ private static class SimpleVerifier extends SecureMessageVerifier { protected PublicKey createPublicKey() { return PUBLIC_KEY; } } /** Simple SecureMessage. */ private static class StubSecureMessage extends SecureMessageAdapter { private byte[] data; private static Random random = new Random(); private byte[] signature; StubSecureMessage() throws Exception { data = new byte[1024]; random.nextBytes(data); Signature sig = Signature.getInstance("SHA1withDSA"); sig.initSign(PRIVATE_KEY); sig.update(data); signature = sig.sign(); } public byte[] getSecureSignature() { return signature; } public void updateSignatureWithSecuredBytes(Signature signature) throws SignatureException { signature.update(data); } } /** An Adapter so we can do different stuff easily if we want. */ private static class SecureMessageAdapter implements SecureMessage { private int secureStatus = -10; public byte[] getSecureSignature() { return null; } public int getSecureStatus() { return secureStatus; } public void setSecureStatus(int secureStatus) { this.secureStatus = secureStatus; } public void updateSignatureWithSecuredBytes(Signature signature) throws SignatureException { } } }