Commit 0e77a47c authored by akwizgran's avatar akwizgran

Refactor key handling to use public classes.

parent 421ca309
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.crypto.CryptoConstants.KEY_TYPE_AGREEMENT;
/**
* Type-safe wrapper for a private key used for key agreement.
*/
@Immutable
@NotNullByDefault
public class AgreementPrivateKey extends Bytes implements PrivateKey {
public AgreementPrivateKey(byte[] encoded) {
super(encoded);
}
@Override
public String getKeyType() {
return KEY_TYPE_AGREEMENT;
}
@Override
public byte[] getEncoded() {
return getBytes();
}
}
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.crypto.CryptoConstants.KEY_TYPE_AGREEMENT;
import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_AGREEMENT_PUBLIC_KEY_BYTES;
/**
* Type-safe wrapper for a public key used for key agreement.
*/
@Immutable
@NotNullByDefault
public class AgreementPublicKey extends Bytes implements PublicKey {
public AgreementPublicKey(byte[] encoded) {
super(encoded);
if (encoded.length == 0 ||
encoded.length > MAX_AGREEMENT_PUBLIC_KEY_BYTES) {
throw new IllegalArgumentException();
}
}
@Override
public String getKeyType() {
return KEY_TYPE_AGREEMENT;
}
@Override
public byte[] getEncoded() {
return getBytes();
}
}
......@@ -7,11 +7,21 @@ public interface CryptoConstants {
*/
int MAX_AGREEMENT_PUBLIC_KEY_BYTES = 32;
/**
* The key type for agreement key pairs.
*/
String KEY_TYPE_AGREEMENT = "Curve25519";
/**
* The maximum length of a signature public key in bytes.
*/
int MAX_SIGNATURE_PUBLIC_KEY_BYTES = 32;
/**
* The key type for signature key pairs.
*/
String KEY_TYPE_SIGNATURE = "Ed25519";
/**
* The maximum length of a signature in bytes.
*/
......
......@@ -8,6 +8,11 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface PrivateKey {
/**
* Returns the type of this key pair.
*/
String getKeyType();
/**
* Returns the encoded representation of this key.
*/
......
......@@ -8,6 +8,11 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface PublicKey {
/**
* Returns the type of this key pair.
*/
String getKeyType();
/**
* Returns the encoded representation of this key.
*/
......
package org.briarproject.bramble.crypto;
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.crypto.CryptoConstants.KEY_TYPE_SIGNATURE;
/**
* Type-safe wrapper for a public key used for signing.
*/
@Immutable
@NotNullByDefault
class Curve25519PrivateKey extends Bytes implements PrivateKey {
public class SignaturePrivateKey extends Bytes implements PrivateKey {
Curve25519PrivateKey(byte[] bytes) {
public SignaturePrivateKey(byte[] bytes) {
super(bytes);
}
@Override
public String getKeyType() {
return KEY_TYPE_SIGNATURE;
}
@Override
public byte[] getEncoded() {
return getBytes();
......
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.crypto.CryptoConstants.KEY_TYPE_SIGNATURE;
import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_SIGNATURE_PUBLIC_KEY_BYTES;
/**
* Type-safe wrapper for a public key used for verifying signatures.
*/
@Immutable
@NotNullByDefault
public class SignaturePublicKey extends Bytes implements PublicKey {
public SignaturePublicKey(byte[] encoded) {
super(encoded);
if (encoded.length == 0 ||
encoded.length > MAX_SIGNATURE_PUBLIC_KEY_BYTES) {
throw new IllegalArgumentException();
}
}
@Override
public String getKeyType() {
return KEY_TYPE_SIGNATURE;
}
@Override
public byte[] getEncoded() {
return getBytes();
}
}
......@@ -4,12 +4,16 @@ import net.i2p.crypto.eddsa.EdDSAPrivateKey;
import net.i2p.crypto.eddsa.EdDSAPublicKey;
import net.i2p.crypto.eddsa.KeyPairGenerator;
import org.briarproject.bramble.api.crypto.AgreementPrivateKey;
import org.briarproject.bramble.api.crypto.AgreementPublicKey;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.crypto.KeyParser;
import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.crypto.SignaturePrivateKey;
import org.briarproject.bramble.api.crypto.SignaturePublicKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.SecureRandomProvider;
import org.briarproject.bramble.util.ByteUtils;
......@@ -31,6 +35,7 @@ import javax.annotation.Nullable;
import javax.inject.Inject;
import static java.util.logging.Level.INFO;
import static org.briarproject.bramble.api.crypto.CryptoConstants.KEY_TYPE_AGREEMENT;
import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.now;
......@@ -125,9 +130,9 @@ class CryptoComponentImpl implements CryptoComponent {
// Package access for testing
byte[] performRawKeyAgreement(PrivateKey priv, PublicKey pub)
throws GeneralSecurityException {
if (!(priv instanceof Curve25519PrivateKey))
if (!priv.getKeyType().equals(KEY_TYPE_AGREEMENT))
throw new IllegalArgumentException();
if (!(pub instanceof Curve25519PublicKey))
if (!pub.getKeyType().equals(KEY_TYPE_AGREEMENT))
throw new IllegalArgumentException();
long start = now();
byte[] secret = curve25519.calculateAgreement(pub.getEncoded(),
......@@ -143,8 +148,8 @@ class CryptoComponentImpl implements CryptoComponent {
@Override
public KeyPair generateAgreementKeyPair() {
Curve25519KeyPair keyPair = curve25519.generateKeyPair();
PublicKey pub = new Curve25519PublicKey(keyPair.getPublicKey());
PrivateKey priv = new Curve25519PrivateKey(keyPair.getPrivateKey());
PublicKey pub = new AgreementPublicKey(keyPair.getPublicKey());
PrivateKey priv = new AgreementPrivateKey(keyPair.getPrivateKey());
return new KeyPair(pub, priv);
}
......@@ -158,9 +163,9 @@ class CryptoComponentImpl implements CryptoComponent {
java.security.KeyPair keyPair =
signatureKeyPairGenerator.generateKeyPair();
EdDSAPublicKey edPublicKey = (EdDSAPublicKey) keyPair.getPublic();
PublicKey publicKey = new EdPublicKey(edPublicKey.getAbyte());
PublicKey publicKey = new SignaturePublicKey(edPublicKey.getAbyte());
EdDSAPrivateKey edPrivateKey = (EdDSAPrivateKey) keyPair.getPrivate();
PrivateKey privateKey = new EdPrivateKey(edPrivateKey.getSeed());
PrivateKey privateKey = new SignaturePrivateKey(edPrivateKey.getSeed());
return new KeyPair(publicKey, privateKey);
}
......
package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.AgreementPrivateKey;
import org.briarproject.bramble.api.crypto.AgreementPublicKey;
import org.briarproject.bramble.api.crypto.KeyParser;
import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.crypto.PublicKey;
......@@ -14,14 +16,14 @@ class Curve25519KeyParser implements KeyParser {
public PublicKey parsePublicKey(byte[] encodedKey)
throws GeneralSecurityException {
if (encodedKey.length != 32) throw new GeneralSecurityException();
return new Curve25519PublicKey(encodedKey);
return new AgreementPublicKey(encodedKey);
}
@Override
public PrivateKey parsePrivateKey(byte[] encodedKey)
throws GeneralSecurityException {
if (encodedKey.length != 32) throw new GeneralSecurityException();
return new Curve25519PrivateKey(clamp(encodedKey));
return new AgreementPrivateKey(clamp(encodedKey));
}
static byte[] clamp(byte[] b) {
......
package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
class Curve25519PublicKey extends Bytes implements PublicKey {
Curve25519PublicKey(byte[] bytes) {
super(bytes);
}
@Override
public byte[] getEncoded() {
return getBytes();
}
}
......@@ -3,6 +3,8 @@ package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.KeyParser;
import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.crypto.SignaturePrivateKey;
import org.briarproject.bramble.api.crypto.SignaturePublicKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.security.GeneralSecurityException;
......@@ -14,13 +16,13 @@ class EdKeyParser implements KeyParser {
public PublicKey parsePublicKey(byte[] encodedKey)
throws GeneralSecurityException {
if (encodedKey.length != 32) throw new GeneralSecurityException();
return new EdPublicKey(encodedKey);
return new SignaturePublicKey(encodedKey);
}
@Override
public PrivateKey parsePrivateKey(byte[] encodedKey)
throws GeneralSecurityException {
if (encodedKey.length != 32) throw new GeneralSecurityException();
return new EdPrivateKey(encodedKey);
return new SignaturePrivateKey(encodedKey);
}
}
package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
class EdPrivateKey extends Bytes implements PrivateKey {
EdPrivateKey(byte[] bytes) {
super(bytes);
}
@Override
public byte[] getEncoded() {
return getBytes();
}
}
package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
class EdPublicKey extends Bytes implements PublicKey {
EdPublicKey(byte[] bytes) {
super(bytes);
}
@Override
public byte[] getEncoded() {
return getBytes();
}
}
......@@ -17,6 +17,7 @@ import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import static net.i2p.crypto.eddsa.EdDSAEngine.SIGNATURE_ALGORITHM;
import static org.briarproject.bramble.api.crypto.CryptoConstants.KEY_TYPE_SIGNATURE;
@NotNullByDefault
class EdSignature implements Signature {
......@@ -39,7 +40,7 @@ class EdSignature implements Signature {
@Override
public void initSign(PrivateKey k) throws GeneralSecurityException {
if (!(k instanceof EdPrivateKey))
if (!k.getKeyType().equals(KEY_TYPE_SIGNATURE))
throw new IllegalArgumentException();
EdDSAPrivateKey privateKey = new EdDSAPrivateKey(
new EdDSAPrivateKeySpec(k.getEncoded(), CURVE_SPEC));
......@@ -48,7 +49,7 @@ class EdSignature implements Signature {
@Override
public void initVerify(PublicKey k) throws GeneralSecurityException {
if (!(k instanceof EdPublicKey))
if (!k.getKeyType().equals(KEY_TYPE_SIGNATURE))
throw new IllegalArgumentException();
EdDSAPublicKey publicKey = new EdDSAPublicKey(
new EdDSAPublicKeySpec(k.getEncoded(), CURVE_SPEC));
......
......@@ -49,6 +49,7 @@ import javax.annotation.concurrent.Immutable;
@NotNullByDefault
public class MessageEncrypter {
private static final String KEY_TYPE = "SEC1_brainpoolp512r1";
private static final ECDomainParameters PARAMETERS;
private static final int MESSAGE_KEY_BITS = 512;
private static final int MAC_KEY_BITS = 256;
......@@ -69,7 +70,7 @@ public class MessageEncrypter {
MessageEncrypter(SecureRandom random) {
generator = new ECKeyPairGenerator();
generator.init(new ECKeyGenerationParameters(PARAMETERS, random));
parser = new Sec1KeyParser(PARAMETERS, MESSAGE_KEY_BITS);
parser = new Sec1KeyParser(KEY_TYPE, PARAMETERS, MESSAGE_KEY_BITS);
KeyEncoder encoder = new PublicKeyEncoder();
ephemeralGenerator = new EphemeralKeyPairGenerator(generator, encoder);
ephemeralParser = new PublicKeyParser(PARAMETERS);
......@@ -80,11 +81,11 @@ public class MessageEncrypter {
// Return a wrapper that uses the SEC 1 encoding
ECPublicKeyParameters ecPublicKey =
(ECPublicKeyParameters) keyPair.getPublic();
PublicKey publicKey = new Sec1PublicKey(ecPublicKey);
PublicKey publicKey = new Sec1PublicKey(KEY_TYPE, ecPublicKey);
ECPrivateKeyParameters ecPrivateKey =
(ECPrivateKeyParameters) keyPair.getPrivate();
PrivateKey privateKey =
new Sec1PrivateKey(ecPrivateKey, MESSAGE_KEY_BITS);
new Sec1PrivateKey(KEY_TYPE, ecPrivateKey, MESSAGE_KEY_BITS);
return new KeyPair(publicKey, privateKey);
}
......
......@@ -31,11 +31,13 @@ class Sec1KeyParser implements KeyParser {
private static final Logger LOG =
Logger.getLogger(Sec1KeyParser.class.getName());
private final String keyType;
private final ECDomainParameters params;
private final BigInteger modulus;
private final int keyBits, bytesPerInt, publicKeyBytes, privateKeyBytes;
Sec1KeyParser(ECDomainParameters params, int keyBits) {
Sec1KeyParser(String keyType, ECDomainParameters params, int keyBits) {
this.keyType = keyType;
this.params = params;
this.keyBits = keyBits;
modulus = ((ECCurve.Fp) params.getCurve()).getQ();
......@@ -80,7 +82,7 @@ class Sec1KeyParser implements KeyParser {
throw new GeneralSecurityException();
// Construct a public key from the point (x, y) and the params
ECPublicKeyParameters k = new ECPublicKeyParameters(pub, params);
PublicKey p = new Sec1PublicKey(k);
PublicKey p = new Sec1PublicKey(keyType, k);
logDuration(LOG, "Parsing public key", start);
return p;
}
......@@ -97,7 +99,7 @@ class Sec1KeyParser implements KeyParser {
throw new GeneralSecurityException();
// Construct a private key from the private value and the params
ECPrivateKeyParameters k = new ECPrivateKeyParameters(d, params);
PrivateKey p = new Sec1PrivateKey(k, keyBits);
PrivateKey p = new Sec1PrivateKey(keyType, k, keyBits);
logDuration(LOG, "Parsing private key", start);
return p;
}
......
......@@ -10,14 +10,21 @@ import javax.annotation.concurrent.Immutable;
@NotNullByDefault
class Sec1PrivateKey implements PrivateKey {
private final String keyType;
private final ECPrivateKeyParameters key;
private final int bytesPerInt;
Sec1PrivateKey(ECPrivateKeyParameters key, int keyBits) {
Sec1PrivateKey(String keyType, ECPrivateKeyParameters key, int keyBits) {
this.keyType = keyType;
this.key = key;
bytesPerInt = (keyBits + 7) / 8;
}
@Override
public String getKeyType() {
return keyType;
}
@Override
public byte[] getEncoded() {
byte[] encodedKey = new byte[bytesPerInt];
......
......@@ -15,12 +15,19 @@ import javax.annotation.concurrent.Immutable;
@NotNullByDefault
class Sec1PublicKey implements PublicKey {
private final String keyType;
private final ECPublicKeyParameters key;
Sec1PublicKey(ECPublicKeyParameters key) {
Sec1PublicKey(String keyType, ECPublicKeyParameters key) {
this.keyType = keyType;
this.key = key;
}
@Override
public String getKeyType() {
return keyType;
}
@Override
public byte[] getEncoded() {
return key.getQ().getEncoded(false);
......
package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.crypto.SignaturePrivateKey;
import org.briarproject.bramble.api.crypto.SignaturePublicKey;
import org.junit.Test;
import java.security.GeneralSecurityException;
......@@ -157,11 +159,11 @@ public class EdSignatureTest extends SignatureTest {
byte[] signatureBytes = fromHexString(vector[3]);
EdSignature signature = new EdSignature();
signature.initSign(new EdPrivateKey(privateKeyBytes));
signature.initSign(new SignaturePrivateKey(privateKeyBytes));
signature.update(messageBytes);
assertArrayEquals(signatureBytes, signature.sign());
signature.initVerify(new EdPublicKey(publicKeyBytes));
signature.initVerify(new SignaturePublicKey(publicKeyBytes));
signature.update(messageBytes);
assertTrue(signature.verify(signatureBytes));
}
......
package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.AgreementPublicKey;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.crypto.PublicKey;
......@@ -58,7 +59,7 @@ public class KeyAgreementTest extends BrambleTestCase {
@Test(expected = GeneralSecurityException.class)
public void testRejectsInvalidPublicKey() throws Exception {
KeyPair keyPair = crypto.generateAgreementKeyPair();
PublicKey invalid = new Curve25519PublicKey(new byte[32]);
PublicKey invalid = new AgreementPublicKey(new byte[32]);
crypto.deriveSharedSecret(SHARED_SECRET_LABEL, invalid, keyPair,
inputs);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment