mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-23 18:15:22 +00:00
clean fingerprint
This commit is contained in:
parent
a11173676f
commit
c07056f385
@ -1,43 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2016 Open Whisper Systems
|
||||
*
|
||||
* Licensed according to the LICENSE file in this repository.
|
||||
*/
|
||||
package org.session.libsignal.libsignal.fingerprint;
|
||||
|
||||
import org.session.libsignal.libsignal.util.ByteUtil;
|
||||
|
||||
public class DisplayableFingerprint {
|
||||
|
||||
private final String localFingerprintNumbers;
|
||||
private final String remoteFingerprintNumbers;
|
||||
|
||||
DisplayableFingerprint(byte[] localFingerprint, byte[] remoteFingerprint)
|
||||
{
|
||||
this.localFingerprintNumbers = getDisplayStringFor(localFingerprint);
|
||||
this.remoteFingerprintNumbers = getDisplayStringFor(remoteFingerprint);
|
||||
}
|
||||
|
||||
public String getDisplayText() {
|
||||
if (localFingerprintNumbers.compareTo(remoteFingerprintNumbers) <= 0) {
|
||||
return localFingerprintNumbers + remoteFingerprintNumbers;
|
||||
} else {
|
||||
return remoteFingerprintNumbers + localFingerprintNumbers;
|
||||
}
|
||||
}
|
||||
|
||||
private String getDisplayStringFor(byte[] fingerprint) {
|
||||
return getEncodedChunk(fingerprint, 0) +
|
||||
getEncodedChunk(fingerprint, 5) +
|
||||
getEncodedChunk(fingerprint, 10) +
|
||||
getEncodedChunk(fingerprint, 15) +
|
||||
getEncodedChunk(fingerprint, 20) +
|
||||
getEncodedChunk(fingerprint, 25);
|
||||
}
|
||||
|
||||
private String getEncodedChunk(byte[] hash, int offset) {
|
||||
long chunk = ByteUtil.byteArray5ToLong(hash, offset) % 100000;
|
||||
return String.format("%05d", chunk);
|
||||
}
|
||||
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2016 Open Whisper Systems
|
||||
*
|
||||
* Licensed according to the LICENSE file in this repository.
|
||||
*/
|
||||
package org.session.libsignal.libsignal.fingerprint;
|
||||
|
||||
import org.session.libsignal.libsignal.fingerprint.DisplayableFingerprint;
|
||||
import org.session.libsignal.libsignal.fingerprint.ScannableFingerprint;
|
||||
|
||||
public class Fingerprint {
|
||||
|
||||
private final DisplayableFingerprint displayableFingerprint;
|
||||
private final ScannableFingerprint scannableFingerprint;
|
||||
|
||||
public Fingerprint(DisplayableFingerprint displayableFingerprint,
|
||||
ScannableFingerprint scannableFingerprint)
|
||||
{
|
||||
this.displayableFingerprint = displayableFingerprint;
|
||||
this.scannableFingerprint = scannableFingerprint;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A text fingerprint that can be displayed and compared remotely.
|
||||
*/
|
||||
public DisplayableFingerprint getDisplayableFingerprint() {
|
||||
return displayableFingerprint;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A scannable fingerprint that can be scanned anc compared locally.
|
||||
*/
|
||||
public ScannableFingerprint getScannableFingerprint() {
|
||||
return scannableFingerprint;
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2016 Open Whisper Systems
|
||||
*
|
||||
* Licensed according to the LICENSE file in this repository.
|
||||
*/
|
||||
package org.session.libsignal.libsignal.fingerprint;
|
||||
|
||||
import org.session.libsignal.libsignal.IdentityKey;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface FingerprintGenerator {
|
||||
public Fingerprint createFor(String localStableIdentifier, IdentityKey localIdentityKey,
|
||||
String remoteStableIdentifier, IdentityKey remoteIdentityKey);
|
||||
|
||||
public Fingerprint createFor(String localStableIdentifier, List<IdentityKey> localIdentityKey,
|
||||
String remoteStableIdentifier, List<IdentityKey> remoteIdentityKey);
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2016 Open Whisper Systems
|
||||
*
|
||||
* Licensed according to the LICENSE file in this repository.
|
||||
*/
|
||||
package org.session.libsignal.libsignal.fingerprint;
|
||||
|
||||
public class FingerprintIdentifierMismatchException extends Exception {
|
||||
|
||||
private final String localIdentifier;
|
||||
private final String remoteIdentifier;
|
||||
private final String scannedLocalIdentifier;
|
||||
private final String scannedRemoteIdentifier;
|
||||
|
||||
public FingerprintIdentifierMismatchException(String localIdentifier, String remoteIdentifier,
|
||||
String scannedLocalIdentifier, String scannedRemoteIdentifier)
|
||||
{
|
||||
this.localIdentifier = localIdentifier;
|
||||
this.remoteIdentifier = remoteIdentifier;
|
||||
this.scannedLocalIdentifier = scannedLocalIdentifier;
|
||||
this.scannedRemoteIdentifier = scannedRemoteIdentifier;
|
||||
}
|
||||
|
||||
public String getScannedRemoteIdentifier() {
|
||||
return scannedRemoteIdentifier;
|
||||
}
|
||||
|
||||
public String getScannedLocalIdentifier() {
|
||||
return scannedLocalIdentifier;
|
||||
}
|
||||
|
||||
public String getRemoteIdentifier() {
|
||||
return remoteIdentifier;
|
||||
}
|
||||
|
||||
public String getLocalIdentifier() {
|
||||
return localIdentifier;
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2016 Open Whisper Systems
|
||||
*
|
||||
* Licensed according to the LICENSE file in this repository.
|
||||
*/
|
||||
package org.session.libsignal.libsignal.fingerprint;
|
||||
|
||||
public class FingerprintParsingException extends Exception {
|
||||
|
||||
public FingerprintParsingException(Exception nested) {
|
||||
super(nested);
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,26 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2016 Open Whisper Systems
|
||||
*
|
||||
* Licensed according to the LICENSE file in this repository.
|
||||
*/
|
||||
package org.session.libsignal.libsignal.fingerprint;
|
||||
|
||||
public class FingerprintVersionMismatchException extends Exception {
|
||||
|
||||
private final int theirVersion;
|
||||
private final int ourVersion;
|
||||
|
||||
public FingerprintVersionMismatchException(int theirVersion, int ourVersion) {
|
||||
super();
|
||||
this.theirVersion = theirVersion;
|
||||
this.ourVersion = ourVersion;
|
||||
}
|
||||
|
||||
public int getTheirVersion() {
|
||||
return theirVersion;
|
||||
}
|
||||
|
||||
public int getOurVersion() {
|
||||
return ourVersion;
|
||||
}
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2016 Open Whisper Systems
|
||||
*
|
||||
* Licensed according to the LICENSE file in this repository.
|
||||
*/
|
||||
package org.session.libsignal.libsignal.fingerprint;
|
||||
|
||||
import org.session.libsignal.libsignal.IdentityKey;
|
||||
import org.session.libsignal.libsignal.util.ByteUtil;
|
||||
import org.session.libsignal.libsignal.util.IdentityKeyComparator;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class NumericFingerprintGenerator implements FingerprintGenerator {
|
||||
|
||||
private static final int FINGERPRINT_VERSION = 0;
|
||||
|
||||
private final int iterations;
|
||||
|
||||
/**
|
||||
* Construct a fingerprint generator for 60 digit numerics.
|
||||
*
|
||||
* @param iterations The number of internal iterations to perform in the process of
|
||||
* generating a fingerprint. This needs to be constant, and synchronized
|
||||
* across all clients.
|
||||
*
|
||||
* The higher the iteration count, the higher the security level:
|
||||
*
|
||||
* - 1024 ~ 109.7 bits
|
||||
* - 1400 > 110 bits
|
||||
* - 5200 > 112 bits
|
||||
*/
|
||||
public NumericFingerprintGenerator(int iterations) {
|
||||
this.iterations = iterations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a scannable and displayble fingerprint.
|
||||
*
|
||||
* @param localStableIdentifier The client's "stable" identifier.
|
||||
* @param localIdentityKey The client's identity key.
|
||||
* @param remoteStableIdentifier The remote party's "stable" identifier.
|
||||
* @param remoteIdentityKey The remote party's identity key.
|
||||
* @return A unique fingerprint for this conversation.
|
||||
*/
|
||||
@Override
|
||||
public Fingerprint createFor(String localStableIdentifier, final IdentityKey localIdentityKey,
|
||||
String remoteStableIdentifier, final IdentityKey remoteIdentityKey)
|
||||
{
|
||||
return createFor(localStableIdentifier,
|
||||
new LinkedList<IdentityKey>() {{
|
||||
add(localIdentityKey);
|
||||
}},
|
||||
remoteStableIdentifier,
|
||||
new LinkedList<IdentityKey>() {{
|
||||
add(remoteIdentityKey);
|
||||
}});
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a scannable and displayble fingerprint for logical identities that have multiple
|
||||
* physical keys.
|
||||
*
|
||||
* Do not trust the output of this unless you've been through the device consistency process
|
||||
* for the provided localIdentityKeys.
|
||||
*
|
||||
* @param localStableIdentifier The client's "stable" identifier.
|
||||
* @param localIdentityKeys The client's collection of physical identity keys.
|
||||
* @param remoteStableIdentifier The remote party's "stable" identifier.
|
||||
* @param remoteIdentityKeys The remote party's collection of physical identity key.
|
||||
* @return A unique fingerprint for this conversation.
|
||||
*/
|
||||
public Fingerprint createFor(String localStableIdentifier, List<IdentityKey> localIdentityKeys,
|
||||
String remoteStableIdentifier, List<IdentityKey> remoteIdentityKeys)
|
||||
{
|
||||
byte[] localFingerprint = getFingerprint(iterations, localStableIdentifier, localIdentityKeys);
|
||||
byte[] remoteFingerprint = getFingerprint(iterations, remoteStableIdentifier, remoteIdentityKeys);
|
||||
|
||||
DisplayableFingerprint displayableFingerprint = new DisplayableFingerprint(localFingerprint,
|
||||
remoteFingerprint);
|
||||
|
||||
ScannableFingerprint scannableFingerprint = new ScannableFingerprint(localFingerprint,
|
||||
remoteFingerprint);
|
||||
|
||||
return new Fingerprint(displayableFingerprint, scannableFingerprint);
|
||||
}
|
||||
|
||||
private byte[] getFingerprint(int iterations, String stableIdentifier, List<IdentityKey> unsortedIdentityKeys) {
|
||||
try {
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-512");
|
||||
byte[] publicKey = getLogicalKeyBytes(unsortedIdentityKeys);
|
||||
byte[] hash = ByteUtil.combine(ByteUtil.shortToByteArray(FINGERPRINT_VERSION),
|
||||
publicKey, stableIdentifier.getBytes());
|
||||
|
||||
for (int i=0;i<iterations;i++) {
|
||||
digest.update(hash);
|
||||
hash = digest.digest(publicKey);
|
||||
}
|
||||
|
||||
return hash;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] getLogicalKeyBytes(List<IdentityKey> identityKeys) {
|
||||
ArrayList<IdentityKey> sortedIdentityKeys = new ArrayList<IdentityKey>(identityKeys);
|
||||
Collections.sort(sortedIdentityKeys, new IdentityKeyComparator());
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
||||
for (IdentityKey identityKey : sortedIdentityKeys) {
|
||||
byte[] publicKeyBytes = identityKey.getPublicKey().serialize();
|
||||
baos.write(publicKeyBytes, 0, publicKeyBytes.length);
|
||||
}
|
||||
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2016 Open Whisper Systems
|
||||
*
|
||||
* Licensed according to the LICENSE file in this repository.
|
||||
*/
|
||||
package org.session.libsignal.libsignal.fingerprint;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
|
||||
import org.session.libsignal.libsignal.fingerprint.FingerprintParsingException;
|
||||
import org.session.libsignal.libsignal.fingerprint.FingerprintProtos.CombinedFingerprints;
|
||||
import org.session.libsignal.libsignal.fingerprint.FingerprintProtos.LogicalFingerprint;
|
||||
import org.session.libsignal.libsignal.fingerprint.FingerprintVersionMismatchException;
|
||||
import org.session.libsignal.libsignal.util.ByteUtil;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
|
||||
public class ScannableFingerprint {
|
||||
|
||||
private static final int VERSION = 1;
|
||||
|
||||
private final CombinedFingerprints fingerprints;
|
||||
|
||||
ScannableFingerprint(byte[] localFingerprintData, byte[] remoteFingerprintData)
|
||||
{
|
||||
LogicalFingerprint localFingerprint = LogicalFingerprint.newBuilder()
|
||||
.setContent(ByteString.copyFrom(ByteUtil.trim(localFingerprintData, 32)))
|
||||
.build();
|
||||
|
||||
LogicalFingerprint remoteFingerprint = LogicalFingerprint.newBuilder()
|
||||
.setContent(ByteString.copyFrom(ByteUtil.trim(remoteFingerprintData, 32)))
|
||||
.build();
|
||||
|
||||
this.fingerprints = CombinedFingerprints.newBuilder()
|
||||
.setVersion(VERSION)
|
||||
.setLocalFingerprint(localFingerprint)
|
||||
.setRemoteFingerprint(remoteFingerprint)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A byte string to be displayed in a QR code.
|
||||
*/
|
||||
public byte[] getSerialized() {
|
||||
return fingerprints.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare a scanned QR code with what we expect.
|
||||
*
|
||||
* @param scannedFingerprintData The scanned data
|
||||
* @return True if matching, otehrwise false.
|
||||
* @throws FingerprintVersionMismatchException if the scanned fingerprint is the wrong version.
|
||||
*/
|
||||
public boolean compareTo(byte[] scannedFingerprintData)
|
||||
throws FingerprintVersionMismatchException,
|
||||
FingerprintParsingException
|
||||
{
|
||||
try {
|
||||
CombinedFingerprints scanned = CombinedFingerprints.parseFrom(scannedFingerprintData);
|
||||
|
||||
if (!scanned.hasRemoteFingerprint() || !scanned.hasLocalFingerprint() ||
|
||||
!scanned.hasVersion() || scanned.getVersion() != VERSION)
|
||||
{
|
||||
throw new FingerprintVersionMismatchException(scanned.getVersion(), VERSION);
|
||||
}
|
||||
|
||||
return MessageDigest.isEqual(fingerprints.getLocalFingerprint().getContent().toByteArray(), scanned.getRemoteFingerprint().getContent().toByteArray()) &&
|
||||
MessageDigest.isEqual(fingerprints.getRemoteFingerprint().getContent().toByteArray(), scanned.getLocalFingerprint().getContent().toByteArray());
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
throw new FingerprintParsingException(e);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user