diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/client/ClientHelper.java b/bramble-api/src/main/java/org/briarproject/bramble/api/client/ClientHelper.java index 591ef458e..bd5b8c55c 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/client/ClientHelper.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/client/ClientHelper.java @@ -1,6 +1,8 @@ package org.briarproject.bramble.api.client; 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.BdfList; import org.briarproject.bramble.api.db.DbException; @@ -96,14 +98,18 @@ public interface ClientHelper { BdfList toList(Author a); - byte[] sign(String label, BdfList toSign, byte[] privateKey) + byte[] sign(String label, BdfList toSign, PrivateKey privateKey) throws FormatException, GeneralSecurityException; void verifySignature(byte[] signature, String label, BdfList signed, - byte[] publicKey) throws FormatException, GeneralSecurityException; + PublicKey publicKey) + throws FormatException, GeneralSecurityException; Author parseAndValidateAuthor(BdfList author) throws FormatException; + PublicKey parseAndValidateAgreementPublicKey(byte[] publicKeyBytes) + throws FormatException; + TransportProperties parseAndValidateTransportProperties( BdfDictionary properties) throws FormatException; diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/Contact.java b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/Contact.java index 479a0ce53..14e890c07 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/Contact.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/Contact.java @@ -1,5 +1,6 @@ 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.AuthorId; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; @@ -8,7 +9,6 @@ import javax.annotation.Nullable; 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_PUBLIC_KEY_LENGTH; import static org.briarproject.bramble.util.StringUtils.toUtf8; @Immutable @@ -21,21 +21,17 @@ public class Contact { @Nullable private final String alias; @Nullable - private final byte[] handshakePublicKey; + private final PublicKey handshakePublicKey; private final boolean verified; public Contact(ContactId id, Author author, AuthorId localAuthorId, - @Nullable String alias, @Nullable byte[] handshakePublicKey, + @Nullable String alias, @Nullable PublicKey handshakePublicKey, boolean verified) { if (alias != null) { int aliasLength = toUtf8(alias).length; if (aliasLength == 0 || aliasLength > MAX_AUTHOR_NAME_LENGTH) throw new IllegalArgumentException(); } - if (handshakePublicKey != null && (handshakePublicKey.length == 0 || - handshakePublicKey.length > MAX_PUBLIC_KEY_LENGTH)) { - throw new IllegalArgumentException(); - } this.id = id; this.author = author; this.localAuthorId = localAuthorId; @@ -62,7 +58,7 @@ public class Contact { } @Nullable - public byte[] getHandshakePublicKey() { + public PublicKey getHandshakePublicKey() { return handshakePublicKey; } diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/PendingContact.java b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/PendingContact.java index 4989a11cf..c0093c68c 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/PendingContact.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/PendingContact.java @@ -1,5 +1,6 @@ package org.briarproject.bramble.api.contact; +import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import javax.annotation.concurrent.Immutable; @@ -9,12 +10,12 @@ import javax.annotation.concurrent.Immutable; public class PendingContact { private final PendingContactId id; - private final byte[] publicKey; + private final PublicKey publicKey; private final String alias; private final PendingContactState state; private final long timestamp; - public PendingContact(PendingContactId id, byte[] publicKey, + public PendingContact(PendingContactId id, PublicKey publicKey, String alias, PendingContactState state, long timestamp) { this.id = id; this.publicKey = publicKey; @@ -27,7 +28,7 @@ public class PendingContact { return id; } - public byte[] getPublicKey() { + public PublicKey getPublicKey() { return publicKey; } diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/AgreementPrivateKey.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/AgreementPrivateKey.java new file mode 100644 index 000000000..3e1cd624e --- /dev/null +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/AgreementPrivateKey.java @@ -0,0 +1,30 @@ +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(); + } +} diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/AgreementPublicKey.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/AgreementPublicKey.java new file mode 100644 index 000000000..fa595fa4c --- /dev/null +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/AgreementPublicKey.java @@ -0,0 +1,35 @@ +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(); + } +} diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/CryptoComponent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/CryptoComponent.java index fdc83aabb..4ad811524 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/CryptoComponent.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/CryptoComponent.java @@ -55,7 +55,7 @@ public interface CryptoComponent { * signature, to prevent it from being repurposed or colliding with a * signature created for another purpose */ - byte[] sign(String label, byte[] toSign, byte[] privateKey) + byte[] sign(String label, byte[] toSign, PrivateKey privateKey) throws GeneralSecurityException; /** @@ -68,7 +68,7 @@ public interface CryptoComponent { * @return true if the signature was valid, false otherwise. */ 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 diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/CryptoConstants.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/CryptoConstants.java index b9f772d2b..01b080266 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/CryptoConstants.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/CryptoConstants.java @@ -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. */ diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/KeyPair.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/KeyPair.java index 587d696e2..28b2b1036 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/KeyPair.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/KeyPair.java @@ -15,6 +15,8 @@ public class KeyPair { private final PrivateKey privateKey; public KeyPair(PublicKey publicKey, PrivateKey privateKey) { + if (!publicKey.getKeyType().equals(privateKey.getKeyType())) + throw new IllegalArgumentException(); this.publicKey = publicKey; this.privateKey = privateKey; } diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/PrivateKey.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/PrivateKey.java index edf478c40..f53ef5ef8 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/PrivateKey.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/PrivateKey.java @@ -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. */ diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/PublicKey.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/PublicKey.java index e5cc522ca..c091e6e0a 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/PublicKey.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/PublicKey.java @@ -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. */ diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/SignaturePrivateKey.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/SignaturePrivateKey.java new file mode 100644 index 000000000..1680d54af --- /dev/null +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/SignaturePrivateKey.java @@ -0,0 +1,30 @@ +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; + +/** + * Type-safe wrapper for a public key used for signing. + */ +@Immutable +@NotNullByDefault +public class SignaturePrivateKey extends Bytes implements PrivateKey { + + public SignaturePrivateKey(byte[] bytes) { + super(bytes); + } + + @Override + public String getKeyType() { + return KEY_TYPE_SIGNATURE; + } + + @Override + public byte[] getEncoded() { + return getBytes(); + } +} diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/SignaturePublicKey.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/SignaturePublicKey.java new file mode 100644 index 000000000..12b743d10 --- /dev/null +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/SignaturePublicKey.java @@ -0,0 +1,35 @@ +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(); + } +} diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java index 16094da18..5a2eaa719 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java @@ -4,6 +4,8 @@ import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.PendingContact; 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.identity.Author; import org.briarproject.bramble.api.identity.AuthorId; @@ -622,8 +624,8 @@ public interface DatabaseComponent { /** * Sets the handshake key pair for the identity with the given ID. */ - void setHandshakeKeyPair(Transaction txn, AuthorId local, byte[] publicKey, - byte[] privateKey) throws DbException; + void setHandshakeKeyPair(Transaction txn, AuthorId local, + PublicKey publicKey, PrivateKey privateKey) throws DbException; /** * Sets the reordering window for the given transport key set in the given diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/identity/Author.java b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/Author.java index 4d2d030e5..ca7598e49 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/identity/Author.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/Author.java @@ -1,13 +1,14 @@ package org.briarproject.bramble.api.identity; import org.briarproject.bramble.api.Nameable; +import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; -import org.briarproject.bramble.util.StringUtils; 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_PUBLIC_KEY_LENGTH; +import static org.briarproject.bramble.util.StringUtils.toUtf8; /** * A pseudonym for a user. @@ -24,14 +25,14 @@ public class Author implements Nameable { private final AuthorId id; private final int formatVersion; private final String name; - private final byte[] publicKey; + private final PublicKey publicKey; public Author(AuthorId id, int formatVersion, String name, - byte[] publicKey) { - int nameLength = StringUtils.toUtf8(name).length; + PublicKey publicKey) { + int nameLength = toUtf8(name).length; if (nameLength == 0 || nameLength > MAX_AUTHOR_NAME_LENGTH) throw new IllegalArgumentException(); - if (publicKey.length == 0 || publicKey.length > MAX_PUBLIC_KEY_LENGTH) + if (!publicKey.getKeyType().equals(KEY_TYPE_SIGNATURE)) throw new IllegalArgumentException(); this.id = id; this.formatVersion = formatVersion; @@ -63,7 +64,7 @@ public class Author implements Nameable { /** * Returns the public key used to verify the pseudonym's signatures. */ - public byte[] getPublicKey() { + public PublicKey getPublicKey() { return publicKey; } diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/identity/AuthorFactory.java b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/AuthorFactory.java index 6423562e8..162a68aa0 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/identity/AuthorFactory.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/AuthorFactory.java @@ -1,5 +1,6 @@ package org.briarproject.bramble.api.identity; +import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; @NotNullByDefault @@ -9,12 +10,12 @@ public interface AuthorFactory { * Creates an author with the current format version and the given name and * 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. */ - 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 diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/identity/Identity.java b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/Identity.java index 48e42d756..4d60768eb 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/identity/Identity.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/Identity.java @@ -1,13 +1,13 @@ 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 java.util.Arrays; - import javax.annotation.Nullable; 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 @NotNullByDefault @@ -15,15 +15,24 @@ public class Identity { private final LocalAuthor localAuthor; @Nullable - private final byte[] handshakePublicKey, handshakePrivateKey; + private final PublicKey handshakePublicKey; + @Nullable + private final PrivateKey handshakePrivateKey; private final long created; public Identity(LocalAuthor localAuthor, - @Nullable byte[] handshakePublicKey, - @Nullable byte[] handshakePrivateKey, long created) { + @Nullable PublicKey handshakePublicKey, + @Nullable PrivateKey handshakePrivateKey, long created) { if (handshakePublicKey != null) { - int keyLength = handshakePublicKey.length; - if (keyLength == 0 || keyLength > MAX_AGREEMENT_PUBLIC_KEY_BYTES) + if (handshakePrivateKey == null) + 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(); } this.localAuthor = localAuthor; @@ -57,7 +66,7 @@ public class Identity { * Returns the public key used for handshaking, or null if no key exists. */ @Nullable - public byte[] getHandshakePublicKey() { + public PublicKey getHandshakePublicKey() { return handshakePublicKey; } @@ -65,7 +74,7 @@ public class Identity { * Returns the private key used for handshaking, or null if no key exists. */ @Nullable - public byte[] getHandshakePrivateKey() { + public PrivateKey getHandshakePrivateKey() { return handshakePrivateKey; } @@ -76,21 +85,4 @@ public class Identity { public long getTimeCreated() { 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; - } } diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/identity/IdentityManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/IdentityManager.java index 2d25a561a..be2e28d3e 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/identity/IdentityManager.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/IdentityManager.java @@ -1,6 +1,7 @@ package org.briarproject.bramble.api.identity; import org.briarproject.bramble.api.crypto.CryptoExecutor; +import org.briarproject.bramble.api.crypto.KeyPair; import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.Transaction; @@ -41,9 +42,6 @@ public interface IdentityManager { * Returns the cached handshake keys or loads them from the database. *

* Read-only. - * - * @return A two-element array containing the public key in the first - * element and the private key in the second */ - byte[][] getHandshakeKeys(Transaction txn) throws DbException; + KeyPair getHandshakeKeys(Transaction txn) throws DbException; } diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/identity/LocalAuthor.java b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/LocalAuthor.java index 5eb9775ac..1bc8df84b 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/identity/LocalAuthor.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/LocalAuthor.java @@ -1,9 +1,13 @@ 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 javax.annotation.concurrent.Immutable; +import static org.briarproject.bramble.api.crypto.CryptoConstants.KEY_TYPE_SIGNATURE; + /** * A pseudonym for the local user. */ @@ -11,18 +15,20 @@ import javax.annotation.concurrent.Immutable; @NotNullByDefault public class LocalAuthor extends Author { - private final byte[] privateKey; + private final PrivateKey privateKey; public LocalAuthor(AuthorId id, int formatVersion, String name, - byte[] publicKey, byte[] privateKey) { + PublicKey publicKey, PrivateKey privateKey) { super(id, formatVersion, name, publicKey); + if (!privateKey.getKeyType().equals(KEY_TYPE_SIGNATURE)) + throw new IllegalArgumentException(); this.privateKey = privateKey; } /** * Returns the private key used to generate the pseudonym's signatures. */ - public byte[] getPrivateKey() { + public PrivateKey getPrivateKey() { return privateKey; } } diff --git a/bramble-api/src/test/java/org/briarproject/bramble/test/TestUtils.java b/bramble-api/src/test/java/org/briarproject/bramble/test/TestUtils.java index 65a1e3869..004977060 100644 --- a/bramble-api/src/test/java/org/briarproject/bramble/test/TestUtils.java +++ b/bramble-api/src/test/java/org/briarproject/bramble/test/TestUtils.java @@ -5,7 +5,13 @@ import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.PendingContact; import org.briarproject.bramble.api.contact.PendingContactId; +import org.briarproject.bramble.api.crypto.AgreementPrivateKey; +import org.briarproject.bramble.api.crypto.AgreementPublicKey; +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.identity.Author; import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.Identity; @@ -32,9 +38,9 @@ import java.util.concurrent.atomic.AtomicInteger; import static java.util.Arrays.asList; import static org.briarproject.bramble.api.contact.PendingContactState.WAITING_FOR_CONNECTION; import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_AGREEMENT_PUBLIC_KEY_BYTES; +import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_SIGNATURE_PUBLIC_KEY_BYTES; import static org.briarproject.bramble.api.identity.Author.FORMAT_VERSION; 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.api.plugin.TransportId.MAX_TRANSPORT_ID_LENGTH; import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH; import static org.briarproject.bramble.api.sync.ClientId.MAX_CLIENT_ID_LENGTH; @@ -101,10 +107,28 @@ public class TestUtils { return new SecretKey(getRandomBytes(SecretKey.LENGTH)); } + public static PublicKey getSignaturePublicKey() { + byte[] key = getRandomBytes(MAX_SIGNATURE_PUBLIC_KEY_BYTES); + return new SignaturePublicKey(key); + } + + public static PrivateKey getSignaturePrivateKey() { + return new SignaturePrivateKey(getRandomBytes(123)); + } + + public static PublicKey getAgreementPublicKey() { + byte[] key = getRandomBytes(MAX_AGREEMENT_PUBLIC_KEY_BYTES); + return new AgreementPublicKey(key); + } + + public static PrivateKey getAgreementPrivateKey() { + return new AgreementPrivateKey(getRandomBytes(123)); + } + public static Identity getIdentity() { LocalAuthor localAuthor = getLocalAuthor(); - byte[] handshakePub = getRandomBytes(MAX_AGREEMENT_PUBLIC_KEY_BYTES); - byte[] handshakePriv = getRandomBytes(MAX_AGREEMENT_PUBLIC_KEY_BYTES); + PublicKey handshakePub = getAgreementPublicKey(); + PrivateKey handshakePriv = getAgreementPrivateKey(); return new Identity(localAuthor, handshakePub, handshakePriv, timestamp); } @@ -113,8 +137,8 @@ public class TestUtils { AuthorId id = new AuthorId(getRandomId()); int nameLength = 1 + random.nextInt(MAX_AUTHOR_NAME_LENGTH); String name = getRandomString(nameLength); - byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH); - byte[] privateKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH); + PublicKey publicKey = getSignaturePublicKey(); + PrivateKey privateKey = getSignaturePrivateKey(); return new LocalAuthor(id, FORMAT_VERSION, name, publicKey, privateKey); } @@ -122,7 +146,7 @@ public class TestUtils { AuthorId id = new AuthorId(getRandomId()); int nameLength = 1 + random.nextInt(MAX_AUTHOR_NAME_LENGTH); String name = getRandomString(nameLength); - byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH); + PublicKey publicKey = getSignaturePublicKey(); return new Author(id, FORMAT_VERSION, name, publicKey); } @@ -155,7 +179,7 @@ public class TestUtils { public static PendingContact getPendingContact(int nameLength) { PendingContactId id = new PendingContactId(getRandomId()); - byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH); + PublicKey publicKey = getAgreementPublicKey(); String alias = getRandomString(nameLength); return new PendingContact(id, publicKey, alias, WAITING_FOR_CONNECTION, timestamp); @@ -179,7 +203,7 @@ public class TestUtils { boolean verified) { return new Contact(c, remote, local, getRandomString(MAX_AUTHOR_NAME_LENGTH), - getRandomBytes(MAX_PUBLIC_KEY_LENGTH), verified); + getAgreementPublicKey(), verified); } public static double getMedian(Collection samples) { diff --git a/bramble-core/src/main/java/org/briarproject/bramble/client/ClientHelperImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/client/ClientHelperImpl.java index d8362ce29..4bb5c68cd 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/client/ClientHelperImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/client/ClientHelperImpl.java @@ -3,6 +3,9 @@ package org.briarproject.bramble.client; import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.crypto.CryptoComponent; +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.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfReader; @@ -305,14 +308,15 @@ class ClientHelperImpl implements ClientHelper { } @Override - public byte[] sign(String label, BdfList toSign, byte[] privateKey) + public byte[] sign(String label, BdfList toSign, PrivateKey privateKey) throws FormatException, GeneralSecurityException { return crypto.sign(label, toByteArray(toSign), privateKey); } @Override public void verifySignature(byte[] signature, String label, BdfList signed, - byte[] publicKey) throws FormatException, GeneralSecurityException { + PublicKey publicKey) + throws FormatException, GeneralSecurityException { if (!crypto.verifySignature(signature, label, toByteArray(signed), publicKey)) { throw new GeneralSecurityException("Invalid signature"); @@ -327,11 +331,29 @@ class ClientHelperImpl implements ClientHelper { if (formatVersion != FORMAT_VERSION) throw new FormatException(); String name = author.getString(1); checkLength(name, 1, MAX_AUTHOR_NAME_LENGTH); - byte[] publicKey = author.getRaw(2); - checkLength(publicKey, 1, MAX_PUBLIC_KEY_LENGTH); + byte[] publicKeyBytes = author.getRaw(2); + checkLength(publicKeyBytes, 1, MAX_PUBLIC_KEY_LENGTH); + KeyParser parser = crypto.getSignatureKeyParser(); + PublicKey publicKey; + try { + publicKey = parser.parsePublicKey(publicKeyBytes); + } catch (GeneralSecurityException e) { + throw new FormatException(); + } return authorFactory.createAuthor(formatVersion, name, publicKey); } + @Override + public PublicKey parseAndValidateAgreementPublicKey(byte[] publicKeyBytes) + throws FormatException { + KeyParser parser = crypto.getAgreementKeyParser(); + try { + return parser.parsePublicKey(publicKeyBytes); + } catch (GeneralSecurityException e) { + throw new FormatException(); + } + } + @Override public TransportProperties parseAndValidateTransportProperties( BdfDictionary properties) throws FormatException { diff --git a/bramble-core/src/main/java/org/briarproject/bramble/contact/PendingContactFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/contact/PendingContactFactoryImpl.java index a901cb60d..5a008b136 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/contact/PendingContactFactoryImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/contact/PendingContactFactoryImpl.java @@ -39,8 +39,8 @@ class PendingContactFactoryImpl implements PendingContactFactory { PublicKey publicKey = parseHandshakeLink(link); PendingContactId id = getPendingContactId(publicKey); long timestamp = clock.currentTimeMillis(); - return new PendingContact(id, publicKey.getEncoded(), alias, - WAITING_FOR_CONNECTION, timestamp); + return new PendingContact(id, publicKey, alias, WAITING_FOR_CONNECTION, + timestamp); } private PublicKey parseHandshakeLink(String link) throws FormatException { diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/Curve25519KeyParser.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/AgreementKeyParser.java similarity index 72% rename from bramble-core/src/main/java/org/briarproject/bramble/crypto/Curve25519KeyParser.java rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/AgreementKeyParser.java index e7b39ad8d..7b966aa2f 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/Curve25519KeyParser.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/AgreementKeyParser.java @@ -1,5 +1,7 @@ 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; @@ -7,21 +9,24 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import java.security.GeneralSecurityException; +import javax.annotation.concurrent.Immutable; + +@Immutable @NotNullByDefault -class Curve25519KeyParser implements KeyParser { +class AgreementKeyParser implements KeyParser { @Override 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) { diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/CryptoComponentImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/CryptoComponentImpl.java index dc0470a6f..d1cad3869 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/CryptoComponentImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/CryptoComponentImpl.java @@ -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,8 @@ 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.api.crypto.CryptoConstants.KEY_TYPE_SIGNATURE; 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; @@ -80,8 +86,8 @@ class CryptoComponentImpl implements CryptoComponent { signatureKeyPairGenerator = new KeyPairGenerator(); signatureKeyPairGenerator.initialize(SIGNATURE_KEY_PAIR_BITS, secureRandom); - agreementKeyParser = new Curve25519KeyParser(); - signatureKeyParser = new EdKeyParser(); + agreementKeyParser = new AgreementKeyParser(); + signatureKeyParser = new SignatureKeyParser(); messageEncrypter = new MessageEncrypter(secureRandom); } @@ -125,9 +131,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 +149,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 +164,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); } @@ -195,21 +201,22 @@ class CryptoComponentImpl implements CryptoComponent { } @Override - public byte[] sign(String label, byte[] toSign, byte[] privateKey) + public byte[] sign(String label, byte[] toSign, PrivateKey privateKey) throws GeneralSecurityException { - PrivateKey key = signatureKeyParser.parsePrivateKey(privateKey); Signature sig = new EdSignature(); - sig.initSign(key); + sig.initSign(privateKey); updateSignature(sig, label, toSign); return sig.sign(); } @Override public boolean verifySignature(byte[] signature, String label, - byte[] signed, byte[] publicKey) throws GeneralSecurityException { - PublicKey key = signatureKeyParser.parsePublicKey(publicKey); + byte[] signed, PublicKey publicKey) + throws GeneralSecurityException { + if (!publicKey.getKeyType().equals(KEY_TYPE_SIGNATURE)) + throw new IllegalArgumentException(); Signature sig = new EdSignature(); - sig.initVerify(key); + sig.initVerify(publicKey); updateSignature(sig, label, signed); return sig.verify(signature); } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/Curve25519PrivateKey.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/Curve25519PrivateKey.java deleted file mode 100644 index b7f1a0cc5..000000000 --- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/Curve25519PrivateKey.java +++ /dev/null @@ -1,18 +0,0 @@ -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 Curve25519PrivateKey extends Bytes implements PrivateKey { - - Curve25519PrivateKey(byte[] bytes) { - super(bytes); - } - - @Override - public byte[] getEncoded() { - return getBytes(); - } -} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/Curve25519PublicKey.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/Curve25519PublicKey.java deleted file mode 100644 index 94d703d01..000000000 --- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/Curve25519PublicKey.java +++ /dev/null @@ -1,18 +0,0 @@ -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(); - } -} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/EdPrivateKey.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/EdPrivateKey.java deleted file mode 100644 index c58912db1..000000000 --- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/EdPrivateKey.java +++ /dev/null @@ -1,18 +0,0 @@ -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(); - } -} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/EdPublicKey.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/EdPublicKey.java deleted file mode 100644 index 862011f7e..000000000 --- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/EdPublicKey.java +++ /dev/null @@ -1,18 +0,0 @@ -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(); - } -} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/EdSignature.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/EdSignature.java index 081e810ff..aeb95836f 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/EdSignature.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/EdSignature.java @@ -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)); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/MessageEncrypter.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/MessageEncrypter.java index 6a86ad97c..7154ea327 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/MessageEncrypter.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/MessageEncrypter.java @@ -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); } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/Sec1KeyParser.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/Sec1KeyParser.java index a769af06d..c3b6ac9ab 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/Sec1KeyParser.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/Sec1KeyParser.java @@ -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; } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/Sec1PrivateKey.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/Sec1PrivateKey.java index 89e297c43..7d93a9cbb 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/Sec1PrivateKey.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/Sec1PrivateKey.java @@ -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]; diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/Sec1PublicKey.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/Sec1PublicKey.java index a7fd114e8..3f4046f42 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/Sec1PublicKey.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/Sec1PublicKey.java @@ -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); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/EdKeyParser.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/SignatureKeyParser.java similarity index 67% rename from bramble-core/src/main/java/org/briarproject/bramble/crypto/EdKeyParser.java rename to bramble-core/src/main/java/org/briarproject/bramble/crypto/SignatureKeyParser.java index 0e8f0844f..4e7b38c5b 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/EdKeyParser.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/SignatureKeyParser.java @@ -3,24 +3,29 @@ 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; +import javax.annotation.concurrent.Immutable; + +@Immutable @NotNullByDefault -class EdKeyParser implements KeyParser { +class SignatureKeyParser implements KeyParser { @Override 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); } } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java index c59230802..a4a836d3b 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java @@ -5,6 +5,8 @@ import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.PendingContact; import org.briarproject.bramble.api.contact.PendingContactId; import org.briarproject.bramble.api.contact.PendingContactState; +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.db.DataTooNewException; import org.briarproject.bramble.api.db.DataTooOldException; @@ -689,8 +691,8 @@ interface Database { /** * Sets the handshake key pair for the identity with the given ID. */ - void setHandshakeKeyPair(T txn, AuthorId local, byte[] publicKey, - byte[] privateKey) throws DbException; + void setHandshakeKeyPair(T txn, AuthorId local, PublicKey publicKey, + PrivateKey privateKey) throws DbException; /** * Marks the given message as shared. diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java index 475e9da5a..c11aaa7de 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java @@ -7,6 +7,8 @@ import org.briarproject.bramble.api.contact.PendingContactId; import org.briarproject.bramble.api.contact.event.ContactAddedEvent; import org.briarproject.bramble.api.contact.event.ContactRemovedEvent; import org.briarproject.bramble.api.contact.event.ContactVerifiedEvent; +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.db.CommitAction; import org.briarproject.bramble.api.db.CommitAction.Visitor; @@ -1037,7 +1039,7 @@ class DatabaseComponentImpl implements DatabaseComponent { @Override public void setHandshakeKeyPair(Transaction transaction, AuthorId local, - byte[] publicKey, byte[] privateKey) throws DbException { + PublicKey publicKey, PrivateKey privateKey) throws DbException { if (transaction.isReadOnly()) throw new IllegalArgumentException(); T txn = unbox(transaction); if (!db.containsIdentity(txn, local)) diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java index e7d3a5a49..caecf111e 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java @@ -5,7 +5,13 @@ import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.PendingContact; import org.briarproject.bramble.api.contact.PendingContactId; import org.briarproject.bramble.api.contact.PendingContactState; +import org.briarproject.bramble.api.crypto.AgreementPrivateKey; +import org.briarproject.bramble.api.crypto.AgreementPublicKey; +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.db.DataTooNewException; import org.briarproject.bramble.api.db.DataTooOldException; import org.briarproject.bramble.api.db.DbClosedException; @@ -677,7 +683,7 @@ abstract class JdbcDatabase implements Database { ps.setBytes(1, remote.getId().getBytes()); ps.setInt(2, remote.getFormatVersion()); ps.setString(3, remote.getName()); - ps.setBytes(4, remote.getPublicKey()); + ps.setBytes(4, remote.getPublicKey().getEncoded()); ps.setBytes(5, local.getBytes()); ps.setBoolean(6, verified); int affected = ps.executeUpdate(); @@ -887,12 +893,12 @@ abstract class JdbcDatabase implements Database { ps.setBytes(1, local.getId().getBytes()); ps.setInt(2, local.getFormatVersion()); ps.setString(3, local.getName()); - ps.setBytes(4, local.getPublicKey()); - ps.setBytes(5, local.getPrivateKey()); + ps.setBytes(4, local.getPublicKey().getEncoded()); + ps.setBytes(5, local.getPrivateKey().getEncoded()); if (i.getHandshakePublicKey() == null) ps.setNull(6, BINARY); - else ps.setBytes(6, i.getHandshakePublicKey()); + else ps.setBytes(6, i.getHandshakePublicKey().getEncoded()); if (i.getHandshakePrivateKey() == null) ps.setNull(7, BINARY); - else ps.setBytes(7, i.getHandshakePrivateKey()); + else ps.setBytes(7, i.getHandshakePrivateKey().getEncoded()); ps.setLong(8, i.getTimeCreated()); int affected = ps.executeUpdate(); if (affected != 1) throw new DbStateException(); @@ -1068,7 +1074,7 @@ abstract class JdbcDatabase implements Database { + " VALUES (?, ?, ?, ?, ?)"; ps = txn.prepareStatement(sql); ps.setBytes(1, p.getId().getBytes()); - ps.setBytes(2, p.getPublicKey()); + ps.setBytes(2, p.getPublicKey().getEncoded()); ps.setString(3, p.getAlias()); ps.setInt(4, p.getState().getValue()); ps.setLong(5, p.getTimestamp()); @@ -1444,14 +1450,16 @@ abstract class JdbcDatabase implements Database { int formatVersion = rs.getInt(2); String name = rs.getString(3); String alias = rs.getString(4); - byte[] publicKey = rs.getBytes(5); - byte[] handshakePublicKey = rs.getBytes(6); + PublicKey publicKey = new SignaturePublicKey(rs.getBytes(5)); + byte[] handshakePub = rs.getBytes(6); AuthorId localAuthorId = new AuthorId(rs.getBytes(7)); boolean verified = rs.getBoolean(8); rs.close(); ps.close(); Author author = new Author(authorId, formatVersion, name, publicKey); + PublicKey handshakePublicKey = handshakePub == null ? + null : new AgreementPublicKey(handshakePub); return new Contact(c, author, localAuthorId, alias, handshakePublicKey, verified); } catch (SQLException e) { @@ -1479,12 +1487,14 @@ abstract class JdbcDatabase implements Database { int formatVersion = rs.getInt(3); String name = rs.getString(4); String alias = rs.getString(5); - byte[] publicKey = rs.getBytes(6); - byte[] handshakePublicKey = rs.getBytes(7); + PublicKey publicKey = new SignaturePublicKey(rs.getBytes(6)); + byte[] handshakePub = rs.getBytes(7); AuthorId localAuthorId = new AuthorId(rs.getBytes(8)); boolean verified = rs.getBoolean(9); Author author = new Author(authorId, formatVersion, name, publicKey); + PublicKey handshakePublicKey = handshakePub == null ? + null : new AgreementPublicKey(handshakePub); contacts.add(new Contact(contactId, author, localAuthorId, alias, handshakePublicKey, verified)); } @@ -1540,12 +1550,14 @@ abstract class JdbcDatabase implements Database { int formatVersion = rs.getInt(2); String name = rs.getString(3); String alias = rs.getString(4); - byte[] publicKey = rs.getBytes(5); - byte[] handshakePublicKey = rs.getBytes(6); + PublicKey publicKey = new SignaturePublicKey(rs.getBytes(5)); + byte[] handshakePub = rs.getBytes(6); AuthorId localAuthorId = new AuthorId(rs.getBytes(7)); boolean verified = rs.getBoolean(8); Author author = new Author(remote, formatVersion, name, publicKey); + PublicKey handshakePublicKey = handshakePub == null ? + null : new AgreementPublicKey(handshakePub); contacts.add(new Contact(contactId, author, localAuthorId, alias, handshakePublicKey, verified)); } @@ -1756,16 +1768,20 @@ abstract class JdbcDatabase implements Database { if (!rs.next()) throw new DbStateException(); int formatVersion = rs.getInt(1); String name = rs.getString(2); - byte[] publicKey = rs.getBytes(3); - byte[] privateKey = rs.getBytes(4); - byte[] handshakePublicKey = rs.getBytes(5); - byte[] handshakePrivateKey = rs.getBytes(6); + PublicKey publicKey = new SignaturePublicKey(rs.getBytes(3)); + PrivateKey privateKey = new SignaturePrivateKey(rs.getBytes(4)); + byte[] handshakePub = rs.getBytes(5); + byte[] handshakePriv = rs.getBytes(6); long created = rs.getLong(7); if (rs.next()) throw new DbStateException(); rs.close(); ps.close(); LocalAuthor local = new LocalAuthor(a, formatVersion, name, publicKey, privateKey); + PublicKey handshakePublicKey = handshakePub == null ? + null : new AgreementPublicKey(handshakePub); + PrivateKey handshakePrivateKey = handshakePriv == null ? + null : new AgreementPrivateKey(handshakePriv); return new Identity(local, handshakePublicKey, handshakePrivateKey, created); } catch (SQLException e) { @@ -1792,13 +1808,17 @@ abstract class JdbcDatabase implements Database { AuthorId authorId = new AuthorId(rs.getBytes(1)); int formatVersion = rs.getInt(2); String name = rs.getString(3); - byte[] publicKey = rs.getBytes(4); - byte[] privateKey = rs.getBytes(5); - byte[] handshakePublicKey = rs.getBytes(6); - byte[] handshakePrivateKey = rs.getBytes(7); + PublicKey publicKey = new SignaturePublicKey(rs.getBytes(4)); + PrivateKey privateKey = new SignaturePrivateKey(rs.getBytes(5)); + byte[] handshakePub = rs.getBytes(6); + byte[] handshakePriv = rs.getBytes(7); long created = rs.getLong(8); LocalAuthor local = new LocalAuthor(authorId, formatVersion, name, publicKey, privateKey); + PublicKey handshakePublicKey = handshakePub == null ? + null : new AgreementPublicKey(handshakePub); + PrivateKey handshakePrivateKey = handshakePriv == null ? + null : new AgreementPrivateKey(handshakePriv); identities.add(new Identity(local, handshakePublicKey, handshakePrivateKey, created)); } @@ -2395,7 +2415,7 @@ abstract class JdbcDatabase implements Database { List pendingContacts = new ArrayList<>(); while (rs.next()) { PendingContactId id = new PendingContactId(rs.getBytes(1)); - byte[] publicKey = rs.getBytes(2); + PublicKey publicKey = new AgreementPublicKey(rs.getBytes(2)); String alias = rs.getString(3); PendingContactState state = PendingContactState.fromValue(rs.getInt(4)); @@ -3182,15 +3202,15 @@ abstract class JdbcDatabase implements Database { @Override public void setHandshakeKeyPair(Connection txn, AuthorId local, - byte[] publicKey, byte[] privateKey) throws DbException { + PublicKey publicKey, PrivateKey privateKey) throws DbException { PreparedStatement ps = null; try { String sql = "UPDATE localAuthors" + " SET handshakePublicKey = ?, handshakePrivateKey = ?" + " WHERE authorId = ?"; ps = txn.prepareStatement(sql); - ps.setBytes(1, publicKey); - ps.setBytes(2, privateKey); + ps.setBytes(1, publicKey.getEncoded()); + ps.setBytes(2, privateKey.getEncoded()); ps.setBytes(3, local.getBytes()); int affected = ps.executeUpdate(); if (affected < 0 || affected > 1) throw new DbStateException(); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/identity/AuthorFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/identity/AuthorFactoryImpl.java index c0a125a1d..85885414f 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/identity/AuthorFactoryImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/identity/AuthorFactoryImpl.java @@ -2,13 +2,13 @@ package org.briarproject.bramble.identity; import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.KeyPair; +import org.briarproject.bramble.api.crypto.PrivateKey; +import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.AuthorFactory; import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; -import org.briarproject.bramble.util.ByteUtils; -import org.briarproject.bramble.util.StringUtils; import javax.annotation.concurrent.Immutable; import javax.inject.Inject; @@ -16,6 +16,8 @@ import javax.inject.Inject; import static org.briarproject.bramble.api.identity.Author.FORMAT_VERSION; import static org.briarproject.bramble.api.identity.AuthorId.LABEL; import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES; +import static org.briarproject.bramble.util.ByteUtils.writeUint32; +import static org.briarproject.bramble.util.StringUtils.toUtf8; @Immutable @NotNullByDefault @@ -29,13 +31,13 @@ class AuthorFactoryImpl implements AuthorFactory { } @Override - public Author createAuthor(String name, byte[] publicKey) { + public Author createAuthor(String name, PublicKey publicKey) { return createAuthor(FORMAT_VERSION, name, publicKey); } @Override public Author createAuthor(int formatVersion, String name, - byte[] publicKey) { + PublicKey publicKey) { AuthorId id = getId(formatVersion, name, publicKey); return new Author(id, formatVersion, name, publicKey); } @@ -43,16 +45,17 @@ class AuthorFactoryImpl implements AuthorFactory { @Override public LocalAuthor createLocalAuthor(String name) { KeyPair signatureKeyPair = crypto.generateSignatureKeyPair(); - byte[] publicKey = signatureKeyPair.getPublic().getEncoded(); - byte[] privateKey = signatureKeyPair.getPrivate().getEncoded(); + PublicKey publicKey = signatureKeyPair.getPublic(); + PrivateKey privateKey = signatureKeyPair.getPrivate(); AuthorId id = getId(FORMAT_VERSION, name, publicKey); return new LocalAuthor(id, FORMAT_VERSION, name, publicKey, privateKey); } - private AuthorId getId(int formatVersion, String name, byte[] publicKey) { + private AuthorId getId(int formatVersion, String name, + PublicKey publicKey) { byte[] formatVersionBytes = new byte[INT_32_BYTES]; - ByteUtils.writeUint32(formatVersion, formatVersionBytes, 0); + writeUint32(formatVersion, formatVersionBytes, 0); return new AuthorId(crypto.hash(LABEL, formatVersionBytes, - StringUtils.toUtf8(name), publicKey)); + toUtf8(name), publicKey.getEncoded())); } } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/identity/IdentityManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/identity/IdentityManagerImpl.java index 15f7a613f..d5d5e0b6f 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/identity/IdentityManagerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/identity/IdentityManagerImpl.java @@ -2,6 +2,8 @@ package org.briarproject.bramble.identity; import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.KeyPair; +import org.briarproject.bramble.api.crypto.PrivateKey; +import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.Transaction; @@ -73,8 +75,8 @@ class IdentityManagerImpl implements IdentityManager, OpenDatabaseHook { long start = now(); LocalAuthor localAuthor = authorFactory.createLocalAuthor(name); KeyPair handshakeKeyPair = crypto.generateAgreementKeyPair(); - byte[] handshakePub = handshakeKeyPair.getPublic().getEncoded(); - byte[] handshakePriv = handshakeKeyPair.getPrivate().getEncoded(); + PublicKey handshakePub = handshakeKeyPair.getPublic(); + PrivateKey handshakePriv = handshakeKeyPair.getPrivate(); logDuration(LOG, "Creating identity", start); return new Identity(localAuthor, handshakePub, handshakePriv, clock.currentTimeMillis()); @@ -98,9 +100,9 @@ class IdentityManagerImpl implements IdentityManager, OpenDatabaseHook { } else if (shouldStoreKeys) { // Handshake keys were generated when loading the identity - // store them - byte[] handshakePub = + PublicKey handshakePub = requireNonNull(cached.getHandshakePublicKey()); - byte[] handshakePriv = + PrivateKey handshakePriv = requireNonNull(cached.getHandshakePrivateKey()); db.setHandshakeKeyPair(txn, cached.getId(), handshakePub, handshakePriv); @@ -122,12 +124,12 @@ class IdentityManagerImpl implements IdentityManager, OpenDatabaseHook { } @Override - public byte[][] getHandshakeKeys(Transaction txn) throws DbException { + public KeyPair getHandshakeKeys(Transaction txn) throws DbException { Identity cached = getCachedIdentity(txn); - return new byte[][] { - cached.getHandshakePublicKey(), - cached.getHandshakePrivateKey() - }; + PublicKey handshakePub = requireNonNull(cached.getHandshakePublicKey()); + PrivateKey handshakePriv = + requireNonNull(cached.getHandshakePrivateKey()); + return new KeyPair(handshakePub, handshakePriv); } /** @@ -159,8 +161,8 @@ class IdentityManagerImpl implements IdentityManager, OpenDatabaseHook { LOG.info("Identity loaded"); if (i.hasHandshakeKeyPair()) return i; KeyPair handshakeKeyPair = crypto.generateAgreementKeyPair(); - byte[] handshakePub = handshakeKeyPair.getPublic().getEncoded(); - byte[] handshakePriv = handshakeKeyPair.getPrivate().getEncoded(); + PublicKey handshakePub = handshakeKeyPair.getPublic(); + PrivateKey handshakePriv = handshakeKeyPair.getPrivate(); LOG.info("Handshake key pair generated"); shouldStoreKeys = true; return new Identity(i.getLocalAuthor(), handshakePub, handshakePriv, diff --git a/bramble-core/src/test/java/org/briarproject/bramble/client/ClientHelperImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/client/ClientHelperImplTest.java index 33888d7a1..47a10e9a6 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/client/ClientHelperImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/client/ClientHelperImplTest.java @@ -3,6 +3,9 @@ package org.briarproject.bramble.client; import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.crypto.CryptoComponent; +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.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfEntry; import org.briarproject.bramble.api.data.BdfList; @@ -43,6 +46,8 @@ import static org.briarproject.bramble.test.TestUtils.getAuthor; import static org.briarproject.bramble.test.TestUtils.getMessage; import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getRandomId; +import static org.briarproject.bramble.test.TestUtils.getSignaturePrivateKey; +import static org.briarproject.bramble.test.TestUtils.getSignaturePublicKey; import static org.briarproject.bramble.util.StringUtils.getRandomString; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -66,6 +71,7 @@ public class ClientHelperImplTest extends BrambleTestCase { context.mock(CryptoComponent.class); private final AuthorFactory authorFactory = context.mock(AuthorFactory.class); + private final KeyParser keyParser = context.mock(KeyParser.class); private final GroupId groupId = new GroupId(getRandomId()); private final BdfDictionary dictionary = new BdfDictionary(); @@ -262,24 +268,25 @@ public class ClientHelperImplTest extends BrambleTestCase { @Test public void testSign() throws Exception { - byte[] privateKey = getRandomBytes(42); - byte[] signed = getRandomBytes(42); + PrivateKey privateKey = getSignaturePrivateKey(); + byte[] signature = getRandomBytes(42); byte[] bytes = expectToByteArray(list); context.checking(new Expectations() {{ oneOf(cryptoComponent).sign(label, bytes, privateKey); - will(returnValue(signed)); + will(returnValue(signature)); }}); - assertArrayEquals(signed, clientHelper.sign(label, list, privateKey)); + assertArrayEquals(signature, + clientHelper.sign(label, list, privateKey)); context.assertIsSatisfied(); } @Test public void testVerifySignature() throws Exception { byte[] signature = getRandomBytes(MAX_SIGNATURE_LENGTH); - byte[] publicKey = getRandomBytes(42); byte[] signed = expectToByteArray(list); + PublicKey publicKey = getSignaturePublicKey(); context.checking(new Expectations() {{ oneOf(cryptoComponent).verifySignature(signature, label, signed, @@ -294,8 +301,8 @@ public class ClientHelperImplTest extends BrambleTestCase { @Test public void testVerifyWrongSignature() throws Exception { byte[] signature = getRandomBytes(MAX_SIGNATURE_LENGTH); - byte[] publicKey = getRandomBytes(42); byte[] signed = expectToByteArray(list); + PublicKey publicKey = getSignaturePublicKey(); context.checking(new Expectations() {{ oneOf(cryptoComponent).verifySignature(signature, label, signed, @@ -315,6 +322,10 @@ public class ClientHelperImplTest extends BrambleTestCase { @Test public void testParsesAndEncodesAuthor() throws Exception { context.checking(new Expectations() {{ + oneOf(cryptoComponent).getSignatureKeyParser(); + will(returnValue(keyParser)); + oneOf(keyParser).parsePublicKey(author.getPublicKey().getEncoded()); + will(returnValue(author.getPublicKey())); oneOf(authorFactory).createAuthor(author.getFormatVersion(), author.getName(), author.getPublicKey()); will(returnValue(author)); @@ -329,10 +340,14 @@ public class ClientHelperImplTest extends BrambleTestCase { BdfList authorList = BdfList.of( author.getFormatVersion(), author.getName(), - author.getPublicKey() + author.getPublicKey().getEncoded() ); context.checking(new Expectations() {{ + oneOf(cryptoComponent).getSignatureKeyParser(); + will(returnValue(keyParser)); + oneOf(keyParser).parsePublicKey(author.getPublicKey().getEncoded()); + will(returnValue(author.getPublicKey())); oneOf(authorFactory).createAuthor(author.getFormatVersion(), author.getName(), author.getPublicKey()); will(returnValue(author)); @@ -355,7 +370,7 @@ public class ClientHelperImplTest extends BrambleTestCase { BdfList invalidAuthor = BdfList.of( author.getFormatVersion(), author.getName(), - author.getPublicKey(), + author.getPublicKey().getEncoded(), "foo" ); clientHelper.parseAndValidateAuthor(invalidAuthor); @@ -366,7 +381,7 @@ public class ClientHelperImplTest extends BrambleTestCase { BdfList invalidAuthor = BdfList.of( null, author.getName(), - author.getPublicKey() + author.getPublicKey().getEncoded() ); clientHelper.parseAndValidateAuthor(invalidAuthor); } @@ -377,7 +392,7 @@ public class ClientHelperImplTest extends BrambleTestCase { BdfList invalidAuthor = BdfList.of( "foo", author.getName(), - author.getPublicKey() + author.getPublicKey().getEncoded() ); clientHelper.parseAndValidateAuthor(invalidAuthor); } @@ -387,7 +402,7 @@ public class ClientHelperImplTest extends BrambleTestCase { BdfList invalidAuthor = BdfList.of( author.getFormatVersion() + 1, author.getName(), - author.getPublicKey() + author.getPublicKey().getEncoded() ); clientHelper.parseAndValidateAuthor(invalidAuthor); } @@ -397,7 +412,7 @@ public class ClientHelperImplTest extends BrambleTestCase { BdfList invalidAuthor = BdfList.of( author.getFormatVersion(), "", - author.getPublicKey() + author.getPublicKey().getEncoded() ); clientHelper.parseAndValidateAuthor(invalidAuthor); } @@ -407,7 +422,7 @@ public class ClientHelperImplTest extends BrambleTestCase { BdfList invalidAuthor = BdfList.of( author.getFormatVersion(), getRandomString(MAX_AUTHOR_NAME_LENGTH + 1), - author.getPublicKey() + author.getPublicKey().getEncoded() ); clientHelper.parseAndValidateAuthor(invalidAuthor); } @@ -417,7 +432,7 @@ public class ClientHelperImplTest extends BrambleTestCase { BdfList invalidAuthor = BdfList.of( author.getFormatVersion(), null, - author.getPublicKey() + author.getPublicKey().getEncoded() ); clientHelper.parseAndValidateAuthor(invalidAuthor); } @@ -472,6 +487,24 @@ public class ClientHelperImplTest extends BrambleTestCase { clientHelper.parseAndValidateAuthor(invalidAuthor); } + @Test(expected = FormatException.class) + public void testRejectsAuthorWithInvalidPublicKey() throws Exception { + BdfList invalidAuthor = BdfList.of( + author.getFormatVersion(), + author.getName(), + author.getPublicKey().getEncoded() + ); + + context.checking(new Expectations() {{ + oneOf(cryptoComponent).getSignatureKeyParser(); + will(returnValue(keyParser)); + oneOf(keyParser).parsePublicKey(author.getPublicKey().getEncoded()); + will(throwException(new GeneralSecurityException())); + }}); + + clientHelper.parseAndValidateAuthor(invalidAuthor); + } + private byte[] expectToByteArray(BdfList list) throws Exception { BdfWriter bdfWriter = context.mock(BdfWriter.class); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/contact/PendingContactFactoryImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/contact/PendingContactFactoryImplTest.java index c575357cc..70fb1f67a 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/contact/PendingContactFactoryImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/contact/PendingContactFactoryImplTest.java @@ -21,7 +21,7 @@ import static org.briarproject.bramble.api.contact.HandshakeLinkConstants.ID_LAB import static org.briarproject.bramble.api.contact.HandshakeLinkConstants.RAW_LINK_BYTES; import static org.briarproject.bramble.api.contact.PendingContactState.WAITING_FOR_CONNECTION; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; -import static org.briarproject.bramble.test.TestUtils.getRandomBytes; +import static org.briarproject.bramble.test.TestUtils.getAgreementPublicKey; import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.util.StringUtils.getRandomString; import static org.junit.Assert.assertArrayEquals; @@ -34,12 +34,11 @@ public class PendingContactFactoryImplTest extends BrambleMockTestCase { private final CryptoComponent crypto = context.mock(CryptoComponent.class); private final Clock clock = context.mock(Clock.class); private final KeyParser keyParser = context.mock(KeyParser.class); - private final PublicKey publicKey = context.mock(PublicKey.class); private final PendingContactFactory pendingContactFactory = new PendingContactFactoryImpl(crypto, clock); private final String alias = getRandomString(MAX_AUTHOR_NAME_LENGTH); - private final byte[] publicKeyBytes = getRandomBytes(RAW_LINK_BYTES - 1); + private final PublicKey publicKey = getAgreementPublicKey(); private final byte[] idBytes = getRandomId(); private final long timestamp = System.currentTimeMillis(); @@ -64,7 +63,7 @@ public class PendingContactFactoryImplTest extends BrambleMockTestCase { context.checking(new Expectations() {{ oneOf(crypto).getAgreementKeyParser(); will(returnValue(keyParser)); - oneOf(keyParser).parsePublicKey(with(equal(publicKeyBytes))); + oneOf(keyParser).parsePublicKey(publicKey.getEncoded()); will(throwException(new GeneralSecurityException())); }}); @@ -95,11 +94,9 @@ public class PendingContactFactoryImplTest extends BrambleMockTestCase { context.checking(new Expectations() {{ oneOf(crypto).getAgreementKeyParser(); will(returnValue(keyParser)); - oneOf(keyParser).parsePublicKey(with(equal(publicKeyBytes))); + oneOf(keyParser).parsePublicKey(publicKey.getEncoded()); will(returnValue(publicKey)); - allowing(publicKey).getEncoded(); - will(returnValue(publicKeyBytes)); - oneOf(crypto).hash(ID_LABEL, publicKeyBytes); + oneOf(crypto).hash(ID_LABEL, publicKey.getEncoded()); will(returnValue(idBytes)); oneOf(clock).currentTimeMillis(); will(returnValue(timestamp)); @@ -108,7 +105,8 @@ public class PendingContactFactoryImplTest extends BrambleMockTestCase { PendingContact p = pendingContactFactory.createPendingContact(link, alias); assertArrayEquals(idBytes, p.getId().getBytes()); - assertArrayEquals(publicKeyBytes, p.getPublicKey()); + assertArrayEquals(publicKey.getEncoded(), + p.getPublicKey().getEncoded()); assertEquals(alias, p.getAlias()); assertEquals(WAITING_FOR_CONNECTION, p.getState()); assertEquals(timestamp, p.getTimestamp()); @@ -121,6 +119,7 @@ public class PendingContactFactoryImplTest extends BrambleMockTestCase { private String encodeLink(int formatVersion) { byte[] rawLink = new byte[RAW_LINK_BYTES]; rawLink[0] = (byte) formatVersion; + byte[] publicKeyBytes = publicKey.getEncoded(); arraycopy(publicKeyBytes, 0, rawLink, 1, publicKeyBytes.length); String base32 = Base32.encode(rawLink).toLowerCase(); assertEquals(BASE32_LINK_BYTES, base32.length()); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/EdSignatureTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/EdSignatureTest.java index 62bf21819..903908d02 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/EdSignatureTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/EdSignatureTest.java @@ -1,6 +1,10 @@ package org.briarproject.bramble.crypto; import org.briarproject.bramble.api.crypto.KeyPair; +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.junit.Test; import java.security.GeneralSecurityException; @@ -137,14 +141,14 @@ public class EdSignatureTest extends SignatureTest { } @Override - protected byte[] sign(String label, byte[] toSign, byte[] privateKey) + protected byte[] sign(String label, byte[] toSign, PrivateKey privateKey) throws GeneralSecurityException { return crypto.sign(label, toSign, privateKey); } @Override protected boolean verify(byte[] signature, String label, byte[] signed, - byte[] publicKey) throws GeneralSecurityException { + PublicKey publicKey) throws GeneralSecurityException { return crypto.verifySignature(signature, label, signed, publicKey); } @@ -157,11 +161,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)); } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyAgreementTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyAgreementTest.java index f0505f4f1..92bb9fc38 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyAgreementTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyAgreementTest.java @@ -1,5 +1,6 @@ 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,18 +59,18 @@ 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); } @Test - public void testRfc7748TestVector() throws Exception { + public void testRfc7748TestVector() { // Private keys need to be clamped because curve25519-java does the // clamping at key generation time, not multiplication time - byte[] aPriv = Curve25519KeyParser.clamp(fromHexString(ALICE_PRIVATE)); + byte[] aPriv = AgreementKeyParser.clamp(fromHexString(ALICE_PRIVATE)); byte[] aPub = fromHexString(ALICE_PUBLIC); - byte[] bPriv = Curve25519KeyParser.clamp(fromHexString(BOB_PRIVATE)); + byte[] bPriv = AgreementKeyParser.clamp(fromHexString(BOB_PRIVATE)); byte[] bPub = fromHexString(BOB_PUBLIC); byte[] sharedSecret = fromHexString(SHARED_SECRET); Curve25519 curve25519 = Curve25519.getInstance("java"); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyEncodingAndParsingTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyEncodingAndParsingTest.java index 7c14ca505..38a9aa093 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyEncodingAndParsingTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyEncodingAndParsingTest.java @@ -23,7 +23,7 @@ public class KeyEncodingAndParsingTest extends BrambleTestCase { new CryptoComponentImpl(new TestSecureRandomProvider(), null); @Test - public void testAgreementPublicKeyLength() throws Exception { + public void testAgreementPublicKeyLength() { // Generate 10 agreement key pairs for (int i = 0; i < 10; i++) { KeyPair keyPair = crypto.generateAgreementKeyPair(); @@ -70,7 +70,7 @@ public class KeyEncodingAndParsingTest extends BrambleTestCase { } @Test - public void testAgreementKeyParserByFuzzing() throws Exception { + public void testAgreementKeyParserByFuzzing() { KeyParser parser = crypto.getAgreementKeyParser(); // Generate a key pair to get the proper public key length KeyPair p = crypto.generateAgreementKeyPair(); @@ -92,7 +92,7 @@ public class KeyEncodingAndParsingTest extends BrambleTestCase { } @Test - public void testSignaturePublicKeyLength() throws Exception { + public void testSignaturePublicKeyLength() { // Generate 10 signature key pairs for (int i = 0; i < 10; i++) { KeyPair keyPair = crypto.generateSignatureKeyPair(); @@ -107,10 +107,10 @@ public class KeyEncodingAndParsingTest extends BrambleTestCase { // Generate 10 signature key pairs for (int i = 0; i < 10; i++) { KeyPair keyPair = crypto.generateSignatureKeyPair(); - byte[] key = keyPair.getPrivate().getEncoded(); + PrivateKey privateKey = keyPair.getPrivate(); // Sign some random data and check the length of the signature byte[] toBeSigned = getRandomBytes(1234); - byte[] signature = crypto.sign("label", toBeSigned, key); + byte[] signature = crypto.sign("label", toBeSigned, privateKey); assertTrue(signature.length <= MAX_SIGNATURE_BYTES); } } @@ -123,16 +123,15 @@ public class KeyEncodingAndParsingTest extends BrambleTestCase { PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate(); byte[] message = getRandomBytes(123); - byte[] signature = crypto.sign("test", message, - privateKey.getEncoded()); + byte[] signature = crypto.sign("test", message, privateKey); // Verify the signature assertTrue(crypto.verifySignature(signature, "test", message, - publicKey.getEncoded())); + publicKey)); // Encode and parse the public key - no exceptions should be thrown publicKey = parser.parsePublicKey(publicKey.getEncoded()); // Verify the signature again assertTrue(crypto.verifySignature(signature, "test", message, - publicKey.getEncoded())); + publicKey)); } @Test @@ -143,23 +142,21 @@ public class KeyEncodingAndParsingTest extends BrambleTestCase { PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate(); byte[] message = getRandomBytes(123); - byte[] signature = crypto.sign("test", message, - privateKey.getEncoded()); + byte[] signature = crypto.sign("test", message, privateKey); // Verify the signature assertTrue(crypto.verifySignature(signature, "test", message, - publicKey.getEncoded())); + publicKey)); // Encode and parse the private key - no exceptions should be thrown privateKey = parser.parsePrivateKey(privateKey.getEncoded()); // Sign the data again - the signatures should be the same - byte[] signature1 = crypto.sign("test", message, - privateKey.getEncoded()); + byte[] signature1 = crypto.sign("test", message, privateKey); assertTrue(crypto.verifySignature(signature1, "test", message, - publicKey.getEncoded())); + publicKey)); assertArrayEquals(signature, signature1); } @Test - public void testSignatureKeyParserByFuzzing() throws Exception { + public void testSignatureKeyParserByFuzzing() { KeyParser parser = crypto.getSignatureKeyParser(); // Generate a key pair to get the proper public key length KeyPair p = crypto.generateSignatureKeyPair(); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/SignatureTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/SignatureTest.java index 2939541b3..808420d1f 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/SignatureTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/SignatureTest.java @@ -2,6 +2,8 @@ package org.briarproject.bramble.crypto; import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.KeyPair; +import org.briarproject.bramble.api.crypto.PrivateKey; +import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.test.TestSecureRandomProvider; import org.briarproject.bramble.test.TestUtils; @@ -19,23 +21,24 @@ public abstract class SignatureTest extends BrambleTestCase { protected final CryptoComponent crypto; - private final byte[] publicKey, privateKey; + private final PublicKey publicKey; + private final PrivateKey privateKey; private final String label = StringUtils.getRandomString(42); private final byte[] inputBytes = TestUtils.getRandomBytes(123); protected abstract KeyPair generateKeyPair(); protected abstract byte[] sign(String label, byte[] toSign, - byte[] privateKey) throws GeneralSecurityException; + PrivateKey privateKey) throws GeneralSecurityException; protected abstract boolean verify(byte[] signature, String label, - byte[] signed, byte[] publicKey) throws GeneralSecurityException; + byte[] signed, PublicKey publicKey) throws GeneralSecurityException; SignatureTest() { crypto = new CryptoComponentImpl(new TestSecureRandomProvider(), null); KeyPair k = generateKeyPair(); - publicKey = k.getPublic().getEncoded(); - privateKey = k.getPrivate().getEncoded(); + publicKey = k.getPublic(); + privateKey = k.getPrivate(); } @Test @@ -51,7 +54,7 @@ public abstract class SignatureTest extends BrambleTestCase { public void testDifferentKeysProduceDifferentSignatures() throws Exception { // Generate second private key KeyPair k2 = generateKeyPair(); - byte[] privateKey2 = k2.getPrivate().getEncoded(); + PrivateKey privateKey2 = k2.getPrivate(); // Calculate the signature with each key byte[] sig1 = sign(label, inputBytes, privateKey); byte[] sig2 = sign(label, inputBytes, privateKey2); @@ -92,7 +95,7 @@ public abstract class SignatureTest extends BrambleTestCase { public void testDifferentKeyFailsVerification() throws Exception { // Generate second private key KeyPair k2 = generateKeyPair(); - byte[] privateKey2 = k2.getPrivate().getEncoded(); + PrivateKey privateKey2 = k2.getPrivate(); // calculate the signature with different key, should fail to verify byte[] sig = sign(label, inputBytes, privateKey2); assertFalse(verify(sig, label, inputBytes, publicKey)); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java index 4968bf81e..1de270ad0 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java @@ -5,6 +5,8 @@ import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.PendingContactId; import org.briarproject.bramble.api.contact.event.ContactAddedEvent; import org.briarproject.bramble.api.contact.event.ContactRemovedEvent; +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.db.ContactExistsException; import org.briarproject.bramble.api.db.DatabaseComponent; @@ -66,7 +68,6 @@ import java.util.concurrent.atomic.AtomicReference; import static java.util.Arrays.asList; import static java.util.Collections.emptyMap; import static java.util.Collections.singletonList; -import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_AGREEMENT_PUBLIC_KEY_BYTES; import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE; import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED; import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE; @@ -75,13 +76,14 @@ import static org.briarproject.bramble.api.sync.validation.MessageState.DELIVERE import static org.briarproject.bramble.api.sync.validation.MessageState.UNKNOWN; import static org.briarproject.bramble.api.transport.TransportConstants.REORDERING_WINDOW_SIZE; import static org.briarproject.bramble.db.DatabaseConstants.MAX_OFFERED_MESSAGES; +import static org.briarproject.bramble.test.TestUtils.getAgreementPrivateKey; +import static org.briarproject.bramble.test.TestUtils.getAgreementPublicKey; import static org.briarproject.bramble.test.TestUtils.getAuthor; import static org.briarproject.bramble.test.TestUtils.getClientId; import static org.briarproject.bramble.test.TestUtils.getContact; import static org.briarproject.bramble.test.TestUtils.getGroup; import static org.briarproject.bramble.test.TestUtils.getIdentity; import static org.briarproject.bramble.test.TestUtils.getMessage; -import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getSecretKey; import static org.briarproject.bramble.test.TestUtils.getTransportId; @@ -476,8 +478,8 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { } try { - byte[] publicKey = getRandomBytes(MAX_AGREEMENT_PUBLIC_KEY_BYTES); - byte[] privateKey = getRandomBytes(123); + PublicKey publicKey = getAgreementPublicKey(); + PrivateKey privateKey = getAgreementPrivateKey(); db.transaction(false, transaction -> db.setHandshakeKeyPair(transaction, localAuthor.getId(), publicKey, privateKey)); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java index 9093baa07..9b8b280de 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java @@ -3,6 +3,8 @@ package org.briarproject.bramble.db; import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.PendingContact; +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.db.DatabaseConfig; import org.briarproject.bramble.api.db.DbException; @@ -58,7 +60,6 @@ import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; import static java.util.concurrent.TimeUnit.SECONDS; import static org.briarproject.bramble.api.contact.PendingContactState.FAILED; -import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_AGREEMENT_PUBLIC_KEY_BYTES; import static org.briarproject.bramble.api.db.Metadata.REMOVE; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE; @@ -72,13 +73,14 @@ import static org.briarproject.bramble.db.DatabaseConstants.DB_SETTINGS_NAMESPAC import static org.briarproject.bramble.db.DatabaseConstants.LAST_COMPACTED_KEY; import static org.briarproject.bramble.db.DatabaseConstants.MAX_COMPACTION_INTERVAL_MS; import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory; +import static org.briarproject.bramble.test.TestUtils.getAgreementPrivateKey; +import static org.briarproject.bramble.test.TestUtils.getAgreementPublicKey; import static org.briarproject.bramble.test.TestUtils.getAuthor; import static org.briarproject.bramble.test.TestUtils.getClientId; import static org.briarproject.bramble.test.TestUtils.getGroup; import static org.briarproject.bramble.test.TestUtils.getIdentity; import static org.briarproject.bramble.test.TestUtils.getMessage; import static org.briarproject.bramble.test.TestUtils.getPendingContact; -import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getSecretKey; import static org.briarproject.bramble.test.TestUtils.getTestDirectory; @@ -2250,8 +2252,8 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { Identity withoutKeys = new Identity(localAuthor, null, null, identity.getTimeCreated()); assertFalse(withoutKeys.hasHandshakeKeyPair()); - byte[] publicKey = getRandomBytes(MAX_AGREEMENT_PUBLIC_KEY_BYTES); - byte[] privateKey = getRandomBytes(123); + PublicKey publicKey = getAgreementPublicKey(); + PrivateKey privateKey = getAgreementPrivateKey(); Database db = open(false); Connection txn = db.startTransaction(); @@ -2262,8 +2264,12 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { db.setHandshakeKeyPair(txn, localAuthor.getId(), publicKey, privateKey); retrieved = db.getIdentity(txn, localAuthor.getId()); assertTrue(retrieved.hasHandshakeKeyPair()); - assertArrayEquals(publicKey, retrieved.getHandshakePublicKey()); - assertArrayEquals(privateKey, retrieved.getHandshakePrivateKey()); + PublicKey handshakePub = retrieved.getHandshakePublicKey(); + assertNotNull(handshakePub); + assertArrayEquals(publicKey.getEncoded(), handshakePub.getEncoded()); + PrivateKey handshakePriv = retrieved.getHandshakePrivateKey(); + assertNotNull(handshakePriv); + assertArrayEquals(privateKey.getEncoded(), handshakePriv.getEncoded()); db.commitTransaction(txn); db.close(); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/identity/IdentityManagerImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/identity/IdentityManagerImplTest.java index 05a8c5ec2..16d2f8135 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/identity/IdentityManagerImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/identity/IdentityManagerImplTest.java @@ -18,6 +18,8 @@ import org.junit.Before; import org.junit.Test; import static java.util.Collections.singletonList; +import static org.briarproject.bramble.test.TestUtils.getAgreementPrivateKey; +import static org.briarproject.bramble.test.TestUtils.getAgreementPublicKey; import static org.briarproject.bramble.test.TestUtils.getIdentity; import static org.junit.Assert.assertEquals; @@ -28,21 +30,16 @@ public class IdentityManagerImplTest extends BrambleMockTestCase { private final AuthorFactory authorFactory = context.mock(AuthorFactory.class); private final Clock clock = context.mock(Clock.class); - private final PublicKey handshakePublicKey = context.mock(PublicKey.class); - private final PrivateKey handshakePrivateKey = - context.mock(PrivateKey.class); private final Transaction txn = new Transaction(null, false); private final Identity identityWithKeys = getIdentity(); private final LocalAuthor localAuthor = identityWithKeys.getLocalAuthor(); private final Identity identityWithoutKeys = new Identity(localAuthor, null, null, identityWithKeys.getTimeCreated()); + private final PublicKey handshakePublicKey = getAgreementPublicKey(); + private final PrivateKey handshakePrivateKey = getAgreementPrivateKey(); private final KeyPair handshakeKeyPair = new KeyPair(handshakePublicKey, handshakePrivateKey); - private final byte[] handshakePublicKeyBytes = - identityWithKeys.getHandshakePublicKey(); - private final byte[] handshakePrivateKeyBytes = - identityWithKeys.getHandshakePrivateKey(); private IdentityManagerImpl identityManager; @@ -69,12 +66,8 @@ public class IdentityManagerImplTest extends BrambleMockTestCase { will(returnValue(singletonList(identityWithoutKeys))); oneOf(crypto).generateAgreementKeyPair(); will(returnValue(handshakeKeyPair)); - oneOf(handshakePublicKey).getEncoded(); - will(returnValue(handshakePublicKeyBytes)); - oneOf(handshakePrivateKey).getEncoded(); - will(returnValue(handshakePrivateKeyBytes)); oneOf(db).setHandshakeKeyPair(txn, localAuthor.getId(), - handshakePublicKeyBytes, handshakePrivateKeyBytes); + handshakePublicKey, handshakePrivateKey); }}); identityManager.onDatabaseOpened(txn); @@ -104,10 +97,6 @@ public class IdentityManagerImplTest extends BrambleMockTestCase { will(returnValue(singletonList(identityWithoutKeys))); oneOf(crypto).generateAgreementKeyPair(); will(returnValue(handshakeKeyPair)); - oneOf(handshakePublicKey).getEncoded(); - will(returnValue(handshakePublicKeyBytes)); - oneOf(handshakePrivateKey).getEncoded(); - will(returnValue(handshakePrivateKeyBytes)); }}); assertEquals(localAuthor, identityManager.getLocalAuthor()); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/keyagreement/KeyAgreementProtocolTest.java b/bramble-core/src/test/java/org/briarproject/bramble/keyagreement/KeyAgreementProtocolTest.java index 516f7f1b2..78b375631 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/keyagreement/KeyAgreementProtocolTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/keyagreement/KeyAgreementProtocolTest.java @@ -16,10 +16,13 @@ import org.jmock.lib.legacy.ClassImposteriser; import org.junit.Rule; import org.junit.Test; +import static java.util.Collections.emptyList; import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH; import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.MASTER_KEY_LABEL; import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.PROTOCOL_VERSION; import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.SHARED_SECRET_LABEL; +import static org.briarproject.bramble.test.TestUtils.getAgreementPrivateKey; +import static org.briarproject.bramble.test.TestUtils.getAgreementPublicKey; import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getSecretKey; import static org.hamcrest.Matchers.equalTo; @@ -34,21 +37,17 @@ public class KeyAgreementProtocolTest extends BrambleTestCase { setImposteriser(ClassImposteriser.INSTANCE); }}; - private final PublicKey alicePubKey = - context.mock(PublicKey.class, "alice"); - private final byte[] alicePubKeyBytes = getRandomBytes(32); + private final PublicKey alicePubKey = getAgreementPublicKey(); private final byte[] aliceCommit = getRandomBytes(COMMIT_LENGTH); private final byte[] alicePayload = getRandomBytes(COMMIT_LENGTH + 8); private final byte[] aliceConfirm = getRandomBytes(SecretKey.LENGTH); - private final PublicKey bobPubKey = context.mock(PublicKey.class, "bob"); - private final byte[] bobPubKeyBytes = getRandomBytes(32); + private final PublicKey bobPubKey = getAgreementPublicKey(); private final byte[] bobCommit = getRandomBytes(COMMIT_LENGTH); private final byte[] bobPayload = getRandomBytes(COMMIT_LENGTH + 19); private final byte[] bobConfirm = getRandomBytes(SecretKey.LENGTH); - private final PublicKey badPubKey = context.mock(PublicKey.class, "bad"); - private final byte[] badPubKeyBytes = getRandomBytes(32); + private final PublicKey badPubKey = getAgreementPublicKey(); private final byte[] badCommit = getRandomBytes(COMMIT_LENGTH); private final byte[] badConfirm = getRandomBytes(SecretKey.LENGTH); @@ -64,15 +63,13 @@ public class KeyAgreementProtocolTest extends BrambleTestCase { PayloadEncoder payloadEncoder; @Mock KeyAgreementTransport transport; - @Mock - PublicKey ourPubKey; @Test public void testAliceProtocol() throws Exception { // set up - Payload theirPayload = new Payload(bobCommit, null); - Payload ourPayload = new Payload(aliceCommit, null); - KeyPair ourKeyPair = new KeyPair(ourPubKey, null); + Payload theirPayload = new Payload(bobCommit, emptyList()); + Payload ourPayload = new Payload(aliceCommit, emptyList()); + KeyPair ourKeyPair = new KeyPair(alicePubKey, getAgreementPrivateKey()); SecretKey sharedSecret = getSecretKey(); SecretKey masterKey = getSecretKey(); @@ -87,24 +84,18 @@ public class KeyAgreementProtocolTest extends BrambleTestCase { will(returnValue(alicePayload)); allowing(payloadEncoder).encode(theirPayload); will(returnValue(bobPayload)); - allowing(ourPubKey).getEncoded(); - will(returnValue(alicePubKeyBytes)); allowing(crypto).getAgreementKeyParser(); will(returnValue(keyParser)); - allowing(alicePubKey).getEncoded(); - will(returnValue(alicePubKeyBytes)); - allowing(bobPubKey).getEncoded(); - will(returnValue(bobPubKeyBytes)); // Alice sends her public key - oneOf(transport).sendKey(alicePubKeyBytes); + oneOf(transport).sendKey(alicePubKey.getEncoded()); // Alice receives Bob's public key oneOf(callbacks).connectionWaiting(); oneOf(transport).receiveKey(); - will(returnValue(bobPubKeyBytes)); + will(returnValue(bobPubKey.getEncoded())); oneOf(callbacks).initialRecordReceived(); - oneOf(keyParser).parsePublicKey(bobPubKeyBytes); + oneOf(keyParser).parsePublicKey(bobPubKey.getEncoded()); will(returnValue(bobPubKey)); // Alice verifies Bob's public key @@ -114,7 +105,7 @@ public class KeyAgreementProtocolTest extends BrambleTestCase { // Alice computes shared secret oneOf(crypto).deriveSharedSecret(SHARED_SECRET_LABEL, bobPubKey, ourKeyPair, new byte[] {PROTOCOL_VERSION}, - alicePubKeyBytes, bobPubKeyBytes); + alicePubKey.getEncoded(), bobPubKey.getEncoded()); will(returnValue(sharedSecret)); // Alice sends her confirmation record @@ -146,9 +137,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase { @Test public void testBobProtocol() throws Exception { // set up - Payload theirPayload = new Payload(aliceCommit, null); - Payload ourPayload = new Payload(bobCommit, null); - KeyPair ourKeyPair = new KeyPair(ourPubKey, null); + Payload theirPayload = new Payload(aliceCommit, emptyList()); + Payload ourPayload = new Payload(bobCommit, emptyList()); + KeyPair ourKeyPair = new KeyPair(bobPubKey, getAgreementPrivateKey()); SecretKey sharedSecret = getSecretKey(); SecretKey masterKey = getSecretKey(); @@ -163,20 +154,14 @@ public class KeyAgreementProtocolTest extends BrambleTestCase { will(returnValue(bobPayload)); allowing(payloadEncoder).encode(theirPayload); will(returnValue(alicePayload)); - allowing(ourPubKey).getEncoded(); - will(returnValue(bobPubKeyBytes)); allowing(crypto).getAgreementKeyParser(); will(returnValue(keyParser)); - allowing(alicePubKey).getEncoded(); - will(returnValue(alicePubKeyBytes)); - allowing(bobPubKey).getEncoded(); - will(returnValue(bobPubKeyBytes)); // Bob receives Alice's public key oneOf(transport).receiveKey(); - will(returnValue(alicePubKeyBytes)); + will(returnValue(alicePubKey.getEncoded())); oneOf(callbacks).initialRecordReceived(); - oneOf(keyParser).parsePublicKey(alicePubKeyBytes); + oneOf(keyParser).parsePublicKey(alicePubKey.getEncoded()); will(returnValue(alicePubKey)); // Bob verifies Alice's public key @@ -184,12 +169,12 @@ public class KeyAgreementProtocolTest extends BrambleTestCase { will(returnValue(aliceCommit)); // Bob sends his public key - oneOf(transport).sendKey(bobPubKeyBytes); + oneOf(transport).sendKey(bobPubKey.getEncoded()); // Bob computes shared secret oneOf(crypto).deriveSharedSecret(SHARED_SECRET_LABEL, alicePubKey, ourKeyPair, new byte[] {PROTOCOL_VERSION}, - alicePubKeyBytes, bobPubKeyBytes); + alicePubKey.getEncoded(), bobPubKey.getEncoded()); will(returnValue(sharedSecret)); // Bob receives Alices's confirmation record @@ -221,9 +206,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase { @Test(expected = AbortException.class) public void testAliceProtocolAbortOnBadKey() throws Exception { // set up - Payload theirPayload = new Payload(bobCommit, null); - Payload ourPayload = new Payload(aliceCommit, null); - KeyPair ourKeyPair = new KeyPair(ourPubKey, null); + Payload theirPayload = new Payload(bobCommit, emptyList()); + Payload ourPayload = new Payload(aliceCommit, emptyList()); + KeyPair ourKeyPair = new KeyPair(alicePubKey, getAgreementPrivateKey()); KeyAgreementProtocol protocol = new KeyAgreementProtocol(callbacks, crypto, keyAgreementCrypto, payloadEncoder, transport, @@ -232,20 +217,18 @@ public class KeyAgreementProtocolTest extends BrambleTestCase { // expectations context.checking(new Expectations() {{ // Helpers - allowing(ourPubKey).getEncoded(); - will(returnValue(alicePubKeyBytes)); allowing(crypto).getAgreementKeyParser(); will(returnValue(keyParser)); // Alice sends her public key - oneOf(transport).sendKey(alicePubKeyBytes); + oneOf(transport).sendKey(alicePubKey.getEncoded()); // Alice receives a bad public key oneOf(callbacks).connectionWaiting(); oneOf(transport).receiveKey(); - will(returnValue(badPubKeyBytes)); + will(returnValue(badPubKey.getEncoded())); oneOf(callbacks).initialRecordReceived(); - oneOf(keyParser).parsePublicKey(badPubKeyBytes); + oneOf(keyParser).parsePublicKey(badPubKey.getEncoded()); will(returnValue(badPubKey)); // Alice verifies Bob's public key @@ -258,7 +241,7 @@ public class KeyAgreementProtocolTest extends BrambleTestCase { // Alice never computes shared secret never(crypto).deriveSharedSecret(SHARED_SECRET_LABEL, badPubKey, ourKeyPair, new byte[] {PROTOCOL_VERSION}, - alicePubKeyBytes, bobPubKeyBytes); + alicePubKey.getEncoded(), bobPubKey.getEncoded()); }}); // execute @@ -268,9 +251,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase { @Test(expected = AbortException.class) public void testBobProtocolAbortOnBadKey() throws Exception { // set up - Payload theirPayload = new Payload(aliceCommit, null); - Payload ourPayload = new Payload(bobCommit, null); - KeyPair ourKeyPair = new KeyPair(ourPubKey, null); + Payload theirPayload = new Payload(aliceCommit, emptyList()); + Payload ourPayload = new Payload(bobCommit, emptyList()); + KeyPair ourKeyPair = new KeyPair(bobPubKey, getAgreementPrivateKey()); KeyAgreementProtocol protocol = new KeyAgreementProtocol(callbacks, crypto, keyAgreementCrypto, payloadEncoder, transport, @@ -279,16 +262,14 @@ public class KeyAgreementProtocolTest extends BrambleTestCase { // expectations context.checking(new Expectations() {{ // Helpers - allowing(ourPubKey).getEncoded(); - will(returnValue(bobPubKeyBytes)); allowing(crypto).getAgreementKeyParser(); will(returnValue(keyParser)); // Bob receives a bad public key oneOf(transport).receiveKey(); - will(returnValue(badPubKeyBytes)); + will(returnValue(badPubKey.getEncoded())); oneOf(callbacks).initialRecordReceived(); - oneOf(keyParser).parsePublicKey(badPubKeyBytes); + oneOf(keyParser).parsePublicKey(badPubKey.getEncoded()); will(returnValue(badPubKey)); // Bob verifies Alice's public key @@ -299,7 +280,7 @@ public class KeyAgreementProtocolTest extends BrambleTestCase { oneOf(transport).sendAbort(false); // Bob never sends his public key - never(transport).sendKey(bobPubKeyBytes); + never(transport).sendKey(bobPubKey.getEncoded()); }}); // execute @@ -309,9 +290,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase { @Test(expected = AbortException.class) public void testAliceProtocolAbortOnBadConfirm() throws Exception { // set up - Payload theirPayload = new Payload(bobCommit, null); - Payload ourPayload = new Payload(aliceCommit, null); - KeyPair ourKeyPair = new KeyPair(ourPubKey, null); + Payload theirPayload = new Payload(bobCommit, emptyList()); + Payload ourPayload = new Payload(aliceCommit, emptyList()); + KeyPair ourKeyPair = new KeyPair(alicePubKey, getAgreementPrivateKey()); SecretKey sharedSecret = getSecretKey(); KeyAgreementProtocol protocol = new KeyAgreementProtocol(callbacks, @@ -325,22 +306,18 @@ public class KeyAgreementProtocolTest extends BrambleTestCase { will(returnValue(alicePayload)); allowing(payloadEncoder).encode(theirPayload); will(returnValue(bobPayload)); - allowing(ourPubKey).getEncoded(); - will(returnValue(alicePubKeyBytes)); allowing(crypto).getAgreementKeyParser(); will(returnValue(keyParser)); - allowing(bobPubKey).getEncoded(); - will(returnValue(bobPubKeyBytes)); // Alice sends her public key - oneOf(transport).sendKey(alicePubKeyBytes); + oneOf(transport).sendKey(alicePubKey.getEncoded()); // Alice receives Bob's public key oneOf(callbacks).connectionWaiting(); oneOf(transport).receiveKey(); - will(returnValue(bobPubKeyBytes)); + will(returnValue(bobPubKey.getEncoded())); oneOf(callbacks).initialRecordReceived(); - oneOf(keyParser).parsePublicKey(bobPubKeyBytes); + oneOf(keyParser).parsePublicKey(bobPubKey.getEncoded()); will(returnValue(bobPubKey)); // Alice verifies Bob's public key @@ -350,7 +327,7 @@ public class KeyAgreementProtocolTest extends BrambleTestCase { // Alice computes shared secret oneOf(crypto).deriveSharedSecret(SHARED_SECRET_LABEL, bobPubKey, ourKeyPair, new byte[] {PROTOCOL_VERSION}, - alicePubKeyBytes, bobPubKeyBytes); + alicePubKey.getEncoded(), bobPubKey.getEncoded()); will(returnValue(sharedSecret)); // Alice sends her confirmation record @@ -384,9 +361,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase { @Test(expected = AbortException.class) public void testBobProtocolAbortOnBadConfirm() throws Exception { // set up - Payload theirPayload = new Payload(aliceCommit, null); - Payload ourPayload = new Payload(bobCommit, null); - KeyPair ourKeyPair = new KeyPair(ourPubKey, null); + Payload theirPayload = new Payload(aliceCommit, emptyList()); + Payload ourPayload = new Payload(bobCommit, emptyList()); + KeyPair ourKeyPair = new KeyPair(bobPubKey, getAgreementPrivateKey()); SecretKey sharedSecret = getSecretKey(); KeyAgreementProtocol protocol = new KeyAgreementProtocol(callbacks, @@ -400,18 +377,14 @@ public class KeyAgreementProtocolTest extends BrambleTestCase { will(returnValue(bobPayload)); allowing(payloadEncoder).encode(theirPayload); will(returnValue(alicePayload)); - allowing(ourPubKey).getEncoded(); - will(returnValue(bobPubKeyBytes)); allowing(crypto).getAgreementKeyParser(); will(returnValue(keyParser)); - allowing(alicePubKey).getEncoded(); - will(returnValue(alicePubKeyBytes)); // Bob receives Alice's public key oneOf(transport).receiveKey(); - will(returnValue(alicePubKeyBytes)); + will(returnValue(alicePubKey.getEncoded())); oneOf(callbacks).initialRecordReceived(); - oneOf(keyParser).parsePublicKey(alicePubKeyBytes); + oneOf(keyParser).parsePublicKey(alicePubKey.getEncoded()); will(returnValue(alicePubKey)); // Bob verifies Alice's public key @@ -419,12 +392,12 @@ public class KeyAgreementProtocolTest extends BrambleTestCase { will(returnValue(aliceCommit)); // Bob sends his public key - oneOf(transport).sendKey(bobPubKeyBytes); + oneOf(transport).sendKey(bobPubKey.getEncoded()); // Bob computes shared secret oneOf(crypto).deriveSharedSecret(SHARED_SECRET_LABEL, alicePubKey, ourKeyPair, new byte[] {PROTOCOL_VERSION}, - alicePubKeyBytes, bobPubKeyBytes); + alicePubKey.getEncoded(), bobPubKey.getEncoded()); will(returnValue(sharedSecret)); // Bob receives a bad confirmation record diff --git a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationFactory.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationFactory.java index a07aee2f8..061afd6e1 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationFactory.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationFactory.java @@ -2,6 +2,7 @@ package org.briarproject.briar.api.privategroup.invitation; import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.crypto.CryptoExecutor; +import org.briarproject.bramble.api.crypto.PrivateKey; import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; @@ -21,7 +22,7 @@ public interface GroupInvitationFactory { */ @CryptoExecutor byte[] signInvitation(Contact c, GroupId privateGroupId, long timestamp, - byte[] privateKey); + PrivateKey privateKey); /** * Returns a token to be signed by the creator when inviting a member to diff --git a/briar-core/src/main/java/org/briarproject/briar/feed/FeedFactoryImpl.java b/briar-core/src/main/java/org/briarproject/briar/feed/FeedFactoryImpl.java index 8a0b41776..b8e9f2740 100644 --- a/briar-core/src/main/java/org/briarproject/briar/feed/FeedFactoryImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/feed/FeedFactoryImpl.java @@ -4,6 +4,8 @@ import com.rometools.rome.feed.synd.SyndFeed; import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.client.ClientHelper; +import org.briarproject.bramble.api.crypto.PrivateKey; +import org.briarproject.bramble.api.crypto.SignaturePrivateKey; import org.briarproject.bramble.api.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfEntry; import org.briarproject.bramble.api.data.BdfList; @@ -70,7 +72,8 @@ class FeedFactoryImpl implements FeedFactory { String url = d.getString(KEY_FEED_URL); BdfList authorList = d.getList(KEY_FEED_AUTHOR); - byte[] privateKey = d.getRaw(KEY_FEED_PRIVATE_KEY); + PrivateKey privateKey = + new SignaturePrivateKey(d.getRaw(KEY_FEED_PRIVATE_KEY)); Author author = clientHelper.parseAndValidateAuthor(authorList); LocalAuthor localAuthor = new LocalAuthor(author.getId(), author.getFormatVersion(), author.getName(), diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/AbstractProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/introduction/AbstractProtocolEngine.java index 635021e49..b7b20d065 100644 --- a/briar-core/src/main/java/org/briarproject/briar/introduction/AbstractProtocolEngine.java +++ b/briar-core/src/main/java/org/briarproject/briar/introduction/AbstractProtocolEngine.java @@ -5,6 +5,7 @@ import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.client.ContactGroupFactory; import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.ContactManager; +import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.data.BdfDictionary; import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DbException; @@ -83,7 +84,7 @@ abstract class AbstractProtocolEngine } Message sendAcceptMessage(Transaction txn, PeerSession s, long timestamp, - byte[] ephemeralPublicKey, long acceptTimestamp, + PublicKey ephemeralPublicKey, long acceptTimestamp, Map transportProperties, boolean visible) throws DbException { Message m = messageEncoder diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/AcceptMessage.java b/briar-core/src/main/java/org/briarproject/briar/introduction/AcceptMessage.java index 6cadae73b..d76957616 100644 --- a/briar-core/src/main/java/org/briarproject/briar/introduction/AcceptMessage.java +++ b/briar-core/src/main/java/org/briarproject/briar/introduction/AcceptMessage.java @@ -1,5 +1,6 @@ package org.briarproject.briar.introduction; +import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.properties.TransportProperties; @@ -17,14 +18,13 @@ import javax.annotation.concurrent.Immutable; class AcceptMessage extends AbstractIntroductionMessage { private final SessionId sessionId; - private final byte[] ephemeralPublicKey; + private final PublicKey ephemeralPublicKey; private final long acceptTimestamp; private final Map transportProperties; protected AcceptMessage(MessageId messageId, GroupId groupId, long timestamp, @Nullable MessageId previousMessageId, - SessionId sessionId, - byte[] ephemeralPublicKey, + SessionId sessionId, PublicKey ephemeralPublicKey, long acceptTimestamp, Map transportProperties) { super(messageId, groupId, timestamp, previousMessageId); @@ -38,7 +38,7 @@ class AcceptMessage extends AbstractIntroductionMessage { return sessionId; } - public byte[] getEphemeralPublicKey() { + public PublicKey getEphemeralPublicKey() { return ephemeralPublicKey; } diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeProtocolEngine.java index d7ef81893..6fb2b9421 100644 --- a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeProtocolEngine.java +++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeProtocolEngine.java @@ -6,6 +6,8 @@ import org.briarproject.bramble.api.client.ContactGroupFactory; import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.crypto.KeyPair; +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.data.BdfDictionary; import org.briarproject.bramble.api.db.ContactExistsException; @@ -272,9 +274,9 @@ class IntroduceeProtocolEngine markRequestsUnavailableToAnswer(txn, s); // Create ephemeral key pair and get local transport properties - KeyPair keyPair = crypto.generateKeyPair(); - byte[] publicKey = keyPair.getPublic().getEncoded(); - byte[] privateKey = keyPair.getPrivate().getEncoded(); + KeyPair keyPair = crypto.generateAgreementKeyPair(); + PublicKey publicKey = keyPair.getPublic(); + PrivateKey privateKey = keyPair.getPrivate(); Map transportProperties = transportPropertyManager.getLocalProperties(txn); diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeSession.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeSession.java index 5a6967a90..1f4e902c5 100644 --- a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeSession.java +++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeSession.java @@ -1,5 +1,7 @@ package org.briarproject.briar.introduction; +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.identity.Author; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; @@ -70,7 +72,7 @@ class IntroduceeSession extends Session static IntroduceeSession addLocalAccept(IntroduceeSession s, IntroduceeState state, Message acceptMessage, - byte[] ephemeralPublicKey, byte[] ephemeralPrivateKey, + PublicKey ephemeralPublicKey, PrivateKey ephemeralPrivateKey, long acceptTimestamp, Map transportProperties) { Local local = new Local(s.local.alice, acceptMessage.getId(), @@ -190,7 +192,7 @@ class IntroduceeSession extends Session @Nullable final MessageId lastMessageId; @Nullable - final byte[] ephemeralPublicKey; + final PublicKey ephemeralPublicKey; @Nullable final Map transportProperties; final long acceptTimestamp; @@ -198,7 +200,7 @@ class IntroduceeSession extends Session final byte[] macKey; private Common(boolean alice, @Nullable MessageId lastMessageId, - @Nullable byte[] ephemeralPublicKey, @Nullable + @Nullable PublicKey ephemeralPublicKey, @Nullable Map transportProperties, long acceptTimestamp, @Nullable byte[] macKey) { this.alice = alice; @@ -213,11 +215,12 @@ class IntroduceeSession extends Session static class Local extends Common { final long lastMessageTimestamp; @Nullable - final byte[] ephemeralPrivateKey; + final PrivateKey ephemeralPrivateKey; Local(boolean alice, @Nullable MessageId lastMessageId, - long lastMessageTimestamp, @Nullable byte[] ephemeralPublicKey, - @Nullable byte[] ephemeralPrivateKey, @Nullable + long lastMessageTimestamp, + @Nullable PublicKey ephemeralPublicKey, + @Nullable PrivateKey ephemeralPrivateKey, @Nullable Map transportProperties, long acceptTimestamp, @Nullable byte[] macKey) { super(alice, lastMessageId, ephemeralPublicKey, transportProperties, @@ -239,7 +242,7 @@ class IntroduceeSession extends Session Remote(boolean alice, Author author, @Nullable MessageId lastMessageId, - @Nullable byte[] ephemeralPublicKey, @Nullable + @Nullable PublicKey ephemeralPublicKey, @Nullable Map transportProperties, long acceptTimestamp, @Nullable byte[] macKey) { super(alice, lastMessageId, ephemeralPublicKey, transportProperties, diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionCrypto.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionCrypto.java index 79b77a149..df3a33d3b 100644 --- a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionCrypto.java +++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionCrypto.java @@ -1,6 +1,7 @@ package org.briarproject.briar.introduction; import org.briarproject.bramble.api.crypto.KeyPair; +import org.briarproject.bramble.api.crypto.PrivateKey; import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.AuthorId; @@ -28,7 +29,7 @@ interface IntroductionCrypto { /** * Generates an agreement key pair. */ - KeyPair generateKeyPair(); + KeyPair generateAgreementKeyPair(); /** * Derives a session master key for Alice or Bob. @@ -74,7 +75,7 @@ interface IntroductionCrypto { * (from {@link LocalAuthor#getPrivateKey()}) * @return The signature as a byte array */ - byte[] sign(SecretKey macKey, byte[] privateKey) + byte[] sign(SecretKey macKey, PrivateKey privateKey) throws GeneralSecurityException; /** diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionCryptoImpl.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionCryptoImpl.java index d892c58b3..877c95d45 100644 --- a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionCryptoImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionCryptoImpl.java @@ -4,7 +4,6 @@ import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.client.ClientHelper; 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; @@ -61,7 +60,7 @@ class IntroductionCryptoImpl implements IntroductionCrypto { } @Override - public KeyPair generateKeyPair() { + public KeyPair generateAgreementKeyPair() { return crypto.generateAgreementKeyPair(); } @@ -82,21 +81,17 @@ class IntroductionCryptoImpl implements IntroductionCrypto { ); } - SecretKey deriveMasterKey(byte[] publicKey, byte[] privateKey, - byte[] remotePublicKey, boolean alice) + SecretKey deriveMasterKey(PublicKey publicKey, PrivateKey privateKey, + PublicKey remotePublicKey, boolean alice) throws GeneralSecurityException { - KeyParser kp = crypto.getAgreementKeyParser(); - PublicKey remoteEphemeralPublicKey = kp.parsePublicKey(remotePublicKey); - PublicKey ephemeralPublicKey = kp.parsePublicKey(publicKey); - PrivateKey ephemeralPrivateKey = kp.parsePrivateKey(privateKey); - KeyPair keyPair = new KeyPair(ephemeralPublicKey, ephemeralPrivateKey); + KeyPair keyPair = new KeyPair(publicKey, privateKey); return crypto.deriveSharedSecret( LABEL_MASTER_KEY, - remoteEphemeralPublicKey, + remotePublicKey, keyPair, new byte[] {MAJOR_VERSION}, - alice ? publicKey : remotePublicKey, - alice ? remotePublicKey : publicKey + alice ? publicKey.getEncoded() : remotePublicKey.getEncoded(), + alice ? remotePublicKey.getEncoded() : publicKey.getEncoded() ); } @@ -177,13 +172,9 @@ class IntroductionCryptoImpl implements IntroductionCrypto { } @Override - public byte[] sign(SecretKey macKey, byte[] privateKey) + public byte[] sign(SecretKey macKey, PrivateKey privateKey) throws GeneralSecurityException { - return crypto.sign( - LABEL_AUTH_SIGN, - getNonce(macKey), - privateKey - ); + return crypto.sign(LABEL_AUTH_SIGN, getNonce(macKey), privateKey); } @Override @@ -194,7 +185,7 @@ class IntroductionCryptoImpl implements IntroductionCrypto { verifySignature(macKey, s.getRemote().author.getPublicKey(), signature); } - void verifySignature(SecretKey macKey, byte[] publicKey, + void verifySignature(SecretKey macKey, PublicKey publicKey, byte[] signature) throws GeneralSecurityException { byte[] nonce = getNonce(macKey); if (!crypto.verifySignature(signature, LABEL_AUTH_SIGN, nonce, diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionValidator.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionValidator.java index b62604fe5..a4ac7a45d 100644 --- a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionValidator.java +++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionValidator.java @@ -15,10 +15,9 @@ import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.system.Clock; import org.briarproject.briar.api.client.SessionId; -import java.util.Collections; - import javax.annotation.concurrent.Immutable; +import static java.util.Collections.singletonList; import static org.briarproject.bramble.api.crypto.CryptoConstants.MAC_BYTES; import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_SIGNATURE_BYTES; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; @@ -84,8 +83,7 @@ class IntroductionValidator extends BdfMessageValidator { return new BdfMessageContext(meta); } else { MessageId dependency = new MessageId(previousMessageId); - return new BdfMessageContext(meta, - Collections.singletonList(dependency)); + return new BdfMessageContext(meta, singletonList(dependency)); } } @@ -101,6 +99,7 @@ class IntroductionValidator extends BdfMessageValidator { byte[] ephemeralPublicKey = body.getRaw(3); checkLength(ephemeralPublicKey, 0, MAX_PUBLIC_KEY_LENGTH); + clientHelper.parseAndValidateAgreementPublicKey(ephemeralPublicKey); long timestamp = body.getLong(4); if (timestamp < 0) throw new FormatException(); @@ -111,15 +110,13 @@ class IntroductionValidator extends BdfMessageValidator { .parseAndValidateTransportPropertiesMap(transportProperties); SessionId sessionId = new SessionId(sessionIdBytes); - BdfDictionary meta = messageEncoder - .encodeMetadata(ACCEPT, sessionId, m.getTimestamp(), false, - false, false); + BdfDictionary meta = messageEncoder.encodeMetadata(ACCEPT, sessionId, + m.getTimestamp(), false, false, false); if (previousMessageId == null) { return new BdfMessageContext(meta); } else { MessageId dependency = new MessageId(previousMessageId); - return new BdfMessageContext(meta, - Collections.singletonList(dependency)); + return new BdfMessageContext(meta, singletonList(dependency)); } } @@ -140,12 +137,10 @@ class IntroductionValidator extends BdfMessageValidator { checkLength(signature, 1, MAX_SIGNATURE_BYTES); SessionId sessionId = new SessionId(sessionIdBytes); - BdfDictionary meta = messageEncoder - .encodeMetadata(AUTH, sessionId, m.getTimestamp(), false, false, - false); + BdfDictionary meta = messageEncoder.encodeMetadata(AUTH, sessionId, + m.getTimestamp(), false, false, false); MessageId dependency = new MessageId(previousMessageId); - return new BdfMessageContext(meta, - Collections.singletonList(dependency)); + return new BdfMessageContext(meta, singletonList(dependency)); } private BdfMessageContext validateActivateMessage(Message m, BdfList body) @@ -162,15 +157,13 @@ class IntroductionValidator extends BdfMessageValidator { checkLength(mac, MAC_BYTES); SessionId sessionId = new SessionId(sessionIdBytes); - BdfDictionary meta = messageEncoder - .encodeMetadata(ACTIVATE, sessionId, m.getTimestamp(), false, - false, false); + BdfDictionary meta = messageEncoder.encodeMetadata(ACTIVATE, sessionId, + m.getTimestamp(), false, false, false); if (previousMessageId == null) { return new BdfMessageContext(meta); } else { MessageId dependency = new MessageId(previousMessageId); - return new BdfMessageContext(meta, - Collections.singletonList(dependency)); + return new BdfMessageContext(meta, singletonList(dependency)); } } @@ -185,15 +178,13 @@ class IntroductionValidator extends BdfMessageValidator { checkLength(previousMessageId, UniqueId.LENGTH); SessionId sessionId = new SessionId(sessionIdBytes); - BdfDictionary meta = messageEncoder - .encodeMetadata(type, sessionId, m.getTimestamp(), false, false, - false); + BdfDictionary meta = messageEncoder.encodeMetadata(type, sessionId, + m.getTimestamp(), false, false, false); if (previousMessageId == null) { return new BdfMessageContext(meta); } else { MessageId dependency = new MessageId(previousMessageId); - return new BdfMessageContext(meta, - Collections.singletonList(dependency)); + return new BdfMessageContext(meta, singletonList(dependency)); } } diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/MessageEncoder.java b/briar-core/src/main/java/org/briarproject/briar/introduction/MessageEncoder.java index 98d06b39d..38a4841ea 100644 --- a/briar-core/src/main/java/org/briarproject/briar/introduction/MessageEncoder.java +++ b/briar-core/src/main/java/org/briarproject/briar/introduction/MessageEncoder.java @@ -1,5 +1,6 @@ package org.briarproject.briar.introduction; +import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.data.BdfDictionary; import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; @@ -35,7 +36,7 @@ interface MessageEncoder { Message encodeAcceptMessage(GroupId contactGroupId, long timestamp, @Nullable MessageId previousMessageId, SessionId sessionId, - byte[] ephemeralPublicKey, long acceptTimestamp, + PublicKey ephemeralPublicKey, long acceptTimestamp, Map transportProperties); Message encodeDeclineMessage(GroupId contactGroupId, long timestamp, diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/MessageEncoderImpl.java b/briar-core/src/main/java/org/briarproject/briar/introduction/MessageEncoderImpl.java index 91df8046c..e11d6ecd3 100644 --- a/briar-core/src/main/java/org/briarproject/briar/introduction/MessageEncoderImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/introduction/MessageEncoderImpl.java @@ -2,6 +2,7 @@ package org.briarproject.briar.introduction; import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.client.ClientHelper; +import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.identity.Author; @@ -105,13 +106,13 @@ class MessageEncoderImpl implements MessageEncoder { @Override public Message encodeAcceptMessage(GroupId contactGroupId, long timestamp, @Nullable MessageId previousMessageId, SessionId sessionId, - byte[] ephemeralPublicKey, long acceptTimestamp, + PublicKey ephemeralPublicKey, long acceptTimestamp, Map transportProperties) { BdfList body = BdfList.of( ACCEPT.getValue(), sessionId, previousMessageId, - ephemeralPublicKey, + ephemeralPublicKey.getEncoded(), acceptTimestamp, clientHelper.toDictionary(transportProperties) ); diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/MessageParserImpl.java b/briar-core/src/main/java/org/briarproject/briar/introduction/MessageParserImpl.java index f934af3a0..fb727c0b4 100644 --- a/briar-core/src/main/java/org/briarproject/briar/introduction/MessageParserImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/introduction/MessageParserImpl.java @@ -2,6 +2,8 @@ package org.briarproject.briar.introduction; import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.client.ClientHelper; +import org.briarproject.bramble.api.crypto.AgreementPublicKey; +import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfEntry; import org.briarproject.bramble.api.data.BdfList; @@ -86,7 +88,7 @@ class MessageParserImpl implements MessageParser { byte[] previousMsgBytes = body.getOptionalRaw(2); MessageId previousMessageId = (previousMsgBytes == null ? null : new MessageId(previousMsgBytes)); - byte[] ephemeralPublicKey = body.getRaw(3); + PublicKey ephemeralPublicKey = new AgreementPublicKey(body.getRaw(3)); long acceptTimestamp = body.getLong(4); Map transportProperties = clientHelper .parseAndValidateTransportPropertiesMap(body.getDictionary(5)); diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/SessionParserImpl.java b/briar-core/src/main/java/org/briarproject/briar/introduction/SessionParserImpl.java index 471d8efa2..421b93649 100644 --- a/briar-core/src/main/java/org/briarproject/briar/introduction/SessionParserImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/introduction/SessionParserImpl.java @@ -2,6 +2,10 @@ package org.briarproject.briar.introduction; import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.client.ClientHelper; +import org.briarproject.bramble.api.crypto.AgreementPrivateKey; +import org.briarproject.bramble.api.crypto.AgreementPublicKey; +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.BdfEntry; import org.briarproject.bramble.api.identity.Author; @@ -122,12 +126,12 @@ class SessionParserImpl implements SessionParser { MessageId lastLocalMessageId = getMessageId(d, SESSION_KEY_LAST_LOCAL_MESSAGE_ID); long localTimestamp = d.getLong(SESSION_KEY_LOCAL_TIMESTAMP); - byte[] ephemeralPublicKey = - d.getOptionalRaw(SESSION_KEY_EPHEMERAL_PUBLIC_KEY); + PublicKey ephemeralPublicKey = + getEphemeralPublicKey(d, SESSION_KEY_EPHEMERAL_PUBLIC_KEY); BdfDictionary tpDict = d.getOptionalDictionary(SESSION_KEY_TRANSPORT_PROPERTIES); - byte[] ephemeralPrivateKey = - d.getOptionalRaw(SESSION_KEY_EPHEMERAL_PRIVATE_KEY); + PrivateKey ephemeralPrivateKey = + getEphemeralPrivateKey(d, SESSION_KEY_EPHEMERAL_PRIVATE_KEY); Map transportProperties = tpDict == null ? null : clientHelper .parseAndValidateTransportPropertiesMap(tpDict); @@ -143,8 +147,8 @@ class SessionParserImpl implements SessionParser { Author remoteAuthor = getAuthor(d, SESSION_KEY_REMOTE_AUTHOR); MessageId lastRemoteMessageId = getMessageId(d, SESSION_KEY_LAST_REMOTE_MESSAGE_ID); - byte[] ephemeralPublicKey = - d.getOptionalRaw(SESSION_KEY_EPHEMERAL_PUBLIC_KEY); + PublicKey ephemeralPublicKey = + getEphemeralPublicKey(d, SESSION_KEY_EPHEMERAL_PUBLIC_KEY); BdfDictionary tpDict = d.getOptionalDictionary(SESSION_KEY_TRANSPORT_PROPERTIES); Map transportProperties = @@ -195,4 +199,17 @@ class SessionParserImpl implements SessionParser { return map; } + @Nullable + private PublicKey getEphemeralPublicKey(BdfDictionary d, String key) + throws FormatException { + byte[] keyBytes = d.getOptionalRaw(key); + return keyBytes == null ? null : new AgreementPublicKey(keyBytes); + } + + @Nullable + private PrivateKey getEphemeralPrivateKey(BdfDictionary d, String key) + throws FormatException { + byte[] keyBytes = d.getOptionalRaw(key); + return keyBytes == null ? null : new AgreementPrivateKey(keyBytes); + } } diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationFactoryImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationFactoryImpl.java index c8fc2b4ba..9172e33f6 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationFactoryImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationFactoryImpl.java @@ -4,6 +4,7 @@ import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.client.ContactGroupFactory; import org.briarproject.bramble.api.contact.Contact; +import org.briarproject.bramble.api.crypto.PrivateKey; import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; @@ -35,7 +36,7 @@ class GroupInvitationFactoryImpl implements GroupInvitationFactory { @Override public byte[] signInvitation(Contact c, GroupId privateGroupId, - long timestamp, byte[] privateKey) { + long timestamp, PrivateKey privateKey) { AuthorId creatorId = c.getLocalAuthorId(); AuthorId memberId = c.getAuthor().getId(); BdfList token = createInviteToken(creatorId, memberId, privateGroupId, diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageParserImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageParserImpl.java index d15dda40f..cd850f949 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageParserImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageParserImpl.java @@ -19,7 +19,6 @@ import org.briarproject.briar.api.privategroup.PrivateGroupFactory; import javax.annotation.concurrent.Immutable; import javax.inject.Inject; -import static org.briarproject.bramble.api.identity.Author.FORMAT_VERSION; import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_AVAILABLE_TO_ANSWER; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_INVITATION_ACCEPTED; @@ -105,14 +104,7 @@ class MessageParserImpl implements MessageParser { String text = body.getOptionalString(4); byte[] signature = body.getRaw(5); - // Format version, name, public key - int formatVersion = creatorList.getLong(0).intValue(); - if (formatVersion != FORMAT_VERSION) throw new FormatException(); - String creatorName = creatorList.getString(1); - byte[] creatorPublicKey = creatorList.getRaw(2); - - Author creator = authorFactory.createAuthor(formatVersion, creatorName, - creatorPublicKey); + Author creator = clientHelper.parseAndValidateAuthor(creatorList); PrivateGroup privateGroup = privateGroupFactory.createPrivateGroup( groupName, creator, salt); return new InviteMessage(m.getId(), m.getGroupId(), diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/BlogMessageParserImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogMessageParserImpl.java index 9bb080bb2..e111bcd15 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/BlogMessageParserImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogMessageParserImpl.java @@ -4,7 +4,6 @@ import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.identity.Author; -import org.briarproject.bramble.api.identity.AuthorFactory; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.briar.api.blog.Blog; import org.briarproject.briar.api.blog.BlogFactory; @@ -12,21 +11,16 @@ import org.briarproject.briar.api.blog.BlogFactory; import javax.annotation.concurrent.Immutable; import javax.inject.Inject; -import static org.briarproject.bramble.api.identity.Author.FORMAT_VERSION; - @Immutable @NotNullByDefault class BlogMessageParserImpl extends MessageParserImpl { private final BlogFactory blogFactory; - private final AuthorFactory authorFactory; @Inject - BlogMessageParserImpl(ClientHelper clientHelper, BlogFactory blogFactory, - AuthorFactory authorFactory) { + BlogMessageParserImpl(ClientHelper clientHelper, BlogFactory blogFactory) { super(clientHelper); this.blogFactory = blogFactory; - this.authorFactory = authorFactory; } @Override @@ -35,14 +29,7 @@ class BlogMessageParserImpl extends MessageParserImpl { BdfList authorList = descriptor.getList(0); boolean rssFeed = descriptor.getBoolean(1); - // Format version, name, public key - int formatVersion = authorList.getLong(0).intValue(); - if (formatVersion != FORMAT_VERSION) throw new FormatException(); - String name = authorList.getString(1); - byte[] publicKey = authorList.getRaw(2); - - Author author = authorFactory.createAuthor(formatVersion, name, - publicKey); + Author author = clientHelper.parseAndValidateAuthor(authorList); if (rssFeed) return blogFactory.createFeedBlog(author); else return blogFactory.createBlog(author); } diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/MessageParserImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/MessageParserImpl.java index 9ad4db67b..48a001c4a 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/MessageParserImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/MessageParserImpl.java @@ -30,7 +30,7 @@ import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_VISIBLE_IN abstract class MessageParserImpl implements MessageParser { - private final ClientHelper clientHelper; + protected final ClientHelper clientHelper; MessageParserImpl(ClientHelper clientHelper) { this.clientHelper = clientHelper; diff --git a/briar-core/src/test/java/org/briarproject/briar/forum/ForumPostValidatorTest.java b/briar-core/src/test/java/org/briarproject/briar/forum/ForumPostValidatorTest.java index 7369c671d..091d16b4c 100644 --- a/briar-core/src/test/java/org/briarproject/briar/forum/ForumPostValidatorTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/forum/ForumPostValidatorTest.java @@ -3,6 +3,7 @@ package org.briarproject.briar.forum; import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.UniqueId; import org.briarproject.bramble.api.client.BdfMessageContext; +import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.identity.Author; @@ -37,9 +38,9 @@ public class ForumPostValidatorTest extends ValidatorTestCase { private final byte[] signature = getRandomBytes(MAX_SIGNATURE_LENGTH); private final Author author = getAuthor(); private final String authorName = author.getName(); - private final byte[] authorPublicKey = author.getPublicKey(); + private final PublicKey authorPublicKey = author.getPublicKey(); private final BdfList authorList = BdfList.of(author.getFormatVersion(), - authorName, authorPublicKey); + authorName, authorPublicKey.getEncoded()); private final BdfList signedWithParent = BdfList.of(groupId, timestamp, parentId.getBytes(), authorList, text); private final BdfList signedWithoutParent = BdfList.of(groupId, timestamp, diff --git a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionCryptoIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionCryptoIntegrationTest.java index c256d102b..e05a9ab0e 100644 --- a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionCryptoIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionCryptoIntegrationTest.java @@ -64,8 +64,8 @@ public class IntroductionCryptoIntegrationTest extends BrambleTestCase { crypto.isAlice(introducee1.getId(), introducee2.getId()); alice = isAlice ? introducee1 : introducee2; bob = isAlice ? introducee2 : introducee1; - aliceEphemeral = crypto.generateKeyPair(); - bobEphemeral = crypto.generateKeyPair(); + aliceEphemeral = crypto.generateAgreementKeyPair(); + bobEphemeral = crypto.generateAgreementKeyPair(); } @Test @@ -86,30 +86,25 @@ public class IntroductionCryptoIntegrationTest extends BrambleTestCase { @Test public void testDeriveMasterKey() throws Exception { - SecretKey aliceMasterKey = - crypto.deriveMasterKey(aliceEphemeral.getPublic().getEncoded(), - aliceEphemeral.getPrivate().getEncoded(), - bobEphemeral.getPublic().getEncoded(), true); - SecretKey bobMasterKey = - crypto.deriveMasterKey(bobEphemeral.getPublic().getEncoded(), - bobEphemeral.getPrivate().getEncoded(), - aliceEphemeral.getPublic().getEncoded(), false); + SecretKey aliceMasterKey = crypto.deriveMasterKey( + aliceEphemeral.getPublic(), aliceEphemeral.getPrivate(), + bobEphemeral.getPublic(), true); + SecretKey bobMasterKey = crypto.deriveMasterKey( + bobEphemeral.getPublic(), bobEphemeral.getPrivate(), + aliceEphemeral.getPublic(), false); assertArrayEquals(aliceMasterKey.getBytes(), bobMasterKey.getBytes()); } @Test public void testAliceAuthMac() throws Exception { SecretKey aliceMacKey = crypto.deriveMacKey(masterKey, true); - Local local = new Local(true, null, -1, - aliceEphemeral.getPublic().getEncoded(), - aliceEphemeral.getPrivate().getEncoded(), aliceTransport, + Local local = new Local(true, null, -1, aliceEphemeral.getPublic(), + aliceEphemeral.getPrivate(), aliceTransport, aliceAcceptTimestamp, aliceMacKey.getBytes()); - Remote remote = new Remote(false, bob, null, - bobEphemeral.getPublic().getEncoded(), bobTransport, - bobAcceptTimestamp, null); - byte[] aliceMac = - crypto.authMac(aliceMacKey, introducer.getId(), alice.getId(), - local, remote); + Remote remote = new Remote(false, bob, null, bobEphemeral.getPublic(), + bobTransport, bobAcceptTimestamp, null); + byte[] aliceMac = crypto.authMac(aliceMacKey, introducer.getId(), + alice.getId(), local, remote); // verify from Bob's perspective crypto.verifyAuthMac(aliceMac, aliceMacKey, introducer.getId(), @@ -119,16 +114,14 @@ public class IntroductionCryptoIntegrationTest extends BrambleTestCase { @Test public void testBobAuthMac() throws Exception { SecretKey bobMacKey = crypto.deriveMacKey(masterKey, false); - Local local = new Local(false, null, -1, - bobEphemeral.getPublic().getEncoded(), - bobEphemeral.getPrivate().getEncoded(), bobTransport, + Local local = new Local(false, null, -1, bobEphemeral.getPublic(), + bobEphemeral.getPrivate(), bobTransport, bobAcceptTimestamp, bobMacKey.getBytes()); Remote remote = new Remote(true, alice, null, - aliceEphemeral.getPublic().getEncoded(), aliceTransport, + aliceEphemeral.getPublic(), aliceTransport, aliceAcceptTimestamp, null); - byte[] bobMac = - crypto.authMac(bobMacKey, introducer.getId(), bob.getId(), - local, remote); + byte[] bobMac = crypto.authMac(bobMacKey, introducer.getId(), + bob.getId(), local, remote); // verify from Alice's perspective crypto.verifyAuthMac(bobMac, bobMacKey, introducer.getId(), diff --git a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTest.java index 32d172c0d..7e313436b 100644 --- a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTest.java @@ -42,9 +42,8 @@ import java.util.Collection; import java.util.Map; import java.util.concurrent.TimeoutException; -import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.bramble.test.TestPluginConfigModule.TRANSPORT_ID; -import static org.briarproject.bramble.test.TestUtils.getRandomBytes; +import static org.briarproject.bramble.test.TestUtils.getAgreementPublicKey; import static org.briarproject.bramble.test.TestUtils.getSecretKey; import static org.briarproject.bramble.test.TestUtils.getTransportProperties; import static org.briarproject.bramble.test.TestUtils.getTransportPropertiesMap; @@ -1149,8 +1148,7 @@ public class IntroductionIntegrationTest testModifiedResponse( m -> new AcceptMessage(m.getMessageId(), m.getGroupId(), m.getTimestamp(), m.getPreviousMessageId(), - m.getSessionId(), - getRandomBytes(MAX_PUBLIC_KEY_LENGTH), + m.getSessionId(), getAgreementPublicKey(), m.getAcceptTimestamp(), m.getTransportProperties()) ); } @@ -1216,8 +1214,8 @@ public class IntroductionIntegrationTest @ParametersNotNullByDefault private abstract class IntroductionListener implements EventListener { - protected volatile boolean aborted = false; - protected volatile Event latestEvent; + volatile boolean aborted = false; + volatile Event latestEvent; @SuppressWarnings("WeakerAccess") IntroductionResponse getResponse() { diff --git a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionValidatorTest.java b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionValidatorTest.java index 32da49db3..249ba8852 100644 --- a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionValidatorTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionValidatorTest.java @@ -2,6 +2,7 @@ package org.briarproject.briar.introduction; import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.client.BdfMessageContext; +import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfEntry; import org.briarproject.bramble.api.data.BdfList; @@ -14,8 +15,9 @@ import org.junit.Test; import javax.annotation.Nullable; import static org.briarproject.bramble.api.crypto.CryptoConstants.MAC_BYTES; +import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_AGREEMENT_PUBLIC_KEY_BYTES; import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_SIGNATURE_BYTES; -import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; +import static org.briarproject.bramble.test.TestUtils.getAgreementPublicKey; import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.util.StringUtils.getRandomString; @@ -40,6 +42,7 @@ public class IntroductionValidatorTest extends ValidatorTestCase { private final MessageId previousMsgId = new MessageId(getRandomId()); private final String text = getRandomString(MAX_INTRODUCTION_TEXT_LENGTH); private final BdfDictionary meta = new BdfDictionary(); + private final PublicKey ephemeralPublicKey = getAgreementPublicKey(); private final long acceptTimestamp = 42; private final BdfDictionary transportProperties = BdfDictionary.of( new BdfEntry("transportId", new BdfDictionary()) @@ -123,8 +126,9 @@ public class IntroductionValidatorTest extends ValidatorTestCase { @Test public void testAcceptsAccept() throws Exception { BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(), - previousMsgId.getBytes(), getRandomBytes(MAX_PUBLIC_KEY_LENGTH), + previousMsgId.getBytes(), ephemeralPublicKey.getEncoded(), acceptTimestamp, transportProperties); + expectParsePublicKey(); context.checking(new Expectations() {{ oneOf(clientHelper).parseAndValidateTransportPropertiesMap( transportProperties); @@ -139,32 +143,31 @@ public class IntroductionValidatorTest extends ValidatorTestCase { @Test(expected = FormatException.class) public void testRejectsTooShortBodyForAccept() throws Exception { BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(), - previousMsgId.getBytes(), - getRandomBytes(MAX_PUBLIC_KEY_LENGTH), acceptTimestamp); + previousMsgId.getBytes(), ephemeralPublicKey.getEncoded(), + acceptTimestamp); validator.validateMessage(message, group, body); } @Test(expected = FormatException.class) public void testRejectsTooLongBodyForAccept() throws Exception { BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(), - previousMsgId.getBytes(), getRandomBytes(MAX_PUBLIC_KEY_LENGTH), + previousMsgId.getBytes(), ephemeralPublicKey.getEncoded(), acceptTimestamp, transportProperties, null); validator.validateMessage(message, group, body); } @Test(expected = FormatException.class) public void testRejectsInvalidSessionIdForAccept() throws Exception { - BdfList body = - BdfList.of(ACCEPT.getValue(), null, previousMsgId.getBytes(), - getRandomBytes(MAX_PUBLIC_KEY_LENGTH), acceptTimestamp, - transportProperties); + BdfList body = BdfList.of(ACCEPT.getValue(), null, + previousMsgId.getBytes(), ephemeralPublicKey.getEncoded(), + acceptTimestamp, transportProperties); validator.validateMessage(message, group, body); } @Test(expected = FormatException.class) public void testRejectsInvalidPreviousMsgIdForAccept() throws Exception { BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(), 1, - getRandomBytes(MAX_PUBLIC_KEY_LENGTH), acceptTimestamp, + ephemeralPublicKey.getEncoded(), acceptTimestamp, transportProperties); validator.validateMessage(message, group, body); } @@ -173,16 +176,17 @@ public class IntroductionValidatorTest extends ValidatorTestCase { public void testRejectsTooLongPublicKeyForAccept() throws Exception { BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(), previousMsgId.getBytes(), - getRandomBytes(MAX_PUBLIC_KEY_LENGTH + 1), acceptTimestamp, - transportProperties); + getRandomBytes(MAX_AGREEMENT_PUBLIC_KEY_BYTES + 1), + acceptTimestamp, transportProperties); validator.validateMessage(message, group, body); } @Test(expected = FormatException.class) public void testRejectsNegativeTimestampForAccept() throws Exception { BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(), - previousMsgId.getBytes(), getRandomBytes(MAX_PUBLIC_KEY_LENGTH), + previousMsgId.getBytes(), ephemeralPublicKey.getEncoded(), -1, transportProperties); + expectParsePublicKey(); validator.validateMessage(message, group, body); } @@ -190,9 +194,9 @@ public class IntroductionValidatorTest extends ValidatorTestCase { public void testRejectsEmptyTransportPropertiesForAccept() throws Exception { BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(), - previousMsgId.getBytes(), - getRandomBytes(MAX_PUBLIC_KEY_LENGTH + 1), acceptTimestamp, - new BdfDictionary()); + previousMsgId.getBytes(), ephemeralPublicKey.getEncoded(), + acceptTimestamp, new BdfDictionary()); + expectParsePublicKey(); validator.validateMessage(message, group, body); } @@ -271,8 +275,7 @@ public class IntroductionValidatorTest extends ValidatorTestCase { @Test(expected = FormatException.class) public void testRejectsInvalidPreviousMsgIdForAuth() throws Exception { BdfList body = BdfList.of(AUTH.getValue(), sessionId.getBytes(), - 1, getRandomBytes(MAC_BYTES), - signature); + 1, getRandomBytes(MAC_BYTES), signature); validator.validateMessage(message, group, body); } @@ -294,8 +297,8 @@ public class IntroductionValidatorTest extends ValidatorTestCase { @Test(expected = FormatException.class) public void testRejectsTooLongMacForAuth() throws Exception { BdfList body = BdfList.of(AUTH.getValue(), sessionId.getBytes(), - previousMsgId.getBytes(), - getRandomBytes(MAC_BYTES + 1), signature); + previousMsgId.getBytes(), getRandomBytes(MAC_BYTES + 1), + signature); validator.validateMessage(message, group, body); } @@ -360,9 +363,8 @@ public class IntroductionValidatorTest extends ValidatorTestCase { @Test(expected = FormatException.class) public void testRejectsInvalidSessionIdForActivate() throws Exception { - BdfList body = - BdfList.of(ACTIVATE.getValue(), null, previousMsgId.getBytes(), - mac); + BdfList body = BdfList.of(ACTIVATE.getValue(), null, + previousMsgId.getBytes(), mac); validator.validateMessage(message, group, body); } @@ -375,9 +377,8 @@ public class IntroductionValidatorTest extends ValidatorTestCase { @Test(expected = FormatException.class) public void testRejectsPreviousMsgIdNullForActivate() throws Exception { - BdfList body = - BdfList.of(ACTIVATE.getValue(), sessionId.getBytes(), null, - mac); + BdfList body = BdfList.of(ACTIVATE.getValue(), sessionId.getBytes(), + null, mac); validator.validateMessage(message, group, body); } @@ -434,6 +435,13 @@ public class IntroductionValidatorTest extends ValidatorTestCase { // Introduction Helper Methods // + private void expectParsePublicKey() throws Exception { + context.checking(new Expectations() {{ + oneOf(clientHelper).parseAndValidateAgreementPublicKey( + ephemeralPublicKey.getEncoded()); + will(returnValue(ephemeralPublicKey)); + }}); + } private void expectEncodeRequestMetadata() { context.checking(new Expectations() {{ oneOf(messageEncoder).encodeRequestMetadata(message.getTimestamp()); @@ -443,9 +451,8 @@ public class IntroductionValidatorTest extends ValidatorTestCase { private void expectEncodeMetadata(MessageType type) { context.checking(new Expectations() {{ - oneOf(messageEncoder) - .encodeMetadata(type, sessionId, message.getTimestamp(), - false, false, false); + oneOf(messageEncoder).encodeMetadata(type, sessionId, + message.getTimestamp(), false, false, false); will(returnValue(meta)); }}); } diff --git a/briar-core/src/test/java/org/briarproject/briar/introduction/MessageEncoderParserIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/introduction/MessageEncoderParserIntegrationTest.java index 01675c3fc..a6d93a6b9 100644 --- a/briar-core/src/test/java/org/briarproject/briar/introduction/MessageEncoderParserIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/introduction/MessageEncoderParserIntegrationTest.java @@ -2,6 +2,7 @@ package org.briarproject.briar.introduction; import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.client.ClientHelper; +import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.data.BdfDictionary; import org.briarproject.bramble.api.data.MetadataEncoder; import org.briarproject.bramble.api.identity.Author; @@ -24,7 +25,7 @@ import javax.inject.Inject; import static org.briarproject.bramble.api.crypto.CryptoConstants.MAC_BYTES; import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_SIGNATURE_BYTES; -import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; +import static org.briarproject.bramble.test.TestUtils.getAgreementPublicKey; import static org.briarproject.bramble.test.TestUtils.getGroup; import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getRandomId; @@ -66,8 +67,7 @@ public class MessageEncoderParserIntegrationTest extends BrambleTestCase { private final MessageId previousMsgId = new MessageId(getRandomId()); private final Author author; private final String text = getRandomString(MAX_INTRODUCTION_TEXT_LENGTH); - private final byte[] ephemeralPublicKey = - getRandomBytes(MAX_PUBLIC_KEY_LENGTH); + private final PublicKey ephemeralPublicKey = getAgreementPublicKey(); private final byte[] mac = getRandomBytes(MAC_BYTES); private final byte[] signature = getRandomBytes(MAX_SIGNATURE_BYTES); @@ -173,7 +173,8 @@ public class MessageEncoderParserIntegrationTest extends BrambleTestCase { assertEquals(m.getTimestamp(), am.getTimestamp()); assertEquals(previousMsgId, am.getPreviousMessageId()); assertEquals(sessionId, am.getSessionId()); - assertArrayEquals(ephemeralPublicKey, am.getEphemeralPublicKey()); + assertArrayEquals(ephemeralPublicKey.getEncoded(), + am.getEphemeralPublicKey().getEncoded()); assertEquals(acceptTimestamp, am.getAcceptTimestamp()); assertEquals(transportProperties, am.getTransportProperties()); } diff --git a/briar-core/src/test/java/org/briarproject/briar/introduction/SessionEncoderParserIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/introduction/SessionEncoderParserIntegrationTest.java index df29af3d7..d11f1b32a 100644 --- a/briar-core/src/test/java/org/briarproject/briar/introduction/SessionEncoderParserIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/introduction/SessionEncoderParserIntegrationTest.java @@ -2,6 +2,8 @@ package org.briarproject.briar.introduction; import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.client.ClientHelper; +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.data.BdfDictionary; import org.briarproject.bramble.api.identity.Author; @@ -21,7 +23,8 @@ import java.util.Map; import javax.inject.Inject; -import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; +import static org.briarproject.bramble.test.TestUtils.getAgreementPrivateKey; +import static org.briarproject.bramble.test.TestUtils.getAgreementPublicKey; import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getTransportId; @@ -37,6 +40,7 @@ import static org.briarproject.briar.test.BriarTestUtils.getRealAuthor; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -64,13 +68,10 @@ public class SessionEncoderParserIntegrationTest extends BrambleTestCase { private final MessageId lastRemoteMessageId2 = new MessageId(getRandomId()); private final Author author1; private final Author author2; - private final byte[] ephemeralPublicKey = - getRandomBytes(MAX_PUBLIC_KEY_LENGTH); - private final byte[] ephemeralPrivateKey = - getRandomBytes(MAX_PUBLIC_KEY_LENGTH); + private final PublicKey ephemeralPublicKey = getAgreementPublicKey(); + private final PrivateKey ephemeralPrivateKey = getAgreementPrivateKey(); private final byte[] masterKey = getRandomBytes(SecretKey.LENGTH); - private final byte[] remoteEphemeralPublicKey = - getRandomBytes(MAX_PUBLIC_KEY_LENGTH); + private final PublicKey remoteEphemeralPublicKey = getAgreementPublicKey(); private final Map transportProperties = getTransportPropertiesMap(3); private final Map @@ -193,13 +194,22 @@ public class SessionEncoderParserIntegrationTest extends BrambleTestCase { assertEquals(localTimestamp, s1.getLocal().lastMessageTimestamp); assertEquals(s1.getLocal().lastMessageTimestamp, s2.getLocal().lastMessageTimestamp); - assertArrayEquals(ephemeralPublicKey, s1.getLocal().ephemeralPublicKey); - assertArrayEquals(s1.getLocal().ephemeralPublicKey, - s2.getLocal().ephemeralPublicKey); - assertArrayEquals(ephemeralPrivateKey, - s1.getLocal().ephemeralPrivateKey); - assertArrayEquals(s1.getLocal().ephemeralPrivateKey, - s2.getLocal().ephemeralPrivateKey); + PublicKey s1LocalEphemeralPub = s1.getLocal().ephemeralPublicKey; + PublicKey s2LocalEphemeralPub = s2.getLocal().ephemeralPublicKey; + assertNotNull(s1LocalEphemeralPub); + assertNotNull(s2LocalEphemeralPub); + assertArrayEquals(ephemeralPublicKey.getEncoded(), + s1LocalEphemeralPub.getEncoded()); + assertArrayEquals(s1LocalEphemeralPub.getEncoded(), + s2LocalEphemeralPub.getEncoded()); + PrivateKey s1LocalEphemeralPriv = s1.getLocal().ephemeralPrivateKey; + PrivateKey s2LocalEphemeralPriv = s2.getLocal().ephemeralPrivateKey; + assertNotNull(s1LocalEphemeralPriv); + assertNotNull(s2LocalEphemeralPriv); + assertArrayEquals(ephemeralPrivateKey.getEncoded(), + s1LocalEphemeralPriv.getEncoded()); + assertArrayEquals(s1LocalEphemeralPriv.getEncoded(), + s2LocalEphemeralPriv.getEncoded()); assertEquals(transportProperties, s1.getLocal().transportProperties); assertEquals(s1.getLocal().transportProperties, s2.getLocal().transportProperties); @@ -217,10 +227,14 @@ public class SessionEncoderParserIntegrationTest extends BrambleTestCase { assertEquals(lastRemoteMessageId, s1.getRemote().lastMessageId); assertEquals(s1.getRemote().lastMessageId, s2.getRemote().lastMessageId); - assertArrayEquals(remoteEphemeralPublicKey, - s1.getRemote().ephemeralPublicKey); - assertArrayEquals(s1.getRemote().ephemeralPublicKey, - s2.getRemote().ephemeralPublicKey); + PublicKey s1RemoteEphemeralPub = s1.getRemote().ephemeralPublicKey; + PublicKey s2RemoteEphemeralPub = s2.getRemote().ephemeralPublicKey; + assertNotNull(s1RemoteEphemeralPub); + assertNotNull(s2RemoteEphemeralPub); + assertArrayEquals(remoteEphemeralPublicKey.getEncoded(), + s1RemoteEphemeralPub.getEncoded()); + assertArrayEquals(s1RemoteEphemeralPub.getEncoded(), + s2RemoteEphemeralPub.getEncoded()); assertEquals(remoteTransportProperties, s1.getRemote().transportProperties); assertEquals(s1.getRemote().transportProperties, @@ -311,7 +325,7 @@ public class SessionEncoderParserIntegrationTest extends BrambleTestCase { ephemeralPublicKey, ephemeralPrivateKey, transportProperties, acceptTimestamp, localMacKey); Remote remote = new Remote(false, author2, lastRemoteMessageId, - remoteEphemeralPublicKey, remoteTransportProperties, + remoteEphemeralPublicKey, remoteTransportProperties, remoteAcceptTimestamp, remoteMacKey); return new IntroduceeSession(sessionId, LOCAL_ACCEPTED, requestTimestamp, groupId1, author1, local, remote, diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/PrivateGroupIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/PrivateGroupIntegrationTest.java index 61c2fcdd9..99aa1fdff 100644 --- a/briar-core/src/test/java/org/briarproject/briar/privategroup/PrivateGroupIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/PrivateGroupIntegrationTest.java @@ -29,6 +29,7 @@ import static org.briarproject.briar.api.privategroup.Visibility.INVISIBLE; import static org.briarproject.briar.api.privategroup.Visibility.REVEALED_BY_CONTACT; import static org.briarproject.briar.api.privategroup.Visibility.REVEALED_BY_US; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; /** @@ -164,7 +165,7 @@ public class PrivateGroupIntegrationTest getGroupMember(groupManager2, author1.getId()).getVisibility()); // 1 reveals the contact relationship to 2 - assertTrue(contactId2From1 != null); + assertNotNull(contactId2From1); groupInvitationManager1.revealRelationship(contactId2From1, groupId0); sync1To2(1, true); sync2To1(1, true); diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationIntegrationTest.java index 2b648d5bc..783a7e2c2 100644 --- a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationIntegrationTest.java @@ -458,8 +458,8 @@ public class GroupInvitationIntegrationTest sync1To0(1, true); } - private void sendInvitation(long timestamp, @Nullable String text) throws - DbException { + private void sendInvitation(long timestamp, @Nullable String text) + throws DbException { byte[] signature = groupInvitationFactory.signInvitation(contact1From0, privateGroup0.getId(), timestamp, author0.getPrivateKey()); groupInvitationManager0