我正在为我的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加密。