Commit 6f31a3c2 authored by akwizgran's avatar akwizgran

Merge branch 'key-pair-refactoring' into 'master'

Key pair refactoring

See merge request !1083
parents d3469e37 d2951eb3
Pipeline #3314 passed with stage
in 7 minutes and 38 seconds
package org.briarproject.bramble.api.client; package org.briarproject.bramble.api.client;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
...@@ -96,14 +98,18 @@ public interface ClientHelper { ...@@ -96,14 +98,18 @@ public interface ClientHelper {
BdfList toList(Author a); BdfList toList(Author a);
byte[] sign(String label, BdfList toSign, byte[] privateKey) byte[] sign(String label, BdfList toSign, PrivateKey privateKey)
throws FormatException, GeneralSecurityException; throws FormatException, GeneralSecurityException;
void verifySignature(byte[] signature, String label, BdfList signed, void verifySignature(byte[] signature, String label, BdfList signed,
byte[] publicKey) throws FormatException, GeneralSecurityException; PublicKey publicKey)
throws FormatException, GeneralSecurityException;
Author parseAndValidateAuthor(BdfList author) throws FormatException; Author parseAndValidateAuthor(BdfList author) throws FormatException;
PublicKey parseAndValidateAgreementPublicKey(byte[] publicKeyBytes)
throws FormatException;
TransportProperties parseAndValidateTransportProperties( TransportProperties parseAndValidateTransportProperties(
BdfDictionary properties) throws FormatException; BdfDictionary properties) throws FormatException;
......
package org.briarproject.bramble.api.contact; package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
...@@ -8,7 +9,6 @@ import javax.annotation.Nullable; ...@@ -8,7 +9,6 @@ import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.util.StringUtils.toUtf8; import static org.briarproject.bramble.util.StringUtils.toUtf8;
@Immutable @Immutable
...@@ -21,21 +21,17 @@ public class Contact { ...@@ -21,21 +21,17 @@ public class Contact {
@Nullable @Nullable
private final String alias; private final String alias;
@Nullable @Nullable
private final byte[] handshakePublicKey; private final PublicKey handshakePublicKey;
private final boolean verified; private final boolean verified;
public Contact(ContactId id, Author author, AuthorId localAuthorId, public Contact(ContactId id, Author author, AuthorId localAuthorId,
@Nullable String alias, @Nullable byte[] handshakePublicKey, @Nullable String alias, @Nullable PublicKey handshakePublicKey,
boolean verified) { boolean verified) {
if (alias != null) { if (alias != null) {
int aliasLength = toUtf8(alias).length; int aliasLength = toUtf8(alias).length;
if (aliasLength == 0 || aliasLength > MAX_AUTHOR_NAME_LENGTH) if (aliasLength == 0 || aliasLength > MAX_AUTHOR_NAME_LENGTH)
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
if (handshakePublicKey != null && (handshakePublicKey.length == 0 ||
handshakePublicKey.length > MAX_PUBLIC_KEY_LENGTH)) {
throw new IllegalArgumentException();
}
this.id = id; this.id = id;
this.author = author; this.author = author;
this.localAuthorId = localAuthorId; this.localAuthorId = localAuthorId;
...@@ -62,7 +58,7 @@ public class Contact { ...@@ -62,7 +58,7 @@ public class Contact {
} }
@Nullable @Nullable
public byte[] getHandshakePublicKey() { public PublicKey getHandshakePublicKey() {
return handshakePublicKey; return handshakePublicKey;
} }
......
package org.briarproject.bramble.api.contact; package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
...@@ -9,12 +10,12 @@ import javax.annotation.concurrent.Immutable; ...@@ -9,12 +10,12 @@ import javax.annotation.concurrent.Immutable;
public class PendingContact { public class PendingContact {
private final PendingContactId id; private final PendingContactId id;
private final byte[] publicKey; private final PublicKey publicKey;
private final String alias; private final String alias;
private final PendingContactState state; private final PendingContactState state;
private final long timestamp; private final long timestamp;
public PendingContact(PendingContactId id, byte[] publicKey, public PendingContact(PendingContactId id, PublicKey publicKey,
String alias, PendingContactState state, long timestamp) { String alias, PendingContactState state, long timestamp) {
this.id = id; this.id = id;
this.publicKey = publicKey; this.publicKey = publicKey;
...@@ -27,7 +28,7 @@ public class PendingContact { ...@@ -27,7 +28,7 @@ public class PendingContact {
return id; return id;
} }
public byte[] getPublicKey() { public PublicKey getPublicKey() {
return publicKey; return publicKey;
} }
......
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();
}
}
...@@ -55,7 +55,7 @@ public interface CryptoComponent { ...@@ -55,7 +55,7 @@ public interface CryptoComponent {
* signature, to prevent it from being repurposed or colliding with a * signature, to prevent it from being repurposed or colliding with a
* signature created for another purpose * signature created for another purpose
*/ */
byte[] sign(String label, byte[] toSign, byte[] privateKey) byte[] sign(String label, byte[] toSign, PrivateKey privateKey)
throws GeneralSecurityException; throws GeneralSecurityException;
/** /**
...@@ -68,7 +68,7 @@ public interface CryptoComponent { ...@@ -68,7 +68,7 @@ public interface CryptoComponent {
* @return true if the signature was valid, false otherwise. * @return true if the signature was valid, false otherwise.
*/ */
boolean verifySignature(byte[] signature, String label, byte[] signed, boolean verifySignature(byte[] signature, String label, byte[] signed,
byte[] publicKey) throws GeneralSecurityException; PublicKey publicKey) throws GeneralSecurityException;
/** /**
* Returns the hash of the given inputs. The inputs are unambiguously * Returns the hash of the given inputs. The inputs are unambiguously
......
...@@ -7,11 +7,21 @@ public interface CryptoConstants { ...@@ -7,11 +7,21 @@ public interface CryptoConstants {
*/ */
int MAX_AGREEMENT_PUBLIC_KEY_BYTES = 32; 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. * The maximum length of a signature public key in bytes.
*/ */
int MAX_SIGNATURE_PUBLIC_KEY_BYTES = 32; 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. * The maximum length of a signature in bytes.
*/ */
......
...@@ -15,6 +15,8 @@ public class KeyPair { ...@@ -15,6 +15,8 @@ public class KeyPair {
private final PrivateKey privateKey; private final PrivateKey privateKey;
public KeyPair(PublicKey publicKey, PrivateKey privateKey) { public KeyPair(PublicKey publicKey, PrivateKey privateKey) {
if (!publicKey.getKeyType().equals(privateKey.getKeyType()))
throw new IllegalArgumentException();
this.publicKey = publicKey; this.publicKey = publicKey;
this.privateKey = privateKey; this.privateKey = privateKey;
} }
......
...@@ -8,6 +8,11 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault; ...@@ -8,6 +8,11 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault @NotNullByDefault
public interface PrivateKey { public interface PrivateKey {
/**
* Returns the type of this key pair.
*/
String getKeyType();
/** /**
* Returns the encoded representation of this key. * Returns the encoded representation of this key.
*/ */
......
...@@ -8,6 +8,11 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault; ...@@ -8,6 +8,11 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault @NotNullByDefault
public interface PublicKey { public interface PublicKey {
/**
* Returns the type of this key pair.
*/
String getKeyType();
/** /**
* Returns the encoded representation of this key. * 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.Bytes;
import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; 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 @NotNullByDefault
class Curve25519PrivateKey extends Bytes implements PrivateKey { public class SignaturePrivateKey extends Bytes implements PrivateKey {
Curve25519PrivateKey(byte[] bytes) { public SignaturePrivateKey(byte[] bytes) {
super(bytes); super(bytes);
} }
@Override
public String getKeyType() {
return KEY_TYPE_SIGNATURE;
}
@Override @Override
public byte[] getEncoded() { public byte[] getEncoded() {
return getBytes(); 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,6 +4,8 @@ import org.briarproject.bramble.api.contact.Contact; ...@@ -4,6 +4,8 @@ import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.PendingContact; import org.briarproject.bramble.api.contact.PendingContact;
import org.briarproject.bramble.api.contact.PendingContactId; import org.briarproject.bramble.api.contact.PendingContactId;
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.SecretKey;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.AuthorId;
...@@ -622,8 +624,8 @@ public interface DatabaseComponent { ...@@ -622,8 +624,8 @@ public interface DatabaseComponent {
/** /**
* Sets the handshake key pair for the identity with the given ID. * Sets the handshake key pair for the identity with the given ID.
*/ */
void setHandshakeKeyPair(Transaction txn, AuthorId local, byte[] publicKey, void setHandshakeKeyPair(Transaction txn, AuthorId local,
byte[] privateKey) throws DbException; PublicKey publicKey, PrivateKey privateKey) throws DbException;
/** /**
* Sets the reordering window for the given transport key set in the given * Sets the reordering window for the given transport key set in the given
......
package org.briarproject.bramble.api.identity; package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.api.Nameable; import org.briarproject.bramble.api.Nameable;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.util.StringUtils;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.crypto.CryptoConstants.KEY_TYPE_SIGNATURE;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.bramble.util.StringUtils.toUtf8;
/** /**
* A pseudonym for a user. * A pseudonym for a user.
...@@ -24,14 +25,14 @@ public class Author implements Nameable { ...@@ -24,14 +25,14 @@ public class Author implements Nameable {
private final AuthorId id; private final AuthorId id;
private final int formatVersion; private final int formatVersion;
private final String name; private final String name;
private final byte[] publicKey; private final PublicKey publicKey;
public Author(AuthorId id, int formatVersion, String name, public Author(AuthorId id, int formatVersion, String name,
byte[] publicKey) { PublicKey publicKey) {
int nameLength = StringUtils.toUtf8(name).length; int nameLength = toUtf8(name).length;
if (nameLength == 0 || nameLength > MAX_AUTHOR_NAME_LENGTH) if (nameLength == 0 || nameLength > MAX_AUTHOR_NAME_LENGTH)
throw new IllegalArgumentException(); throw new IllegalArgumentException();
if (publicKey.length == 0 || publicKey.length > MAX_PUBLIC_KEY_LENGTH) if (!publicKey.getKeyType().equals(KEY_TYPE_SIGNATURE))
throw new IllegalArgumentException(); throw new IllegalArgumentException();
this.id = id; this.id = id;
this.formatVersion = formatVersion; this.formatVersion = formatVersion;
...@@ -63,7 +64,7 @@ public class Author implements Nameable { ...@@ -63,7 +64,7 @@ public class Author implements Nameable {
/** /**
* Returns the public key used to verify the pseudonym's signatures. * Returns the public key used to verify the pseudonym's signatures.
*/ */
public byte[] getPublicKey() { public PublicKey getPublicKey() {
return publicKey; return publicKey;
} }
......
package org.briarproject.bramble.api.identity; package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault @NotNullByDefault
...@@ -9,12 +10,12 @@ public interface AuthorFactory { ...@@ -9,12 +10,12 @@ public interface AuthorFactory {
* Creates an author with the current format version and the given name and * Creates an author with the current format version and the given name and
* public key. * public key.
*/ */
Author createAuthor(String name, byte[] publicKey); Author createAuthor(String name, PublicKey publicKey);
/** /**
* Creates an author with the given format version, name and public key. * Creates an author with the given format version, name and public key.
*/ */
Author createAuthor(int formatVersion, String name, byte[] publicKey); Author createAuthor(int formatVersion, String name, PublicKey publicKey);
/** /**
* Creates a local author with the current format version and the given * Creates a local author with the current format version and the given
......
package org.briarproject.bramble.api.identity; package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.Arrays;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_AGREEMENT_PUBLIC_KEY_BYTES; import static org.briarproject.bramble.api.crypto.CryptoConstants.KEY_TYPE_AGREEMENT;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
...@@ -15,15 +15,24 @@ public class Identity { ...@@ -15,15 +15,24 @@ public class Identity {
private final LocalAuthor localAuthor; private final LocalAuthor localAuthor;
@Nullable @Nullable
private final byte[] handshakePublicKey, handshakePrivateKey; private final PublicKey handshakePublicKey;
@Nullable
private final PrivateKey handshakePrivateKey;
private final long created; private final long created;
public Identity(LocalAuthor localAuthor, public Identity(LocalAuthor localAuthor,
@Nullable byte[] handshakePublicKey, @Nullable PublicKey handshakePublicKey,
@Nullable byte[] handshakePrivateKey, long created) { @Nullable PrivateKey handshakePrivateKey, long created) {
if (handshakePublicKey != null) { if (handshakePublicKey != null) {
int keyLength = handshakePublicKey.length; if (handshakePrivateKey == null)
if (keyLength == 0 || keyLength > MAX_AGREEMENT_PUBLIC_KEY_BYTES) throw new IllegalArgumentException();
if (!handshakePublicKey.getKeyType().equals(KEY_TYPE_AGREEMENT))
throw new IllegalArgumentException();
}
if (handshakePrivateKey != null) {
if (handshakePublicKey == null)
throw new IllegalArgumentException();
if (!handshakePrivateKey.getKeyType().equals(KEY_TYPE_AGREEMENT))
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
this.localAuthor = localAuthor; this.localAuthor = localAuthor;
...@@ -57,7 +66,7 @@ public class Identity { ...@@ -57,7 +66,7 @@ public class Identity {
* Returns the public key used for handshaking, or null if no key exists. * Returns the public key used for handshaking, or null if no key exists.
*/ */
@Nullable @Nullable
public byte[] getHandshakePublicKey() { public PublicKey getHandshakePublicKey() {
return handshakePublicKey; return handshakePublicKey;
} }
...@@ -65,7 +74,7 @@ public class Identity { ...@@ -65,7 +74,7 @@ public class Identity {
* Returns the private key used for handshaking, or null if no key exists. * Returns the private key used for handshaking, or null if no key exists.
*/ */
@Nullable @Nullable
public byte[] getHandshakePrivateKey() { public PrivateKey getHandshakePrivateKey() {
return handshakePrivateKey; return handshakePrivateKey;
} }
...@@ -76,21 +85,4 @@ public class Identity { ...@@ -76,21 +85,4 @@ public class Identity {
public long getTimeCreated() { public long getTimeCreated() {
return created; return created;
} }
@Override
public int hashCode() {
return localAuthor.getId().hashCode();
}
@Override
public boolean equals(Object o) {
if (o instanceof Identity) {
Identity i = (Identity) o;
return created == i.created &&
localAuthor.equals(i.localAuthor) &&
Arrays.equals(handshakePublicKey, i.handshakePublicKey) &&
Arrays.equals(handshakePrivateKey, i.handshakePrivateKey);
}
return false;
}
} }