From 06a57ef81184d08634e2efaf30ca6555065925e9 Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Tue, 9 Nov 2021 15:32:53 -0800 Subject: [PATCH] Replace curve25519-java with libsignal-server These APIs stemmed from a common source long ago, so there's not much to change! --- service/pom.xml | 5 - .../auth/CertificateGenerator.java | 11 +- .../UnidentifiedDeliveryConfiguration.java | 4 +- .../textsecuregcm/crypto/Curve.java | 103 ------------------ .../textsecuregcm/crypto/DjbECPrivateKey.java | 29 ----- .../textsecuregcm/crypto/DjbECPublicKey.java | 54 --------- .../textsecuregcm/crypto/ECKeyPair.java | 25 ----- .../textsecuregcm/crypto/ECPrivateKey.java | 12 -- .../textsecuregcm/crypto/ECPublicKey.java | 15 --- .../workers/CertificateCommand.java | 13 ++- .../auth/CertificateGeneratorTest.java | 2 +- .../CertificateControllerTest.java | 2 +- 12 files changed, 21 insertions(+), 254 deletions(-) delete mode 100644 service/src/main/java/org/whispersystems/textsecuregcm/crypto/Curve.java delete mode 100644 service/src/main/java/org/whispersystems/textsecuregcm/crypto/DjbECPrivateKey.java delete mode 100644 service/src/main/java/org/whispersystems/textsecuregcm/crypto/DjbECPublicKey.java delete mode 100644 service/src/main/java/org/whispersystems/textsecuregcm/crypto/ECKeyPair.java delete mode 100644 service/src/main/java/org/whispersystems/textsecuregcm/crypto/ECPrivateKey.java delete mode 100644 service/src/main/java/org/whispersystems/textsecuregcm/crypto/ECPublicKey.java diff --git a/service/pom.xml b/service/pom.xml index dfb12a7ba..6b77ec7cd 100644 --- a/service/pom.xml +++ b/service/pom.xml @@ -44,11 +44,6 @@ libsignal-server 0.15.0 - - org.whispersystems - curve25519-java - 0.5.0 - io.dropwizard diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/auth/CertificateGenerator.java b/service/src/main/java/org/whispersystems/textsecuregcm/auth/CertificateGenerator.java index 26b06b6b6..a3a189add 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/auth/CertificateGenerator.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/auth/CertificateGenerator.java @@ -7,8 +7,8 @@ package org.whispersystems.textsecuregcm.auth; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; -import org.whispersystems.textsecuregcm.crypto.Curve; -import org.whispersystems.textsecuregcm.crypto.ECPrivateKey; +import org.signal.libsignal.protocol.ecc.Curve; +import org.signal.libsignal.protocol.ecc.ECPrivateKey; import org.whispersystems.textsecuregcm.entities.MessageProtos.SenderCertificate; import org.whispersystems.textsecuregcm.entities.MessageProtos.ServerCertificate; import org.whispersystems.textsecuregcm.storage.Account; @@ -46,7 +46,12 @@ public class CertificateGenerator { } byte[] certificate = builder.build().toByteArray(); - byte[] signature = Curve.calculateSignature(privateKey, certificate); + byte[] signature; + try { + signature = Curve.calculateSignature(privateKey, certificate); + } catch (org.signal.libsignal.protocol.InvalidKeyException e) { + throw new InvalidKeyException(e); + } return SenderCertificate.newBuilder() .setCertificate(ByteString.copyFrom(certificate)) diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/configuration/UnidentifiedDeliveryConfiguration.java b/service/src/main/java/org/whispersystems/textsecuregcm/configuration/UnidentifiedDeliveryConfiguration.java index eddd1d9d0..123d34447 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/configuration/UnidentifiedDeliveryConfiguration.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/configuration/UnidentifiedDeliveryConfiguration.java @@ -8,8 +8,8 @@ package org.whispersystems.textsecuregcm.configuration; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import org.whispersystems.textsecuregcm.crypto.Curve; -import org.whispersystems.textsecuregcm.crypto.ECPrivateKey; +import org.signal.libsignal.protocol.ecc.Curve; +import org.signal.libsignal.protocol.ecc.ECPrivateKey; import org.whispersystems.textsecuregcm.util.ByteArrayAdapter; import javax.validation.constraints.NotNull; diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/crypto/Curve.java b/service/src/main/java/org/whispersystems/textsecuregcm/crypto/Curve.java deleted file mode 100644 index 65eb4257d..000000000 --- a/service/src/main/java/org/whispersystems/textsecuregcm/crypto/Curve.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2013-2020 Signal Messenger, LLC - * SPDX-License-Identifier: AGPL-3.0-only - */ - -package org.whispersystems.textsecuregcm.crypto; - -import org.whispersystems.curve25519.Curve25519; -import org.whispersystems.curve25519.Curve25519KeyPair; - -import java.security.InvalidKeyException; - -import static org.whispersystems.curve25519.Curve25519.BEST; - -public class Curve { - - public static final int DJB_TYPE = 0x05; - - public static ECKeyPair generateKeyPair() { - Curve25519KeyPair keyPair = Curve25519.getInstance(BEST).generateKeyPair(); - - return new ECKeyPair(new DjbECPublicKey(keyPair.getPublicKey()), - new DjbECPrivateKey(keyPair.getPrivateKey())); - } - - public static ECPublicKey decodePoint(byte[] bytes, int offset) - throws InvalidKeyException - { - if (bytes == null || bytes.length - offset < 1) { - throw new InvalidKeyException("No key type identifier"); - } - - int type = bytes[offset] & 0xFF; - - switch (type) { - case Curve.DJB_TYPE: - if (bytes.length - offset < 33) { - throw new InvalidKeyException("Bad key length: " + bytes.length); - } - - byte[] keyBytes = new byte[32]; - System.arraycopy(bytes, offset+1, keyBytes, 0, keyBytes.length); - return new DjbECPublicKey(keyBytes); - default: - throw new InvalidKeyException("Bad key type: " + type); - } - } - - public static ECPrivateKey decodePrivatePoint(byte[] bytes) { - return new DjbECPrivateKey(bytes); - } - - public static byte[] calculateAgreement(ECPublicKey publicKey, ECPrivateKey privateKey) - throws InvalidKeyException - { - if (publicKey == null) { - throw new InvalidKeyException("public value is null"); - } - - if (privateKey == null) { - throw new InvalidKeyException("private value is null"); - } - - if (publicKey.getType() != privateKey.getType()) { - throw new InvalidKeyException("Public and private keys must be of the same type!"); - } - - if (publicKey.getType() == DJB_TYPE) { - return Curve25519.getInstance(BEST) - .calculateAgreement(((DjbECPublicKey) publicKey).getPublicKey(), - ((DjbECPrivateKey) privateKey).getPrivateKey()); - } else { - throw new InvalidKeyException("Unknown type: " + publicKey.getType()); - } - } - - public static byte[] calculateSignature(ECPrivateKey signingKey, byte[] message) - throws InvalidKeyException - { - if (signingKey == null || message == null) { - throw new InvalidKeyException("Values must not be null"); - } - - if (signingKey.getType() == DJB_TYPE) { - return Curve25519.getInstance(BEST) - .calculateSignature(((DjbECPrivateKey) signingKey).getPrivateKey(), message); - } else { - throw new InvalidKeyException("Unknown type: " + signingKey.getType()); - } - } - - public static boolean verifySignature(ECPublicKey signingKey, byte[] message, byte[] signature) - throws InvalidKeyException - { - if (signingKey.getType() == DJB_TYPE) { - return Curve25519.getInstance(BEST) - .verifySignature(((DjbECPublicKey) signingKey).getPublicKey(), message, signature); - } else { - throw new InvalidKeyException("Unknown type: " + signingKey.getType()); - } - } - -} diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/crypto/DjbECPrivateKey.java b/service/src/main/java/org/whispersystems/textsecuregcm/crypto/DjbECPrivateKey.java deleted file mode 100644 index 47ffc84bb..000000000 --- a/service/src/main/java/org/whispersystems/textsecuregcm/crypto/DjbECPrivateKey.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2013-2020 Signal Messenger, LLC - * SPDX-License-Identifier: AGPL-3.0-only - */ - -package org.whispersystems.textsecuregcm.crypto; - -public class DjbECPrivateKey implements ECPrivateKey { - - private final byte[] privateKey; - - DjbECPrivateKey(byte[] privateKey) { - this.privateKey = privateKey; - } - - @Override - public byte[] serialize() { - return privateKey; - } - - @Override - public int getType() { - return Curve.DJB_TYPE; - } - - public byte[] getPrivateKey() { - return privateKey; - } -} diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/crypto/DjbECPublicKey.java b/service/src/main/java/org/whispersystems/textsecuregcm/crypto/DjbECPublicKey.java deleted file mode 100644 index a24a96e35..000000000 --- a/service/src/main/java/org/whispersystems/textsecuregcm/crypto/DjbECPublicKey.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2013-2020 Signal Messenger, LLC - * SPDX-License-Identifier: AGPL-3.0-only - */ - -package org.whispersystems.textsecuregcm.crypto; - -import org.whispersystems.textsecuregcm.util.ByteUtil; - -import java.math.BigInteger; -import java.util.Arrays; - -public class DjbECPublicKey implements ECPublicKey { - - private final byte[] publicKey; - - DjbECPublicKey(byte[] publicKey) { - this.publicKey = publicKey; - } - - @Override - public byte[] serialize() { - byte[] type = {Curve.DJB_TYPE}; - return ByteUtil.combine(type, publicKey); - } - - @Override - public int getType() { - return Curve.DJB_TYPE; - } - - @Override - public boolean equals(Object other) { - if (other == null) return false; - if (!(other instanceof DjbECPublicKey)) return false; - - DjbECPublicKey that = (DjbECPublicKey)other; - return Arrays.equals(this.publicKey, that.publicKey); - } - - @Override - public int hashCode() { - return Arrays.hashCode(publicKey); - } - - @Override - public int compareTo(ECPublicKey another) { - return new BigInteger(publicKey).compareTo(new BigInteger(((DjbECPublicKey)another).publicKey)); - } - - public byte[] getPublicKey() { - return publicKey; - } -} diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/crypto/ECKeyPair.java b/service/src/main/java/org/whispersystems/textsecuregcm/crypto/ECKeyPair.java deleted file mode 100644 index ad4120d22..000000000 --- a/service/src/main/java/org/whispersystems/textsecuregcm/crypto/ECKeyPair.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2013-2020 Signal Messenger, LLC - * SPDX-License-Identifier: AGPL-3.0-only - */ - -package org.whispersystems.textsecuregcm.crypto; - -public class ECKeyPair { - - private final ECPublicKey publicKey; - private final ECPrivateKey privateKey; - - ECKeyPair(ECPublicKey publicKey, ECPrivateKey privateKey) { - this.publicKey = publicKey; - this.privateKey = privateKey; - } - - public ECPublicKey getPublicKey() { - return publicKey; - } - - public ECPrivateKey getPrivateKey() { - return privateKey; - } -} diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/crypto/ECPrivateKey.java b/service/src/main/java/org/whispersystems/textsecuregcm/crypto/ECPrivateKey.java deleted file mode 100644 index bac0d3234..000000000 --- a/service/src/main/java/org/whispersystems/textsecuregcm/crypto/ECPrivateKey.java +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2013-2020 Signal Messenger, LLC - * SPDX-License-Identifier: AGPL-3.0-only - */ - -package org.whispersystems.textsecuregcm.crypto; - -public interface ECPrivateKey { - public byte[] serialize(); - public int getType(); -} - diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/crypto/ECPublicKey.java b/service/src/main/java/org/whispersystems/textsecuregcm/crypto/ECPublicKey.java deleted file mode 100644 index 5511b0aaf..000000000 --- a/service/src/main/java/org/whispersystems/textsecuregcm/crypto/ECPublicKey.java +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2013-2020 Signal Messenger, LLC - * SPDX-License-Identifier: AGPL-3.0-only - */ - -package org.whispersystems.textsecuregcm.crypto; - -public interface ECPublicKey extends Comparable { - - public static final int KEY_SIZE = 33; - - public byte[] serialize(); - - public int getType(); -} diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/workers/CertificateCommand.java b/service/src/main/java/org/whispersystems/textsecuregcm/workers/CertificateCommand.java index f3e25ccd4..c0186c25a 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/workers/CertificateCommand.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/workers/CertificateCommand.java @@ -10,9 +10,9 @@ import com.google.protobuf.ByteString; import net.sourceforge.argparse4j.impl.Arguments; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; -import org.whispersystems.textsecuregcm.crypto.Curve; -import org.whispersystems.textsecuregcm.crypto.ECKeyPair; -import org.whispersystems.textsecuregcm.crypto.ECPrivateKey; +import org.signal.libsignal.protocol.ecc.Curve; +import org.signal.libsignal.protocol.ecc.ECKeyPair; +import org.signal.libsignal.protocol.ecc.ECPrivateKey; import org.whispersystems.textsecuregcm.entities.MessageProtos; import java.io.IOException; @@ -91,7 +91,12 @@ public class CertificateCommand extends Command { .build() .toByteArray(); - byte[] signature = Curve.calculateSignature(key, certificate); + byte[] signature; + try { + signature = Curve.calculateSignature(key, certificate); + } catch (org.signal.libsignal.protocol.InvalidKeyException e) { + throw new InvalidKeyException(e); + } byte[] signedCertificate = MessageProtos.ServerCertificate.newBuilder() .setCertificate(ByteString.copyFrom(certificate)) diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/auth/CertificateGeneratorTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/auth/CertificateGeneratorTest.java index adbbcc3b7..62903a7e9 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/auth/CertificateGeneratorTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/auth/CertificateGeneratorTest.java @@ -14,7 +14,7 @@ import java.security.InvalidKeyException; import java.util.Base64; import java.util.UUID; import org.junit.jupiter.api.Test; -import org.whispersystems.textsecuregcm.crypto.Curve; +import org.signal.libsignal.protocol.ecc.Curve; import org.whispersystems.textsecuregcm.storage.Account; import org.whispersystems.textsecuregcm.storage.Device; diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/CertificateControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/CertificateControllerTest.java index 38028bd37..ac34653dd 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/CertificateControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/CertificateControllerTest.java @@ -26,6 +26,7 @@ import org.apache.commons.lang3.StringUtils; import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.signal.libsignal.protocol.ecc.Curve; import org.signal.libsignal.zkgroup.ServerSecretParams; import org.signal.libsignal.zkgroup.VerificationFailedException; import org.signal.libsignal.zkgroup.auth.AuthCredentialResponse; @@ -36,7 +37,6 @@ import org.whispersystems.textsecuregcm.auth.CertificateGenerator; import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.OptionalAccess; import org.whispersystems.textsecuregcm.controllers.CertificateController; -import org.whispersystems.textsecuregcm.crypto.Curve; import org.whispersystems.textsecuregcm.entities.DeliveryCertificate; import org.whispersystems.textsecuregcm.entities.GroupCredentials; import org.whispersystems.textsecuregcm.entities.MessageProtos.SenderCertificate;