/** * Encrypt a message. * * @param paddedMessage The plaintext message bytes, optionally padded to a constant multiple. * @return A ciphertext message encrypted to the recipient+device tuple. */ public CiphertextMessage Encrypt(byte[] paddedMessage) { lock (SessionLock) { SessionRecord sessionRecord = _sessionStore.LoadSession(_remoteAddress); SessionState sessionState = sessionRecord.GetSessionState(); ChainKey chainKey = sessionState.GetSenderChainKey(); MessageKeys messageKeys = chainKey.GetMessageKeys(); IEcPublicKey senderEphemeral = sessionState.GetSenderRatchetKey(); uint previousCounter = sessionState.GetPreviousCounter(); uint sessionVersion = sessionState.GetSessionVersion(); byte[] ciphertextBody = GetCiphertext(sessionVersion, messageKeys, paddedMessage); CiphertextMessage ciphertextMessage = new SignalMessage(sessionVersion, messageKeys.GetMacKey(), senderEphemeral, chainKey.GetIndex(), previousCounter, ciphertextBody, sessionState.GetLocalIdentityKey(), sessionState.GetRemoteIdentityKey()); if (sessionState.HasUnacknowledgedPreKeyMessage()) { SessionState.UnacknowledgedPreKeyMessageItems items = sessionState.GetUnacknowledgedPreKeyMessageItems(); uint localRegistrationId = sessionState.GetLocalRegistrationId(); ciphertextMessage = new PreKeySignalMessage(sessionVersion, localRegistrationId, items.GetPreKeyId(), items.GetSignedPreKeyId(), items.GetBaseKey(), sessionState.GetLocalIdentityKey(), (SignalMessage)ciphertextMessage); } sessionState.SetSenderChainKey(chainKey.GetNextChainKey()); _sessionStore.StoreSession(_remoteAddress, sessionRecord); return(ciphertextMessage); } }
private ChainKey GetOrCreateChainKey(SessionState sessionState, IEcPublicKey theirEphemeral) { try { if (sessionState.HasReceiverChain(theirEphemeral)) { return(sessionState.GetReceiverChainKey(theirEphemeral)); } else { RootKey rootKey = sessionState.GetRootKey(); EcKeyPair ourEphemeral = sessionState.GetSenderRatchetKeyPair(); Pair <RootKey, ChainKey> receiverChain = rootKey.CreateChain(theirEphemeral, ourEphemeral); EcKeyPair ourNewEphemeral = Curve.GenerateKeyPair(); Pair <RootKey, ChainKey> senderChain = receiverChain.First().CreateChain(theirEphemeral, ourNewEphemeral); sessionState.SetRootKey(senderChain.First()); sessionState.AddReceiverChain(theirEphemeral, receiverChain.Second()); sessionState.SetPreviousCounter(Math.Max(sessionState.GetSenderChainKey().GetIndex() - 1, 0)); sessionState.SetSenderChain(ourNewEphemeral, senderChain.Second()); return(receiverChain.Second()); } } catch (InvalidKeyException e) { throw new InvalidMessageException(e); } }
private MessageKeys GetOrCreateMessageKeys(SessionState sessionState, IEcPublicKey theirEphemeral, ChainKey chainKey, uint counter) { if (chainKey.GetIndex() > counter) { if (sessionState.HasMessageKeys(theirEphemeral, counter)) { return(sessionState.RemoveMessageKeys(theirEphemeral, counter)); } else { throw new DuplicateMessageException($"Received message with old counter: {chainKey.GetIndex()} , {counter}"); } } //Avoiding a uint overflow uint chainKeyIndex = chainKey.GetIndex(); if ((counter > chainKeyIndex) && (counter - chainKeyIndex > 2000)) { throw new InvalidMessageException("Over 2000 messages into the future!"); } while (chainKey.GetIndex() < counter) { MessageKeys messageKeys = chainKey.GetMessageKeys(); sessionState.SetMessageKeys(theirEphemeral, messageKeys); chainKey = chainKey.GetNextChainKey(); } sessionState.SetReceiverChainKey(theirEphemeral, chainKey.GetNextChainKey()); return(chainKey.GetMessageKeys()); }
private Pair <StorageProtos.SessionStructure.Types.Chain, uint> GetReceiverChain(IEcPublicKey senderEphemeral) { IList <StorageProtos.SessionStructure.Types.Chain> receiverChains = _sessionStructure.ReceiverChainsList; uint index = 0; foreach (StorageProtos.SessionStructure.Types.Chain receiverChain in receiverChains) { try { IEcPublicKey chainSenderRatchetKey = Curve.DecodePoint(receiverChain.SenderRatchetKey.ToByteArray(), 0); if (chainSenderRatchetKey.Equals(senderEphemeral)) { return(new Pair <StorageProtos.SessionStructure.Types.Chain, uint>(receiverChain, index)); } } catch (InvalidKeyException e) { Debug.WriteLine(e.ToString(), "SessionRecordV2"); } index++; } return(null); }
private byte[] Decrypt(SessionState sessionState, SignalMessage ciphertextMessage) { if (!sessionState.HasSenderChain()) { throw new InvalidMessageException("Uninitialized session!"); } if (ciphertextMessage.GetMessageVersion() != sessionState.GetSessionVersion()) { throw new InvalidMessageException($"Message version {ciphertextMessage.GetMessageVersion()}, but session version {sessionState.GetSessionVersion()}"); } uint messageVersion = ciphertextMessage.GetMessageVersion(); IEcPublicKey theirEphemeral = ciphertextMessage.GetSenderRatchetKey(); uint counter = ciphertextMessage.GetCounter(); ChainKey chainKey = GetOrCreateChainKey(sessionState, theirEphemeral); MessageKeys messageKeys = GetOrCreateMessageKeys(sessionState, theirEphemeral, chainKey, counter); ciphertextMessage.VerifyMac(messageVersion, sessionState.GetRemoteIdentityKey(), sessionState.GetLocalIdentityKey(), messageKeys.GetMacKey()); byte[] plaintext = GetPlaintext(messageVersion, messageKeys, ciphertextMessage.GetBody()); sessionState.ClearUnacknowledgedPreKeyMessage(); return(plaintext); }
public PreKeySignalMessage(uint messageVersion, uint registrationId, May <uint> preKeyId, uint signedPreKeyId, IEcPublicKey baseKey, IdentityKey identityKey, SignalMessage message) { _version = messageVersion; _registrationId = registrationId; _preKeyId = preKeyId; _signedPreKeyId = signedPreKeyId; _baseKey = baseKey; _identityKey = identityKey; _message = message; PreKeySignalMessage preKeySignalMessage = new PreKeySignalMessage { SignedPreKeyId = signedPreKeyId, BaseKey = ByteString.CopyFrom(baseKey.Serialize()), IdentityKey = ByteString.CopyFrom(identityKey.Serialize()), Message = ByteString.CopyFrom(message.Serialize()), RegistrationId = registrationId }; if (preKeyId.HasValue) // .isPresent() { preKeySignalMessage.PreKeyId = preKeyId.ForceGetValue(); // get() } byte[] versionBytes = { ByteUtil.IntsToByteHighAndLow((int)_version, (int)CurrentVersion) }; byte[] messageBytes = preKeySignalMessage.ToByteArray(); _serialized = ByteUtil.Combine(versionBytes, messageBytes); }
private SenderKeyState(uint id, uint iteration, byte[] chainKey, IEcPublicKey signatureKeyPublic, May <IEcPrivateKey> signatureKeyPrivate) { StorageProtos.SenderKeyStateStructure.Types.SenderChainKey senderChainKeyStructure = StorageProtos.SenderKeyStateStructure.Types.SenderChainKey.CreateBuilder() .SetIteration(iteration) .SetSeed(ByteString.CopyFrom(chainKey)) .Build(); StorageProtos.SenderKeyStateStructure.Types.SenderSigningKey.Builder signingKeyStructure = StorageProtos.SenderKeyStateStructure.Types.SenderSigningKey.CreateBuilder() .SetPublic(ByteString.CopyFrom(signatureKeyPublic.Serialize())); if (signatureKeyPrivate.HasValue) { signingKeyStructure.SetPrivate(ByteString.CopyFrom(signatureKeyPrivate.ForceGetValue().Serialize())); } _senderKeyStateStructure = StorageProtos.SenderKeyStateStructure.CreateBuilder() .SetSenderKeyId(id) .SetSenderChainKey(senderChainKeyStructure) .SetSenderSigningKey(signingKeyStructure) .Build(); }
public SignalMessage(uint messageVersion, byte[] macKey, IEcPublicKey senderRatchetKey, uint counter, uint previousCounter, byte[] ciphertext, IdentityKey senderIdentityKey, IdentityKey receiverIdentityKey) { byte[] version = { ByteUtil.IntsToByteHighAndLow((int)messageVersion, (int)CurrentVersion) }; byte[] message = new SignalMessage { ratchedKeyOneofCase_ = RatchedKeyOneofOneofCase.RatchetKey, RatchetKey = ByteString.CopyFrom(senderRatchetKey.Serialize()), //TODO serialize ok? counterOneofCase_ = CounterOneofOneofCase.Counter, Counter = counter, previousCounterOneofCase_ = PreviousCounterOneofOneofCase.PreviousCounter, PreviousCounter = previousCounter, ciphertextOneofCase_ = CiphertextOneofOneofCase.Ciphertext, Ciphertext = ByteString.CopyFrom(ciphertext), }.ToByteArray(); byte[] mac = GetMac(senderIdentityKey, receiverIdentityKey, macKey, ByteUtil.Combine(version, message)); _serialized = ByteUtil.Combine(version, message, mac); _senderRatchetKey = senderRatchetKey; _counter = counter; _previousCounter = previousCounter; _ciphertext = ciphertext; _messageVersion = messageVersion; }
private SenderKeyState(uint id, uint iteration, byte[] chainKey, IEcPublicKey signatureKeyPublic, May <IEcPrivateKey> signatureKeyPrivate) { SenderKeyStateStructure.Types.SenderChainKey senderChainKeyStructure = new SenderKeyStateStructure.Types.SenderChainKey { Iteration = iteration, Seed = ByteString.CopyFrom(chainKey) }; SenderKeyStateStructure.Types.SenderSigningKey signingKeyStructure = new SenderKeyStateStructure.Types.SenderSigningKey { Public = ByteString.CopyFrom(signatureKeyPublic.Serialize()) }; if (signatureKeyPrivate.HasValue) { signingKeyStructure.Private = ByteString.CopyFrom(signatureKeyPrivate.ForceGetValue().Serialize()); } _senderKeyStateStructure = new SenderKeyStateStructure { SenderKeyId = id, SenderChainKey = senderChainKeyStructure, SenderSigningKey = signingKeyStructure }; }
public PreKeySignalMessage(uint messageVersion, uint registrationId, May <uint> preKeyId, uint signedPreKeyId, IEcPublicKey baseKey, IdentityKey identityKey, SignalMessage message) { _version = messageVersion; _registrationId = registrationId; _preKeyId = preKeyId; _signedPreKeyId = signedPreKeyId; _baseKey = baseKey; _identityKey = identityKey; _message = message; WhisperProtos.PreKeySignalMessage.Builder builder = WhisperProtos.PreKeySignalMessage.CreateBuilder() .SetSignedPreKeyId(signedPreKeyId) .SetBaseKey(ByteString.CopyFrom(baseKey.Serialize())) .SetIdentityKey(ByteString.CopyFrom(identityKey.Serialize())) .SetMessage(ByteString.CopyFrom(message.Serialize())) .SetRegistrationId(registrationId); if (preKeyId.HasValue) // .isPresent() { builder.SetPreKeyId(preKeyId.ForceGetValue()); // get() } byte[] versionBytes = { ByteUtil.IntsToByteHighAndLow((int)_version, (int)CurrentVersion) }; byte[] messageBytes = builder.Build().ToByteArray(); _serialized = ByteUtil.Combine(versionBytes, messageBytes); }
public UnacknowledgedPreKeyMessageItems(May <uint> preKeyId, uint signedPreKeyId, IEcPublicKey baseKey) { _preKeyId = preKeyId; _signedPreKeyId = signedPreKeyId; _baseKey = baseKey; }
public void AddSenderKeyState(uint id, uint iteration, byte[] chainKey, IEcPublicKey signatureKey) { _senderKeyStates.AddFirst(new SenderKeyState(id, iteration, chainKey, signatureKey)); if (_senderKeyStates.Count > MaxStates) { _senderKeyStates.RemoveLast(); } }
public EcKeyPair GetSenderRatchetKeyPair() { IEcPublicKey publicKey = GetSenderRatchetKey(); IEcPrivateKey privateKey = Curve.DecodePrivatePoint(_sessionStructure.SenderChain .SenderRatchetKeyPrivate .ToByteArray()); return(new EcKeyPair(publicKey, privateKey)); }
/// <summary> /// Build a new session from a {@link org.whispersystems.libsignal.state.PreKeyBundle} retrieved from /// a server. /// </summary> /// @param preKey A PreKey for the destination recipient, retrieved from a server. /// @throws InvalidKeyException when the {@link org.whispersystems.libsignal.state.PreKeyBundle} is /// badly formatted. /// @throws org.whispersystems.libsignal.UntrustedIdentityException when the sender's /// {@link IdentityKey} is not /// trusted. /// public void Process(PreKeyBundle preKey) { lock (SessionCipher.SessionLock) { if (!_identityKeyStore.IsTrustedIdentity(_remoteAddress, preKey.GetIdentityKey(), Direction.Sending)) { throw new UntrustedIdentityException(_remoteAddress.Name, preKey.GetIdentityKey()); } if (preKey.GetSignedPreKey() != null && !Curve.VerifySignature(preKey.GetIdentityKey().GetPublicKey(), preKey.GetSignedPreKey().Serialize(), preKey.GetSignedPreKeySignature())) { throw new InvalidKeyException("Invalid signature on device key!"); } if (preKey.GetSignedPreKey() == null) { throw new InvalidKeyException("No signed prekey!"); } SessionRecord sessionRecord = _sessionStore.LoadSession(_remoteAddress); EcKeyPair ourBaseKey = Curve.GenerateKeyPair(); IEcPublicKey theirSignedPreKey = preKey.GetSignedPreKey(); IEcPublicKey test = preKey.GetPreKey(); May <IEcPublicKey> theirOneTimePreKey = (test == null) ? May <IEcPublicKey> .NoValue : new May <IEcPublicKey>(test); May <uint> theirOneTimePreKeyId = theirOneTimePreKey.HasValue ? new May <uint>(preKey.GetPreKeyId()) : May <uint> .NoValue; AliceSignalProtocolParameters.Builder parameters = AliceSignalProtocolParameters.NewBuilder(); parameters.SetOurBaseKey(ourBaseKey) .SetOurIdentityKey(_identityKeyStore.GetIdentityKeyPair()) .SetTheirIdentityKey(preKey.GetIdentityKey()) .SetTheirSignedPreKey(theirSignedPreKey) .SetTheirRatchetKey(theirSignedPreKey) .SetTheirOneTimePreKey(theirOneTimePreKey); if (!sessionRecord.IsFresh()) { sessionRecord.ArchiveCurrentState(); } RatchetingSession.InitializeSession(sessionRecord.GetSessionState(), parameters.Create()); sessionRecord.GetSessionState().SetUnacknowledgedPreKeyMessage(theirOneTimePreKeyId, preKey.GetSignedPreKeyId(), ourBaseKey.GetPublicKey()); sessionRecord.GetSessionState().SetLocalRegistrationId(_identityKeyStore.GetLocalRegistrationId()); sessionRecord.GetSessionState().SetRemoteRegistrationId(preKey.GetRegistrationId()); sessionRecord.GetSessionState().SetAliceBaseKey(ourBaseKey.GetPublicKey().Serialize()); _identityKeyStore.SaveIdentity(_remoteAddress, preKey.GetIdentityKey()); _sessionStore.StoreSession(_remoteAddress, sessionRecord); } }
public EcKeyPair GetPendingKeyExchangeRatchetKey() { IEcPublicKey publicKey = Curve.DecodePoint(_sessionStructure.PendingKeyExchange .LocalRatchetKey.ToByteArray(), 0); IEcPrivateKey privateKey = Curve.DecodePrivatePoint(_sessionStructure.PendingKeyExchange .LocalRatchetKeyPrivate .ToByteArray()); return(new EcKeyPair(publicKey, privateKey)); }
public Pair <RootKey, ChainKey> CreateChain(IEcPublicKey theirRatchetKey, EcKeyPair ourRatchetKey) { byte[] sharedSecret = Curve.CalculateAgreement(theirRatchetKey, ourRatchetKey.GetPrivateKey()); byte[] derivedSecretBytes = _kdf.DeriveSecrets(sharedSecret, _key, Encoding.UTF8.GetBytes("WhisperRatchet"), DerivedRootSecrets.Size); DerivedRootSecrets derivedSecrets = new DerivedRootSecrets(derivedSecretBytes); RootKey newRootKey = new RootKey(_kdf, derivedSecrets.GetRootKey()); ChainKey newChainKey = new ChainKey(_kdf, derivedSecrets.GetChainKey(), 0); return(new Pair <RootKey, ChainKey>(newRootKey, newChainKey)); }
public static bool VerifySignature(IEcPublicKey signingKey, byte[] message, byte[] signature) { if (signingKey.GetKeyType() == DjbType) { return(Curve25519.GetInstance(Curve25519ProviderType.Best) .VerifySignature(((DjbEcPublicKey)signingKey).GetPublicKey(), message, signature)); } else { throw new InvalidKeyException("Unknown type: " + signingKey.GetKeyType()); } }
public PreKeyBundle(uint registrationId, uint deviceId, uint preKeyId, IEcPublicKey preKeyPublic, uint signedPreKeyId, IEcPublicKey signedPreKeyPublic, byte[] signedPreKeySignature, IdentityKey identityKey) { _registrationId = registrationId; _deviceId = deviceId; _preKeyId = preKeyId; _preKeyPublic = preKeyPublic; _signedPreKeyId = signedPreKeyId; _signedPreKeyPublic = signedPreKeyPublic; _signedPreKeySignature = signedPreKeySignature; _identityKey = identityKey; }
public EcKeyPair GetKeyPair() { try { IEcPublicKey publicKey = Curve.DecodePoint(_structure.PublicKey.ToByteArray(), 0); IEcPrivateKey privateKey = Curve.DecodePrivatePoint(_structure.PrivateKey.ToByteArray()); return(new EcKeyPair(publicKey, privateKey)); } catch (InvalidKeyException e) { throw new Exception(e.Message); } }
public SenderKeyDistributionMessage(uint id, uint iteration, byte[] chainKey, IEcPublicKey signatureKey) { byte[] version = { ByteUtil.IntsToByteHighAndLow((int)CurrentVersion, (int)CurrentVersion) }; byte[] protobuf = WhisperProtos.SenderKeyDistributionMessage.CreateBuilder() .SetId(id) .SetIteration(iteration) .SetChainKey(ByteString.CopyFrom(chainKey)) .SetSigningKey(ByteString.CopyFrom(signatureKey.Serialize())) .Build().ToByteArray(); _id = id; _iteration = iteration; _chainKey = chainKey; _signatureKey = signatureKey; _serialized = ByteUtil.Combine(version, protobuf); }
public void SetReceiverChainKey(IEcPublicKey senderEphemeral, ChainKey chainKey) { Pair <SessionStructure.Types.Chain, uint> chainAndIndex = GetReceiverChain(senderEphemeral); SessionStructure.Types.Chain chain = chainAndIndex.First(); SessionStructure.Types.Chain.Types.ChainKey chainKeyStructure = new SessionStructure.Types.Chain.Types.ChainKey { Key = ByteString.CopyFrom(chainKey.GetKey()), Index = chainKey.GetIndex() }; chain.ChainKey = chainKeyStructure; _sessionStructure.ReceiverChains[(int)chainAndIndex.Second()] = chain; }
public void VerifySignature(IEcPublicKey signatureKey) { try { byte[][] parts = ByteUtil.Split(_serialized, _serialized.Length - SignatureLength, SignatureLength); if (!Curve.VerifySignature(signatureKey, parts[0], parts[1])) { throw new InvalidMessageException("Invalid signature!"); } } catch (InvalidKeyException e) { throw new InvalidMessageException(e); } }
BobSignalProtocolParameters(IdentityKeyPair ourIdentityKey, EcKeyPair ourSignedPreKey, EcKeyPair ourRatchetKey, May <EcKeyPair> ourOneTimePreKey, IdentityKey theirIdentityKey, IEcPublicKey theirBaseKey) { _ourIdentityKey = ourIdentityKey; _ourSignedPreKey = ourSignedPreKey; _ourRatchetKey = ourRatchetKey; _ourOneTimePreKey = ourOneTimePreKey; _theirIdentityKey = theirIdentityKey; _theirBaseKey = theirBaseKey; if (ourIdentityKey == null || ourSignedPreKey == null || ourRatchetKey == null || ourOneTimePreKey == null || theirIdentityKey == null || theirBaseKey == null) { throw new Exception("Null value!"); } }
public SenderKeyDistributionMessage(uint id, uint iteration, byte[] chainKey, IEcPublicKey signatureKey) { byte[] version = { ByteUtil.IntsToByteHighAndLow((int)CurrentVersion, (int)CurrentVersion) }; byte[] protobuf = new SenderKeyDistributionMessage { Id = id, Iteration = iteration, ChainKey = ByteString.CopyFrom(chainKey), SigningKey = ByteString.CopyFrom(signatureKey.Serialize()) }.ToByteArray(); _id = id; _iteration = iteration; _chainKey = chainKey; _signatureKey = signatureKey; _serialized = ByteUtil.Combine(version, protobuf); }
public void SetReceiverChainKey(IEcPublicKey senderEphemeral, ChainKey chainKey) { Pair <StorageProtos.SessionStructure.Types.Chain, uint> chainAndIndex = GetReceiverChain(senderEphemeral); StorageProtos.SessionStructure.Types.Chain chain = chainAndIndex.First(); StorageProtos.SessionStructure.Types.Chain.Types.ChainKey chainKeyStructure = StorageProtos.SessionStructure.Types.Chain.Types.ChainKey.CreateBuilder() .SetKey(ByteString.CopyFrom(chainKey.GetKey())) .SetIndex(chainKey.GetIndex()) .Build(); StorageProtos.SessionStructure.Types.Chain updatedChain = chain.ToBuilder().SetChainKey(chainKeyStructure).Build(); _sessionStructure = _sessionStructure.ToBuilder() .SetReceiverChains((int)chainAndIndex.Second(), updatedChain) // TODO: conv .Build(); }
public ChainKey GetReceiverChainKey(IEcPublicKey senderEphemeral) { Pair <StorageProtos.SessionStructure.Types.Chain, uint> receiverChainAndIndex = GetReceiverChain(senderEphemeral); StorageProtos.SessionStructure.Types.Chain receiverChain = receiverChainAndIndex.First(); if (receiverChain == null) { return(null); } else { return(new ChainKey(Hkdf.CreateFor(GetSessionVersion()), receiverChain.ChainKey.Key.ToByteArray(), receiverChain.ChainKey.Index)); } }
SymmetricSignalProtocolParameters(EcKeyPair ourBaseKey, EcKeyPair ourRatchetKey, IdentityKeyPair ourIdentityKey, IEcPublicKey theirBaseKey, IEcPublicKey theirRatchetKey, IdentityKey theirIdentityKey) { _ourBaseKey = ourBaseKey; _ourRatchetKey = ourRatchetKey; _ourIdentityKey = ourIdentityKey; _theirBaseKey = theirBaseKey; _theirRatchetKey = theirRatchetKey; _theirIdentityKey = theirIdentityKey; if (ourBaseKey == null || ourRatchetKey == null || ourIdentityKey == null || theirBaseKey == null || theirRatchetKey == null || theirIdentityKey == null) { throw new Exception("Null values!"); } }
public static byte[] CalculateAgreement(IEcPublicKey publicKey, IEcPrivateKey privateKey) { if (publicKey.GetKeyType() != privateKey.GetKeyType()) { throw new InvalidKeyException("Public and private keys must be of the same type!"); } if (publicKey.GetKeyType() == DjbType) { return(Curve25519.GetInstance(Curve25519ProviderType.Best) .CalculateAgreement(((DjbEcPublicKey)publicKey).GetPublicKey(), ((DjbEcPrivateKey)privateKey).GetPrivateKey())); } else { throw new InvalidKeyException("Unknown type: " + publicKey.GetKeyType()); } }
public void AddReceiverChain(IEcPublicKey senderRatchetKey, ChainKey chainKey) { StorageProtos.SessionStructure.Types.Chain.Types.ChainKey chainKeyStructure = StorageProtos.SessionStructure.Types.Chain.Types.ChainKey.CreateBuilder() .SetKey(ByteString.CopyFrom(chainKey.GetKey())) .SetIndex(chainKey.GetIndex()) .Build(); StorageProtos.SessionStructure.Types.Chain chain = StorageProtos.SessionStructure.Types.Chain.CreateBuilder() .SetChainKey(chainKeyStructure) .SetSenderRatchetKey(ByteString.CopyFrom(senderRatchetKey.Serialize())) .Build(); _sessionStructure = _sessionStructure.ToBuilder().AddReceiverChains(chain).Build(); if (_sessionStructure.ReceiverChainsList.Count > 5) { _sessionStructure = _sessionStructure.ToBuilder() /*.ClearReceiverChains()*/.Build(); //RemoveReceiverChains(0) TODO: why does it work without } }
public SignalMessage(byte[] serialized) { try { byte[][] messageParts = ByteUtil.Split(serialized, 1, serialized.Length - 1 - MacLength, MacLength); byte version = messageParts[0][0]; byte[] message = messageParts[1]; byte[] mac = messageParts[2]; if (ByteUtil.HighBitsToInt(version) < CurrentVersion) { throw new LegacyMessageException("Legacy message: " + ByteUtil.HighBitsToInt(version)); } if (ByteUtil.HighBitsToInt(version) > CurrentVersion) { throw new InvalidMessageException("Unknown version: " + ByteUtil.HighBitsToInt(version)); } SignalMessage signalMessage = Parser.ParseFrom(message); if (signalMessage.CiphertextOneofCase == CiphertextOneofOneofCase.None || signalMessage.CounterOneofCase == CounterOneofOneofCase.None || signalMessage.RatchedKeyOneofCase == RatchedKeyOneofOneofCase.None) { throw new InvalidMessageException("Incomplete message."); } _serialized = serialized; _senderRatchetKey = Curve.DecodePoint(signalMessage.RatchetKey.ToByteArray(), 0); _messageVersion = (uint)ByteUtil.HighBitsToInt(version); _counter = signalMessage.Counter; _previousCounter = signalMessage.PreviousCounter; _ciphertext = signalMessage.Ciphertext.ToByteArray(); } catch (/*InvalidProtocolBufferException | InvalidKeyException | Parse*/ Exception e) { throw new InvalidMessageException(e); } }