【问题标题】:UWP ECDSP SignatureUWP ECDSP 签名
【发布时间】:2017-05-05 02:17:53
【问题描述】:

我想用这个代码做一个 ECDSA 签名:

AsymmetricKeyAlgorithmProvider objAsymmAlgProv = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.EcdsaSha256);
CryptographicKey keypair = objAsymmAlgProv.CreateKeyPairWithCurveName(EccCurveNames.SecP256r1);
BinaryStringEncoding encoding = BinaryStringEncoding.Utf8;
buffMsg = CryptographicBuffer.ConvertStringToBinary("Test Message", encoding);
IBuffer buffSIG = CryptographicEngine.Sign(keypair, buffMsg);
byte [] SignByteArray = buffSIG.ToArray();
bool res = CryptographicEngine.VerifySignature(keypair, buffMsg, buffSIG);

VerifySignature 总是返回 true,这没关系。

但是我的签名有些问题。

为什么签名长度 (SignByteArray) 是固定的? (0x40 字节)。

为什么SignByteArray [0]SignByteArray [2] 的值不正确? (我觉得应该是0x30和0x02)

我期待像https://kjur.github.io/jsrsasign/sample-ecdsa.html这样的东西

【问题讨论】:

    标签: c# cryptography uwp ecdsa


    【解决方案1】:

    ECDSA 规范最后确定这对(rs)是签名。它忽略了指出应该如何写下来。

    Windows 和 .NET 使用 IEEE (P)1363 格式,即 big-endian r concat big-endian srs 的大小相同(由密钥大小决定),因此签名的长度始终是偶数,而 r 是前半部分。

    OpenSSL 使用 ASN.1/DER 编码,即 SEQUENCE(INTEGER(r), INTEGER(s))。 DER 编码可以一直下降到 6 个字节(30 04 02 00 02 00,在简并 r=0,s=0 中),并且平均比 IEEE 形式大 6 个字节。它编码为30 [length, one or more bytes] 02 [length, one or more bytes] [optional padding 00] [big-endian r with no leading 00s] 02 [length, one or more bytes] [optional padding 00] [big-endian s with no leading 00s]

    DER 表单过于依赖数据,无法具体描述,因此举个例子应该会有所帮助。假设我们在 32 位字段中使用曲线并生成 (r=1016, s=2289644760)。

    IEEE 1363:

    // r
    00 00 03 F8
    // s
    88 79 34 D8
    

    DER:

    SEQUENCE(INTEGER(1016), INTEGER(2289644760))
    
    // Encode r
    // 1016 => 0x3F8 => 03 F8 (length 02)
    SEQUENCE(
        02 02
           03 F8,
        INTEGER(2289644760))
    
    // Encode s
    // 2289644760 => 0x887934D8 => 88 79 34 D8
    // But since the high bit is set this is a negative number (-2005322536),
    // and s is defined to be positive.  So insert a 00 to ensure the high bit is clear.
    //   => 00 88 79 34 D8 (length 05)
    SEQUENCE(
        02 02
           03 F8
        02 05
           00 88 79 34 D8)
    
    // And encode the sequence, whose payload length we can now count as 11 (0B)
    30 0B
       02 02
          03 F8
       02 05
          00 88 79 34 D8
    

    所以 Windows/.NET 发出 00 00 03 F8 88 79 34 D8,而 OpenSSL 发出 30 0B 02 02 03 F8 02 05 00 88 79 34 D8。但他们都只是说(r, s) = (1016, 2289644760)

    (旁白:您观察到 DER 编码中的 signature[2] == 0x02 对于您正在使用的大小密钥是正确的,但是在大约 496 位密钥处,从统计上看,SEQUENCE 长度可能需要超过一个字节;因此对于 P-521 密钥,它最有可能以 03 81 88 02 开头,88 字节的可变性)

    【讨论】:

    • 这正是我想要的!非常感谢!
    猜你喜欢
    • 2016-10-25
    • 2017-07-22
    • 1970-01-01
    • 2017-03-14
    • 1970-01-01
    • 2020-06-19
    • 2017-12-04
    • 2018-04-23
    • 1970-01-01
    相关资源
    最近更新 更多