ASN.1 格式的 RSA 私钥 PEM 包含额外字节

RSA Private Key PEM in ASN.1 Format Contains Extra Bytes

我正在查看 PEM 格式的 RSA 私钥。当我解码 base64 字符串并查看密钥的组成部分时,其中一些有一个额外的字节,特别是模数、P、DP 和 IQ。它们都有一个前导 0x00 字节。我通过将 byte[] 缩减到 256 或 128 的预期长度来处理这个问题,这样我就可以将它们与 .NET RSAParameters 和 RSACryptoServiceProvider 一起使用,但我想知道为什么这些 INTEGER 结构中的一些有额外的字节而其他的没有.看起来在线和其他将 PEM 解码为 XML 等的库可以很好地处理这个问题,RFC 的这一部分也是如此,只是你必须防止的东西,或者只是一个问题,因为我正在使用解码后的 .NET 库?下面是一个 257 字节模数的例子:

00 B7 55 AA 3F 14 89 BC CE ED AF 80 1C 54 2A DF 
AB 3C 6A 44 B4 55 58 90 0E 0D 32 96 E6 EF 35 2D 
AD B7 44 A7 AB CE 6F D3 BB 9D B4 4B FD 0A DE 87 
96 03 55 23 81 49 FE 1B 3E CE 62 B6 2F B1 4C 33 
E4 F8 C2 09 5F 0E 10 78 22 D0 F3 C9 BF B9 AC AC 
11 00 17 28 09 23 10 D5 8A C9 2B E2 86 96 A7 E2 
57 68 D7 3B 63 BE 74 ED B8 02 E2 63 EF F5 40 85 
0C A6 9F D0 B6 88 36 8B 4E 6B 35 27 BE 11 CC C8 
C3 0A 66 25 E0 AB B6 DD 6D E6 2B AF 9E 1C D7 11 
CE 5F E7 C8 1F EB 3D 79 B3 B2 E1 FF D8 20 6D 76 
A2 43 9E 20 67 58 97 39 46 D8 73 F6 F0 76 01 E0 
61 8E 4A EE C4 03 A6 44 C7 D3 50 E3 C8 62 CF 33 
D1 37 6B 85 F5 D4 3C 6D 1F 1A 14 B3 30 B5 E0 82 
A5 94 83 4F 7A 17 DA 86 2B F7 2A 47 A3 5F D2 D5 
7B 96 32 86 27 5E 2A 6A 85 6E C6 24 15 A9 09 65 
BB 04 8C 0D 39 F7 15 D4 F0 F8 5F 0F B0 1D A7 2F 
D7

下面是未用前导 0x00 填充的 "D" 参数示例:

04 07 EF 8A 5D 88 3D C7 8B 00 5D DF C1 96 03 BE 
FF 20 1D 0C A8 07 BF 7B 1F 9D 2A 26 3F C2 3A 93 
E4 40 B5 33 18 E1 EA 94 E8 7D C0 61 EF F8 3E A0 
F4 C7 CD 75 0D 4C 72 0A EA 7C CF 26 B3 4E 4A A1 
D1 3A 6A FA 55 11 D5 A2 66 57 C5 EA DA 49 4A AB 
41 06 41 52 1A 1C 47 A5 BA 90 A5 75 72 20 94 E0 
79 24 AA 60 A2 12 6E 1B AA AC 91 A7 F8 0B 88 21 
64 14 85 81 4D F3 6D 12 B7 56 BE DD F6 04 3B B1 
CC 95 A6 8C 9D A6 8D BF 05 C1 72 A4 0B 03 75 F6 
40 B6 8E 25 91 3D 87 84 CD 23 EF 2C 29 13 DD A7 
75 6E 48 F4 DE 49 98 4F B7 09 CF 5A A3 F5 39 05 
37 C8 2B 79 64 F0 B8 AD 11 EF 79 FD 78 C0 6B 2B 
50 7F DE BC 59 3D D1 A1 90 59 B7 7E 57 B4 2C A0 
D2 20 D2 D6 7C 4A B3 3C 63 5D FA E6 67 18 58 AC 
F3 EF 0E E1 C0 C9 B6 D9 8C D1 8E 3D CE 8A FF F0 
12 BF C2 FE 72 DC 07 E4 3C 00 5B BE 05 D9 5A 61 

以及不带前导0的DP参数:

3E 50 B2 28 A3 B1 71 F3 D5 31 B1 2D FD B3 60 4B 
57 F8 C1 46 C7 89 B7 95 F4 7D AE 54 F2 EA 11 98 
F7 61 93 30 50 D9 24 19 BF 7F 06 19 DB 97 01 06 
8B 20 D7 7A 5E 1A FA 76 9A 0E 27 46 AB FF 25 3C 
74 61 E2 9B 3E CE A5 F9 58 40 70 15 94 F2 58 3E 
DB E4 90 91 3C 50 B0 24 8F C7 A7 55 EB E3 59 A7 
5D 01 19 29 4F F9 F9 E6 EB 78 D1 93 14 61 E4 5C 
36 D7 E7 82 58 E7 C5 60 21 F3 1E 5A D4 49 C6 D1 

RSA模数为正数,ASN.1整数均有符号。

因此,如果前导 0x00 不存在,则此字节编码将表示一个负数,因为第一个字节将设置高位 (0xB7 >= 0x80)。因此,0x00 被插入到 DER 数据流中。

.NET 的表示基于 Windows CAPI 表示。 CAPI 使用领域知识知道值都是无符号整数,然后省略前导 0x00 字节。因此,由在 DER 数据和 .NET/CAPI 数据之间进行转换的人根据需要添加或删除字节。

这些值被编码为 INTEGER ASN 类型,它使用两个补码表示法。也就是说,如果最高有效位设置为 1,则该数字为负数。但是,key 中的所有数字(模数、指数、素数)都是正数,并且在前面加上额外的前导零八位字节来表示正整数。如果最高有效位已设置为 0,则不会添加额外的字节。