关于 .net Framework 4.7 中 ECDiffieHellmanCng 实施的秘密协议的问题?
Questions about secret agreement from ECDiffieHellmanCng implementation in .net framework 4.7?
我有以下代码:
var curve = ECCurve.NamedCurves.nistP256;
var ecdhSender = ECDiffieHellman.Create(curve);
var ecdhReceiver = ECDiffieHellman.Create(curve);
我的理解是,我应该能够通过使用 ecdhReceiver.PublicKey 使用 ecdhSender 对象或使用 ecdhSender.PublicKey 使用 ecdhReceiver 对象来计算秘密协议,并且两个秘密协议值应该相同。如果这是一个错误的假设,请告诉我。
由于ECDiffieHellman.Create returns ECDiffieHellman类型,我写了下面的代码来获取秘密协议:
string receiverHexString = null;
using (SafeNCryptSecretHandle secretAgreement = (ecdhReceiver as ECDiffieHellmanCng).DeriveSecretAgreementHandle(ecdhSender.PublicKey))
{
byte[] secretAgreementBytes = new byte[32];
IntPtr pointer = secretAgreement.DangerousGetHandle();
Marshal.Copy(pointer, secretAgreementBytes, 0, secretAgreementBytes.Length);
receiverHexString = BitConverter.ToString(secretAgreementBytes).Replace("-", string.Empty).ToLower();
Console.WriteLine($"receiver secretAgreement: 0x{receiverHexString}");
}
string senderHexString = null;
using (SafeNCryptSecretHandle secretAgreement = (ecdhSender as ECDiffieHellmanCng).DeriveSecretAgreementHandle(ecdhReceiver.PublicKey))
{
byte[] secretAgreementBytes = new byte[32];
IntPtr pointer = secretAgreement.DangerousGetHandle();
Marshal.Copy(pointer, secretAgreementBytes, 0, secretAgreementBytes.Length);
senderHexString = BitConverter.ToString(secretAgreementBytes).Replace("-", string.Empty).ToLower();
Console.WriteLine($"sender secretAgreement: 0x{senderHexString}");
}
Assert.AreEqual(receiverHexString, senderHexString);
我的断言失败了。显然我做错了什么(如果秘密协议应该相同的话)。
这是我从句柄中提取字节的方式吗?或者别的什么?
从 开始,没有记录的方法从 CNG 获取原始秘密协议值,这就是 .NET 不公开它的原因。
.NET 中 ECDH 的预期用途是
ECCurve curve = ECCurve.NamedCurves.nistP256;
// Usually you'll only have one private key (yours), so this isn't representative of
// real code. An `ECDiffieHellman` object doesn't necessarily have a private key,
// but an `ECDiffieHellmanPublicKey` object definitely doesn't.
using (ECDiffieHellman bobPrivate = ECDiffieHellman.Create(curve))
using (ECDiffieHellman alicePrivate = ECDiffieHellman.Create(curve))
using (ECDiffieHellmanPublicKey bobPublic = bobPrivate.PublicKey)
using (ECDiffieHellmanPublicKey alicePublic = alicePrivate.PublicKey)
{
byte[] ba = bobPrivate.DeriveKeyFromHash(alicePublic, HashAlgorithmName.SHA256);
byte[] ab = alicePrivate.DeriveKeyFromHash(bobPublic, HashAlgorithmName.SHA256);
// ba and ab have the same contents.
}
还有
DeriveKeyFromHash(ECDiffieHellmanPublicKey otherPartyPublicKey, HashAlgorithmName hashAlgorithm, byte[] secretPrepend, byte[] secretAppend)
DeriveKeyFromHmac(ECDiffieHellmanPublicKey otherPartyPublicKey, HashAlgorithmName hashAlgorithm, byte[] hmacKey)
DeriveKeyFromHmac(ECDiffieHellmanPublicKey otherPartyPublicKey, HashAlgorithmName hashAlgorithm, byte[] hmacKey, byte[] secretPrepend, byte[] secretAppend)
DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed)
如果 bobPrivate 和 alicePublic(或者相反,alicePrivate 和 bobPublic)不变,那么提供相同的输入将产生相同的输出。
注意: 如果可以,您应该避免具体谈论 ECDiffieHellmanCng
。当 ECDH 最终进入 .NET 标准时,ECDHCng class 不会。从 .NET 4.6.2 开始,一切都可以在基础 class 上完成(打开持久密钥除外); .NET Core 倾向于不 return public 类型来自其 Create()
工厂方法。
我有以下代码:
var curve = ECCurve.NamedCurves.nistP256;
var ecdhSender = ECDiffieHellman.Create(curve);
var ecdhReceiver = ECDiffieHellman.Create(curve);
我的理解是,我应该能够通过使用 ecdhReceiver.PublicKey 使用 ecdhSender 对象或使用 ecdhSender.PublicKey 使用 ecdhReceiver 对象来计算秘密协议,并且两个秘密协议值应该相同。如果这是一个错误的假设,请告诉我。
由于ECDiffieHellman.Create returns ECDiffieHellman类型,我写了下面的代码来获取秘密协议:
string receiverHexString = null;
using (SafeNCryptSecretHandle secretAgreement = (ecdhReceiver as ECDiffieHellmanCng).DeriveSecretAgreementHandle(ecdhSender.PublicKey))
{
byte[] secretAgreementBytes = new byte[32];
IntPtr pointer = secretAgreement.DangerousGetHandle();
Marshal.Copy(pointer, secretAgreementBytes, 0, secretAgreementBytes.Length);
receiverHexString = BitConverter.ToString(secretAgreementBytes).Replace("-", string.Empty).ToLower();
Console.WriteLine($"receiver secretAgreement: 0x{receiverHexString}");
}
string senderHexString = null;
using (SafeNCryptSecretHandle secretAgreement = (ecdhSender as ECDiffieHellmanCng).DeriveSecretAgreementHandle(ecdhReceiver.PublicKey))
{
byte[] secretAgreementBytes = new byte[32];
IntPtr pointer = secretAgreement.DangerousGetHandle();
Marshal.Copy(pointer, secretAgreementBytes, 0, secretAgreementBytes.Length);
senderHexString = BitConverter.ToString(secretAgreementBytes).Replace("-", string.Empty).ToLower();
Console.WriteLine($"sender secretAgreement: 0x{senderHexString}");
}
Assert.AreEqual(receiverHexString, senderHexString);
我的断言失败了。显然我做错了什么(如果秘密协议应该相同的话)。
这是我从句柄中提取字节的方式吗?或者别的什么?
从
.NET 中 ECDH 的预期用途是
ECCurve curve = ECCurve.NamedCurves.nistP256;
// Usually you'll only have one private key (yours), so this isn't representative of
// real code. An `ECDiffieHellman` object doesn't necessarily have a private key,
// but an `ECDiffieHellmanPublicKey` object definitely doesn't.
using (ECDiffieHellman bobPrivate = ECDiffieHellman.Create(curve))
using (ECDiffieHellman alicePrivate = ECDiffieHellman.Create(curve))
using (ECDiffieHellmanPublicKey bobPublic = bobPrivate.PublicKey)
using (ECDiffieHellmanPublicKey alicePublic = alicePrivate.PublicKey)
{
byte[] ba = bobPrivate.DeriveKeyFromHash(alicePublic, HashAlgorithmName.SHA256);
byte[] ab = alicePrivate.DeriveKeyFromHash(bobPublic, HashAlgorithmName.SHA256);
// ba and ab have the same contents.
}
还有
DeriveKeyFromHash(ECDiffieHellmanPublicKey otherPartyPublicKey, HashAlgorithmName hashAlgorithm, byte[] secretPrepend, byte[] secretAppend)
DeriveKeyFromHmac(ECDiffieHellmanPublicKey otherPartyPublicKey, HashAlgorithmName hashAlgorithm, byte[] hmacKey)
DeriveKeyFromHmac(ECDiffieHellmanPublicKey otherPartyPublicKey, HashAlgorithmName hashAlgorithm, byte[] hmacKey, byte[] secretPrepend, byte[] secretAppend)
DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed)
如果 bobPrivate 和 alicePublic(或者相反,alicePrivate 和 bobPublic)不变,那么提供相同的输入将产生相同的输出。
注意: 如果可以,您应该避免具体谈论 ECDiffieHellmanCng
。当 ECDH 最终进入 .NET 标准时,ECDHCng class 不会。从 .NET 4.6.2 开始,一切都可以在基础 class 上完成(打开持久密钥除外); .NET Core 倾向于不 return public 类型来自其 Create()
工厂方法。