Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ajax/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何将ECDSA DER编码的签名数据转换为microsoft CNG支持的格式?_C++_Cryptography_Elliptic Curve_Cng - Fatal编程技术网

C++ 如何将ECDSA DER编码的签名数据转换为microsoft CNG支持的格式?

C++ 如何将ECDSA DER编码的签名数据转换为microsoft CNG支持的格式?,c++,cryptography,elliptic-curve,cng,C++,Cryptography,Elliptic Curve,Cng,我正在准备一个微型驱动程序,使用Microsoft CNG的NCryptSignHash功能执行智能卡登录 当我在智能卡中使用SECP521R1 EC密钥执行签名时,它会生成长度为139的签名数据,作为ECC签名数据格式: ECDSASignature::=序列{ r整数, s整数 } 示例签名数据为 3081880242201A2001E9C0151C55BCAA188F201020A84180B339E61E6EAD0B277321CAB81C87DAFC2AC65D542D0B01C5E

我正在准备一个微型驱动程序,使用Microsoft CNG的
NCryptSignHash
功能执行智能卡登录

当我在智能卡中使用SECP521R1 EC密钥执行签名时,它会生成长度为139的签名数据,作为ECC签名数据格式:

ECDSASignature::=序列{
r整数,
s整数
}
示例签名数据为

3081880242201A2001E9C0151C55BCAA188F201020A84180B339E61E6EAD0B277321CAB81C87DAFC2AC65D542D0B01C5E25E9209C47CFDDFD5BCAFA0D2AF2E7FD86701024200C103E534BD1378D8B6F562FB058D5045615DCD9462ED0F923076EF581210DD95BF2891358F5F743DECA0608CEFA40AF4188A27F4
但当我使用
MS\u KEY\u STORAGE\u PROVIDER
执行签名时,它会生成一个长度为132字节的符号

将符号数据大小从139减少到132的步骤是什么

将符号数据大小从139减少到132的步骤是什么

您有一个ASN.1编码的签名(如下所示)。Java、OpenSSL和其他一些库都使用它。您需要P1363格式的签名,它是
r | | s
的串联,没有ASN.1编码。P1363由Crypto++和其他一些库使用。(还有另一种常见的签名格式,那就是OpenPGP)

对于
r | | s
的串联,
r
s
必须为66字节,因为八位字节边界上的secp-521r1字段元素大小。这意味着过程是,您必须剥离外部
序列
,然后剥离两个
整数
,然后将两个整数的值串联起来

使用样本数据格式化的
r|s
签名将是:

01 A2 00 1E ... 7F D8 67 01 || 00 C1 03 E5 ... 0A 26 A7 F4
Microsoft.Net 2.0具有ASN.1类,允许您操作ASN.1编码的数据。看


$echo 08188024201A2001E9C0151C55BCAA188F201020A84180B339E61ED61F6EAD0B277321驾驶室
81C87DAFC2AC65D542D0B01C3C5E25E9209C47CFDDFD5BBCAFA0D2AF2E7FD86701024200C103E5
34BD1378D8B6F5652FB058F7D5045615DCD940462ED0F923073076EF581210D0DD95BF2891358F5F
743DB2EC009A0608CEFAA9A40AF41718881D0A26A7F4 | xxd-r-p>signature.bin
$dumpasn1 signature.bin
0 136:序列{
366:整数
:01 A2 00 1E 9C 01 51 C5 5B CA 18 8F 20 10 20 A8
:41 80 B3 39 E6 1E DE 61 F6 EA D0 B2 77 32 1C AB
:81 C8 7D AF C2 AC 65 D5 42 D0 D0 B0 1C 3C 5E 25
:E9 20 9C 47 CF DD FD 5B BC AF A0 D2 AF 2E 7F D8
:     67 01
71 66:整数
:00 C1 03 E5 34 BD 13 78 D8 B6 F5 65 2F B0 58 F7
:D5 04 56 15 DC D9 40 46 2E D0 F9 23 07 30 76 EF
:58 12 10 D0 DD 95 BF 28 91 35 8F 5F 74 3D B2 EC
:00 9A 06 08 CE FA A9 A4 0A F4 17 18 88 1D 0A 26
:A7 F4
:   }
0个警告,0个错误。

另一项值得注意的内容是,.Net使用了中详述的XML格式。它的格式不同于ASN.1、P1363、OpenPGP、CNG和其他库

ASN.1到P1363的转换相当简单。您可以在上看到使用Crypto++库的示例


您可能会在Code Project中找到有用的信息。

您的输入是一种X9.62签名格式,它是一个包含两个ASN.1/DER编码签名的序列。这些整数是大小可变的有符号大端数。它们以最小字节数编码。这意味着编码的大小可能会有所不同

139字节是常见的,因为它假定
r
s
的编码的最大大小。这些值是使用模运算计算的,因此它们可以包含任意数量的位,最多可以包含顺序为
n
的位,这与密钥大小521位相同


132字节由ISO/IEC 7816-8/IEEE P1363规定,该标准是处理智能卡签名的标准。签名包括
r
s
的串联,其中
r
s
被编码为最小字节数,以字节为单位显示与顺序相同大小的值。
r
s
是静态大小的无符号大端数

r
s
的字节数的计算是
ceil((双)n/8)
(n+8-1)/8
,其中8是字节中的位数。因此,如果椭圆曲线是521位,那么结果大小是66字节,因此它们总共消耗132字节


现在开始解码。有多种处理方法:执行完整的ASN.1解析,获取整数,然后以最符合逻辑的ISO 7816-8格式重新编码

但是,您也可以看到,您可以简单地复制字节,因为
r
s
始终是非负的(因此是无符号的)和大端。所以你只需要补偿尺寸。否则,唯一困难的部分是能够解码X9.62结构中组件的长度


<强>警告< /强>:C++中的代码代替C++,如我所预期的.NET.NET语言;当我写答案的主要部分时,问题中没有指出的语言

class-ConvertECDSASignature
{
专用静态int字节\大小\位=8;
专用静态字节ASN1_序列=0x30;
私有静态字节ASN1_INTEGER=0x02;
公共静态字节[]lightweightConvertSignatureFromX9\u 62ToISO7816\u 8(整数顺序字节,字节[]x9\u 62)
{
整数偏移=0;
如果(x9_62[偏移量++!=ASN1_序列)
{
抛出新的非法签名FormatException(“输入不是序列”);
}
int sequenceSize=parseLength(x9_62,偏移量,输出偏移量);
int sequenceValueOffset=偏移量;
int nBytes=(orderInBits+字节大小\u位-1)/字节大小\u位;
字节[]iso7816_8=新字节[2*n字节];
//检索并复制r
如果(x9_62[offset++]