Внедрение ЕС Диффи-Хеллмана с TPM - PullRequest
0 голосов
/ 08 ноября 2018

Я пытаюсь зашифровать / расшифровать сообщение с помощью 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?

...