[英]C# - How to calculate ASN.1 DER encoding of a particular hash algorithm?
[英]How to generate two RSA for ASN.1 DER encoding their modulus with and without padding (bug in sample code?)
我的问题基本上如下:
如何生成两种 2048 位 RSA 密钥,以便它们的无符号大端模数在进行 ASN.1 DER 编码时需要前缀为0x00
而另一种不需要?
我有代码片段和解释我在下面尝试做的事情。 所以,我尝试这样做的原因和我使用的方法。
我把它作为一个上下文,因为我在生成这样的一对时遇到了问题,可能是我误解了一些东西。 也可能是这种情况下,对0x00
前缀的要求非常罕见,我没有设法通过随机生成来做到这一点(我不这么认为,但我不知道如何计算/估计它,我也不知道在网上找到了这样的例子)。
所以,我在考虑编码 2048 位 RSA 模数的 ASN.1 DER。 在 .NET(和许多其他框架)中,序列被编码为无符号大端字节数组。
这样做的一个实际结果似乎是,如果模数的第一个字节介于 0x00(十进制:0)和 0x7F(十进制:127)之间,那么在 DER“标题”之后将不会添加零字节。 否则添加一个 0x00 字节。 这样做是因为在 ASN.1 DER 编码中发生有符号整数,否则字节将被解释为负数(并且模数是无符号大端整数)。
一般来说,关于这个逻辑有一些很好的解释
https://crypto.stackexchange.com/questions/1795/how-can-i-convert-a-der-ecdsa-signature-to-asn-1
并且在
对dumpasn1
/ asn1playground稍加修改,以 crypto.stackexchange 中提供的示例并在此处修改从 ECDSA 到 RSA 的解释,我收集前缀为0x00
的模数情况的序列如下:
这里第5.
点是关键。 只有在设置了无符号模数数组的 MSB 时才会添加它。
或者,用代码术语来说,这就是我的样子
var key = RSA.Create(2048);
var parameters = key.ExportParameters(includePrivateParameters: false);
var modulus = parameters.Modulus!;
// See this check here assuming MSB is in first byte in the array and this checks if the MSB bit is set.
bool isModulusMsbSet = (modulus[0] & 0x80) != 0;
// See here choosing the first version of the same array and concatenating a leading 0x00
// if the MSB is set on unsigned, big endian modulus.
var prefix = isModulusMsbSet ? new byte[] { 0x30, 0x82, 0x01, 0xa, 0x02, 0x82, 0x01, 0x01 }.Concat(new byte[] { 0x0 }).ToArray() : new byte[] { 0x30, 0x82, 0x1, 0xa, 0x2, 0x82, 0x1, 0x1 };
为了更接近我的问题和问题的原因,我尝试生成非填充案例的代码:
RSA? key = null;
do
{
var testKey = RSA.Create(2048);
var parameters = testKey.ExportParameters(includePrivateParameters: false);
var modulusBytes = parameters.Modulus!;
// See here the checking of MSB is inverted from != to ==.
// I.e. accept this key only if 0x00 padding is not needed.
if((modulusBytes[0] & 0x80) == 0)
{
key = testKey;
}
} while(key == null);
但是这个循环永远不会停止! 在我看来,这似乎表明 MSB 总是设置的! 但不应该RSA.Create(2048);
偶尔创建一个可接受的密钥? 是否有另一个很好的案例来为填充案例生成测试材料?
我也部分地询问,因为我不确定是否应该在 ASN.1 DER 编码序言序列中考虑条件0x00
。
目前尚不清楚您要解决什么问题。 对我来说,您似乎正在尝试解决 XY 问题。
我不是最好的解释这些事情,我会尝试解释:
在我看来,这似乎表明 MSB 总是设置的!
这是意料之中的。 RSA 公钥大小除以 8,无需提醒(例如 512、1024、2048 等)。 结果,模数将消耗KeySizeInBits / 8
个字节,并且该整数中的所有位都表示模数。 由于整数忽略前导零(如十进制, 1
和001
表示相同的数字1
),模数的第一位(或 MSB)必须为 1。否则它被忽略,然后你的模数将不是 2048 位,它将是 2047 甚至更少,最长可达 2040 位。 这些是 RSA 公钥模数的无效长度(在没有提醒的情况下不会除以 8)。 将 RSA 模数想象成一个长位字符串,其中长度计数从设置为 1 的第一位开始。
只是一个非常说明性的例子。 这个位串需要多少位?
0 1 0 1 0 1 0 1
答案是 7,前导零位被忽略,计数从第一位开始1
。 并且 7 不会在没有提醒的情况下除以 8。 和这个:
1 0 0 0 0 0 0 0
正好是 8 位。 在 ASN.1 中,整数是两个补码值,当字节中的第一位为 0 时,整数为正,否则为负。 由于 RSA 模数中的 MSB 为 1,并且该数字是正数,因此作为编码的一部分,它在前面用零字节填充。 然而,这个零字节不是公钥的一部分,它是编码的一部分。
此外,模数是两个素数的乘积: N = p*q
。 并且产品总是奇数。 这意味着 RSA 模数的最后一位也将以 1 结尾。 所以对于 RSA 公钥,模数中的第一位和最后一位都设置为 1。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.