簡體   English   中英

C#-將公鑰Blob導入ECDiffieHellmanCng

[英]C# - importing a public key blob into ECDiffieHellmanCng

我在使用ECDiffieHellmanCng類交換密鑰時遇到了麻煩:

第1步-創建公鑰

public byte[] CreatePublicKey()
{
    using (ECDiffieHellmanCng cng = new ECDiffieHellmanCng())
    {
        cng.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
        cng.HashAlgorithm = CngAlgorithm.Sha512;
        return cng.PublicKey.ToByteArray();
    }
}

第2步-交換並獲取私鑰

public byte[] CreatePrivateKey(byte[] publicKey1, byte[] publicKey2)
{
    using(ECDiffieHellmanCng cng = new ECDiffieHellmanCng(CngKey.Import(publicKey1, CngKeyBlobFormat.EccPublicBlob)))
    {
        cng.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
        cng.HashAlgorithm = CngAlgorithm.Sha512;
        return cng.DeriveKeyMaterial(CngKey.Import(publicKey2, CngKeyBlobFormat.EccPublicBlob));
    }
}

byte[] alicePublicKey = CreatePublicKey();
byte[] bobPublicKey = CreatePublicKey();

// This fails
byte[] alicePrivateKey = CreatePrivateKey(alicePublicKey, bobPublicKey);
byte[] bobPrivateKey = CreatePrivateKey(bobPublicKey, alicePublicKey);

具體來說,它無法通過CreatePrivateKey(...)方法在此行上執行:

return cng.DeriveKeyMaterial(CngKey.Import(publicKey2, CngKeyBlobFormat.EccPublicBlob));

錯誤

System.Security.Cryptography.CryptographicException:'密鑰不存在。

我究竟做錯了什么?

問題是您正在嘗試使用兩個公用密鑰派生共享秘密( DeriveKeyMaterial結果)。 這將行不通,因為您需要一個方的私鑰和另一方的公鑰(不需要第一方的公鑰,因為它可以從私鑰派生)。 這是一個示例(我固定了一些術語,因為現在它們具有誤導性CreatePrivateKey不會創建私鑰)。 請注意,您通常不會像這樣導出私鑰,而是將其存儲在容器中,因此僅舉例來說:

public static (byte[] publicKey, byte[] privateKey) CreateKeyPair() {
    using (ECDiffieHellmanCng cng = new ECDiffieHellmanCng(
        // need to do this to be able to export private key
        CngKey.Create(
            CngAlgorithm.ECDiffieHellmanP256,
            null,
            new CngKeyCreationParameters
                { ExportPolicy = CngExportPolicies.AllowPlaintextExport }))) {
        cng.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
        cng.HashAlgorithm = CngAlgorithm.Sha512;
        // export both private and public keys and return
        var pr = cng.Key.Export(CngKeyBlobFormat.EccPrivateBlob);
        var pub = cng.PublicKey.ToByteArray();
        return (pub, pr);
    }
}

public static byte[] CreateSharedSecret(byte[] privateKey, byte[] publicKey) {
    // this returns shared secret, not private key
    // initialize algorithm with private key of one party
    using (ECDiffieHellmanCng cng = new ECDiffieHellmanCng(CngKey.Import(privateKey, CngKeyBlobFormat.EccPrivateBlob))) {
        cng.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
        cng.HashAlgorithm = CngAlgorithm.Sha512;
        // use public key of another party
        return cng.DeriveKeyMaterial(CngKey.Import(publicKey, CngKeyBlobFormat.EccPublicBlob));
    }
}

現在具有以上兩個功能:

var aliceKeyPair = CreateKeyPair();
var bobKeyPair = CreateKeyPair();                                
byte[] bobSharedSecret = CreateSharedSecret(bobKeyPair.privateKey, aliceKeyPair.publicKey);
byte[] aliceSharedSecret = CreateSharedSecret(aliceKeyPair.privateKey, bobKeyPair.publicKey);
// derived shared secrets are the same - the whole point of this algoritm
Debug.Assert(aliceSharedSecret.SequenceEqual(bobSharedSecret));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM