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