/// <summary> /// Decrypts the key and HMAC concatenation (<see cref="OmemoMessage.cipherText"/>) with the given <paramref name="session"/>. /// </summary> /// <param name="authMsg">The <see cref="OmemoAuthenticatedMessage"/> containing the key and HMAC.</param> /// <param name="session">The <see cref="OmemoSessionModel"/> that should be used for decryption.</param> /// <returns>key || HMAC</returns> private byte[] DecryptKeyHmacForDevice(OmemoAuthenticatedMessage authMsg, OmemoSessionModel session) { OmemoMessage msg = new OmemoMessage(authMsg.OMEMO_MESSAGE); byte[] plainText = TrySkippedMessageKeys(msg, authMsg.HMAC, session); if (!(plainText is null)) { return(plainText); } if (session.dhR is null || !msg.DH.Equals(session.dhR.pubKey)) { SkipMessageKeys(session, msg.PN); session.InitDhRatchet(msg); } SkipMessageKeys(session, msg.N); // If no receive chain has been initialized yet, initialize it now. // This happens in case we received a key exchange message with a new session and now would like to send our first message. if (session.ckR is null) { session.InitReceiverKeyChain(); } byte[] mk = LibSignalUtils.KDF_CK(session.ckR, 0x01); session.ckR = LibSignalUtils.KDF_CK(session.ckR, 0x02); ++session.nR; return(DecryptKeyHmacForDevice(mk, msg, authMsg.HMAC, session.assData)); }
/// <summary> /// Decrypts the key and HMAC concatenation (<see cref="OmemoMessage.cipherText"/>) with the given <paramref name="session"/>. /// </summary> /// <param name="authMsg">The <see cref="OmemoAuthenticatedMessage"/> containing the key and HMAC.</param> /// <param name="session">The <see cref="OmemoSessionModel"/> that should be used for decryption.</param> /// <returns>key || HMAC</returns> public byte[] DecryptKeyHmacForDevice(OmemoAuthenticatedMessage authMsg, OmemoSessionModel session) { OmemoMessage msg = new OmemoMessage(authMsg.OMEMO_MESSAGE); byte[] plainText = TrySkippedMessageKeys(msg, authMsg.HMAC, session); if (!(plainText is null)) { return(plainText); } if (session.dhR is null || !msg.DH.Equals(session.dhR)) { SkipMessageKeys(session, msg.PN); session.InitDhRatchet(msg); } SkipMessageKeys(session, msg.N); byte[] mk = LibSignalUtils.KDF_CK(session.ckR, 0x01); Logger.Trace("[" + nameof(DecryptKeyHmacForDevice) + "] " + nameof(session.ckR) + ": " + CryptoUtils.ToHexString(session.ckR)); session.ckR = LibSignalUtils.KDF_CK(session.ckR, 0x02); ++session.nR; byte[] result = DecryptKeyHmacForDevice(mk, msg, authMsg.HMAC, session.assData); // Update the session state: if (session.state == SessionState.SEND) { session.state = SessionState.READY; } Logger.Trace("[" + nameof(DecryptKeyHmacForDevice) + "] " + nameof(session.state) + ": " + session.state); return(result); }