Exemplo n.º 1
0
        private void TryVerifySignature(Smb2SinglePacket singlePacket, ulong sessionId, byte[] messageBytes)
        {
            // [MS-SMB2] 3.2.5.1.3
            //If the MessageId is 0xFFFFFFFFFFFFFFFF, no verification is necessary.
            if (singlePacket.Header.MessageId == 0xFFFFFFFFFFFFFFFF)
            {
                return;
            }

            Smb2CryptoInfo cryptoInfo = null;

            //[MS-SMB2] 3.2.5.1.3
            //If the SMB2 header of the response has SMB2_FLAGS_SIGNED set in the Flags field, the client MUST verify the signature
            if (singlePacket.Header.Flags.HasFlag(Packet_Header_Flags_Values.FLAGS_SIGNED))
            {
                //This is for the session binding success situation.
                //After the session setup success, the cryptoInfoTable will be updated with new signingkey
                //The new signingkey is not in the cryptoInfoTable now. Cannot verify the signature before the table is updated.

                if (cryptoInfoTable.TryGetValue(sessionId, out cryptoInfo))
                {
                    if (!VerifySignature(singlePacket, cryptoInfo, messageBytes))
                    {
                        //If signature verification fails, the client MUST discard the received message and do no further processing for it.
                        //The client MAY also choose to disconnect the connection.
                        //Throw exception here.
                        throw new InvalidOperationException("Incorrect signed packet: " + singlePacket.ToString());
                    }
                }
            }
        }
        /// <summary>
        /// Verify the signature of a Smb2SinglePacket
        /// </summary>
        /// <param name="packet">The packet to be verified</param>
        /// <param name="cryptoInfo">The cryptoInfo of smb2client</param>
        /// <returns>True when signature verification succeeds and false when fails</returns>
        private bool VerifySignature(Smb2SinglePacket packet, Smb2CryptoInfo cryptoInfo)
        {
            if (cryptoInfo.DisableVerifySignature)
            {
                // Skip the verification.
                return(true);
            }

            try
            {
                if (IsErrorPacket(packet.Header))
                {
                    packet = packet.Error;
                }
                //save the 16-byte signature from the Signature field in the SMB2 Header
                byte[] originalSignature = packet.Header.Signature;

                //zero out the 16-byte signature field in the SMB2 Header of the incoming message.
                packet.Header.Signature = new byte[Smb2Consts.SignatureSize];
                byte[] bytesToCompute = packet.ToBytes();

                //Compute the message with signing key
                byte[] computedSignature = new byte[] { };
                if (Smb2Utility.IsSmb3xFamily(cryptoInfo.Dialect))
                {
                    //[MS-SMB2] 3.1.5.1
                    //If Session.Connection.Dialect belongs to the SMB 3.x dialect family,
                    //the receiver MUST compute a 16-byte hash by using AES-128-CMAC over the entire message,
                    //beginning with the SMB2 Header from step 2, and using the key provided.
                    //The AES-128-CMAC is specified in [RFC4493].

                    //TD has mentioned to use Session.SigningKey for SESSION_SETUP Response and Channel.SigningKey for other responses
                    //In the current SDK, the SigningKey is the Channel.SigningKey
                    computedSignature = AesCmac128.ComputeHash(cryptoInfo.SigningKey, bytesToCompute);
                }
                else
                {
                    //[MS-SMB2] 3.1.5.1
                    //If Session.Connection.Dialect is "2.002" or "2.100", the receiver MUST compute a 32-byte hash by using HMAC-SHA256 over the entire message,
                    //beginning with the SMB2 Header from step 2, and using the key provided.
                    //The HMAC-SHA256 hash is specified in [FIPS180-2] and [RFC2104].

                    HMACSHA256 hmacSha = new HMACSHA256(cryptoInfo.SigningKey);
                    computedSignature = hmacSha.ComputeHash(bytesToCompute);
                }
                packet.Header.Signature = originalSignature;

                //[MS-SMB2] 3.1.5.1
                //If the first 16 bytes (the high-order portion) of the computed signature from step 3 or step 4 matches the saved signature from step 1, the message is signed correctly
                // compare the first 16 bytes of the originalSignature and computedSignature
                return(originalSignature.SequenceEqual(computedSignature.Take(16)));
            }
            catch (Exception ex)
            {
                throw new Exception("Error happened during signature verification of packet: " + packet.ToString() + ". Exception message: " + ex.Message);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Generate encrypt/decrypt and signing keys according to the smb2 dialect, cryptographicKey(session key), PreauthIntegrityHashValue and existing cryptInfo
        /// If the param cryptoInfo is not null, then the param cipherId will be ignored.
        /// The binding session should use the same cipherId as the master session.
        /// </summary>
        /// <param name="dialect">Smb2 dialect</param>
        /// <param name="cryptographicKey">The key to derive new encrypt/decrypt/signing key </param>
        /// <param name="enableSigning">True if signing is enabled, otherwise false</param>
        /// <param name="enableEncryption">True if encrypt is enabled, otherwise false</param>
        /// <param name="cryptoInfo">The existing cryptoInfo. This is for the binding session</param>
        /// <param name="preauthIntegrityHashValue">The preauthentication integrity hash value, for smb dialect 311 only </param>
        /// <param name="cipherId">The ID of the cipher that was negotiated for this connection</param>
        public Smb2CryptoInfo(
            DialectRevision dialect,
            byte[] cryptographicKey,
            bool enableSigning,
            bool enableEncryption,
            bool disableVerifySignature,
            Smb2CryptoInfo cryptoInfo        = null,
            byte[] preauthIntegrityHashValue = null,
            EncryptionAlgorithm cipherId     = EncryptionAlgorithm.ENCRYPTION_AES128_CCM)
        {
            if (dialect >= DialectRevision.Smb311 && dialect != DialectRevision.Smb2Unknown && preauthIntegrityHashValue == null)
            {
                if (cryptoInfo == null && enableEncryption) // For the alternative channel, the cryptoinfo should be the same as the main channel.
                {
                    throw new ArgumentNullException("For SMB 3.11, null preauthIntegrityHashValue is not allowed when encryption is enabled.");
                }

                if (enableSigning) // For the alternative channel, the signingkey should be recalculated.
                {
                    throw new ArgumentNullException("For SMB 3.11, null preauthIntegrityHashValue is not allowed when signing is enabled.");
                }
            }

            DisableVerifySignature = disableVerifySignature;
            Dialect = dialect;

            SessionKey     = cryptographicKey;
            FullSessionKey = cryptographicKey;

            // TD indicates that when signing the message the protocol uses
            // the first 16 bytes of the cryptographic key for this authenticated context.
            // If the cryptographic key is less than 16 bytes, it is right-padded with zero bytes.
            if (SessionKey.Length < 16)
            {
                SessionKey = SessionKey.Concat(new byte[16 - SessionKey.Length]).ToArray();
            }

            else if (SessionKey.Length > 16)
            {
                SessionKey = SessionKey.Take(16).ToArray();
            }

            if (Dialect == DialectRevision.Smb2002 || Dialect == DialectRevision.Smb21)
            {
                SigningKey = SessionKey;
            }

            else if (Dialect == DialectRevision.Smb30 || Dialect == DialectRevision.Smb302)
            {
                SigningKey = SP8001008KeyDerivation.CounterModeHmacSha256KeyDerive(
                    SessionKey,
                    Encoding.ASCII.GetBytes("SMB2AESCMAC\0"),
                    Encoding.ASCII.GetBytes("SmbSign\0"),
                    128);
            }
            else // dialect == SMB311
            {
                SigningKey = SP8001008KeyDerivation.CounterModeHmacSha256KeyDerive(
                    SessionKey,
                    Encoding.ASCII.GetBytes("SMBSigningKey\0"),
                    preauthIntegrityHashValue,
                    128);
            }
            if (cryptoInfo == null)
            {
                if (dialect >= DialectRevision.Smb311)
                {
                    CipherId = cipherId;
                }
                else
                {
                    // for pre SMB 3.11 dialects, use AES-128-CCM for encryption
                    CipherId = EncryptionAlgorithm.ENCRYPTION_AES128_CCM;
                }

                /**
                 *  If Connection.CipherId is AES-128-CCM or AES-128-GCM, 'L' is initialized to 128.
                 *  If Connection.CipherId is AES-256-CCM or AES256-GCM, 'L' value is initialized to 256.
                 *
                 *  If Connection.Dialect is “3.1.1” and Connection.CipherId is AES-256(CCM or GCM),
                 *  Session.FullSessionKey as the key derivation key. Otherwise, Session.SessionKey as the key
                 *  derivation key
                 **/

                if (CipherId == EncryptionAlgorithm.ENCRYPTION_AES128_CCM ||
                    CipherId == EncryptionAlgorithm.ENCRYPTION_AES128_GCM)
                {
                    LValue = 128;
                }
                else
                {
                    LValue = 256;
                }

                if (dialect == DialectRevision.Smb311 &&
                    (CipherId == EncryptionAlgorithm.ENCRYPTION_AES256_CCM ||
                     CipherId == EncryptionAlgorithm.ENCRYPTION_AES256_GCM))
                {
                    EncryptionKey = FullSessionKey;
                }
                else
                {
                    EncryptionKey = SessionKey;
                }

                ServerInKey = SP8001008KeyDerivation.CounterModeHmacSha256KeyDerive(
                    EncryptionKey,
                    // If Connection.Dialect is "3.1.1", the case-sensitive ASCII string "SMBC2SCipherKey" as the label;
                    // otherwise, the case-sensitive ASCII string "SMB2AESCCM" as the label.
                    Dialect == DialectRevision.Smb311 ? Encoding.ASCII.GetBytes("SMBC2SCipherKey\0") : Encoding.ASCII.GetBytes("SMB2AESCCM\0"),
                    // If Connection.Dialect is "3.1.1", Session.PreauthIntegrityHashValue as the context;
                    // otherwise, the case-sensitive ASCII string "ServerIn " as context for the algorithm (note the blank space at the end).
                    Dialect == DialectRevision.Smb311 ? preauthIntegrityHashValue : Encoding.ASCII.GetBytes("ServerIn \0"),
                    LValue);

                ServerOutKey = SP8001008KeyDerivation.CounterModeHmacSha256KeyDerive(
                    EncryptionKey,
                    // If Connection.Dialect is "3.100", the case-sensitive ASCII string "SMBS2CCipherKey" as the label;
                    // otherwise, the case-sensitive ASCII string "SMB2AESCCM" as the label.
                    Dialect == DialectRevision.Smb311 ? Encoding.ASCII.GetBytes("SMBS2CCipherKey\0") : Encoding.ASCII.GetBytes("SMB2AESCCM\0"),
                    // If Connection.Dialect is "3.100", Session.PreauthIntegrityHashValue as the context;
                    // otherwise, the case-sensitive ASCII string "ServerOut" as context for the algorithm.
                    Dialect == DialectRevision.Smb311 ? preauthIntegrityHashValue : Encoding.ASCII.GetBytes("ServerOut\0"),
                    LValue);

                ApplicationKey = SP8001008KeyDerivation.CounterModeHmacSha256KeyDerive(
                    SessionKey,
                    // If Connection.Dialect is "3.1.1", the case-sensitive ASCII string "SMBAppKey" as the label;
                    // otherwise, the case-sensitive ASCII string "SMB2APP" as the label.
                    Dialect == DialectRevision.Smb311 ? Encoding.ASCII.GetBytes("SMBAppKey\0") : Encoding.ASCII.GetBytes("SMB2APP\0"),
                    // If Connection.Dialect is "3.1.1", Session.PreauthIntegrityHashValue as the context;
                    // otherwise, the case-sensitive ASCII string "SmbRpc" as context for the algorithm.
                    Dialect == DialectRevision.Smb311 ? preauthIntegrityHashValue : Encoding.ASCII.GetBytes("SmbRpc\0"),
                    128);
            }
            else
            {
                // Reuse encryption/decryption key that is generated in first channel's session setup
                // when send encrypted request in alternative channels
                CipherId       = cryptoInfo.CipherId;
                ServerInKey    = cryptoInfo.ServerInKey;
                ServerOutKey   = cryptoInfo.ServerOutKey;
                ApplicationKey = cryptoInfo.ApplicationKey;
            }

            EnableSessionSigning    = enableSigning;
            EnableSessionEncryption = enableEncryption;
        }
        /// <summary>
        /// Verify the signature of a Smb2SinglePacket
        /// </summary>
        /// <param name="packet">The packet to be verified</param>
        /// <param name="cryptoInfo">The cryptoInfo of smb2client</param>        
        /// <returns>True when signature verification succeeds and false when fails</returns>
        private bool VerifySignature(Smb2SinglePacket packet, Smb2CryptoInfo cryptoInfo, byte[] messageBytes)
        {
            if (cryptoInfo.DisableVerifySignature)
            {
                // Skip the verification.
                return true;
            }

            try
            {
                if (IsErrorPacket(packet.Header))
                {
                    packet = packet.Error;
                }

                byte[] bytesToCompute = messageBytes;
                // Zero out the 16-byte signature field in the SMB2 Header of the incoming message.
                Array.Clear(bytesToCompute, System.Runtime.InteropServices.Marshal.SizeOf(packet.Header) - Smb2Consts.SignatureSize, Smb2Consts.SignatureSize);

                //Compute the message with signing key
                byte[] computedSignature = null;
                if (Smb2Utility.IsSmb3xFamily(cryptoInfo.Dialect))
                {
                    //[MS-SMB2] 3.1.5.1
                    //If Session.Connection.Dialect belongs to the SMB 3.x dialect family,
                    //the receiver MUST compute a 16-byte hash by using AES-128-CMAC over the entire message,
                    //beginning with the SMB2 Header from step 2, and using the key provided.
                    //The AES-128-CMAC is specified in [RFC4493].

                    //TD has mentioned to use Session.SigningKey for SESSION_SETUP Response and Channel.SigningKey for other responses
                    //In the current SDK, the SigningKey is the Channel.SigningKey
                    computedSignature = AesCmac128.ComputeHash(cryptoInfo.SigningKey, bytesToCompute);
                }
                else
                {
                    //[MS-SMB2] 3.1.5.1
                    //If Session.Connection.Dialect is "2.002" or "2.100", the receiver MUST compute a 32-byte hash by using HMAC-SHA256 over the entire message,
                    //beginning with the SMB2 Header from step 2, and using the key provided.
                    //The HMAC-SHA256 hash is specified in [FIPS180-2] and [RFC2104].

                    HMACSHA256 hmacSha = new HMACSHA256(cryptoInfo.SigningKey);
                    computedSignature = hmacSha.ComputeHash(bytesToCompute);
                }

                //[MS-SMB2] 3.1.5.1
                //If the first 16 bytes (the high-order portion) of the computed signature from step 3 or step 4 matches the saved signature from step 1, the message is signed correctly
                // compare the first 16 bytes of the originalSignature and computedSignature
                return packet.Header.Signature.SequenceEqual(computedSignature.Take(Smb2Consts.SignatureSize));
            }
            catch (Exception ex)
            {
                throw new Exception("Error happened during signature verification of packet: " + packet.ToString() + ". Exception message: " + ex.Message);
            }
        }
        /// <summary>
        /// Generate encrypt/decrypt and signing keys according to the smb2 dialect, cryptographicKey(session key), PreauthIntegrityHashValue and existing cryptInfo
        /// If the param cryptoInfo is not null, then the param cipherId will be ignored. 
        /// The binding session should use the same cipherId as the master session.
        /// </summary>
        /// <param name="dialect">Smb2 dialect</param>
        /// <param name="cryptographicKey">The key to derive new encrypt/decrypt/signing key </param>
        /// <param name="enableSigning">True if signing is enabled, otherwise false</param>
        /// <param name="enableEncryption">True if encrypt is enabled, otherwise false</param>
        /// <param name="cryptoInfo">The existing cryptoInfo. This is for the binding session</param>        
        /// <param name="preauthIntegrityHashValue">The preauthentication integrity hash value, for smb dialect 311 only </param>
        /// <param name="cipherId">The ID of the cipher that was negotiated for this connection</param>
        public Smb2CryptoInfo(
            DialectRevision dialect,
            byte[] cryptographicKey,
            bool enableSigning,
            bool enableEncryption,
            Smb2CryptoInfo cryptoInfo = null,
            byte[] preauthIntegrityHashValue = null,
            EncryptionAlgorithm cipherId = EncryptionAlgorithm.ENCRYPTION_AES128_CCM)
        {
            if (dialect >= DialectRevision.Smb311 && dialect != DialectRevision.Smb2Unknown && preauthIntegrityHashValue == null)
            {
                if (cryptoInfo == null && enableEncryption) // For the alternative channel, the cryptoinfo should be the same as the main channel.
                {
                    throw new ArgumentNullException("For SMB 3.11, null preauthIntegrityHashValue is not allowed when encryption is enabled.");
                }

                if(enableSigning) // For the alternative channel, the signingkey should be recalculated.
                {
                    throw new ArgumentNullException("For SMB 3.11, null preauthIntegrityHashValue is not allowed when signing is enabled.");
                }
            }

            Dialect = dialect;

            SessionKey = cryptographicKey;

            // TD indicates that when signing the message the protocol uses
            // the first 16 bytes of the cryptographic key for this authenticated context.
            // If the cryptographic key is less than 16 bytes, it is right-padded with zero bytes.
            if (SessionKey.Length < 16)
                SessionKey = SessionKey.Concat(new byte[16 - SessionKey.Length]).ToArray();

            else if (SessionKey.Length > 16)
                SessionKey = SessionKey.Take(16).ToArray();

            if (Dialect == DialectRevision.Smb2002 || Dialect == DialectRevision.Smb21)
                SigningKey = SessionKey;

            else if (Dialect == DialectRevision.Smb30 || Dialect == DialectRevision.Smb302)
                SigningKey = SP8001008KeyDerivation.CounterModeHmacSha256KeyDerive(
                                SessionKey,
                                Encoding.ASCII.GetBytes("SMB2AESCMAC\0"),
                                Encoding.ASCII.GetBytes("SmbSign\0"),
                                128);
            else // dialect == SMB311
            {
                SigningKey = SP8001008KeyDerivation.CounterModeHmacSha256KeyDerive(
                                SessionKey,
                                Encoding.ASCII.GetBytes("SMBSigningKey\0"),
                                preauthIntegrityHashValue,
                                128);
            }
            if (cryptoInfo == null)
            {
                if (dialect >= DialectRevision.Smb311)
                {
                    CipherId = cipherId;
                }
                else
                {
                    // for pre SMB 3.11 dialects, use AES-128-CCM for encryption
                    CipherId = EncryptionAlgorithm.ENCRYPTION_AES128_CCM;
                }
                ServerInKey = SP8001008KeyDerivation.CounterModeHmacSha256KeyDerive(
                                SessionKey,
                                // If Connection.Dialect is "3.1.1", the case-sensitive ASCII string "SMBC2SCipherKey" as the label;
                                // otherwise, the case-sensitive ASCII string "SMB2AESCCM" as the label.
                                Dialect == DialectRevision.Smb311 ? Encoding.ASCII.GetBytes("SMBC2SCipherKey\0") : Encoding.ASCII.GetBytes("SMB2AESCCM\0"),
                                // If Connection.Dialect is "3.1.1", Session.PreauthIntegrityHashValue as the context;
                                // otherwise, the case-sensitive ASCII string "ServerIn " as context for the algorithm (note the blank space at the end).
                                Dialect == DialectRevision.Smb311 ? preauthIntegrityHashValue : Encoding.ASCII.GetBytes("ServerIn \0"),
                                128);

                ServerOutKey = SP8001008KeyDerivation.CounterModeHmacSha256KeyDerive(
                                SessionKey,
                                // If Connection.Dialect is "3.100", the case-sensitive ASCII string "SMBS2CCipherKey" as the label;
                                // otherwise, the case-sensitive ASCII string "SMB2AESCCM" as the label.
                                Dialect == DialectRevision.Smb311 ? Encoding.ASCII.GetBytes("SMBS2CCipherKey\0") : Encoding.ASCII.GetBytes("SMB2AESCCM\0"),
                                // If Connection.Dialect is "3.100", Session.PreauthIntegrityHashValue as the context;
                                // otherwise, the case-sensitive ASCII string "ServerOut" as context for the algorithm.
                                Dialect == DialectRevision.Smb311 ? preauthIntegrityHashValue : Encoding.ASCII.GetBytes("ServerOut\0"),
                                128);

                ApplicationKey = SP8001008KeyDerivation.CounterModeHmacSha256KeyDerive(
                                SessionKey,
                                // If Connection.Dialect is "3.1.1", the case-sensitive ASCII string "SMBAppKey" as the label;
                                // otherwise, the case-sensitive ASCII string "SMB2APP" as the label.
                                Dialect == DialectRevision.Smb311 ? Encoding.ASCII.GetBytes("SMBAppKey\0") : Encoding.ASCII.GetBytes("SMB2APP\0"),
                                // If Connection.Dialect is "3.1.1", Session.PreauthIntegrityHashValue as the context;
                                // otherwise, the case-sensitive ASCII string "SmbRpc" as context for the algorithm.
                                Dialect == DialectRevision.Smb311 ? preauthIntegrityHashValue : Encoding.ASCII.GetBytes("SmbRpc\0"),
                                128);
            }
            else
            {
                // Reuse encryption/decryption key that is generated in first channel's session setup
                // when send encrypted request in alternative channels
                CipherId = cryptoInfo.CipherId;
                ServerInKey = cryptoInfo.ServerInKey;
                ServerOutKey = cryptoInfo.ServerOutKey;
                ApplicationKey = cryptoInfo.ApplicationKey;
            }

            EnableSessionSigning = enableSigning;
            EnableSessionEncryption = enableEncryption;
        }
Exemplo n.º 6
0
        /// <summary>
        /// Verify the signature of a Smb2SinglePacket
        /// </summary>
        /// <param name="packet">The packet to be verified</param>
        /// <param name="cryptoInfo">The cryptoInfo of smb2client</param>
        /// <returns>True when signature verification succeeds and false when fails</returns>
        private bool VerifySignature(Smb2SinglePacket packet, Smb2CryptoInfo cryptoInfo, byte[] messageBytes)
        {
            if (cryptoInfo.DisableVerifySignature)
            {
                // Skip the verification.
                return(true);
            }

            try
            {
                if (IsErrorPacket(packet.Header))
                {
                    packet = packet.Error;
                }

                byte[] bytesToCompute = messageBytes;
                // Zero out the 16-byte signature field in the SMB2 Header of the incoming message.
                Array.Clear(bytesToCompute, System.Runtime.InteropServices.Marshal.SizeOf(packet.Header) - Smb2Consts.SignatureSize, Smb2Consts.SignatureSize);

                //Compute the message with signing key
                byte[] computedSignature = null;
                if (Smb2Utility.IsSmb3xFamily(cryptoInfo.Dialect))
                {
                    //[MS-SMB2] 3.1.5.1
                    //If Session.Connection.Dialect belongs to the SMB 3.x dialect family,
                    //the receiver MUST compute a 16-byte hash by using AES-128-CMAC over the entire message,
                    //beginning with the SMB2 Header from step 2, and using the key provided.
                    //The AES-128-CMAC is specified in [RFC4493].

                    //TD has mentioned to use Session.SigningKey for SESSION_SETUP Response and Channel.SigningKey for other responses
                    //In the current SDK, the SigningKey is the Channel.SigningKey

                    if (cryptoInfo.SigningId == SigningAlgorithm.AES_GMAC)
                    {
                        var nonce = Smb2Utility.ComputeNonce(packet, this.decodeRole);
                        var(_ciphertext, tag) = AesGmac.ComputeHash(cryptoInfo.SigningKey, nonce, bytesToCompute);

                        computedSignature = tag;
                    }
                    else
                    {
                        computedSignature = AesCmac128.ComputeHash(cryptoInfo.SigningKey, bytesToCompute);
                    }
                }
                else
                {
                    //[MS-SMB2] 3.1.5.1
                    //If Session.Connection.Dialect is "2.002" or "2.100", the receiver MUST compute a 32-byte hash by using HMAC-SHA256 over the entire message,
                    //beginning with the SMB2 Header from step 2, and using the key provided.
                    //The HMAC-SHA256 hash is specified in [FIPS180-2] and [RFC2104].

                    HMACSHA256 hmacSha = new HMACSHA256(cryptoInfo.SigningKey);
                    computedSignature = hmacSha.ComputeHash(bytesToCompute);
                }

                //[MS-SMB2] 3.1.5.1
                //If the first 16 bytes (the high-order portion) of the computed signature from step 3 or step 4 matches the saved signature from step 1, the message is signed correctly
                // compare the first 16 bytes of the originalSignature and computedSignature
                return(packet.Header.Signature.SequenceEqual(computedSignature.Take(Smb2Consts.SignatureSize)));
            }
            catch (Exception ex)
            {
                throw new Exception("Error happened during signature verification of packet: " + packet.ToString() + ". Exception message: " + ex.Message);
            }
        }