我的問題基本上如下:
如何生成兩種 2048 位 RSA 密鑰,以便它們的無符號大端模數0x00在進行 ASN.1 DER 編碼時需要前綴,而另一種則不需要?
我有代碼片段和解釋我在下面嘗試做的事情。所以,我嘗試這樣做的原因和我使用的方法。
我把它作為一個背景關系,因為我在生成這樣的一對時遇到了問題,可能是我誤解了一些東西。也可能是這種情況下,對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
并且在
.net 中 RSA 公鑰模數和指數的格式是什么?
使用dumpasn1/ asn1playground進行一些修改,以 crypto.stackexchange 中提供的示例并在此處修改從 ECDSA 到 RSA 的解釋,我收集帶有前綴的模數情況的序列0x00如下:
- 序列開始:0x30
- 序列長度:0x82 0x01 0x0a
- 整數標簽:0x02
- 模整數長度:0x82 0x01 0x01
- 模數前導零的整數:0x00
- [插入 RSA 模數位元組]
- 其他一些 DER 編碼位元組來結束序列
這一點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);偶爾創建一個可接受的密鑰嗎?是否有另一個很好的案例來為填充案例生成測驗材料?
我也在部分詢問,因為我不確定是否0x00應該在 ASN.1 DER 編碼序言序列中考慮條件。
uj5u.com熱心網友回復:
目前尚不清楚您要解決什么問題。對我來說,您似乎正在嘗試解決 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。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/474949.html
上一篇:c#中重寫屬性
