尝试使用CngKey.Import时出现加密异常,错误消息为“参数不正确”

时间:2019-03-23 11:37:30

标签: c# cryptography aes diffie-hellman

我正在为我的TCP服务器设置一个加密层。在此之前,所有通信都是通过纯文本进行的。我选择使用ECDiffieHellmanCng进行初始密钥交换,然后使用AES进行后续消息交换。

密钥已通过TCP套接字从客户端正确传输,并且它们的长度匹配。

此行出现异常:

sessionKey = server.DeriveKeyMaterial(CngKey.Import(clientPublicKey, 
CngKeyBlobFormat.EccPublicBlob));

异常消息和堆栈跟踪为:

The parameter is incorrect.
at System.Security.Cryptography.NCryptNative.ImportKey(SafeNCryptProviderHandle 
   provider, Byte[] keyBlob, String format)
at System.Security.Cryptography.CngKey.Import(Byte[] keyBlob, String curveName,
   CngKeyBlobFormat format, CngProvider provider)
at System.Security.Cryptography.CngKey.Import(Byte[] keyBlob, CngKeyBlobFormat
   format)

我已经尝试检查长度和实际传输的字节。它们是相同的。我浏览了其他链接以查找这是否是编码问题,但不清楚。

发起密钥交换的客户端代码:

try
{
client = new ECDiffieHellmanCng();

client.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;

client.HashAlgorithm = CngAlgorithm.Sha256;

clientPublicKey = client.PublicKey.ToByteArray();

displayLine("[client public key] Length : " + clientPublicKey.Length.ToString() + " Key: " + BitConverter.ToString(clientPublicKey));

writeByteArrayToClient(clientPublicKey,clientSocket);

}

catch(Exception e)
{
}

/// <summary>
        /// Write a byte array to the client
        /// </summary>
        /// <param name="bytesToSend">user supplied byte array</param>
        /// <param name="tcpClient">socket to write on</param>
        /// <returns></returns>

public bool writeByteArrayToClient(byte[] bytesToSend, TcpClient tcpClient)

{

//Stores the success or failure status
            bool returnFlag = false;

            try
            {
                //Open network stream from the clientsocket to read and write data
                NetworkStream networkStream = tcpClient.GetStream();

                //Flush the stream to remove any residual unsent data
                networkStream.Flush();

                //Write the sendBytes bytes to the networkStream
                networkStream.Write(bytesToSend, 0, bytesToSend.Length);

                //Flush the network stream of any remaining bytes
                networkStream.Flush();

                //Set the return flag to true to indicate success
                returnFlag = true;
            }
            catch (Exception ex)
            {
                //Display exception message and write log to serverLog.txt
                displayLine("[Writing] " + ex.Message + " Thrown while writing to client");

                //Set the return flag to false to indicate failure
                returnFlag = false;
            }

            //Return operation success/failure status to calling function
            return returnFlag;
        }

服务器端:

clientPublicKey = readByteArrayFromClient(10000);
                //displayInMainForm("[client public key] Length : " + clientPublicKey.Length.ToString() + " Key: " + BitConverter.ToString(clientPublicKey));
                //Key Exchange
                serverKeyGenerate();

public void serverKeyGenerate()
        {
            server = new ECDiffieHellmanCng();
            server.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
            server.HashAlgorithm = CngAlgorithm.Sha256;
            ServerPublicKey = server.PublicKey.ToByteArray();
            sessionKey = server.DeriveKeyMaterial(CngKey.Import(clientPublicKey, CngKeyBlobFormat.EccPublicBlob)); //THIS IS WHERE I AM GETTING THE EXCEPTION
        }

/// <summary>
        /// Reads a byte array from the client 
        /// </summary>
        /// <param name="timeout">Specifies how long the socket should wait for data, default value is infinite</param>
        /// <returns></returns>
        private byte[] readByteArrayFromClient(int timeout = Timeout.Infinite)
        {
            //Open network stream from the clientsocket to read and write data
            NetworkStream networkStream = clientSocket.GetStream();

            //Set read timeout value to as supplied by the user, default value is to wait forever
            networkStream.ReadTimeout = timeout;

            //Byte array buffer to read data coming from the clientsocket based on buffer size
            byte[] bytesFrom = new byte[(int)clientSocket.ReceiveBufferSize];

            //Read the data available from the network stream till the buffer is full
            networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);

            //Flush networkstream after the read is complete
            networkStream.Flush();

            //Remove old array reference
            transient = null;

            //Use globally shared transient array to store the bytes read 
            transient = bytesFrom;

            int lastIndex = Array.FindLastIndex(bytesFrom, b => b != 0);
            Array.Resize(ref bytesFrom, lastIndex+1);

            return bytesFrom;
        }

预期结果是应生成会话密钥,而我将随后将其用于AES加密。

0 个答案:

没有答案