private static SignalProtocolAddress GetPreferredProtocolAddress(SignalProtocolStore store, SignalServiceAddress address, int sourceDevice) { SignalProtocolAddress?uuidAddress = address.Uuid.HasValue ? new SignalProtocolAddress(address.Uuid.Value.ToString(), (uint)sourceDevice) : null; SignalProtocolAddress?e164Address = address.GetNumber() != null ? new SignalProtocolAddress(address.GetNumber(), (uint)sourceDevice) : null; if (uuidAddress != null && store.ContainsSession(uuidAddress)) { return(uuidAddress); } else if (e164Address != null && store.ContainsSession(e164Address)) { return(e164Address); } else { return(new SignalProtocolAddress(address.GetIdentifier(), (uint)sourceDevice)); } }
private PreKeyBundle createBobPreKeyBundle(SignalProtocolStore bobStore) { ECKeyPair bobUnsignedPreKey = Curve.generateKeyPair(); int bobUnsignedPreKeyId = new Random().Next((int)Medium.MAX_VALUE); byte[] bobSignature = Curve.calculateSignature(bobStore.GetIdentityKeyPair().getPrivateKey(), bobSignedPreKey.getPublicKey().serialize()); PreKeyBundle bobPreKeyBundle = new PreKeyBundle(1, 1, (uint)bobUnsignedPreKeyId, bobUnsignedPreKey.getPublicKey(), bobSignedPreKeyId, bobSignedPreKey.getPublicKey(), bobSignature, bobStore.GetIdentityKeyPair().getPublicKey()); bobStore.StoreSignedPreKey(bobSignedPreKeyId, new SignedPreKeyRecord(bobSignedPreKeyId, (ulong)DateTime.UtcNow.Ticks, bobSignedPreKey, bobSignature)); bobStore.StorePreKey((uint)bobUnsignedPreKeyId, new PreKeyRecord((uint)bobUnsignedPreKeyId, bobUnsignedPreKey)); return(bobPreKeyBundle); }
private PreKeyBundle createAlicePreKeyBundle(SignalProtocolStore aliceStore) { ECKeyPair aliceUnsignedPreKey = Curve.generateKeyPair(); int aliceUnsignedPreKeyId = new Random().Next((int)Medium.MAX_VALUE); byte[] aliceSignature = Curve.calculateSignature(aliceStore.GetIdentityKeyPair().getPrivateKey(), aliceSignedPreKey.getPublicKey().serialize()); PreKeyBundle alicePreKeyBundle = new PreKeyBundle(1, 1, (uint)aliceUnsignedPreKeyId, aliceUnsignedPreKey.getPublicKey(), aliceSignedPreKeyId, aliceSignedPreKey.getPublicKey(), aliceSignature, aliceStore.GetIdentityKeyPair().getPublicKey()); aliceStore.StoreSignedPreKey(aliceSignedPreKeyId, new SignedPreKeyRecord(aliceSignedPreKeyId, (ulong)DateTime.UtcNow.Ticks, aliceSignedPreKey, aliceSignature)); aliceStore.StorePreKey((uint)aliceUnsignedPreKeyId, new PreKeyRecord((uint)aliceUnsignedPreKeyId, aliceUnsignedPreKey)); return(alicePreKeyBundle); }
/// <summary> /// Construct a SignalServiceMessageSender /// </summary> /// <param name="token">A CancellationToken to cancel the sender's operations</param> /// <param name="urls">The URL of the Signal Service.</param> /// <param name="user">The Signal Service username (eg phone number).</param> /// <param name="password">The Signal Service user password</param> /// <param name="deviceId">Tbe Signal Service device id</param> /// <param name="store">The SignalProtocolStore.</param> /// <param name="pipe">An optional SignalServiceMessagePipe</param> /// <param name="unidentifiedPipe"></param> /// <param name="eventListener">An optional event listener, which fires whenever sessions are /// setup or torn down for a recipient.</param> /// <param name="userAgent"></param> /// <param name="isMultiDevice"></param> public SignalServiceMessageSender(CancellationToken token, SignalServiceConfiguration urls, string user, string password, int deviceId, SignalProtocolStore store, string userAgent, bool isMultiDevice, SignalServiceMessagePipe?pipe, SignalServiceMessagePipe?unidentifiedPipe, IEventListener eventListener) { Token = token; CredentialsProvider = new StaticCredentialsProvider(user, password, null, deviceId); Socket = new PushServiceSocket(urls, CredentialsProvider, userAgent); Store = store; LocalAddress = new SignalServiceAddress(user); Pipe = pipe; UnidentifiedPipe = unidentifiedPipe; IsMultiDevice = isMultiDevice; EventListener = eventListener; }
public byte[] Encrypt(SignalProtocolAddress destinationAddress, SenderCertificate senderCertificate, byte[] paddedPlaintext) { CiphertextMessage message = new SessionCipher(SignalProtocolStore, destinationAddress).encrypt(paddedPlaintext); IdentityKeyPair ourIdentity = SignalProtocolStore.GetIdentityKeyPair(); ECPublicKey theirIdentity = SignalProtocolStore.GetIdentity(destinationAddress).getPublicKey(); ECKeyPair ephemeral = Curve.generateKeyPair(); byte[] ephemeralSalt = ByteUtil.combine(Encoding.ASCII.GetBytes("UnidentifiedDelivery"), theirIdentity.serialize(), ephemeral.getPublicKey().serialize()); EphemeralKeys ephemeralKeys = CalculateEphemeralKeys(theirIdentity, ephemeral.getPrivateKey(), ephemeralSalt); byte[] staticKeyCiphertext = Encrypt(ephemeralKeys.CipherKey, ephemeralKeys.MacKey, ourIdentity.getPublicKey().getPublicKey().serialize()); byte[] staticSalt = ByteUtil.combine(ephemeralKeys.ChainKey, staticKeyCiphertext); StaticKeys staticKeys = CalculateStaticKeys(theirIdentity, ourIdentity.getPrivateKey(), staticSalt); UnidentifiedSenderMessageContent content = new UnidentifiedSenderMessageContent((int)message.getType(), senderCertificate, message.serialize()); byte[] messageBytes = Encrypt(staticKeys.CipherKey, staticKeys.MacKey, content.Serialized); return(new UnidentifiedSenderMessage(ephemeral.getPublicKey(), staticKeyCiphertext, messageBytes).Serialized); }
private void runInteraction(SignalProtocolStore aliceStore, SignalProtocolStore bobStore) { SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS); SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_ADDRESS); String originalMessage = "smert ze smert"; CiphertextMessage aliceMessage = aliceSessionCipher.encrypt(Encoding.UTF8.GetBytes(originalMessage)); Assert.AreEqual(CiphertextMessage.WHISPER_TYPE, aliceMessage.getType()); byte[] plaintext = bobSessionCipher.decrypt(new SignalMessage(aliceMessage.serialize())); Assert.AreEqual(originalMessage, Encoding.UTF8.GetString(plaintext)); CiphertextMessage bobMessage = bobSessionCipher.encrypt(Encoding.UTF8.GetBytes(originalMessage)); Assert.AreEqual(CiphertextMessage.WHISPER_TYPE, bobMessage.getType()); plaintext = aliceSessionCipher.decrypt(new SignalMessage(bobMessage.serialize())); Assert.AreEqual(originalMessage, Encoding.UTF8.GetString(plaintext)); for (int i = 0; i < 10; i++) { String loopingMessage = ("What do we mean by saying that existence precedes essence? " + "We mean that man first of all exists, encounters himself, " + "surges up in the world--and defines himself aftward. " + i); CiphertextMessage aliceLoopingMessage = aliceSessionCipher.encrypt(Encoding.UTF8.GetBytes(loopingMessage)); byte[] loopingPlaintext = bobSessionCipher.decrypt(new SignalMessage(aliceLoopingMessage.serialize())); Assert.AreEqual(loopingMessage, Encoding.UTF8.GetString(loopingPlaintext)); } for (int i = 0; i < 10; i++) { String loopingMessage = ("What do we mean by saying that existence precedes essence? " + "We mean that man first of all exists, encounters himself, " + "surges up in the world--and defines himself aftward. " + i); CiphertextMessage bobLoopingMessage = bobSessionCipher.encrypt(Encoding.UTF8.GetBytes(loopingMessage)); byte[] loopingPlaintext = aliceSessionCipher.decrypt(new SignalMessage(bobLoopingMessage.serialize())); Assert.AreEqual(loopingMessage, Encoding.UTF8.GetString(loopingPlaintext)); } HashSet <Pair <String, CiphertextMessage> > aliceOutOfOrderMessages = new HashSet <Pair <String, CiphertextMessage> >(); for (int i = 0; i < 10; i++) { String loopingMessage = ("What do we mean by saying that existence precedes essence? " + "We mean that man first of all exists, encounters himself, " + "surges up in the world--and defines himself aftward. " + i); CiphertextMessage aliceLoopingMessage = aliceSessionCipher.encrypt(Encoding.UTF8.GetBytes(loopingMessage)); aliceOutOfOrderMessages.Add(new Pair <String, CiphertextMessage>(loopingMessage, aliceLoopingMessage)); } for (int i = 0; i < 10; i++) { String loopingMessage = ("What do we mean by saying that existence precedes essence? " + "We mean that man first of all exists, encounters himself, " + "surges up in the world--and defines himself aftward. " + i); CiphertextMessage aliceLoopingMessage = aliceSessionCipher.encrypt(Encoding.UTF8.GetBytes(loopingMessage)); byte[] loopingPlaintext = bobSessionCipher.decrypt(new SignalMessage(aliceLoopingMessage.serialize())); Assert.AreEqual(loopingMessage, Encoding.UTF8.GetString(loopingPlaintext)); } for (int i = 0; i < 10; i++) { String loopingMessage = ("You can only desire based on what you know: " + i); CiphertextMessage bobLoopingMessage = bobSessionCipher.encrypt(Encoding.UTF8.GetBytes(loopingMessage)); byte[] loopingPlaintext = aliceSessionCipher.decrypt(new SignalMessage(bobLoopingMessage.serialize())); Assert.AreEqual(loopingMessage, Encoding.UTF8.GetString(loopingPlaintext)); } foreach (Pair <String, CiphertextMessage> aliceOutOfOrderMessage in aliceOutOfOrderMessages) { byte[] outOfOrderPlaintext = bobSessionCipher.decrypt(new SignalMessage(aliceOutOfOrderMessage.second().serialize())); Assert.AreEqual(aliceOutOfOrderMessage.first(), Encoding.UTF8.GetString(outOfOrderPlaintext)); } }
public BobDecryptionCallback(SignalProtocolStore bobStore, String originalMessage) { this.bobStore = bobStore; this.originalMessage = originalMessage; }
/** * Constructs a SessionBuilder * @param store The {@link SignalProtocolStore} to store all state information in. * @param remoteAddress The address of the remote user to build a session with. */ public SessionBuilder(SignalProtocolStore store, SignalProtocolAddress remoteAddress) : this(store, store, store, store, remoteAddress) { }
public SignalServiceCipher(SignalServiceAddress localAddress, SignalProtocolStore signalProtocolStore) { this.signalProtocolStore = signalProtocolStore; this.localAddress = localAddress; }
private bool isSessionIdEqual(SignalProtocolStore aliceStore, SignalProtocolStore bobStore) { return(ByteUtil.isEqual(aliceStore.LoadSession(BOB_ADDRESS).getSessionState().getAliceBaseKey(), bobStore.LoadSession(ALICE_ADDRESS).getSessionState().getAliceBaseKey())); }
public (SignalProtocolAddress, byte[]) Decrypt(CertificateValidator validator, byte[] ciphertext, long timestamp) { UnidentifiedSenderMessageContent content; try { IdentityKeyPair ourIdentity = SignalProtocolStore.GetIdentityKeyPair(); UnidentifiedSenderMessage wrapper = new UnidentifiedSenderMessage(ciphertext); byte[] ephemeralSalt = ByteUtil.combine(Encoding.ASCII.GetBytes("UnidentifiedDelivery"), ourIdentity.getPublicKey().getPublicKey().serialize(), wrapper.Ephemeral.serialize()); EphemeralKeys ephemeralKeys = CalculateEphemeralKeys(wrapper.Ephemeral, ourIdentity.getPrivateKey(), ephemeralSalt); byte[] staticKeyBytes = Decrypt(ephemeralKeys.CipherKey, ephemeralKeys.MacKey, wrapper.EncryptedStatic); ECPublicKey staticKey = Curve.decodePoint(staticKeyBytes, 0); byte[] staticSalt = ByteUtil.combine(ephemeralKeys.ChainKey, wrapper.EncryptedStatic); StaticKeys staticKeys = CalculateStaticKeys(staticKey, ourIdentity.getPrivateKey(), staticSalt); byte[] messageBytes = Decrypt(staticKeys.CipherKey, staticKeys.MacKey, wrapper.EncryptedMessage); content = new UnidentifiedSenderMessageContent(messageBytes); validator.Validate(content.SenderCertificate, timestamp); if (!Enumerable.SequenceEqual(content.SenderCertificate.Key.serialize(), staticKeyBytes)) { throw new libsignal.InvalidKeyException("Sender's certificate key does not match key used in message"); } if (content.SenderCertificate.Sender == LocalAddress.Name && content.SenderCertificate.SenderDeviceId == LocalAddress.DeviceId) { throw new SelfSendException(); } } catch (libsignal.InvalidKeyException e) { throw new InvalidMetadataMessageException(e); } catch (InvalidCertificateException e) { throw new InvalidMetadataMessageException(e); } catch (InvalidMacException e) { throw new InvalidMetadataMessageException(e); } try { return(new SignalProtocolAddress(content.SenderCertificate.Sender, (uint)content.SenderCertificate.SenderDeviceId), Decrypt(content)); } catch (InvalidMessageException e) { throw new ProtocolInvalidMessageException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId); } catch (libsignal.InvalidKeyException e) { throw new ProtocolInvalidKeyException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId); } catch (NoSessionException e) { throw new ProtocolNoSessionException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId); } catch (LegacyMessageException e) { throw new ProtocolLegacyMessageException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId); } catch (InvalidVersionException e) { throw new ProtocolInvalidVersionException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId); } catch (DuplicateMessageException e) { throw new ProtocolDuplicateMessageException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId); } catch (InvalidKeyIdException e) { throw new ProtocolInvalidKeyIdException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId); } catch (UntrustedIdentityException e) { throw new ProtocolUntrustedIdentityException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId); } }
public SealedSessionCipher(SignalProtocolStore store, SignalProtocolAddress localAddress) { SignalProtocolStore = store; LocalAddress = localAddress; }