/// <summary> /// /// </summary> /// <param name="envelope"></param> /// <param name="ciphertext"></param> /// <returns></returns> /// <exception cref="InvalidMetadataMessageException"></exception> /// <exception cref="InvalidMetadataVersionException"></exception> /// <exception cref="ProtocolDuplicateMessageException"></exception> /// <exception cref="ProtocolUntrustedIdentityException"></exception> /// <exception cref="ProtocolLegacyMessageException"></exception> /// <exception cref="ProtocolInvalidKeyException"></exception> /// <exception cref="ProtocolInvalidVersionException"></exception> /// <exception cref="ProtocolInvalidMessageException"></exception> /// <exception cref="ProtocolInvalidKeyIdException"></exception> /// <exception cref="ProtocolNoSessionException"></exception> /// <exception cref="SelfSendException"></exception> private Plaintext Decrypt(SignalServiceEnvelope envelope, byte[] ciphertext) { try { byte[] paddedMessage; SignalServiceMetadata metadata; uint sessionVersion; if (!envelope.HasSource() && !envelope.IsUnidentifiedSender()) { throw new ProtocolInvalidMessageException(new InvalidMessageException("Non-UD envelope is missing a source!"), null, 0); } if (envelope.IsPreKeySignalMessage()) { SignalProtocolAddress sourceAddress = GetPreferredProtocolAddress(signalProtocolStore, envelope.GetSourceAddress(), envelope.GetSourceDevice()); SessionCipher sessionCipher = new SessionCipher(signalProtocolStore, sourceAddress); paddedMessage = sessionCipher.decrypt(new PreKeySignalMessage(ciphertext)); metadata = new SignalServiceMetadata(envelope.GetSourceAddress(), envelope.GetSourceDevice(), envelope.GetTimestamp(), false); sessionVersion = sessionCipher.getSessionVersion(); } else if (envelope.IsSignalMessage()) { SignalProtocolAddress sourceAddress = GetPreferredProtocolAddress(signalProtocolStore, envelope.GetSourceAddress(), envelope.GetSourceDevice()); SessionCipher sessionCipher = new SessionCipher(signalProtocolStore, sourceAddress); paddedMessage = sessionCipher.decrypt(new SignalMessage(ciphertext)); metadata = new SignalServiceMetadata(envelope.GetSourceAddress(), envelope.GetSourceDevice(), envelope.GetTimestamp(), false); sessionVersion = sessionCipher.getSessionVersion(); } else if (envelope.IsUnidentifiedSender()) { SealedSessionCipher sealedSessionCipher = new SealedSessionCipher(signalProtocolStore, localAddress.Uuid, localAddress.GetNumber(), 1); DecryptionResult result = sealedSessionCipher.Decrypt(certificateValidator !, ciphertext, (long)envelope.Envelope.ServerTimestamp); SignalServiceAddress resultAddress = new SignalServiceAddress(UuidUtil.Parse(result.SenderUuid), result.SenderE164); SignalProtocolAddress protocolAddress = GetPreferredProtocolAddress(signalProtocolStore, resultAddress, result.DeviceId); paddedMessage = result.PaddedMessage; metadata = new SignalServiceMetadata(resultAddress, result.DeviceId, envelope.GetTimestamp(), true); sessionVersion = (uint)sealedSessionCipher.GetSessionVersion(protocolAddress); } else { throw new InvalidMessageException($"Unknown type: {envelope.GetType()}"); } PushTransportDetails transportDetails = new PushTransportDetails(sessionVersion); byte[] data = transportDetails.GetStrippedPaddingMessageBody(paddedMessage); return(new Plaintext(metadata, data)); } catch (DuplicateMessageException e) { throw new ProtocolDuplicateMessageException(e, envelope.GetSourceIdentifier(), envelope.GetSourceDevice()); } catch (LegacyMessageException e) { throw new ProtocolLegacyMessageException(e, envelope.GetSourceIdentifier(), envelope.GetSourceDevice()); } catch (InvalidMessageException e) { throw new ProtocolInvalidMessageException(e, envelope.GetSourceIdentifier(), envelope.GetSourceDevice()); } catch (InvalidKeyIdException e) { throw new ProtocolInvalidKeyIdException(e, envelope.GetSourceIdentifier(), envelope.GetSourceDevice()); } catch (InvalidKeyException e) { throw new ProtocolInvalidKeyException(e, envelope.GetSourceIdentifier(), envelope.GetSourceDevice()); } catch (libsignal.exceptions.UntrustedIdentityException e) { throw new ProtocolUntrustedIdentityException(e, envelope.GetSourceIdentifier(), envelope.GetSourceDevice()); } catch (InvalidVersionException e) { throw new ProtocolInvalidVersionException(e, envelope.GetSourceIdentifier(), envelope.GetSourceDevice()); } catch (NoSessionException e) { throw new ProtocolNoSessionException(e, envelope.GetSourceIdentifier(), envelope.GetSourceDevice()); } }
public OutgoingPushMessage Encrypt(SignalProtocolAddress destination, UnidentifiedAccess?unidentifiedAccess, byte[] unpaddedMessage) { if (unidentifiedAccess != null) { SealedSessionCipher sessionCipher = new SealedSessionCipher(signalProtocolStore, localAddress.Uuid, localAddress.GetNumber(), 1); PushTransportDetails transportDetails = new PushTransportDetails((uint)sessionCipher.GetSessionVersion(destination)); byte[] ciphertext = sessionCipher.Encrypt(destination, unidentifiedAccess.UnidentifiedCertificate, transportDetails.getPaddedMessageBody(unpaddedMessage)); string body = Base64.EncodeBytes(ciphertext); uint remoteRegistrationId = (uint)sessionCipher.GetRemoteRegistrationId(destination); return(new OutgoingPushMessage((uint)Envelope.Types.Type.UnidentifiedSender, destination.DeviceId, remoteRegistrationId, body)); } else { SessionCipher sessionCipher = new SessionCipher(signalProtocolStore, destination); PushTransportDetails transportDetails = new PushTransportDetails(sessionCipher.getSessionVersion()); CiphertextMessage message = sessionCipher.encrypt(transportDetails.getPaddedMessageBody(unpaddedMessage)); uint remoteRegistrationId = sessionCipher.getRemoteRegistrationId(); string body = Base64.EncodeBytes(message.serialize()); var type = (message.getType()) switch { CiphertextMessage.PREKEY_TYPE => (uint)Envelope.Types.Type.PrekeyBundle, CiphertextMessage.WHISPER_TYPE => (uint)Envelope.Types.Type.Ciphertext, _ => throw new Exception("Bad type: " + message.getType()), }; return(new OutgoingPushMessage(type, destination.DeviceId, remoteRegistrationId, body)); } }
private Plaintext Decrypt(SignalServiceEnvelope envelope, byte[] ciphertext) { try { SignalProtocolAddress sourceAddress = new SignalProtocolAddress(envelope.GetSource(), (uint)envelope.GetSourceDevice()); SessionCipher sessionCipher = new SessionCipher(SignalProtocolStore, sourceAddress); SealedSessionCipher sealedSessionCipher = new SealedSessionCipher(SignalProtocolStore, new SignalProtocolAddress(LocalAddress.E164number, 1)); byte[] paddedMessage; Metadata metadata; uint sessionVersion; if (envelope.IsPreKeySignalMessage()) { paddedMessage = sessionCipher.decrypt(new PreKeySignalMessage(ciphertext)); metadata = new Metadata(envelope.GetSource(), envelope.GetSourceDevice(), envelope.GetTimestamp(), false); sessionVersion = sessionCipher.getSessionVersion(); } else if (envelope.IsSignalMessage()) { paddedMessage = sessionCipher.decrypt(new SignalMessage(ciphertext)); metadata = new Metadata(envelope.GetSource(), envelope.GetSourceDevice(), envelope.GetTimestamp(), false); sessionVersion = sessionCipher.getSessionVersion(); } else if (envelope.IsUnidentifiedSender()) { var results = sealedSessionCipher.Decrypt(CertificateValidator, ciphertext, (long)envelope.Envelope.ServerTimestamp); paddedMessage = results.Item2; metadata = new Metadata(results.Item1.Name, (int)results.Item1.DeviceId, (long)envelope.Envelope.Timestamp, true); sessionVersion = (uint)sealedSessionCipher.GetSessionVersion(new SignalProtocolAddress(metadata.Sender, (uint)metadata.SenderDevice)); } else { throw new InvalidMessageException("Unknown type: " + envelope.GetEnvelopeType() + " from " + envelope.GetSource()); } PushTransportDetails transportDetails = new PushTransportDetails(sessionVersion); byte[] data = transportDetails.GetStrippedPaddingMessageBody(paddedMessage); return(new Plaintext(metadata, data)); } catch (DuplicateMessageException e) { throw new ProtocolDuplicateMessageException(e, envelope.GetSource(), envelope.GetSourceDevice()); } catch (LegacyMessageException e) { throw new ProtocolLegacyMessageException(e, envelope.GetSource(), envelope.GetSourceDevice()); } catch (InvalidMessageException e) { throw new ProtocolInvalidMessageException(e, envelope.GetSource(), envelope.GetSourceDevice()); } catch (InvalidKeyIdException e) { throw new ProtocolInvalidKeyIdException(e, envelope.GetSource(), envelope.GetSourceDevice()); } catch (InvalidKeyException e) { throw new ProtocolInvalidKeyException(e, envelope.GetSource(), envelope.GetSourceDevice()); } catch (libsignal.exceptions.UntrustedIdentityException e) { throw new ProtocolUntrustedIdentityException(e, envelope.GetSource(), envelope.GetSourceDevice()); } catch (InvalidVersionException e) { throw new ProtocolInvalidVersionException(e, envelope.GetSource(), envelope.GetSourceDevice()); } catch (NoSessionException e) { throw new ProtocolNoSessionException(e, envelope.GetSource(), envelope.GetSourceDevice()); } }