【问题标题】:Why does ECDiffieHellmanP256 work with ECDsaCng.SignData()?为什么 ECDiffieHellmanP256 与 ECDsaCng.SignData() 一起使用?
【发布时间】:2021-08-06 05:07:06
【问题描述】:

.NET 中有两种 P256 曲线算法可以与CngKey 一起使用:

让我感到困惑的是,似乎可以使用CngAlgorithm.ECDiffieHellmanP256 创建签名。

示例代码:

// create private key and data
var privateKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256);
Console.WriteLine($"privateKey: {privateKey.Algorithm} {privateKey.KeyUsage}");

// sign data
var data = new byte[] { 1, 2, 3 };
byte[] signature;
using (var dsa = new ECDsaCng(privateKey))
{
    signature = dsa.SignData(data);
    Console.WriteLine($"Signature: {Convert.ToBase64String(signature)}");
}

// create stand-alone public key, just to be sure this is working as expected
var publicKeyBlob = privateKey.Export(CngKeyBlobFormat.EccPublicBlob);
var publicKey = CngKey.Import(publicKeyBlob, CngKeyBlobFormat.EccPublicBlob);
Console.WriteLine($"Public key: {publicKey.Algorithm} {publicKey.KeyUsage} {Convert.ToBase64String(publicKeyBlob)}");

// verify signature
using (var dsa = new ECDsaCng(publicKey))
{
    var verified = dsa.VerifyData(data, signature);
    Console.WriteLine($"Verified: {verified}");
}

输出:

privateKey: ECDH_P256 AllUsages
Signature: I1+Bapp8jxC7hUbTQTDTqscR9uoM/bo0OG1WVxgJUWYWq6jmW38a51JnuVRMXMKHosLOClt+AlrjiL/hG7TaqQ==
Public key: ECDH_P256 AllUsages RUNLMSAAAAC9amJDYvEJF+6HXyIhHoOiyUyu3grcH7leeuiOjMAiGbKwFoLssph+NCpY35g2dSHvNgaU11AavV/gAkPH6UPm
Verified: True

只是为了显示相似性;如果我改用CngAlgorithm.ECDsaP256:

privateKey: ECDSA_P256 AllUsages
Signature: meQ2ywrGWCOnVCaa0bm74Z0Sj37epzSJ5bz/b0x31hGvTn8zk3hcRt5If1+r1PgoR0A1cmSBDF4QUkY0UQjPhw==
Public key: ECDSA_P256 AllUsages RUNTMSAAAADfyG3BtOqGrI63Kh+FPy6V0EmpVX/4mBSbDQ+RxEerlaQCIVq0STrl87D+Re1b+iZ7a8/+S74cHrFNILqYqLXi
Verified: True

请注意,以相反的方式执行此操作 - 尝试使用 DSA 密钥创建 DH 对象 - 使用 new ECDiffieHellmanCng(CngKey.Create(CngAlgorithm.ECDsaP256)) 会导致:

ArgumentException:与 ECDiffieHellmanCng 算法一起使用的键必须具有 ECDiffieHellman 的算法组。参数名称:键

这意味着密钥类型之间存在某种差异。


以这种方式使用 ECDH 密钥实际上是否安全(例如:此代码是否生成安全的数字签名)?

使用 ECDSA 密钥而不是 ECDH 密钥有什么好处(除非您明确不想允许密钥交换)?

