使用TPM实现EC Diffie-Hellman

时间:2018-11-08 08:12:47

标签: c# cryptography diffie-hellman cng tpm

我正在尝试使用EC Diffie-Hellman和两个不同的提供程序来加密/解密消息: Microsoft软件密钥存储提供程序 Microsoft平台加密提供程序。 以下代码适用于前者,而无法正确解密:

bool usePlatform = true; // works correctly when false

CngProvider provider = usePlatform
    ? new CngProvider("Microsoft Platform Crypto Provider")
    : CngProvider.MicrosoftSoftwareKeyStorageProvider;

const string message = "Hello, world!";
byte[] encryptedMessage;

// create keys
CngKey providerKey1 = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256, "test key 1", new CngKeyCreationParameters()
{
    Provider = provider,
    KeyCreationOptions = CngKeyCreationOptions.OverwriteExistingKey,
    ExportPolicy = CngExportPolicies.None,
});

byte[] publicKey1 = providerKey1.Export(CngKeyBlobFormat.EccPublicBlob);

CngKey providerKey2 = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256, "test key 2", new CngKeyCreationParameters()
{
    Provider = provider,
    KeyCreationOptions = CngKeyCreationOptions.OverwriteExistingKey,
    ExportPolicy = CngExportPolicies.None,
});

byte[] publicKey2 = providerKey2.Export(CngKeyBlobFormat.EccPublicBlob);

// encrypt with the private key 1 and the public key 2
using (SymmetricAlgorithm symmetricKey = new AesCng()
{
    Padding = PaddingMode.Zeros,
    Key = new ECDiffieHellmanCng(providerKey1) { KeySize = 256 }
        .DeriveKeyMaterial(ECDiffieHellmanCngPublicKey.FromByteArray(publicKey2, CngKeyBlobFormat.EccPublicBlob))
})
{
    symmetricKey.GenerateIV();

    using (ICryptoTransform encryptor = symmetricKey.CreateEncryptor())
    using (MemoryStream dataStream = new MemoryStream())
    {
        using (CryptoStream cryptoStream = new CryptoStream(dataStream, encryptor, CryptoStreamMode.Write))
        {
            dataStream.Write(symmetricKey.IV, 0, symmetricKey.IV.Length);

            byte[] messageBytes = Encoding.UTF8.GetBytes(message);
            cryptoStream.Write(messageBytes, 0, messageBytes.Length);
        }

        symmetricKey.Clear();
        encryptedMessage = dataStream.ToArray();
    }
}

string decryptedMessage;

// decrypt with the private key 2 and the public key 1
using (SymmetricAlgorithm symmetricKey = new AesCng()
{
    Padding = PaddingMode.Zeros,
    Key = new ECDiffieHellmanCng(providerKey2) { KeySize = 256 }
        .DeriveKeyMaterial(ECDiffieHellmanCngPublicKey.FromByteArray(publicKey1, CngKeyBlobFormat.EccPublicBlob))
})
{
    symmetricKey.IV = encryptedMessage.Take(symmetricKey.BlockSize >> 3).ToArray();

    using (ICryptoTransform decryptor = symmetricKey.CreateDecryptor())
    using (MemoryStream dataStream = new MemoryStream())
    {
        using (CryptoStream cryptoStream = new CryptoStream(dataStream, decryptor, CryptoStreamMode.Write))
        {
            cryptoStream.Write(encryptedMessage, symmetricKey.IV.Length, encryptedMessage.Length - symmetricKey.IV.Length);
        }

        symmetricKey.Clear();
        decryptedMessage = Encoding.UTF8.GetString(dataStream.ToArray()).Trim('\0'); 
    }
}

Debug.Assert(message == decryptedMessage); // the decrypted message doesn't match the original one

解密对称密钥将加密对称密钥与软件提供程序匹配,并且在使用平台提供程序时有所不同。我究竟做错了什么?这是TPM的某些使用问题吗?

0 个答案:

没有答案