diff --git a/briar-android/src/org/briarproject/android/AppModule.java b/briar-android/src/org/briarproject/android/AppModule.java
index e412c9b5bca509ad11613f15fd22a24c25ca1bc8..22d59c206cced7be93fcdc15a98c8519cf0b7b11 100644
--- a/briar-android/src/org/briarproject/android/AppModule.java
+++ b/briar-android/src/org/briarproject/android/AppModule.java
@@ -4,6 +4,8 @@ import android.app.Application;
 
 import org.briarproject.android.api.AndroidNotificationManager;
 import org.briarproject.android.api.ReferenceManager;
+import org.briarproject.api.crypto.CryptoComponent;
+import org.briarproject.api.crypto.PublicKey;
 import org.briarproject.api.crypto.SecretKey;
 import org.briarproject.api.db.DatabaseConfig;
 import org.briarproject.api.event.EventBus;
@@ -13,6 +15,7 @@ import org.briarproject.api.ui.UiCallback;
 import org.briarproject.util.StringUtils;
 
 import java.io.File;
+import java.security.GeneralSecurityException;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -94,16 +97,25 @@ public class AppModule {
 
 	@Provides
 	@Singleton
-	public DevConfig provideDevConfig() {
+	public DevConfig provideDevConfig(CryptoComponent crypto) {
+		final PublicKey pub;
+		try {
+			// TODO fill in
+			pub = crypto.getMessageKeyParser()
+					.parsePublicKey(StringUtils.fromHexString(""));
+		} catch (GeneralSecurityException e) {
+			throw new RuntimeException(e);
+		}
+
 		return new DevConfig() {
 
+			private final PublicKey DEV_PUB_KEY = pub;
 			// TODO fill in
-			private final byte[] DEV_PUB_KEY = StringUtils.fromHexString("");
 			private final String DEV_ONION = "";
 			private final int DEV_REPORT_PORT = 8080;
 
 			@Override
-			public byte[] getDevPublicKey() {
+			public PublicKey getDevPublicKey() {
 				return DEV_PUB_KEY;
 			}
 
diff --git a/briar-api/src/org/briarproject/api/crypto/CryptoComponent.java b/briar-api/src/org/briarproject/api/crypto/CryptoComponent.java
index 5f72ae3120a1a5cdc00ea0845fa449d74c466a6c..dedcafbff7896a3a1b8c957c3e73643d2eef04c6 100644
--- a/briar-api/src/org/briarproject/api/crypto/CryptoComponent.java
+++ b/briar-api/src/org/briarproject/api/crypto/CryptoComponent.java
@@ -27,6 +27,8 @@ public interface CryptoComponent {
 
 	KeyParser getSignatureKeyParser();
 
+	KeyParser getMessageKeyParser();
+
 	/** Generates a random invitation code. */
 	int generateBTInvitationCode();
 
@@ -161,5 +163,5 @@ public interface CryptoComponent {
 	/**
 	 * Encrypts the given plaintext to the given public key.
 	 */
-	String encryptToKey(byte[] publicKey, byte[] plaintext);
+	String encryptToKey(PublicKey publicKey, byte[] plaintext);
 }
diff --git a/briar-api/src/org/briarproject/api/reporting/DevConfig.java b/briar-api/src/org/briarproject/api/reporting/DevConfig.java
index 4152cd927724a3d049d72d58ecc199f17d8522fd..f82e8131804943dbdd00fdada5360eef1bad2166 100644
--- a/briar-api/src/org/briarproject/api/reporting/DevConfig.java
+++ b/briar-api/src/org/briarproject/api/reporting/DevConfig.java
@@ -1,8 +1,10 @@
 package org.briarproject.api.reporting;
 
+import org.briarproject.api.crypto.PublicKey;
+
 public interface DevConfig {
 
-	byte[] getDevPublicKey();
+	PublicKey getDevPublicKey();
 
 	String getDevOnionAddress();
 
diff --git a/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java b/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java
index 87a65ef649042ab83a83d4b1bb91d8490590add4..2411e51989c57386115b767025eec02f3e4068b3 100644
--- a/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java
+++ b/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java
@@ -29,7 +29,6 @@ import org.spongycastle.crypto.params.ECPrivateKeyParameters;
 import org.spongycastle.crypto.params.ECPublicKeyParameters;
 import org.spongycastle.crypto.params.KeyParameter;
 
-import java.io.IOException;
 import java.nio.charset.Charset;
 import java.security.GeneralSecurityException;
 import java.security.SecureRandom;
@@ -95,6 +94,7 @@ class CryptoComponentImpl implements CryptoComponent {
 	private final ECKeyPairGenerator agreementKeyPairGenerator;
 	private final ECKeyPairGenerator signatureKeyPairGenerator;
 	private final KeyParser agreementKeyParser, signatureKeyParser;
+	private final MessageEncrypter messageEncrypter;
 
 	@Inject
 	CryptoComponentImpl(SeedProvider seedProvider) {
@@ -117,6 +117,7 @@ class CryptoComponentImpl implements CryptoComponent {
 				AGREEMENT_KEY_PAIR_BITS);
 		signatureKeyParser = new Sec1KeyParser(PARAMETERS,
 				SIGNATURE_KEY_PAIR_BITS);
+		messageEncrypter = new MessageEncrypter(secureRandom);
 	}
 
 	public SecretKey generateSecretKey() {
@@ -198,6 +199,10 @@ class CryptoComponentImpl implements CryptoComponent {
 		return signatureKeyParser;
 	}
 
+	public KeyParser getMessageKeyParser() {
+		return messageEncrypter.getKeyParser();
+	}
+
 	public int generateBTInvitationCode() {
 		int codeBytes = (CODE_BITS + 7) / 8;
 		byte[] random = new byte[codeBytes];
@@ -440,13 +445,10 @@ class CryptoComponentImpl implements CryptoComponent {
 		}
 	}
 
-	public String encryptToKey(byte[] publicKey, byte[] plaintext) {
-		MessageEncrypter encrypter = new MessageEncrypter(secureRandom);
+	public String encryptToKey(PublicKey publicKey, byte[] plaintext) {
 		try {
-			byte[] ciphertext = encrypter.encrypt(publicKey, plaintext);
+			byte[] ciphertext = messageEncrypter.encrypt(publicKey, plaintext);
 			return AsciiArmour.wrap(ciphertext, 70);
-		} catch (IOException e) {
-			throw new RuntimeException(e);
 		} catch (CryptoException e) {
 			throw new RuntimeException(e);
 		}
diff --git a/briar-core/src/org/briarproject/crypto/MessageEncrypter.java b/briar-core/src/org/briarproject/crypto/MessageEncrypter.java
index 5453bcd2f6f3ddcb0a5c79a677e5e77b41756c22..bbef555e9acd51a282bc5ab0fe35fc2cd29174ed 100644
--- a/briar-core/src/org/briarproject/crypto/MessageEncrypter.java
+++ b/briar-core/src/org/briarproject/crypto/MessageEncrypter.java
@@ -1,5 +1,9 @@
 package org.briarproject.crypto;
 
+import org.briarproject.api.crypto.KeyPair;
+import org.briarproject.api.crypto.KeyParser;
+import org.briarproject.api.crypto.PrivateKey;
+import org.briarproject.api.crypto.PublicKey;
 import org.briarproject.util.StringUtils;
 import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves;
 import org.spongycastle.asn1.x9.X9ECParameters;
@@ -10,7 +14,6 @@ import org.spongycastle.crypto.CipherParameters;
 import org.spongycastle.crypto.CryptoException;
 import org.spongycastle.crypto.DerivationFunction;
 import org.spongycastle.crypto.KeyEncoder;
-import org.spongycastle.crypto.KeyParser;
 import org.spongycastle.crypto.Mac;
 import org.spongycastle.crypto.agreement.ECDHCBasicAgreement;
 import org.spongycastle.crypto.digests.SHA256Digest;
@@ -30,13 +33,11 @@ import org.spongycastle.crypto.params.ECPublicKeyParameters;
 import org.spongycastle.crypto.params.IESWithCipherParameters;
 import org.spongycastle.crypto.parsers.ECIESPublicKeyParser;
 
-import java.io.ByteArrayInputStream;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintStream;
-import java.math.BigInteger;
 import java.nio.charset.Charset;
 import java.security.SecureRandom;
 import java.util.Scanner;
@@ -44,6 +45,7 @@ import java.util.Scanner;
 public class MessageEncrypter {
 
 	private static final ECDomainParameters PARAMETERS;
+	private static final int MESSAGE_KEY_BITS = 512;
 	private static final int MAC_KEY_BITS = 256;
 	private static final int CIPHER_KEY_BITS = 256;
 	private static final int LINE_LENGTH = 70;
@@ -55,40 +57,52 @@ public class MessageEncrypter {
 	}
 
 	private final ECKeyPairGenerator generator;
-	private final EphemeralKeyPairGenerator ephemeralGenerator;
 	private final KeyParser parser;
+	private final EphemeralKeyPairGenerator ephemeralGenerator;
+	private final PublicKeyParser ephemeralParser;
 
 	MessageEncrypter(SecureRandom random) {
 		generator = new ECKeyPairGenerator();
 		generator.init(new ECKeyGenerationParameters(PARAMETERS, random));
+		parser = new Sec1KeyParser(PARAMETERS, MESSAGE_KEY_BITS);
 		KeyEncoder encoder = new PublicKeyEncoder();
 		ephemeralGenerator = new EphemeralKeyPairGenerator(generator, encoder);
-		parser = new PublicKeyParser(PARAMETERS);
+		ephemeralParser = new PublicKeyParser(PARAMETERS);
 	}
 
-	AsymmetricCipherKeyPair generateKeyPair() {
-		return generator.generateKeyPair();
+	KeyPair generateKeyPair() {
+		AsymmetricCipherKeyPair keyPair = generator.generateKeyPair();
+		// Return a wrapper that uses the SEC 1 encoding
+		ECPublicKeyParameters ecPublicKey =
+				(ECPublicKeyParameters) keyPair.getPublic();
+		PublicKey publicKey = new Sec1PublicKey(ecPublicKey);
+		ECPrivateKeyParameters ecPrivateKey =
+				(ECPrivateKeyParameters) keyPair.getPrivate();
+		PrivateKey privateKey =
+				new Sec1PrivateKey(ecPrivateKey, MESSAGE_KEY_BITS);
+		return new KeyPair(publicKey, privateKey);
 	}
 
-	byte[] encrypt(byte[] keyBytes, byte[] plaintext)
-			throws IOException, CryptoException {
-		InputStream in = new ByteArrayInputStream(keyBytes);
-		ECPublicKeyParameters publicKey =
-				(ECPublicKeyParameters) parser.readKey(in);
-		return encrypt(publicKey, plaintext);
+	KeyParser getKeyParser() {
+		return parser;
 	}
 
-	byte[] encrypt(ECPublicKeyParameters pubKey, byte[] plaintext)
-			throws CryptoException {
+	byte[] encrypt(PublicKey pub, byte[] plaintext) throws CryptoException {
+		if (!(pub instanceof Sec1PublicKey))
+			throw new IllegalArgumentException();
 		IESEngine engine = getEngine();
-		engine.init(pubKey, getCipherParameters(), ephemeralGenerator);
+		engine.init(((Sec1PublicKey) pub).getKey(), getCipherParameters(),
+				ephemeralGenerator);
 		return engine.processBlock(plaintext, 0, plaintext.length);
 	}
 
-	byte[] decrypt(ECPrivateKeyParameters privKey, byte[] ciphertext)
+	byte[] decrypt(PrivateKey priv, byte[] ciphertext)
 			throws CryptoException {
+		if (!(priv instanceof Sec1PrivateKey))
+			throw new IllegalArgumentException();
 		IESEngine engine = getEngine();
-		engine.init(privKey, getCipherParameters(), parser);
+		engine.init(((Sec1PrivateKey) priv).getKey(), getCipherParameters(),
+				ephemeralParser);
 		return engine.processBlock(ciphertext, 0, ciphertext.length);
 	}
 
@@ -146,18 +160,15 @@ public class MessageEncrypter {
 				return;
 			}
 			// Generate a key pair
-			AsymmetricCipherKeyPair keyPair = encrypter.generateKeyPair();
-			ECPublicKeyParameters publicKey =
-					(ECPublicKeyParameters) keyPair.getPublic();
-			byte[] publicKeyBytes = publicKey.getQ().getEncoded(false);
+			KeyPair keyPair = encrypter.generateKeyPair();
 			PrintStream out = new PrintStream(new FileOutputStream(args[1]));
-			out.print(StringUtils.toHexString(publicKeyBytes));
+			out.print(
+					StringUtils.toHexString(keyPair.getPublic().getEncoded()));
 			out.flush();
 			out.close();
-			ECPrivateKeyParameters privateKey =
-					(ECPrivateKeyParameters) keyPair.getPrivate();
 			out = new PrintStream(new FileOutputStream(args[2]));
-			out.print(privateKey.getD().toString(16).toUpperCase());
+			out.print(
+					StringUtils.toHexString(keyPair.getPrivate().getEncoded()));
 			out.flush();
 			out.close();
 		} else if (args[0].equals("encrypt")) {
@@ -167,7 +178,9 @@ public class MessageEncrypter {
 			}
 			// Encrypt a decrypted message
 			InputStream in = new FileInputStream(args[1]);
-			byte[] publicKey = StringUtils.fromHexString(readFully(in).trim());
+			byte[] keyBytes = StringUtils.fromHexString(readFully(in).trim());
+			PublicKey publicKey =
+					encrypter.getKeyParser().parsePublicKey(keyBytes);
 			String message = readFully(System.in);
 			byte[] plaintext = message.getBytes(Charset.forName("UTF-8"));
 			byte[] ciphertext = encrypter.encrypt(publicKey, plaintext);
@@ -179,10 +192,9 @@ public class MessageEncrypter {
 			}
 			// Decrypt an encrypted message
 			InputStream in = new FileInputStream(args[1]);
-			byte[] b = StringUtils.fromHexString(readFully(in).trim());
-			BigInteger d = new BigInteger(1, b);
-			ECPrivateKeyParameters privateKey = new ECPrivateKeyParameters(d,
-					PARAMETERS);
+			byte[] keyBytes = StringUtils.fromHexString(readFully(in).trim());
+			PrivateKey privateKey =
+					encrypter.getKeyParser().parsePrivateKey(keyBytes);
 			byte[] ciphertext = AsciiArmour.unwrap(readFully(System.in));
 			byte[] plaintext = encrypter.decrypt(privateKey, ciphertext);
 			System.out.println(new String(plaintext, Charset.forName("UTF-8")));
@@ -193,7 +205,8 @@ public class MessageEncrypter {
 
 	private static void printUsage() {
 		System.err.println("Usage:");
-		System.err.println("MessageEncrypter generate <public_key_file> <private_key_file>");
+		System.err.println(
+				"MessageEncrypter generate <public_key_file> <private_key_file>");
 		System.err.println("MessageEncrypter encrypt <public_key_file>");
 		System.err.println("MessageEncrypter decrypt <private_key_file>");
 	}
diff --git a/briar-tests/src/org/briarproject/crypto/MessageEncrypterTest.java b/briar-tests/src/org/briarproject/crypto/MessageEncrypterTest.java
index 29c07984e5b5d3e66b059cc4f6a7940c80d88d26..351fa48af43aff0e0d6841419d469d8d7fc5e218 100644
--- a/briar-tests/src/org/briarproject/crypto/MessageEncrypterTest.java
+++ b/briar-tests/src/org/briarproject/crypto/MessageEncrypterTest.java
@@ -1,6 +1,9 @@
 package org.briarproject.crypto;
 
 import org.briarproject.BriarTestCase;
+import org.briarproject.api.crypto.KeyPair;
+import org.briarproject.api.crypto.PrivateKey;
+import org.briarproject.api.crypto.PublicKey;
 import org.junit.Test;
 import org.spongycastle.crypto.AsymmetricCipherKeyPair;
 import org.spongycastle.crypto.CryptoException;
@@ -18,9 +21,9 @@ public class MessageEncrypterTest extends BriarTestCase {
 	@Test
 	public void testEncryptionAndDecryption() throws Exception {
 		MessageEncrypter m = new MessageEncrypter(random);
-		AsymmetricCipherKeyPair kp = m.generateKeyPair();
-		ECPublicKeyParameters pub = (ECPublicKeyParameters) kp.getPublic();
-		ECPrivateKeyParameters priv = (ECPrivateKeyParameters) kp.getPrivate();
+		KeyPair kp = m.generateKeyPair();
+		PublicKey pub = kp.getPublic();
+		PrivateKey priv = kp.getPrivate();
 		byte[] plaintext = new byte[123];
 		random.nextBytes(plaintext);
 		byte[] ciphertext = m.encrypt(pub, plaintext);
@@ -31,9 +34,9 @@ public class MessageEncrypterTest extends BriarTestCase {
 	@Test(expected = CryptoException.class)
 	public void testDecryptionFailsWithAlteredCiphertext() throws Exception {
 		MessageEncrypter m = new MessageEncrypter(random);
-		AsymmetricCipherKeyPair kp = m.generateKeyPair();
-		ECPublicKeyParameters pub = (ECPublicKeyParameters) kp.getPublic();
-		ECPrivateKeyParameters priv = (ECPrivateKeyParameters) kp.getPrivate();
+		KeyPair kp = m.generateKeyPair();
+		PublicKey pub = kp.getPublic();
+		PrivateKey priv = kp.getPrivate();
 		byte[] ciphertext = m.encrypt(pub, new byte[123]);
 		ciphertext[random.nextInt(ciphertext.length)] ^= 0xFF;
 		m.decrypt(priv, ciphertext);