【问题讨论】:

    标签: c# cryptography digital-signature elliptic-curve


    【解决方案1】:

    ECDiffieHellmanCng(CngKey.Create(CngAlgorithm.ECDsaP256))
    这意味着密钥类型之间存在某种差异。

    当您尝试在运行时使用CngKeyinitializeECDiffieHellmanCng 验证您提供的CngKey 是特定算法列表的一部分时,MSDN 将它们称为Elliptic Curve Diffie-Hellman (ECDH) algorithm group,它具有四个有效的算法组名称ECDHECDiffieHellmanECDiffieHellmanCngSystem.Security.Cryptography.ECDiffieHellmanCng,其中all refer to the same implementation

    当您使用CngAlgorithm.ECDiffieHellmanP256 创建CngKey 时,您将获得一个有效的ECDH 密钥,该密钥的算法组为ECDH,它可以作为创建ECDiffieHellmanCng 以执行密钥交换的参数有效.

    但是,当您使用 CngAlgorithm.ECDsaP256 创建 CngKey 时,您会得到一个带有 ECDSA 的算法组的密钥,这不是一个有效的算法组来创建一个 ECDiffieHellmanCng 来执行密钥交换.

    ECDSA AlgorithmGroup 用于表示CngKey,其目的是执行椭圆曲线数字签名,并且明确执行密钥交换。此密钥不能与ECDiffieHellmanCng 一起用于执行密钥交换,因为它很可能没有包含足够、有效和/或安全的信息来与另一方执行密钥交换。

    您可以使用ECDsaCng 与 ECDH 和 ECDSA CngKeys 构建有效的 EC 签名,因为它们都包含足够、有效或安全的信息来构建和执行数字签名。但是,由于 MSDN 在执行密钥交换时创建的限制,其实现 ECDiffieHellmanCng,除了可能丢失的信息/格式之外,ECDSA CngKey 密钥阻止正确计算密钥交换,因此相反的情况并不相同.

    我们可以用一个简短的测试脚本来验证这些信息

    CngKey ECDHKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256);
    
    CngKey ECDSAKey = CngKey.Create(CngAlgorithm.ECDsaP256);
    
    Console.WriteLine(ECDHKey.Algorithm);
    Console.WriteLine(ECDHKey.AlgorithmGroup);
    
    Console.WriteLine(ECDSAKey.Algorithm);
    Console.WriteLine(ECDSAKey.AlgorithmGroup);
    
    using var ECDH = new ECDiffieHellmanCng(key: ECDHKey);
    
    Console.WriteLine($"Signature Algorithm: {ECDH.SignatureAlgorithm}");
    
    var ECDSA = new ECDsaCng(key: ECDHKey);
    
    Console.WriteLine($"Signature Algorithm: {ECDSA.SignatureAlgorithm}");
    
    ECDSA.Dispose();
    
    ECDSA = new ECDsaCng(key: ECDSAKey);
    
    Console.WriteLine($"Signature Algorithm: {ECDSA.SignatureAlgorithm}");
    
    ECDSA.Dispose();
    
    // outputs
    ECDH_P256
    ECDH
    ECDSA_P256
    ECDSA
    Signature Algorithm: 
    Signature Algorithm: ECDsa
    Signature Algorithm: ECDsa
    

    我们可以看到 ECDH 包含正确的参数和信息来构建 ECDSA 曲线和 ECDH 曲线,但是 ECDSA 密钥只能与 ECDSA 曲线(ECDsaCng)一起使用,因为它的目的是执行签名.

    使用 ECDSA 密钥而不是 ECDH 密钥有什么好处(除非您明确不想允许密钥交换)?

    以这种方式使用 ECDH 密钥实际上是否安全(例如:此代码是否生成安全的数字签名)?

    我在ECDSA vs ECDH 找到了一篇文章,其中涵盖了两者之间的细微差别,甚至在上面提供了一些信息,说明这些键为何执行不同的功能。这是我认为立即有用的摘录。

    “ECDH 是一种密钥交换方法,双方可以使用它在不安全的通信通道上协商安全密钥。它是 DH (Diffie-Hellman) 密钥交换方法的一种变体。ECDH 代表 Elliptic-curve Diffie-Hellman . 然而,ECDH 只是一种方法,这意味着您不能只将其与特定的椭圆曲线一起使用,您可以将其与许多不同的椭圆曲线一起使用。

    ECDSA 是一种签名算法,可用于对一条数据进行签名,使得对数据的任何更改都会导致签名验证失败,但攻击者将无法正确重新签署数据这样的变化。它是 DSA(数字签名算法)的一种变体。 ECDSA 代表椭圆曲线数字签名算法。此外,ECDSA 仅描述了一种可用于不同椭圆曲线的方法。” -Mecki

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-10-01
      • 2022-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多