mirror of
https://github.com/signalapp/libsignal.git
synced 2026-05-10 09:02:05 +02:00
Add SenderCertificate and ServerCertificate
This commit is contained in:
@@ -136,6 +136,19 @@ public final class Native {
|
||||
|
||||
public static native boolean ScannableFingerprint_Compare(byte[] fprint1, byte[] fprint2);
|
||||
|
||||
public static native long SenderCertificate_Deserialize(byte[] data);
|
||||
public static native void SenderCertificate_Destroy(long handle);
|
||||
public static native byte[] SenderCertificate_GetCertificate(long handle);
|
||||
public static native int SenderCertificate_GetDeviceId(long handle);
|
||||
public static native long SenderCertificate_GetExpiration(long handle);
|
||||
public static native long SenderCertificate_GetKey(long handle);
|
||||
public static native String SenderCertificate_GetSenderE164(long handle);
|
||||
public static native String SenderCertificate_GetSenderUuid(long handle);
|
||||
public static native byte[] SenderCertificate_GetSerialized(long handle);
|
||||
public static native long SenderCertificate_GetServerCertificate(long handle);
|
||||
public static native byte[] SenderCertificate_GetSignature(long handle);
|
||||
public static native boolean SenderCertificate_Validate(long cert, long key, long time);
|
||||
|
||||
public static native long SenderKeyDistributionMessage_Deserialize(byte[] data);
|
||||
public static native void SenderKeyDistributionMessage_Destroy(long handle);
|
||||
public static native byte[] SenderKeyDistributionMessage_GetChainKey(long handle);
|
||||
@@ -165,6 +178,14 @@ public final class Native {
|
||||
public static native byte[] SenderKeyRecord_GetSerialized(long handle);
|
||||
public static native long SenderKeyRecord_New();
|
||||
|
||||
public static native long ServerCertificate_Deserialize(byte[] data);
|
||||
public static native void ServerCertificate_Destroy(long handle);
|
||||
public static native byte[] ServerCertificate_GetCertificate(long handle);
|
||||
public static native long ServerCertificate_GetKey(long handle);
|
||||
public static native int ServerCertificate_GetKeyId(long handle);
|
||||
public static native byte[] ServerCertificate_GetSerialized(long handle);
|
||||
public static native byte[] ServerCertificate_GetSignature(long handle);
|
||||
|
||||
public static native void SessionBuilder_ProcessPreKeyBundle(long bundle, long protocolAddress, SessionStore sessionStore, IdentityKeyStore identityKeyStore);
|
||||
|
||||
public static native byte[] SessionCipher_DecryptPreKeySignalMessage(long message, long protocolAddress, SessionStore sessionStore, IdentityKeyStore identityKeyStore, PreKeyStore prekeyStore, SignedPreKeyStore signedPrekeyStore);
|
||||
|
||||
@@ -1,20 +1,12 @@
|
||||
package org.signal.libsignal.metadata.certificate;
|
||||
|
||||
import org.signal.client.internal.Native;
|
||||
|
||||
import org.whispersystems.libsignal.InvalidKeyException;
|
||||
import org.whispersystems.libsignal.ecc.Curve;
|
||||
import org.whispersystems.libsignal.ecc.ECPublicKey;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.whispersystems.libsignal.InvalidKeyException;
|
||||
|
||||
public class CertificateValidator {
|
||||
|
||||
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
|
||||
private static final Set<Integer> REVOKED = new HashSet<Integer>() {{
|
||||
|
||||
}};
|
||||
|
||||
private final ECPublicKey trustRoot;
|
||||
|
||||
public CertificateValidator(ECPublicKey trustRoot) {
|
||||
@@ -23,17 +15,10 @@ public class CertificateValidator {
|
||||
|
||||
public void validate(SenderCertificate certificate, long validationTime) throws InvalidCertificateException {
|
||||
try {
|
||||
ServerCertificate serverCertificate = certificate.getSigner();
|
||||
validate(serverCertificate);
|
||||
|
||||
if (!Curve.verifySignature(serverCertificate.getKey(), certificate.getCertificate(), certificate.getSignature())) {
|
||||
throw new InvalidCertificateException("Signature failed");
|
||||
}
|
||||
|
||||
if (validationTime > certificate.getExpiration()) {
|
||||
throw new InvalidCertificateException("Certificate is expired");
|
||||
}
|
||||
} catch (InvalidKeyException e) {
|
||||
if (!Native.SenderCertificate_Validate(certificate.nativeHandle(), trustRoot.nativeHandle(), validationTime)) {
|
||||
throw new InvalidCertificateException("Validation failed");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new InvalidCertificateException(e);
|
||||
}
|
||||
}
|
||||
@@ -44,13 +29,8 @@ public class CertificateValidator {
|
||||
if (!Curve.verifySignature(trustRoot, certificate.getCertificate(), certificate.getSignature())) {
|
||||
throw new InvalidCertificateException("Signature failed");
|
||||
}
|
||||
|
||||
if (REVOKED.contains(certificate.getKeyId())) {
|
||||
throw new InvalidCertificateException("Server certificate has been revoked");
|
||||
}
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new InvalidCertificateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,100 +1,73 @@
|
||||
package org.signal.libsignal.metadata.certificate;
|
||||
|
||||
import org.signal.client.internal.Native;
|
||||
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
|
||||
import org.signal.libsignal.metadata.SignalProtos;
|
||||
import org.whispersystems.libsignal.InvalidKeyException;
|
||||
import org.whispersystems.libsignal.ecc.Curve;
|
||||
import org.whispersystems.libsignal.ecc.ECPublicKey;
|
||||
import org.whispersystems.libsignal.InvalidKeyException;
|
||||
import org.whispersystems.libsignal.InvalidMessageException;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
|
||||
public class SenderCertificate {
|
||||
private long handle;
|
||||
|
||||
private final ServerCertificate signer;
|
||||
private final ECPublicKey key;
|
||||
private final int senderDeviceId;
|
||||
private final Optional<String> senderUuid;
|
||||
private final Optional<String> senderE164;
|
||||
private final long expiration;
|
||||
@Override
|
||||
protected void finalize() {
|
||||
Native.SenderCertificate_Destroy(this.handle);
|
||||
}
|
||||
|
||||
private final byte[] serialized;
|
||||
private final byte[] certificate;
|
||||
private final byte[] signature;
|
||||
public long nativeHandle() {
|
||||
return this.handle;
|
||||
}
|
||||
|
||||
public SenderCertificate(byte[] serialized) throws InvalidCertificateException {
|
||||
try {
|
||||
SignalProtos.SenderCertificate wrapper = SignalProtos.SenderCertificate.parseFrom(serialized);
|
||||
|
||||
if (!wrapper.hasSignature() || !wrapper.hasCertificate()) {
|
||||
throw new InvalidCertificateException("Missing fields");
|
||||
}
|
||||
|
||||
SignalProtos.SenderCertificate.Certificate certificate = SignalProtos.SenderCertificate.Certificate.parseFrom(wrapper.getCertificate());
|
||||
|
||||
if (!certificate.hasSigner() ||
|
||||
!certificate.hasIdentityKey() ||
|
||||
!certificate.hasSenderDevice() ||
|
||||
!certificate.hasExpires() ||
|
||||
(!certificate.hasSenderUuid() && !certificate.hasSenderE164()))
|
||||
{
|
||||
throw new InvalidCertificateException("Missing fields");
|
||||
}
|
||||
|
||||
this.signer = new ServerCertificate(certificate.getSigner().toByteArray());
|
||||
this.key = Curve.decodePoint(certificate.getIdentityKey().toByteArray(), 0);
|
||||
this.senderUuid = certificate.hasSenderUuid() ? Optional.of(certificate.getSenderUuid()) : Optional.<String>absent();
|
||||
this.senderE164 = certificate.hasSenderE164() ? Optional.of(certificate.getSenderE164()) : Optional.<String>absent();
|
||||
this.senderDeviceId = certificate.getSenderDevice();
|
||||
this.expiration = certificate.getExpires();
|
||||
|
||||
this.serialized = serialized;
|
||||
this.certificate = wrapper.getCertificate().toByteArray();
|
||||
this.signature = wrapper.getSignature().toByteArray();
|
||||
|
||||
} catch (InvalidProtocolBufferException | InvalidKeyException e) {
|
||||
handle = Native.SenderCertificate_Deserialize(serialized);
|
||||
} catch (Exception e) {
|
||||
throw new InvalidCertificateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public SenderCertificate(long handle) {
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
public ServerCertificate getSigner() {
|
||||
return signer;
|
||||
return new ServerCertificate(Native.SenderCertificate_GetServerCertificate(this.handle));
|
||||
}
|
||||
|
||||
public ECPublicKey getKey() {
|
||||
return key;
|
||||
return new ECPublicKey(Native.SenderCertificate_GetKey(this.handle));
|
||||
}
|
||||
|
||||
public int getSenderDeviceId() {
|
||||
return senderDeviceId;
|
||||
return Native.SenderCertificate_GetDeviceId(this.handle);
|
||||
}
|
||||
|
||||
public Optional<String> getSenderUuid() {
|
||||
return senderUuid;
|
||||
return Optional.fromNullable(Native.SenderCertificate_GetSenderUuid(this.handle));
|
||||
}
|
||||
|
||||
public Optional<String> getSenderE164() {
|
||||
return senderE164;
|
||||
return Optional.fromNullable(Native.SenderCertificate_GetSenderE164(this.handle));
|
||||
}
|
||||
|
||||
public String getSender() {
|
||||
return senderE164.or(senderUuid).orNull();
|
||||
return getSenderE164().or(getSenderUuid()).orNull();
|
||||
}
|
||||
|
||||
public long getExpiration() {
|
||||
return expiration;
|
||||
return Native.SenderCertificate_GetExpiration(this.handle);
|
||||
}
|
||||
|
||||
public byte[] getSerialized() {
|
||||
return serialized;
|
||||
return Native.SenderCertificate_GetSerialized(this.handle);
|
||||
}
|
||||
|
||||
public byte[] getCertificate() {
|
||||
return certificate;
|
||||
return Native.SenderCertificate_GetCertificate(this.handle);
|
||||
}
|
||||
|
||||
public byte[] getSignature() {
|
||||
return signature;
|
||||
return Native.SenderCertificate_GetSignature(this.handle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,64 +1,49 @@
|
||||
package org.signal.libsignal.metadata.certificate;
|
||||
|
||||
import org.signal.client.internal.Native;
|
||||
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
|
||||
import org.signal.libsignal.metadata.SignalProtos;
|
||||
import org.whispersystems.libsignal.ecc.ECPublicKey;
|
||||
import org.whispersystems.libsignal.InvalidKeyException;
|
||||
import org.whispersystems.libsignal.ecc.Curve;
|
||||
import org.whispersystems.libsignal.InvalidMessageException;
|
||||
import org.whispersystems.libsignal.ecc.ECPublicKey;
|
||||
|
||||
public class ServerCertificate {
|
||||
private final long handle;
|
||||
|
||||
private final int keyId;
|
||||
private final ECPublicKey key;
|
||||
@Override
|
||||
protected void finalize() {
|
||||
Native.ServerCertificate_Destroy(this.handle);
|
||||
}
|
||||
|
||||
private final byte[] serialized;
|
||||
private final byte[] certificate;
|
||||
private final byte[] signature;
|
||||
public ServerCertificate(long handle) {
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
public ServerCertificate(byte[] serialized) throws InvalidCertificateException {
|
||||
try {
|
||||
SignalProtos.ServerCertificate wrapper = SignalProtos.ServerCertificate.parseFrom(serialized);
|
||||
|
||||
if (!wrapper.hasCertificate() || !wrapper.hasSignature()) {
|
||||
throw new InvalidCertificateException("Missing fields");
|
||||
}
|
||||
|
||||
SignalProtos.ServerCertificate.Certificate certificate = SignalProtos.ServerCertificate.Certificate.parseFrom(wrapper.getCertificate());
|
||||
|
||||
if (!certificate.hasId() || !certificate.hasKey()) {
|
||||
throw new InvalidCertificateException("Missing fields");
|
||||
}
|
||||
|
||||
this.keyId = certificate.getId();
|
||||
this.key = Curve.decodePoint(certificate.getKey().toByteArray(), 0);
|
||||
this.serialized = serialized;
|
||||
this.certificate = wrapper.getCertificate().toByteArray();
|
||||
this.signature = wrapper.getSignature().toByteArray();
|
||||
|
||||
} catch (InvalidProtocolBufferException | InvalidKeyException e) {
|
||||
this.handle = Native.ServerCertificate_Deserialize(serialized);
|
||||
} catch (Exception e) {
|
||||
throw new InvalidCertificateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public int getKeyId() {
|
||||
return keyId;
|
||||
return Native.ServerCertificate_GetKeyId(this.handle);
|
||||
}
|
||||
|
||||
public ECPublicKey getKey() {
|
||||
return key;
|
||||
return new ECPublicKey(Native.ServerCertificate_GetKey(this.handle));
|
||||
}
|
||||
|
||||
public byte[] getSerialized() {
|
||||
return serialized;
|
||||
return Native.ServerCertificate_GetSerialized(this.handle);
|
||||
}
|
||||
|
||||
public byte[] getCertificate() {
|
||||
return certificate;
|
||||
return Native.ServerCertificate_GetCertificate(this.handle);
|
||||
}
|
||||
|
||||
public byte[] getSignature() {
|
||||
return signature;
|
||||
return Native.ServerCertificate_GetSignature(this.handle);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user