clean fingerprint

This commit is contained in:
ryanzhao 2021-02-03 16:44:08 +11:00
parent a11173676f
commit c07056f385
9 changed files with 0 additions and 1655 deletions

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}
}