Encryption

RSA 私鑰剖析

  • January 11, 2021

我正在學習OpenSSL公鑰基礎設施,並對 RSA 密鑰的結構以及它與相應公鑰的關係感到好奇。

我可以使用 OpenSSL genrsa 命令生成一個私有 RSA 密鑰:

$ openssl genrsa -aes128 -out fd.key 2048
Generating RSA private key, 2048 bit long modulus
....+++
......................................................................................
+++
e is 65537 (0x10001)
Enter pass phrase for fd.key: ****************
Verifying - Enter pass phrase for fd.key: ****************

我知道在生成私鑰時需要考慮三個因素:

  1. 算法
  2. 尺寸
  3. 密碼

在這種情況下,我使用 RSA 算法,2048 位大小,並使用AES-128 加密來加密密鑰

我可以使用rsa 命令查看 RSA 密鑰的結構:

$ openssl rsa -text -in fd.key
Enter pass phrase for fd.key: ****************
Private-Key: (2048 bit)
modulus:
   00:b6:ae:03:fa:d5:ec:3d:7b:1e:a5:33:68:44:5f:
   [...]
publicExponent: 65537 (0x10001)
privateExponent:
   1a:12:ee:41:3c:6a:84:14:3b:be:42:bf:57:8f:dc:
   [...]
prime1:
   00:c9:7e:82:e4:74:69:20:ab:80:15:99:7d:5e:49:
   [...]
prime2:
   00:c9:2c:30:95:3e:cc:a4:07:88:33:32:a5:b1:d7:
   [...]
exponent1:
   68:f4:5e:07:d3:df:42:a6:32:84:8d:bb:f0:d6:36:
   [...]
exponent2:
   5e:b8:00:b3:f4:9a:93:cc:bc:13:27:10:9e:f8:7e:
   [...]
coefficient:
   34:28:cf:72:e5:3f:52:b2:dd:44:56:84:ac:19:00:
   [...]
writing RSA key
-----BEGIN RSA PRIVATE KEY-----
[...]
-----END RSA PRIVATE KEY-----

我還可以使用rsa 命令查看公鑰:

$ openssl rsa -in fd.key -pubout
Enter pass phrase for fd.key: ****************
writing RSA key
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyOYm8hJCi3vKLaud2YTU
O3glFfQUpJ6d4gXiWp//HkDQIvi2BFmvbUyHMh4XWLwPbmaX2dfJ5Aa8+ZIC9KCY
y96Gmbw+v75RzxHq5iFLnZNFhYM2zkMvUUjJs/UqunOL1OoEiC06hb85SBepKtnE
JUUKo/rtZ2Sj/pHvF0Wqu1hLyR3iOxdJb26+m2IhOy4wB3HI6FBcvrMd4Hmejpup
skIRhTQXkV7XQ79yRCTS3ejiGoVvkPKzWxL+OFWOJTduXAk8McMLEozSGZll8bv7
jJUWLhmegvokKS2eLfA4B16yU59EgNbvuoG5doKUeV0LJ03Iiqv81nFB9SqEG/Xe
VQIDAQAB
-----END PUBLIC KEY-----

十六進制維基頁面

一個十六進制數字代表一個半字節(4 位),它是八位字節或字節(8 位)的一半。

我很好奇的一些事情:

  • 哪些數字對應於 2048 位長度?它是素數,指數,係數……?
  • 公鑰與私鑰有什麼關係?它是從數字中計算出來的,還是嵌入在私鑰中?

通過閱讀另一個答案,聽起來 2048 長度對應於模數。

但是,當我計算長度時,我得到 2056:

$ echo "00:b6:ae:03:fa:d5:ec:3d:7b:1e:a5:33:68:44:5f:d0:6a:0b:b5:87:31:80:a0:50:32:b0:7c:73:4b:f8:a2:03:91:89:c2:11:32:69:2e:13:90:71:f6:a9:48:21:00:c5:ad:1c:93:f0:21:27:ce:ca:15:04:53:30:c6:88:7b:45:c0:f2:01:d5:a7:9e:c1:c5:f2:ae:b0:7f:31:68:b7:3c:c3:62:13:eb:40:25:a9:3f:cd:81:90:9f:a1:3f:02:84:d8:6e:73:d2:5d:53:28:cc:97:35:f6:fa:5c:b7:dc:11:fb:60:08:1b:75:f7:74:dc:24:29:3e:ff:fb:ba:dc:77:2c:48:0d:3b:a1:7b:d9:9a:3d:52:7d:9a:d6:c1:f1:e7:46:df:be:75:b0:d2:0f:d2:1c:7b:25:57:94:33:8f:d5:b3:ee:7f:30:98:a9:06:25:b5:ab:b1:a6:ab:f9:f2:52:b8:e7:8f:87:5f:6d:96:36:67:47:38:4c:ef:29:c7:71:e4:07:7c:13:19:3a:e2:b4:3c:85:18:32:77:a6:98:0e:0d:b4:70:01:75:79:de:e9:83:c5:df:41:2f:69:f6:30:8d:13:29:84:9a:84:3a:c0:6a:4c:0d:bd:cd:9b:1e:93:de:8e:c9:a4:02:b7:0f:a2:96:45:ad:b8:3e:3a:d3:fd:4d" | tr ':' '\n' | wc -l
257

每行包含 2 個十六進制數字

257 * 2 = 514

每個數字包含 4 位

514 * 4 = 2056

加起來不應該是2048嗎?

哪些數字對應於 2048 位長度?它是素數,指數,係數……?

實際上只有模數 - 根據定義,密鑰大小與模數大小相同。對於使用 2 個素數的計算,素數通常是密鑰大小的一半(多素數 RSA 速度更快,並且在採用)。私有指數可能達不到完整的密鑰大小;它介於 0 和模數(不包括)之間。大小很有可能與字節模數相同或略小。

公鑰與私鑰有什麼關係?它是從數字中計算出來的,還是嵌入在私鑰中?

它是在密鑰對生成過程中計算出來的——其輸出既是私鑰也是公鑰。私鑰和公鑰共享相同的模數。通常由特定工具(如 OpenSSL)生成的私鑰包含公共指數,因此如果您有私鑰,您也可以提取/使用公鑰。

通常,公共指數是一個已知的小值——例如費馬的第四個素數:0x010001。但由於情況可能並非如此,因此公共指數(以及公共密鑰)通常不是從私鑰組件計算出來的。如果公共指數的大小與私有指數的大小相同,則您無法根據私鑰值計算它。

通過閱讀另一個答案,聽起來 2048 長度對應於模數。但是,當我計算長度時,我得到 2056 …

ASN.1 / DER 編碼的 INTEGER 值是有符號的,大端。由於始終設置正模數的最高有效位 - 假設密鑰大小可被 8 整除 - 它總是用填充字節設置為左填充模數00。否則,編碼將在所謂的二補碼編碼中表示負值- 最高有效位被視為符號位:0 表示正數表示,1 表示負數表示。

所以模數八位字節的有符號編碼是 2048 + 8 位或 257 字節。但是模數的位長(在大多數程式 API 中被稱為)仍然是 2048。


請注意,OpenSSL 顯示了使用中國剩餘定理加速 RSA 計算所需的生成參數。原則上,私鑰也可以僅由私有指數和模數組成。

引用自:https://crypto.stackexchange.com/questions/45151