Move to Signal Protocol written in Rust.
Co-authored-by: Alex Hart <alex@signal.org>
This commit is contained in:
parent
918497fb94
commit
907e8d93a3
14 changed files with 50 additions and 57 deletions
|
@ -364,7 +364,8 @@ dependencies {
|
|||
|
||||
implementation project(':libsignal-service')
|
||||
implementation 'org.signal:zkgroup-android:0.7.0'
|
||||
|
||||
implementation 'org.whispersystems:signal-client-android:0.1.3'
|
||||
implementation 'com.google.protobuf:protobuf-javalite:3.10.0'
|
||||
implementation 'org.signal:argon2:13.1@aar'
|
||||
|
||||
implementation 'org.signal:ringrtc-android:2.8.0'
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
|||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.push.IasTrustStore;
|
||||
import org.thoughtcrime.securesms.util.SetUtil;
|
||||
import org.whispersystems.libsignal.InvalidKeyException;
|
||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||
import org.whispersystems.signalservice.api.push.TrustStore;
|
||||
import org.whispersystems.signalservice.internal.contacts.crypto.Quote;
|
||||
|
@ -69,7 +70,7 @@ class ContactDiscoveryV2 {
|
|||
FuzzyPhoneNumberHelper.OutputResultV2 outputResult = FuzzyPhoneNumberHelper.generateOutputV2(results, inputResult);
|
||||
|
||||
return new DirectoryResult(outputResult.getNumbers(), outputResult.getRewrites(), ignoredNumbers);
|
||||
} catch (SignatureException | UnauthenticatedQuoteException | UnauthenticatedResponseException | Quote.InvalidQuoteFormatException e) {
|
||||
} catch (SignatureException | UnauthenticatedQuoteException | UnauthenticatedResponseException | Quote.InvalidQuoteFormatException |InvalidKeyException e) {
|
||||
Log.w(TAG, "Attestation error.", e);
|
||||
throw new IOException(e);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
|||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.pin.PinState;
|
||||
import org.thoughtcrime.securesms.util.concurrent.SimpleTask;
|
||||
import org.whispersystems.libsignal.InvalidKeyException;
|
||||
import org.whispersystems.signalservice.internal.contacts.crypto.UnauthenticatedResponseException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -29,7 +30,7 @@ final class ConfirmKbsPinRepository {
|
|||
Log.i(TAG, "Pin set on KBS");
|
||||
|
||||
return PinSetResult.SUCCESS;
|
||||
} catch (IOException | UnauthenticatedResponseException e) {
|
||||
} catch (IOException | UnauthenticatedResponseException | InvalidKeyException e) {
|
||||
Log.w(TAG, e);
|
||||
PinState.onPinCreateFailure();
|
||||
return PinSetResult.FAILURE;
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.thoughtcrime.securesms.lock.PinHashing;
|
|||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.pin.PinState;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.libsignal.InvalidKeyException;
|
||||
import org.whispersystems.signalservice.api.KeyBackupService;
|
||||
import org.whispersystems.signalservice.api.KeyBackupServicePinException;
|
||||
import org.whispersystems.signalservice.api.KeyBackupSystemNoDataException;
|
||||
|
@ -60,7 +61,7 @@ public final class RegistrationPinV2MigrationJob extends BaseJob {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void onRun() throws IOException, UnauthenticatedResponseException {
|
||||
protected void onRun() throws IOException, UnauthenticatedResponseException, InvalidKeyException {
|
||||
if (!TextSecurePreferences.isV1RegistrationLockEnabled(context)) {
|
||||
Log.i(TAG, "Registration lock disabled");
|
||||
return;
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.thoughtcrime.securesms.logging.Log;
|
|||
import org.thoughtcrime.securesms.megaphone.Megaphones;
|
||||
import org.thoughtcrime.securesms.registration.service.KeyBackupSystemWrongPinException;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.libsignal.InvalidKeyException;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.KbsPinData;
|
||||
import org.whispersystems.signalservice.api.KeyBackupService;
|
||||
|
@ -90,7 +91,7 @@ public final class PinState {
|
|||
}
|
||||
|
||||
return kbsData;
|
||||
} catch (UnauthenticatedResponseException e) {
|
||||
} catch (UnauthenticatedResponseException | InvalidKeyException e) {
|
||||
Log.w(TAG, "Failed to restore key", e);
|
||||
throw new IOException(e);
|
||||
} catch (KeyBackupServicePinException e) {
|
||||
|
@ -170,7 +171,7 @@ public final class PinState {
|
|||
*/
|
||||
@WorkerThread
|
||||
public static synchronized void onPinChangedOrCreated(@NonNull Context context, @NonNull String pin, @NonNull PinKeyboardType keyboard)
|
||||
throws IOException, UnauthenticatedResponseException
|
||||
throws IOException, UnauthenticatedResponseException, InvalidKeyException
|
||||
{
|
||||
Log.i(TAG, "onPinChangedOrCreated()");
|
||||
|
||||
|
@ -272,7 +273,7 @@ public final class PinState {
|
|||
*/
|
||||
@WorkerThread
|
||||
public static synchronized void onMigrateToRegistrationLockV2(@NonNull Context context, @NonNull String pin)
|
||||
throws IOException, UnauthenticatedResponseException
|
||||
throws IOException, UnauthenticatedResponseException, InvalidKeyException
|
||||
{
|
||||
Log.i(TAG, "onMigrateToRegistrationLockV2()");
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ import org.thoughtcrime.securesms.util.ServiceUtil;
|
|||
import org.thoughtcrime.securesms.webrtc.locks.LockManager;
|
||||
import org.whispersystems.libsignal.InvalidKeyException;
|
||||
import org.whispersystems.libsignal.ecc.Curve;
|
||||
import org.whispersystems.libsignal.ecc.DjbECPublicKey;
|
||||
import org.whispersystems.libsignal.ecc.ECPublicKey;
|
||||
import org.whispersystems.signalservice.api.messages.calls.OfferMessage;
|
||||
|
||||
|
@ -25,11 +24,7 @@ public final class WebRtcUtil {
|
|||
|
||||
public static @NonNull byte[] getPublicKeyBytes(@NonNull byte[] identityKey) throws InvalidKeyException {
|
||||
ECPublicKey key = Curve.decodePoint(identityKey, 0);
|
||||
|
||||
if (key instanceof DjbECPublicKey) {
|
||||
return ((DjbECPublicKey) key).getPublicKey();
|
||||
}
|
||||
throw new InvalidKeyException();
|
||||
return key.getPublicKeyBytes();
|
||||
}
|
||||
|
||||
public static @NonNull LockManager.PhoneState getInCallPhoneState(@NonNull Context context) {
|
||||
|
|
|
@ -441,9 +441,6 @@ dependencyVerification {
|
|||
['org.signal:ringrtc-android:2.8.0',
|
||||
'49965467ed1e8634969af10f318bbaf1dd97b1d55bca05300802a5dcb6ed21a3'],
|
||||
|
||||
['org.signal:signal-metadata-java:0.1.2',
|
||||
'6aaeb6a33bf3161a3e6ac9db7678277f7a4cf5a2c96b84342e4007ee49bab1bd'],
|
||||
|
||||
['org.signal:zkgroup-android:0.7.0',
|
||||
'52b172565bd01526e93ebf1796b834bdc449d4fe3422c1b827e49cb8d4f13fbd'],
|
||||
|
||||
|
@ -453,11 +450,11 @@ dependencyVerification {
|
|||
['org.threeten:threetenbp:1.3.6',
|
||||
'f4c23ffaaed717c3b99c003e0ee02d6d66377fd47d866fec7d971bd8644fc1a7'],
|
||||
|
||||
['org.whispersystems:curve25519-java:0.5.0',
|
||||
'0aadd43cf01d11e9b58f867b3c4f25c3194e8b0623d1953d32dfbfbee009e38d'],
|
||||
['org.whispersystems:signal-client-android:0.1.3',
|
||||
'5d85d61da77db7960f8f8fb48efaeb543716782d73fb01c6d33741baa1ed6cb4'],
|
||||
|
||||
['org.whispersystems:signal-protocol-java:2.8.1',
|
||||
'b19db36839ab008fdccefc7f8c005f2ea43dc7c7298a209bc424e6f9b6d5617b'],
|
||||
['org.whispersystems:signal-client-java:0.1.3',
|
||||
'97679340b9f9a3e61c4ee3bd054abff3b8d0e8ddb95dbd917f4425849e9ff2d6'],
|
||||
|
||||
['pl.tajchert:waitingdots:0.1.0',
|
||||
'2835d49e0787dbcb606c5a60021ced66578503b1e9fddcd7a5ef0cd5f095ba2c'],
|
||||
|
|
|
@ -5,7 +5,7 @@ wrapper {
|
|||
subprojects {
|
||||
ext.lib_signal_service_version_number = "2.15.3"
|
||||
ext.lib_signal_service_group_info = "org.whispersystems"
|
||||
ext.lib_signal_metadata_version = "0.1.2"
|
||||
ext.lib_signal_client_version = "0.1.0"
|
||||
|
||||
if (JavaVersion.current().isJava8Compatible()) {
|
||||
allprojects {
|
||||
|
|
|
@ -32,7 +32,7 @@ dependencies {
|
|||
api 'com.googlecode.libphonenumber:libphonenumber:8.12.6'
|
||||
api 'com.fasterxml.jackson.core:jackson-databind:2.9.9.2'
|
||||
|
||||
api "org.signal:signal-metadata-java:${lib_signal_metadata_version}"
|
||||
api 'org.whispersystems:signal-client-java:0.1.3'
|
||||
api 'com.squareup.okhttp3:okhttp:3.12.10'
|
||||
implementation 'org.threeten:threetenbp:1.3.6'
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.whispersystems.signalservice.api;
|
||||
|
||||
import org.whispersystems.libsignal.InvalidKeyException;
|
||||
import org.whispersystems.libsignal.logging.Log;
|
||||
import org.whispersystems.signalservice.api.crypto.InvalidCiphertextException;
|
||||
import org.whispersystems.signalservice.api.kbs.HashedPin;
|
||||
|
@ -123,7 +124,7 @@ public final class KeyBackupService {
|
|||
|
||||
@Override
|
||||
public KbsPinData restorePin(HashedPin hashedPin)
|
||||
throws UnauthenticatedResponseException, IOException, KeyBackupServicePinException, KeyBackupSystemNoDataException
|
||||
throws UnauthenticatedResponseException, IOException, KeyBackupServicePinException, KeyBackupSystemNoDataException, InvalidKeyException
|
||||
{
|
||||
int attempt = 0;
|
||||
SecureRandom random = new SecureRandom();
|
||||
|
@ -156,7 +157,7 @@ public final class KeyBackupService {
|
|||
}
|
||||
|
||||
private KbsPinData restorePin(HashedPin hashedPin, TokenResponse token)
|
||||
throws UnauthenticatedResponseException, IOException, TokenException, KeyBackupSystemNoDataException
|
||||
throws UnauthenticatedResponseException, IOException, TokenException, KeyBackupSystemNoDataException, InvalidKeyException
|
||||
{
|
||||
try {
|
||||
final int remainingTries = token.getTries();
|
||||
|
@ -197,7 +198,7 @@ public final class KeyBackupService {
|
|||
}
|
||||
}
|
||||
|
||||
private RemoteAttestation getAndVerifyRemoteAttestation() throws UnauthenticatedResponseException, IOException {
|
||||
private RemoteAttestation getAndVerifyRemoteAttestation() throws UnauthenticatedResponseException, IOException, InvalidKeyException {
|
||||
try {
|
||||
return RemoteAttestationUtil.getAndVerifyRemoteAttestation(pushServiceSocket, PushServiceSocket.ClientSet.KeyBackup, iasKeyStore, enclaveName, mrenclave, authorization);
|
||||
} catch (Quote.InvalidQuoteFormatException | UnauthenticatedQuoteException | InvalidCiphertextException | SignatureException e) {
|
||||
|
@ -226,7 +227,7 @@ public final class KeyBackupService {
|
|||
KeyBackupResponse response = pushServiceSocket.putKbsData(authorization, request, remoteAttestation.getCookies(), enclaveName);
|
||||
|
||||
KeyBackupCipher.getKeyDeleteResponseStatus(response, remoteAttestation);
|
||||
} catch (InvalidCiphertextException e) {
|
||||
} catch (InvalidCiphertextException | InvalidKeyException e) {
|
||||
throw new UnauthenticatedResponseException(e);
|
||||
}
|
||||
}
|
||||
|
@ -261,7 +262,7 @@ public final class KeyBackupService {
|
|||
default:
|
||||
throw new AssertionError("Unknown response status " + status);
|
||||
}
|
||||
} catch (InvalidCiphertextException e) {
|
||||
} catch (InvalidCiphertextException | InvalidKeyException e) {
|
||||
throw new UnauthenticatedResponseException(e);
|
||||
}
|
||||
}
|
||||
|
@ -275,7 +276,7 @@ public final class KeyBackupService {
|
|||
public interface RestoreSession extends HashSession {
|
||||
|
||||
KbsPinData restorePin(HashedPin hashedPin)
|
||||
throws UnauthenticatedResponseException, IOException, KeyBackupServicePinException, KeyBackupSystemNoDataException;
|
||||
throws UnauthenticatedResponseException, IOException, KeyBackupServicePinException, KeyBackupSystemNoDataException, InvalidKeyException;
|
||||
}
|
||||
|
||||
public interface PinChangeSession extends HashSession {
|
||||
|
|
|
@ -366,7 +366,7 @@ public class SignalServiceAccountManager {
|
|||
}
|
||||
|
||||
public Map<String, UUID> getRegisteredUsers(KeyStore iasKeyStore, Set<String> e164numbers, String mrenclave)
|
||||
throws IOException, Quote.InvalidQuoteFormatException, UnauthenticatedQuoteException, SignatureException, UnauthenticatedResponseException
|
||||
throws IOException, Quote.InvalidQuoteFormatException, UnauthenticatedQuoteException, SignatureException, UnauthenticatedResponseException, InvalidKeyException
|
||||
{
|
||||
if (e164numbers.isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package org.whispersystems.signalservice.internal.contacts.crypto;
|
||||
|
||||
|
||||
import org.whispersystems.curve25519.Curve25519;
|
||||
import org.whispersystems.curve25519.Curve25519KeyPair;
|
||||
import org.whispersystems.libsignal.InvalidKeyException;
|
||||
import org.whispersystems.libsignal.ecc.Curve;
|
||||
import org.whispersystems.libsignal.ecc.ECKeyPair;
|
||||
import org.whispersystems.libsignal.ecc.ECPublicKey;
|
||||
import org.whispersystems.libsignal.kdf.HKDFv3;
|
||||
import org.whispersystems.libsignal.util.ByteUtil;
|
||||
|
||||
|
@ -11,12 +13,12 @@ public class RemoteAttestationKeys {
|
|||
private final byte[] clientKey = new byte[32];
|
||||
private final byte[] serverKey = new byte[32];
|
||||
|
||||
public RemoteAttestationKeys(Curve25519KeyPair keyPair, byte[] serverPublicEphemeral, byte[] serverPublicStatic) {
|
||||
byte[] ephemeralToEphemeral = Curve25519.getInstance(Curve25519.BEST).calculateAgreement(serverPublicEphemeral, keyPair.getPrivateKey());
|
||||
byte[] ephemeralToStatic = Curve25519.getInstance(Curve25519.BEST).calculateAgreement(serverPublicStatic, keyPair.getPrivateKey());
|
||||
public RemoteAttestationKeys(ECKeyPair keyPair, byte[] serverPublicEphemeral, byte[] serverPublicStatic) throws InvalidKeyException {
|
||||
byte[] ephemeralToEphemeral = Curve.calculateAgreement(ECPublicKey.fromPublicKeyBytes(serverPublicEphemeral), keyPair.getPrivateKey());
|
||||
byte[] ephemeralToStatic = Curve.calculateAgreement(ECPublicKey.fromPublicKeyBytes(serverPublicStatic), keyPair.getPrivateKey());
|
||||
|
||||
byte[] masterSecret = ByteUtil.combine(ephemeralToEphemeral, ephemeralToStatic );
|
||||
byte[] publicKeys = ByteUtil.combine(keyPair.getPublicKey(), serverPublicEphemeral, serverPublicStatic);
|
||||
byte[] publicKeys = ByteUtil.combine(keyPair.getPublicKey().getPublicKeyBytes(), serverPublicEphemeral, serverPublicStatic);
|
||||
|
||||
HKDFv3 generator = new HKDFv3();
|
||||
byte[] keys = generator.deriveSecrets(masterSecret, publicKeys, null, clientKey.length + serverKey.length);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package org.whispersystems.signalservice.internal.push;
|
||||
|
||||
import org.whispersystems.curve25519.Curve25519;
|
||||
import org.whispersystems.curve25519.Curve25519KeyPair;
|
||||
import org.whispersystems.libsignal.util.Pair;
|
||||
import org.whispersystems.libsignal.InvalidKeyException;
|
||||
import org.whispersystems.libsignal.ecc.Curve;
|
||||
import org.whispersystems.libsignal.ecc.ECKeyPair;
|
||||
import org.whispersystems.signalservice.api.crypto.InvalidCiphertextException;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
|
||||
import org.whispersystems.signalservice.internal.contacts.crypto.Quote;
|
||||
|
@ -38,9 +38,9 @@ public final class RemoteAttestationUtil {
|
|||
String enclaveName,
|
||||
String mrenclave,
|
||||
String authorization)
|
||||
throws IOException, Quote.InvalidQuoteFormatException, InvalidCiphertextException, UnauthenticatedQuoteException, SignatureException
|
||||
throws IOException, Quote.InvalidQuoteFormatException, InvalidCiphertextException, UnauthenticatedQuoteException, SignatureException, InvalidKeyException
|
||||
{
|
||||
Curve25519KeyPair keyPair = buildKeyPair();
|
||||
ECKeyPair keyPair = buildKeyPair();
|
||||
ResponsePair result = makeAttestationRequest(socket, clientSet, authorization, enclaveName, keyPair);
|
||||
RemoteAttestationResponse response = JsonUtil.fromJson(result.body, RemoteAttestationResponse.class);
|
||||
|
||||
|
@ -53,9 +53,9 @@ public final class RemoteAttestationUtil {
|
|||
String enclaveName,
|
||||
String mrenclave,
|
||||
String authorization)
|
||||
throws IOException, Quote.InvalidQuoteFormatException, InvalidCiphertextException, UnauthenticatedQuoteException, SignatureException
|
||||
throws IOException, Quote.InvalidQuoteFormatException, InvalidCiphertextException, UnauthenticatedQuoteException, SignatureException, InvalidKeyException
|
||||
{
|
||||
Curve25519KeyPair keyPair = buildKeyPair();
|
||||
ECKeyPair keyPair = buildKeyPair();
|
||||
ResponsePair result = makeAttestationRequest(socket, clientSet, authorization, enclaveName, keyPair);
|
||||
MultiRemoteAttestationResponse response = JsonUtil.fromJson(result.body, MultiRemoteAttestationResponse.class);
|
||||
Map<String, RemoteAttestation> attestations = new HashMap<>();
|
||||
|
@ -76,19 +76,18 @@ public final class RemoteAttestationUtil {
|
|||
return attestations;
|
||||
}
|
||||
|
||||
private static Curve25519KeyPair buildKeyPair() {
|
||||
Curve25519 curve = Curve25519.getInstance(Curve25519.BEST);
|
||||
return curve.generateKeyPair();
|
||||
private static ECKeyPair buildKeyPair() {
|
||||
return Curve.generateKeyPair();
|
||||
}
|
||||
|
||||
private static ResponsePair makeAttestationRequest(PushServiceSocket socket,
|
||||
PushServiceSocket.ClientSet clientSet,
|
||||
String authorization,
|
||||
String enclaveName,
|
||||
Curve25519KeyPair keyPair)
|
||||
ECKeyPair keyPair)
|
||||
throws IOException
|
||||
{
|
||||
RemoteAttestationRequest attestationRequest = new RemoteAttestationRequest(keyPair.getPublicKey());
|
||||
RemoteAttestationRequest attestationRequest = new RemoteAttestationRequest(keyPair.getPublicKey().getPublicKeyBytes());
|
||||
Response response = socket.makeRequest(clientSet, authorization, new LinkedList<String>(), "/v1/attestation/" + enclaveName, "PUT", JsonUtil.toJson(attestationRequest));
|
||||
ResponseBody body = response.body();
|
||||
|
||||
|
@ -113,9 +112,9 @@ public final class RemoteAttestationUtil {
|
|||
private static RemoteAttestation validateAndBuildRemoteAttestation(RemoteAttestationResponse response,
|
||||
List<String> cookies,
|
||||
KeyStore iasKeyStore,
|
||||
Curve25519KeyPair keyPair,
|
||||
ECKeyPair keyPair,
|
||||
String mrenclave)
|
||||
throws Quote.InvalidQuoteFormatException, InvalidCiphertextException, UnauthenticatedQuoteException, SignatureException
|
||||
throws Quote.InvalidQuoteFormatException, InvalidCiphertextException, UnauthenticatedQuoteException, SignatureException, InvalidKeyException
|
||||
{
|
||||
RemoteAttestationKeys keys = new RemoteAttestationKeys(keyPair, response.getServerEphemeralPublic(), response.getServerStaticPublic());
|
||||
Quote quote = new Quote(response.getQuote());
|
||||
|
|
|
@ -24,19 +24,13 @@ dependencyVerification {
|
|||
['com.squareup.okio:okio:1.15.0',
|
||||
'693fa319a7e8843300602b204023b7674f106ebcb577f2dd5807212b66118bd2'],
|
||||
|
||||
['org.signal:signal-metadata-java:0.1.2',
|
||||
'6aaeb6a33bf3161a3e6ac9db7678277f7a4cf5a2c96b84342e4007ee49bab1bd'],
|
||||
|
||||
['org.signal:zkgroup-java:0.7.0',
|
||||
'd0099eedd60d6f7d4df5b288175e5d585228ed8897789926bdab69bf8c05659f'],
|
||||
|
||||
['org.threeten:threetenbp:1.3.6',
|
||||
'f4c23ffaaed717c3b99c003e0ee02d6d66377fd47d866fec7d971bd8644fc1a7'],
|
||||
|
||||
['org.whispersystems:curve25519-java:0.5.0',
|
||||
'0aadd43cf01d11e9b58f867b3c4f25c3194e8b0623d1953d32dfbfbee009e38d'],
|
||||
|
||||
['org.whispersystems:signal-protocol-java:2.8.1',
|
||||
'b19db36839ab008fdccefc7f8c005f2ea43dc7c7298a209bc424e6f9b6d5617b'],
|
||||
['org.whispersystems:signal-client-java:0.1.3',
|
||||
'97679340b9f9a3e61c4ee3bd054abff3b8d0e8ddb95dbd917f4425849e9ff2d6'],
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue