public byte[] Decrypt(byte[] senderKeyMessageBytes, IDecryptionCallback callback) { lock(LOCK) { try { var record = _senderKeyStore.LoadSenderKey(_senderKeyId); if(record.IsEmpty) { throw new Exception("No sender key for: " + _senderKeyId); } var senderKeyMessage = new SenderKeyMessage(senderKeyMessageBytes); var senderKeyState = record.GetSenderKeyState(senderKeyMessage.KeyId); senderKeyMessage.VerifySignature(senderKeyState.SigningKeyPublic); var senderKey = GetSenderKey(senderKeyState, senderKeyMessage.Iteration); byte[] plaintext = GetPlainText(senderKey.Iv, senderKey.CipherKey, senderKeyMessage.CipherText); callback.HandlePlaintext(plaintext); _senderKeyStore.StoreSenderKey(_senderKeyId, record); return plaintext; } catch(Exception e) { throw new InvalidMessageException(e); } } }
/** * Decrypt a SenderKey group message. * * @param senderKeyMessageBytes The received ciphertext. * @param callback A callback that is triggered after decryption is complete, * but before the updated session state has been committed to the session * DB. This allows some implementations to store the committed plaintext * to a DB first, in case they are concerned with a crash happening between * the time the session state is updated but before they're able to store * the plaintext to disk. * @return Plaintext * @throws LegacyMessageException * @throws InvalidMessageException * @throws DuplicateMessageException */ public byte[] Decrypt(byte[] senderKeyMessageBytes, IDecryptionCallback callback) { lock (Lock) { try { SenderKeyRecord record = _senderKeyStore.LoadSenderKey(_senderKeyId); if (record.IsEmpty()) { throw new NoSessionException("No sender key for: " + _senderKeyId); } SenderKeyMessage senderKeyMessage = new SenderKeyMessage(senderKeyMessageBytes); SenderKeyState senderKeyState = record.GetSenderKeyState(senderKeyMessage.GetKeyId()); senderKeyMessage.VerifySignature(senderKeyState.GetSigningKeyPublic()); SenderMessageKey senderKey = GetSenderKey(senderKeyState, senderKeyMessage.GetIteration()); byte[] plaintext = GetPlainText(senderKey.GetIv(), senderKey.GetCipherKey(), senderKeyMessage.GetCipherText()); callback.HandlePlaintext(plaintext); _senderKeyStore.StoreSenderKey(_senderKeyId, record); return(plaintext); } catch (Exception e) when(e is InvalidKeyException || e is InvalidKeyIdException) { throw new InvalidMessageException(e); } } }
/** * Decrypt a message. * * @param ciphertext The {@link SignalMessage} to decrypt. * @param callback A callback that is triggered after decryption is complete, * but before the updated session state has been committed to the session * DB. This allows some implementations to store the committed plaintext * to a DB first, in case they are concerned with a crash happening between * the time the session state is updated but before they're able to store * the plaintext to disk. * * @return The plaintext. * @throws InvalidMessageException if the input is not valid ciphertext. * @throws DuplicateMessageException if the input is a message that has already been received. * @throws LegacyMessageException if the input is a message formatted by a protocol version that * is no longer supported. * @throws NoSessionException if there is no established session for this contact. */ public byte[] Decrypt(SignalMessage ciphertext, IDecryptionCallback callback) { lock (SessionLock) { if (!_sessionStore.ContainsSession(_remoteAddress)) { throw new NoSessionException($"No session for: {_remoteAddress}"); } SessionRecord sessionRecord = _sessionStore.LoadSession(_remoteAddress); byte[] plaintext = Decrypt(sessionRecord, ciphertext); callback.HandlePlaintext(plaintext); _sessionStore.StoreSession(_remoteAddress, sessionRecord); return(plaintext); } }
public byte[] Decrypt(PreKeyWhisperMessage ciphertext, IDecryptionCallback callback) { lock(SESSION_LOCK) { SessionRecord sessionRecord = _sessionStore.LoadSession(_remoteAddress); Maybe<UInt32> unsignedPreKeyId = _sessionBuilder.Process(sessionRecord, ciphertext); byte[] plaintext = Decrypt(sessionRecord, ciphertext.Message); callback.HandlePlaintext(plaintext); _sessionStore.StoreSession(_remoteAddress, sessionRecord); if(unsignedPreKeyId.HasValue) { _preKeyStore.RemovePreKey(unsignedPreKeyId.Value); } return plaintext; } }
/** * Decrypt a message. * * @param ciphertext The {@link PreKeySignalMessage} to decrypt. * @param callback A callback that is triggered after decryption is complete, * but before the updated session state has been committed to the session * DB. This allows some implementations to store the committed plaintext * to a DB first, in case they are concerned with a crash happening between * the time the session state is updated but before they're able to store * the plaintext to disk. * * @return The plaintext. * @throws InvalidMessageException if the input is not valid ciphertext. * @throws DuplicateMessageException if the input is a message that has already been received. * @throws LegacyMessageException if the input is a message formatted by a protocol version that * is no longer supported. * @throws InvalidKeyIdException when there is no local {@link org.whispersystems.libsignal.state.PreKeyRecord} * that corresponds to the PreKey ID in the message. * @throws InvalidKeyException when the message is formatted incorrectly. * @throws UntrustedIdentityException when the {@link IdentityKey} of the sender is untrusted. */ public byte[] Decrypt(PreKeySignalMessage ciphertext, IDecryptionCallback callback) { lock (SessionLock) { SessionRecord sessionRecord = _sessionStore.LoadSession(_remoteAddress); May <uint> unsignedPreKeyId = _sessionBuilder.Process(sessionRecord, ciphertext); byte[] plaintext = Decrypt(sessionRecord, ciphertext.GetSignalMessage()); callback.HandlePlaintext(plaintext); _sessionStore.StoreSession(_remoteAddress, sessionRecord); if (unsignedPreKeyId.HasValue) { _preKeyStore.RemovePreKey(unsignedPreKeyId.ForceGetValue()); } return(plaintext); } }
/** * Decrypt a message. * * @param ciphertext The {@link SignalMessage} to decrypt. * @param callback A callback that is triggered after decryption is complete, * but before the updated session state has been committed to the session * DB. This allows some implementations to store the committed plaintext * to a DB first, in case they are concerned with a crash happening between * the time the session state is updated but before they're able to store * the plaintext to disk. * * @return The plaintext. * @throws InvalidMessageException if the input is not valid ciphertext. * @throws DuplicateMessageException if the input is a message that has already been received. * @throws LegacyMessageException if the input is a message formatted by a protocol version that * is no longer supported. * @throws NoSessionException if there is no established session for this contact. */ public byte[] Decrypt(SignalMessage ciphertext, IDecryptionCallback callback) { lock (SessionLock) { if (!_sessionStore.ContainsSession(_remoteAddress)) { throw new NoSessionException($"No session for: {_remoteAddress}"); } SessionRecord sessionRecord = _sessionStore.LoadSession(_remoteAddress); byte[] plaintext = Decrypt(sessionRecord, ciphertext); if (!_identityKeyStore.IsTrustedIdentity(_remoteAddress, sessionRecord.GetSessionState().GetRemoteIdentityKey(), Direction.Receiving)) { throw new UntrustedIdentityException(_remoteAddress.Name, sessionRecord.GetSessionState().GetRemoteIdentityKey()); } callback.HandlePlaintext(plaintext); _sessionStore.StoreSession(_remoteAddress, sessionRecord); return(plaintext); } }
public byte[] Decrypt(WhisperMessage ciphertext, IDecryptionCallback callback) { lock(SESSION_LOCK) { if(!_sessionStore.ContainsSession(_remoteAddress)) { throw new NoSessionException("No session for: " + _remoteAddress); } SessionRecord sessionRecord = _sessionStore.LoadSession(_remoteAddress); byte[] plaintext = Decrypt(sessionRecord, ciphertext); callback.HandlePlaintext(plaintext); _sessionStore.StoreSession(_remoteAddress, sessionRecord); return plaintext; } }