
我使用 OpenSC 工具在智慧卡上產生了一對 RSA 金鑰,並將其檢索為使用 DKEK 金鑰加密的包裝金鑰 blob:
sc-hsm-tool --create-dkek-share dkek/dkek-share-1.pbe
sc-hsm-tool --create-dkek-share dkek/dkek-share-2.pbe
sc-hsm-tool --initialize --dkek-shares 2
sc-hsm-tool --import-dkek-share dkek/dkek-share-1.pbe
sc-hsm-tool --import-dkek-share dkek/dkek-share-2.pbe
pkcs11-tool -l --pin 123456 --keypairgen --key-type rsa:2048 --id 11 --usage-sign
sc-hsm-tool --wrap-key wrap-key.bin --key-reference 1
我省略了命令的輸出,因為一切都按預期進行。
我現在在文件中擁有加密金鑰wrap-key.bin
以及 dkek-shares 和關聯的密碼。
我發現了很多教程,如何在新的智慧卡上載入此金鑰(一個明顯的例子:https://github.com/OpenSC/OpenSC/wiki/SmartCardHSM),但我沒有,我仍然需要使用密鑰。
我怎麼才能取回它?由於 DKEK 是 256 位元 AES 金鑰,並且我擁有所有關鍵元件,因此應該可以實現,但我不知道如何實現。我假設我首先需要從共享中重建 AES 密鑰,然後從wrap-key.bin
文件中檢索密鑰數據(文件的某些部分是純文本,所以我認為並不是整個文件都被加密),但我找不到任何有關的信息它在任何地方。
編輯:wrap-key.bin
以 ASN.1 格式編碼。我懷疑加密部分開頭是一個八位元組字串,但是沒有密鑰我無法驗證它。
EDIT2:DKEK 部分根據 OpenSSL salted 格式進行格式化http://justsolve.archiveteam.org/wiki/OpenSSL_salted_format但我無法透過簡單地提供密碼來解密它們。也許需要某種形式的與卡片的交互,但我對此表示懷疑。如果是這樣的話,這將如何允許在與舊卡無關的全新卡上載入金鑰?
答案1
在 CardContact 的 Andreas Schwier 的幫助下,我成功解決了這個問題。
第一步是隔離包裝金鑰的加密部分。
您可以使用 openssl 實用程式輕鬆實現它:
[user@localhost opensc]$ openssl asn1parse -in wrap-key.bin -inform der
0:d=0 hl=4 l=1692 cons: SEQUENCE
4:d=1 hl=4 l= 971 prim: OCTET STRING [HEX DUMP]:65623B6828FE1D530C174687AF81978BC12FAB3A1AAF4D4A05FBD1E41D145E15A7D1B4A32CC1A801711B5B1A5CAC98FE8DEFF2DAB46FB72EA0DCDC10BF169EB19FE155A171378E33ED518D1BD9A2ADD75C822E033D4BB308D4EE9665E66B37F32342F1751A59141B48BF450A877F477B3E9EDBC467CE59CDD7AC08949494B2FD4D2B009F61F9F71FF55DD7579160C5A01CF1E38F50D71A8994E53F359EB9D506B481955802C27319763211EFA6490FB6CB92595D70E5162535167314703877842490FDB549D1ABC16E201838F560A951BEF5768DA273272A6233B4B951BFA9C7FD15AB69B11027435E8DC19F339FD36F1393E10404BA794CCE0D57311C2519F915F5D6A3C7C2F3E5859D784FC4C58B66F2C195D27EF11F8D6266C16C852A806EFB5B055BE6D1E44D791A0991B1AC211D4BD621CFCCC67E033260BA1DB299EEAAADBFE8ECF7EE2641BA87FACD18436D8BDE42DA4061078FC3986F4AC04B2914FE343A9484CE28D32D40444378AC8D97B38701AF47379A50388EDCD18556D6472C725F581D0FD04D538394B6E209B120590C6C1977DA998FCA40470DC14E812DD7AC62C50EBB301D644E741F7E13E122B3F23712F4992E6EC7581A4E41B247BFDC7D1CF8AC41D13190F9D7B52C082CA60DF89CE1CD284558B65FD1A318C45C0BD45DB0E40E1F2487425C2876F91A93C47510BEFD72C5E47ED923A3CD993E78BEB5C7907B7479B5430FF991EA047D7D81A2CC94887AF302D873DD1EC4D6606F3067794C1F521D27D8D88E53F25D200E3B62D6FC93C74E26E891F1689538C13514A8DA772821D364D53F8AC036C66EE4D1758F2DEA43E85506090CE29FEEBD65F874F698527895A692A7635FDEC8A44ECC2395650C80BA56516B70493300453327B268C3127EE0A7CF08E131A90A3430ECA955C78AE7411D211C1BC7DCF95CC6598FDB58B8A619E48AFD0D33D1D3B9F6F52280122D01DC914A0D612F2F2F7327DBF3D6060EA95E5491565CC1775E2A0750636AD42B2376C5ABC52DEA1AE71020EC55DF31AA8D58AAA61ED18994F36A7F1E97F1603D1C7A922D4309F73E81837B9AF64811F32170A3C0298C710176D5A97360F3FEB04C0B42C1E3265BEF9E09A20BDD2EEF6DDE40B686A534573C180A737D35B2765DA29974A23F1DD4AEE70781153582A36EE0253FDF9191A1F07E932332BA25C1D7BE59E813B1F0A27F526502F4ACBA6B508BBC30D1C1CCAF553B908F6BF41D6D466D6B43A6F35C1D47F54E839BCF1786705CB7C2BA3365B95244372246B4FC7FBCAE7F58D65601C48434BDE35731813860B4A9F9EB5F1B6E411AA39D2086C9237CF92702FE5159B29C3421F0064FB8B6E9F18735A95B0C13A1
979:d=1 hl=2 l= 46 cons: SEQUENCE
981:d=2 hl=2 l= 20 cons: SEQUENCE
983:d=3 hl=2 l= 11 prim: UTF8STRING :Private Key
996:d=3 hl=2 l= 2 prim: BIT STRING
1000:d=3 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:01
1003:d=2 hl=2 l= 10 cons: SEQUENCE
1005:d=3 hl=2 l= 1 prim: OCTET STRING [HEX DUMP]:11
1008:d=3 hl=2 l= 2 prim: BIT STRING
1012:d=3 hl=2 l= 1 prim: INTEGER :01
1015:d=2 hl=2 l= 10 cons: cont [ 1 ]
1017:d=3 hl=2 l= 8 cons: SEQUENCE
1019:d=4 hl=2 l= 2 cons: SEQUENCE
1021:d=5 hl=2 l= 0 prim: OCTET STRING
1023:d=4 hl=2 l= 2 prim: INTEGER :0800
1027:d=1 hl=4 l= 665 cons: appl [ 7 ]
1031:d=2 hl=5 l= 575 cons: appl [ 33 ]
1036:d=3 hl=5 l= 309 cons: appl [ 78 ]
1041:d=4 hl=3 l= 1 prim: appl [ 41 ]
1045:d=4 hl=2 l= 9 prim: appl [ 2 ]
1056:d=4 hl=5 l= 277 cons: appl [ 73 ]
1061:d=5 hl=2 l= 10 prim: OBJECT :0.4.0.127.0.7.2.2.2.1.2
1073:d=5 hl=4 l= 256 prim: cont [ 1 ]
1333:d=5 hl=2 l= 3 prim: cont [ 2 ]
1338:d=4 hl=3 l= 9 prim: appl [ 32 ]
1350:d=3 hl=5 l= 256 prim: appl [ 55 ]
1611:d=2 hl=2 l= 16 prim: appl [ 2 ]
1629:d=2 hl=3 l= 64 prim: appl [ 55 ]
[user@localhost opensc]$
開頭的長八位元組字串包含所需的資料。由於我不必多次隔離它,因此我只是從終端複製並貼上它。這個過程的自動化留給有野心的讀者當作練習。請注意,出於安全目的,我用隨機生成的位元組替換了實際資料。
為了破解數據,我使用了 SmartCard Shell 和 sc-hsm-workspace 腳本集。
智慧卡外殼可在此處取得:http://www.openscdp.org/scsh3/index.html
要取得腳本有點困難。您需要在智慧卡和支援驗證裝置的 Web 瀏覽器上載入 SSL 憑證。此處提供了更多說明:http://www.cardcontact.de/cdn/activation.html
一旦您有權存取聯絡人卡開發者網絡,您就建立了帳戶,並在管理員批准後,您可以下載 sc-hsm-workspace 腳本集。將其設定為 SmartCard Shell 的工作區目錄。
雖然這些腳本本身都不是解決方案,但所有必要的程式碼片段都可用。
不幸的是,原始程式碼提供了 withInformation contained in this script is confidential and released under NDA
子句,因此我無法發布完整的解決方案,但這個偽代碼應該足以輕鬆地重新建立它:
getEncryptedDkekShare() {
// Can be copy-pasted from keymanager.js
return encdkekshare;
}
getEncryptedDkekPassword() {
// Can be copy-pasted from keymanager.js
return pwd;
}
getDecryptedDkekShare(encdkekshare, pwd) {
// Can be copy-pasted from SmartCardHSM.js,
// please note that you should change line sending
// decrypted data to SmartCard to simple return
return plain.left(32);
}
// The following part can be obtained from decrypt_keyblob.js
dkekshare1= getDecryptedDkekShare(getEncryptedDkekShare(), getEncryptedDkekPassword());
dkekshare2= getDecryptedDkekShare(getEncryptedDkekShare(), getEncryptedDkekPassword());
dkek = new DKEK();
dkek.importDKEKShare(dkekshare1);
dkek.importDKEKShare(dkekshare2);
keyblob = new ByteString("65623B..."); // Encrypted data obtained from wrap-key.bin
dkek.dumpKeyBLOB(keyblob);
安全警告:金鑰將以明文形式轉儲到控制台。
我希望答案提供足夠的資訊來滿足 StackExchange 的高標準而不違反 NDA。我懷疑類似的解決方案可以從 OpenSC 庫的免費開源程式碼衍生出來,但使用 sc-hsm-workspace 腳本被證明是簡單、快速且方便的。