/// <param name="receivedFromUser">comes from local contact book. is null if it is contact invitation</param> internal static InviteSessionDescription Decrypt_Verify(ICryptoLibrary cryptoLibrary, byte[] encryptedSdData, InviteRequestPacket req, InviteAck1Packet ack1, bool ack1SdIsReady, InviteSession session, UserId receivedFromUserNullable, DateTime localTimeNowUtc ) { #region key, iv BinaryProcedures.CreateBinaryWriter(out var ms2, out var w2); req.GetSharedSignedFields(w2); ack1.GetSharedSignedFields(w2, ack1SdIsReady); var iv = cryptoLibrary.GetHashSHA256(ms2.ToArray()).Take(16).ToArray(); ms2.Write(session.SharedInviteAckDhSecret, 0, session.SharedInviteAckDhSecret.Length); var aesKey = cryptoLibrary.GetHashSHA256(ms2.ToArray()); // here SHA256 is used as KDF, together with common fields from packets, including both ECDH public keys and timestamp #endregion // decrypt var plainTextSdData = new byte[encryptedSdData.Length]; cryptoLibrary.ProcessAesCbcBlocks(false, aesKey, iv, encryptedSdData, plainTextSdData); var r = new InviteSessionDescription(); var reader = BinaryProcedures.CreateBinaryReader(plainTextSdData, 0); r.Flags = reader.ReadByte(); if ((r.Flags & FlagsMask_MustBeZero) != 0) { throw new NotImplementedException(); } r.UserCertificate = UserCertificate.Decode_AssertIsValidNow(reader, cryptoLibrary, receivedFromUserNullable, localTimeNowUtc); r.DirectChannelEndPoint = BinaryProcedures.DecodeIPEndPoint(reader); r.NatBehaviour = NatBehaviourModel.Decode(reader); r.DirectChannelToken32 = DirectChannelToken32.Decode(reader); r.SessionType = (SessionType)reader.ReadByte(); r.UserCertificateSignature = UserCertificateSignature.DecodeAndVerify(reader, cryptoLibrary, w => { req.GetSharedSignedFields(w); ack1.GetSharedSignedFields(w, ack1SdIsReady); r.WriteSignedFields(w); }, r.UserCertificate); return(r); }
public static InviteRequestPacket Decode_VerifyNeighborHMAC(byte[] udpData, ConnectionToNeighbor receivedFromNeighbor) { var r = new InviteRequestPacket(); r.DecodedUdpPayloadData = udpData; var reader = BinaryProcedures.CreateBinaryReader(udpData, 1); var flags = reader.ReadByte(); if ((flags & FlagsMask_MustBeZero) != 0) { throw new NotImplementedException(); } r.NeighborToken32 = NeighborToken32.Decode(reader); if (receivedFromNeighbor.LocalNeighborToken32.Equals(r.NeighborToken32) == false) { throw new UnmatchedFieldsException(); } r.ReqTimestamp32S = reader.ReadUInt32(); r.RequesterRegistrationId = RegistrationId.Decode(reader); r.ResponderRegistrationId = RegistrationId.Decode(reader); r.RequesterEcdhePublicKey = EcdhPublicKey.Decode(reader); r.RequesterNatBehaviour = NatBehaviourModel.Decode(reader); if ((flags & FlagsMask_ContactInvitationTokenExists) != 0) { r.ContactInvitationTokenNullable = reader.ReadBytes(ContactInvitationTokenSize); } r.RequesterRegistrationSignature = RegistrationSignature.Decode(reader); r.NumberOfHopsRemaining = reader.ReadByte(); r.ReqP2pSeq16 = RequestP2pSequenceNumber16.Decode(reader); r.NeighborHMAC = HMAC.Decode(reader); if (r.NeighborHMAC.Equals(receivedFromNeighbor.GetNeighborHMAC(r.GetSignedFieldsForNeighborHMAC)) == false) { throw new BadSignatureException("invalid INVITE REQ NeighborHMAC 5902"); } return(r); }