diff --git a/components/net/sf/briar/crypto/ErasableKeyImpl.java b/components/net/sf/briar/crypto/ErasableKeyImpl.java
index 5267e394d5b65feff23bf353e89189a1599695c8..b50c424797e1938d2bf4320670f2ec4cdc888cfd 100644
--- a/components/net/sf/briar/crypto/ErasableKeyImpl.java
+++ b/components/net/sf/briar/crypto/ErasableKeyImpl.java
@@ -1,6 +1,7 @@
 package net.sf.briar.crypto;
 
-import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collection;
 
 import net.sf.briar.api.crypto.ErasableKey;
 import net.sf.briar.util.ByteUtils;
@@ -11,6 +12,8 @@ class ErasableKeyImpl implements ErasableKey {
 
 	private final byte[] key;
 	private final String algorithm;
+
+	private Collection<byte[]> copies = null;
 	private boolean erased = false;
 
 	ErasableKeyImpl(byte[] key, String algorithm) {
@@ -26,6 +29,8 @@ class ErasableKeyImpl implements ErasableKey {
 		if(erased) throw new IllegalStateException();
 		byte[] b = new byte[key.length];
 		System.arraycopy(key, 0, b, 0, key.length);
+		if(copies == null) copies = new ArrayList<byte[]>();
+		copies.add(b);
 		return b;
 	}
 
@@ -40,21 +45,7 @@ class ErasableKeyImpl implements ErasableKey {
 	public void erase() {
 		if(erased) throw new IllegalStateException();
 		ByteUtils.erase(key);
+		if(copies != null) for(byte[] b : copies) ByteUtils.erase(b);
 		erased = true;
 	}
-
-	@Override
-	public int hashCode() {
-		// Not good, but the array can't be used because it's mutable
-		return algorithm.hashCode();
-	}
-
-	@Override
-	public boolean equals(Object o) {
-		if(o instanceof ErasableKeyImpl) {
-			ErasableKeyImpl e = (ErasableKeyImpl) o;
-			return algorithm.equals(e.algorithm) && Arrays.equals(key, e.key);
-		}
-		return false;
-	}
 }
diff --git a/test/build.xml b/test/build.xml
index 6b5083f53ba8ed8207ea2d93dc9656ba1e31b7ae..2644843b78feab0845136cee55befdd64c8bc34b 100644
--- a/test/build.xml
+++ b/test/build.xml
@@ -17,6 +17,7 @@
 			<test name='net.sf.briar.LockFairnessTest'/>
 			<test name='net.sf.briar.ProtocolIntegrationTest'/>
 			<test name='net.sf.briar.crypto.CounterModeTest'/>
+			<test name='net.sf.briar.crypto.ErasableKeyTest'/>
 			<test name='net.sf.briar.crypto.KeyDerivationTest'/>
 			<test name='net.sf.briar.db.BasicH2Test'/>
 			<test name='net.sf.briar.db.DatabaseCleanerImplTest'/>
diff --git a/test/net/sf/briar/crypto/ErasableKeyTest.java b/test/net/sf/briar/crypto/ErasableKeyTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..72f78b19534f9783397d8dd41bc1c38abdeeff22
--- /dev/null
+++ b/test/net/sf/briar/crypto/ErasableKeyTest.java
@@ -0,0 +1,79 @@
+package net.sf.briar.crypto;
+
+import static org.junit.Assert.assertArrayEquals;
+
+import java.util.Random;
+
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.spec.IvParameterSpec;
+
+import junit.framework.TestCase;
+import net.sf.briar.api.crypto.ErasableKey;
+
+import org.junit.Test;
+
+public class ErasableKeyTest extends TestCase {
+
+	private static final String CIPHER = "AES";
+	private static final String CIPHER_MODE = "AES/CTR/NoPadding";
+	private static final int IV_BYTES = 16; // 128 bits
+	private static final int KEY_BYTES = 32; // 256 bits
+	private static final String MAC = "HMacSHA256";
+
+	private final Random random = new Random();
+
+	@Test
+	public void testCopiesAreErased() {
+		byte[] master = new byte[KEY_BYTES];
+		random.nextBytes(master);
+		ErasableKey k = new ErasableKeyImpl(master, CIPHER);
+		byte[] copy = k.getEncoded();
+		assertArrayEquals(master, copy);
+		k.erase();
+		byte[] blank = new byte[KEY_BYTES];
+		assertArrayEquals(blank, master);
+		assertArrayEquals(blank, copy);
+	}
+
+	@Test
+	public void testErasureDoesNotAffectCipher() throws Exception {
+		byte[] key = new byte[KEY_BYTES];
+		random.nextBytes(key);
+		ErasableKey k = new ErasableKeyImpl(key, CIPHER);
+		Cipher c = Cipher.getInstance(CIPHER_MODE);
+		IvParameterSpec iv = new IvParameterSpec(new byte[IV_BYTES]);
+		c.init(Cipher.ENCRYPT_MODE, k, iv);
+		// Encrypt a blank plaintext
+		byte[] plaintext = new byte[123];
+		byte[] ciphertext = c.doFinal(plaintext);
+		// Erase the key and encrypt again - erase() was called after doFinal()
+		k.erase();
+		byte[] ciphertext1 = c.doFinal(plaintext);
+		// Encrypt again - this time erase() was called before doFinal()
+		byte[] ciphertext2 = c.doFinal(plaintext);
+		// The ciphertexts should match
+		assertArrayEquals(ciphertext, ciphertext1);
+		assertArrayEquals(ciphertext, ciphertext2);
+	}
+
+	@Test
+	public void testErasureDoesNotAffectMac() throws Exception {
+		byte[] key = new byte[KEY_BYTES];
+		random.nextBytes(key);
+		ErasableKey k = new ErasableKeyImpl(key, CIPHER);
+		Mac m = Mac.getInstance(MAC);
+		m.init(k);
+		// Authenticate a blank plaintext
+		byte[] plaintext = new byte[123];
+		byte[] mac = m.doFinal(plaintext);
+		// Erase the key and authenticate again
+		k.erase();
+		byte[] mac1 = m.doFinal(plaintext);
+		// Authenticate again
+		byte[] mac2 = m.doFinal(plaintext);
+		// The MACs should match
+		assertArrayEquals(mac, mac1);
+		assertArrayEquals(mac, mac2);
+	}
+}