Revert "Revert "Replace curve25519-java with libsignal-server""
This reverts commit c06a5ac96c
.
This commit is contained in:
parent
2bb8f92af1
commit
3dc0d0bb92
|
@ -44,11 +44,6 @@
|
||||||
<artifactId>libsignal-server</artifactId>
|
<artifactId>libsignal-server</artifactId>
|
||||||
<version>0.15.0</version>
|
<version>0.15.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.whispersystems</groupId>
|
|
||||||
<artifactId>curve25519-java</artifactId>
|
|
||||||
<version>0.5.0</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.dropwizard</groupId>
|
<groupId>io.dropwizard</groupId>
|
||||||
|
|
|
@ -7,8 +7,8 @@ package org.whispersystems.textsecuregcm.auth;
|
||||||
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import org.whispersystems.textsecuregcm.crypto.Curve;
|
import org.signal.libsignal.protocol.ecc.Curve;
|
||||||
import org.whispersystems.textsecuregcm.crypto.ECPrivateKey;
|
import org.signal.libsignal.protocol.ecc.ECPrivateKey;
|
||||||
import org.whispersystems.textsecuregcm.entities.MessageProtos.SenderCertificate;
|
import org.whispersystems.textsecuregcm.entities.MessageProtos.SenderCertificate;
|
||||||
import org.whispersystems.textsecuregcm.entities.MessageProtos.ServerCertificate;
|
import org.whispersystems.textsecuregcm.entities.MessageProtos.ServerCertificate;
|
||||||
import org.whispersystems.textsecuregcm.storage.Account;
|
import org.whispersystems.textsecuregcm.storage.Account;
|
||||||
|
@ -46,7 +46,12 @@ public class CertificateGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] certificate = builder.build().toByteArray();
|
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()
|
return SenderCertificate.newBuilder()
|
||||||
.setCertificate(ByteString.copyFrom(certificate))
|
.setCertificate(ByteString.copyFrom(certificate))
|
||||||
|
|
|
@ -8,8 +8,8 @@ package org.whispersystems.textsecuregcm.configuration;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
import org.whispersystems.textsecuregcm.crypto.Curve;
|
import org.signal.libsignal.protocol.ecc.Curve;
|
||||||
import org.whispersystems.textsecuregcm.crypto.ECPrivateKey;
|
import org.signal.libsignal.protocol.ecc.ECPrivateKey;
|
||||||
import org.whispersystems.textsecuregcm.util.ByteArrayAdapter;
|
import org.whispersystems.textsecuregcm.util.ByteArrayAdapter;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
|
@ -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<ECPublicKey> {
|
|
||||||
|
|
||||||
public static final int KEY_SIZE = 33;
|
|
||||||
|
|
||||||
public byte[] serialize();
|
|
||||||
|
|
||||||
public int getType();
|
|
||||||
}
|
|
|
@ -10,9 +10,9 @@ import com.google.protobuf.ByteString;
|
||||||
import net.sourceforge.argparse4j.impl.Arguments;
|
import net.sourceforge.argparse4j.impl.Arguments;
|
||||||
import net.sourceforge.argparse4j.inf.Namespace;
|
import net.sourceforge.argparse4j.inf.Namespace;
|
||||||
import net.sourceforge.argparse4j.inf.Subparser;
|
import net.sourceforge.argparse4j.inf.Subparser;
|
||||||
import org.whispersystems.textsecuregcm.crypto.Curve;
|
import org.signal.libsignal.protocol.ecc.Curve;
|
||||||
import org.whispersystems.textsecuregcm.crypto.ECKeyPair;
|
import org.signal.libsignal.protocol.ecc.ECKeyPair;
|
||||||
import org.whispersystems.textsecuregcm.crypto.ECPrivateKey;
|
import org.signal.libsignal.protocol.ecc.ECPrivateKey;
|
||||||
import org.whispersystems.textsecuregcm.entities.MessageProtos;
|
import org.whispersystems.textsecuregcm.entities.MessageProtos;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -91,7 +91,12 @@ public class CertificateCommand extends Command {
|
||||||
.build()
|
.build()
|
||||||
.toByteArray();
|
.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()
|
byte[] signedCertificate = MessageProtos.ServerCertificate.newBuilder()
|
||||||
.setCertificate(ByteString.copyFrom(certificate))
|
.setCertificate(ByteString.copyFrom(certificate))
|
||||||
|
|
|
@ -14,7 +14,7 @@ import java.security.InvalidKeyException;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import org.junit.jupiter.api.Test;
|
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.Account;
|
||||||
import org.whispersystems.textsecuregcm.storage.Device;
|
import org.whispersystems.textsecuregcm.storage.Device;
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||||
import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
|
import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
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.ServerSecretParams;
|
||||||
import org.signal.libsignal.zkgroup.VerificationFailedException;
|
import org.signal.libsignal.zkgroup.VerificationFailedException;
|
||||||
import org.signal.libsignal.zkgroup.auth.AuthCredentialResponse;
|
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.DisabledPermittedAuthenticatedAccount;
|
||||||
import org.whispersystems.textsecuregcm.auth.OptionalAccess;
|
import org.whispersystems.textsecuregcm.auth.OptionalAccess;
|
||||||
import org.whispersystems.textsecuregcm.controllers.CertificateController;
|
import org.whispersystems.textsecuregcm.controllers.CertificateController;
|
||||||
import org.whispersystems.textsecuregcm.crypto.Curve;
|
|
||||||
import org.whispersystems.textsecuregcm.entities.DeliveryCertificate;
|
import org.whispersystems.textsecuregcm.entities.DeliveryCertificate;
|
||||||
import org.whispersystems.textsecuregcm.entities.GroupCredentials;
|
import org.whispersystems.textsecuregcm.entities.GroupCredentials;
|
||||||
import org.whispersystems.textsecuregcm.entities.MessageProtos.SenderCertificate;
|
import org.whispersystems.textsecuregcm.entities.MessageProtos.SenderCertificate;
|
||||||
|
|
Loading…
Reference in New Issue