Exemple #1
0
        internal void EncryptAndSign(byte[] inputNullable, int id, EncryptedFieldIds fieldId, out byte[] encrypted, out byte[] hmac)
        {
            if (inputNullable == null)
            {
                encrypted = null;
                hmac      = null;
                return;
            }
            if (inputNullable.Length > 65535)
            {
                throw new ArgumentException(nameof(inputNullable));
            }

            GetIVandKeys(id, fieldId, out var iv, out var aesKey, out var hmacKey);

            // encode length of input and add padding, to make it good for AES
            BinaryProcedures.CreateBinaryWriter(out var ms, out var w);
            w.Write((ushort)inputNullable.Length);
            w.Write(inputNullable);
            var bytesInLastBlock = (int)ms.Position % CryptoLibraries.AesBlockSize;

            if (bytesInLastBlock != 0)
            {
                var bytesRemainingTillFullAesBlock = CryptoLibraries.AesBlockSize - bytesInLastBlock;
                w.Write(_cryptoLibrary.GetRandomBytes(bytesRemainingTillFullAesBlock));
            }

            var inputWithPadding = ms.ToArray();

            encrypted = new byte[inputWithPadding.Length];
            _cryptoLibrary.ProcessAesCbcBlocks(true, aesKey, iv, inputWithPadding, encrypted);

            hmac = _cryptoLibrary.GetSha256HMAC(hmacKey, encrypted);
        }
        /// <param name="ack1SdIsReady">
        /// =true for SD in ACK2
        /// =false for SD in ACK1 (since the SessionDescription is not initialized yet)
        /// </param>
        internal byte[] Encrypt(ICryptoLibrary cryptoLibrary, InviteRequestPacket req, InviteAck1Packet ack1, InviteSession session,
                                bool ack1SdIsReady
                                )
        {
            BinaryProcedures.CreateBinaryWriter(out var ms, out var w);
            w.Write(Flags);
            UserCertificate.Encode(w, false);
            BinaryProcedures.EncodeIPEndPoint(w, DirectChannelEndPoint);
            NatBehaviour.Encode(w);
            DirectChannelToken32.Encode(w);
            w.Write((byte)SessionType);
            UserCertificateSignature.Encode(w);
            var bytesInLastBlock = (int)ms.Position % CryptoLibraries.AesBlockSize;

            if (bytesInLastBlock != 0)
            {
                var bytesRemainingTillFullAesBlock = CryptoLibraries.AesBlockSize - bytesInLastBlock;
                w.Write(cryptoLibrary.GetRandomBytes(bytesRemainingTillFullAesBlock));
            }
            var plainTextSdData = ms.ToArray();
            var encryptedSdData = new byte[plainTextSdData.Length];

            #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

            cryptoLibrary.ProcessAesCbcBlocks(true, aesKey, iv, plainTextSdData, encryptedSdData);

            return(encryptedSdData);
        }
Exemple #3
0
        internal byte[] EncryptIke1Data(ICryptoLibrary cryptoLibrary, Ike1Data ike1Data)
        {
            if (Status != MessageSessionStatusCode.inProgress)
            {
                throw new InvalidOperationException();
            }

            var decryptedMessageData = MessageEncoderDecoder.EncodeIke1DataWithPadding(cryptoLibrary, ike1Data);
            var encryptedMessageData = new byte[decryptedMessageData.Length];

            cryptoLibrary.ProcessAesCbcBlocks(true, _aesKey, _iv, decryptedMessageData, encryptedMessageData);

            Status = MessageSessionStatusCode.encryptionDecryptionCompleted;
            return(encryptedMessageData);
        }
Exemple #4
0
        internal byte[] EncryptShortSingleMessage(ICryptoLibrary cryptoLibrary, string messageText)
        {
            if (Status != MessageSessionStatusCode.inProgress)
            {
                throw new InvalidOperationException();
            }

            var decryptedMessageData = MessageEncoderDecoder.EncodePlainTextMessageWithPadding_plainTextUtf8_256(cryptoLibrary, messageText);
            var encryptedMessageData = new byte[decryptedMessageData.Length];

            cryptoLibrary.ProcessAesCbcBlocks(true, _aesKey, _iv, decryptedMessageData, encryptedMessageData);

            Status = MessageSessionStatusCode.encryptionDecryptionCompleted;
            return(encryptedMessageData);
        }
        /// <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);
        }