前幾天領導找我要一個base64編碼的RSA密鑰(之前某個項目的),即pkcs#1或pkcs#8密鑰格式,解析密鑰格式的der編碼后,發現需要 e n d p q dQ dp invQ 共八個參數,而我只有 e n d 三個參數,一下子有點束手無策,今天突發奇想,之前在python應用rsa密碼算法時,我不也只給了 e n d 就能計算么,是否就說明我遺漏了解題的重要部分,於是,隨着這一靈感進行摸索,最終我實現了領導的需求。
准備RSA密鑰對
利用網站工具生成 RSA 密鑰對,http://web.chacuo.net/netrsakeypair
pubkey:30819f300d06092a864886f70d010101050003818d0030818902818100cd39d6697f1f09b44663065ab02fa8693e80df3cc42682494f43d48b54bd3d8b9439bfaf93f84ecd9938359f355a7e1d50e0de9144813b7402299793e11e1a8eb8ae78a62c94827fb648244aa5ebb62d6b5e1d297379147e4484bf882457404351a3791405d0d1627eff035f82fd79bf15cef4b00cfc1e92e5787937e5d3f1c70203010001
prikey:30820276020100300d06092a864886f70d0101010500048202603082025c02010002818100cd39d6697f1f09b44663065ab02fa8693e80df3cc42682494f43d48b54bd3d8b9439bfaf93f84ecd9938359f355a7e1d50e0de9144813b7402299793e11e1a8eb8ae78a62c94827fb648244aa5ebb62d6b5e1d297379147e4484bf882457404351a3791405d0d1627eff035f82fd79bf15cef4b00cfc1e92e5787937e5d3f1c702030100010281804fed5aa833ae2ee55b146e011be533bde96ddf8397113864bcce3a1519a7aa349641f779b6335add8ff2e84f5d442521ddc1f66cb5356fa63ac1601b63ed8981a1b94f0e5295362309ecc8a698d66a491392b60984d810f3efce4803c89c391a1b22afd2bfefc41d2b4b25fde10130f50e02a069e9053c14cee7bd9d2a9a4081024100e5e8e966a5f8e0c8dea885ad5a46919694f86a25a1d6b3b2c035084ed7da37c8b45a5b75c378ecbb4b9d269deec9c1c84f67ed10a77045f6ea06346ea273c537024100e483d62eb31088135b3748b9c3df343da25325e9e9c524b2507ed13d8b8e3a1f806453af311b649faa0d28735b528cef0ad94e06baa5c08471454a3bb8877ff1024100874854c66cd51457be04c59beaa9e993049763c63f0399fb8d73e72e957eb72267555fc9dcba73fa0595341aec5e55a36b6e08a5ab10ba6a7eec25c00fe1356302406fd8ab638e17605301096d1a2769bf3b0f915cf4418c51aac945590aa39cc88c149e866b3040f51e44f04dc5308496208611d863e8c52a16690e7e07ff08ab31024006e310c6765f86e53cbf05d0db79a9e28e12c1737152650acb7963d9660193b97daf96d1e4b545d5754b8d34a708016a23399a99e1cb811d2e6f4c204ae218c6
解析 pkcs#8 得到 e n d p q u dp dq qp u
30 820276
0201 // Version
00
300d // PrivateKeyAlgorithmIdentifier
06092a864886f70d0101010500
04820260 // PrivateKey
3082025c
0201
00
028181 // n
00cd39d6697f1f09b44663065ab02fa8693e80df3cc42682494f43d48b54bd3d8b9439bfaf93f84ecd9938359f355a7e1d50e0de9144813b7402299793e11e1a8eb8ae78a62c94827fb648244aa5ebb62d6b5e1d297379147e4484bf882457404351a3791405d0d1627eff035f82fd79bf15cef4b00cfc1e92e5787937e5d3f1c7
0203 // e
010001
028180 // d
4fed5aa833ae2ee55b146e011be533bde96ddf8397113864bcce3a1519a7aa349641f779b6335add8ff2e84f5d442521ddc1f66cb5356fa63ac1601b63ed8981a1b94f0e5295362309ecc8a698d66a491392b60984d810f3efce4803c89c391a1b22afd2bfefc41d2b4b25fde10130f50e02a069e9053c14cee7bd9d2a9a4081
0241 // q
00e5e8e966a5f8e0c8dea885ad5a46919694f86a25a1d6b3b2c035084ed7da37c8b45a5b75c378ecbb4b9d269deec9c1c84f67ed10a77045f6ea06346ea273c537
0241 // p
00e483d62eb31088135b3748b9c3df343da25325e9e9c524b2507ed13d8b8e3a1f806453af311b649faa0d28735b528cef0ad94e06baa5c08471454a3bb8877ff1
0241 // dq
00874854c66cd51457be04c59beaa9e993049763c63f0399fb8d73e72e957eb72267555fc9dcba73fa0595341aec5e55a36b6e08a5ab10ba6a7eec25c00fe13563
0240 // dp
6fd8ab638e17605301096d1a2769bf3b0f915cf4418c51aac945590aa39cc88c149e866b3040f51e44f04dc5308496208611d863e8c52a16690e7e07ff08ab31
0240 // Qinv(u)
06e310c6765f86e53cbf05d0db79a9e28e12c1737152650acb7963d9660193b97daf96d1e4b545d5754b8d34a708016a23399a99e1cb811d2e6f4c204ae218c6
根據 e n d 生成 p q u
依賴 pycrypto 庫
from Crypto.PublicKey import RSA
key_para = (int('cd39d6697f1f09b44663065ab02fa8693e80df3cc42682494f43d48b54bd3d8b9439bfaf93f84ecd9938359f355a7e1d50e0de9144813b7402299793e11e1a8eb8ae78a62c94827fb648244aa5ebb62d6b5e1d297379147e4484bf882457404351a3791405d0d1627eff035f82fd79bf15cef4b00cfc1e92e5787937e5d3f1c7', 16),
int('010001', 16),
int('4fed5aa833ae2ee55b146e011be533bde96ddf8397113864bcce3a1519a7aa349641f779b6335add8ff2e84f5d442521ddc1f66cb5356fa63ac1601b63ed8981a1b94f0e5295362309ecc8a698d66a491392b60984d810f3efce4803c89c391a1b22afd2bfefc41d2b4b25fde10130f50e02a069e9053c14cee7bd9d2a9a4081', 16))
a = RSA.construct(key_para)
print('p = ' + hex(a.key.p))
print('q = ' + hex(a.key.q))
print('u = ' + hex(a.key.u))
輸出結果
p = 0xe483d62eb31088135b3748b9c3df343da25325e9e9c524b2507ed13d8b8e3a1f806453af311b649faa0d28735b528cef0ad94e06baa5c08471454a3bb8877ff1
q = 0xe5e8e966a5f8e0c8dea885ad5a46919694f86a25a1d6b3b2c035084ed7da37c8b45a5b75c378ecbb4b9d269deec9c1c84f67ed10a77045f6ea06346ea273c537
u = 0x6e310c6765f86e53cbf05d0db79a9e28e12c1737152650acb7963d9660193b97daf96d1e4b545d5754b8d34a708016a23399a99e1cb811d2e6f4c204ae218c6
總結
(1)通過該接口生成 p q 后(原理后續再研究),再通過兩個公式即可生成 dp dq,這樣一來,就可以實現僅有 e d n 的情況下,組裝為 pkcs#8 格式的key文件了。
dp=d(mod(p-1))
dq=d(mod(q-1))
(2)我是屬於誤打誤撞實現的,在撰寫該文章的過程中,在谷歌搜索 rsa dp dq 發現一個名為《Key Recovery Method for CRT Implementation of RSA》的pdf文檔,在里面看到計算 dp dq 的公式,這才解決了最終的轉pkcs#8的問題,說明我在遇到問題的時候沒有先整理頭緒的習慣,這樣不好,會浪費時間,因為我能遇到的問題基本都已有前輩遇到甚至解決,在密碼學中,我遇到的問題其實是涉及了密鑰恢復的研究,之所以叫恢復而不是攻擊,是根據我是否擁有私鑰為准,沒有私鑰,那就是密鑰攻擊。