Elliptic-Curves

ECC 密鑰是如何儲存的?

  • March 3, 2021

我試圖弄清楚用於儲存 ECC 公鑰和私鑰的典型格式和大小等是什麼。

一些快速研究出現了 X9.62 (我無權訪問)和SEC1。但是還有 X.690 ,其中包括DER,當然還有ASN.1。我們不要忘記PEM

如果有人可以闡明這些事物之間的關係以及常用的內容,我認為這將是有用的。

概括地說,我試圖回答的問題是:我需要實施什麼來體面地支持 ECC。這將包括 ECDH 和通過網路將公鑰傳輸到 TLS 或 SSH 實現,還包括導入和導出使用其他工俱生成的密鑰。

有點相關:ECDSA 的公鑰格式,如 FIPS 186-4 中的?

通過網路將公鑰傳輸到可能的 TLS 或 SSH 實現,還可以導入和導出使用其他工俱生成的密鑰。

TLS有自己的用於臨時公鑰的有線格式,遵循 TLS 其餘部分中使用的編碼樣式。對於(更新的)1.2 及以下版本,請參閱rfc8422 5.4(和 5.4.1),它具有現已過時的 1 字節格式說明符、1 字節曲線標識符以及用於 X9/NIST 曲線的 X9.62 未壓縮格式的點( 5.4.1 中重述的定義)或來自 rfc7748 的 X25519 和 X448 的固定格式。對於 1.3,這實際上是相同的,只是格式消失了,並且“曲線”標識符已擴展為“組”標識符;請參閱 rfc8446 4.2.8 ,尤其是 4.2.8.2。對於實踐中的靜態密鑰,TLS(所有版本)使用包含 ASN.1 中的 SubjectPublicKeyInfo 的 X.509/PKIX 證書,如Conrado所述. (從技術上講,TLS 不需要 X.509,但實際上沒有人使用其他任何東西。)

對於私鑰,OpenSSL(以及許多基於它建構的東西,比如 nodejs PHP python)可以使用 SEC1 ASN.1 格式(也在rfc5915中複製)或 PKCS8,通常僅在 PEM 中(libcrypto 支持 PEM 和 DER,但 libssl 使使用 PEM 更容易);我知道的大多數其他實現都使用PKCS8/rfc5208和/或PKCS12/rfc7292,前者通常是 DER,但有時是 PEM,而後者總是 DER。NSS 和 Windows (schannl) 都有自己的密鑰庫格式,但可以為“自己的”證書和私鑰導入和導出 PKCS12,為“其他”證書導入和導出 X.509,Java 可以做到這一點,直到 2017 年才推薦它。

SSH同樣具有自己的用於臨時(密鑰交換)和靜態(身份驗證)公鑰的有線格式,使用 SSH 的類似 XDR 的編碼。對於 3 條最流行的 X9/NIST 曲線,請參閱rfc5656 第 3 節;在實際包含曲線名稱的身份驗證“算法”名稱之後,有一個值被描述為 SEC1 公鑰(與 X9.62 點相同,但刪除了不必要的混合選項),並且在第 4 節中類似地每個密鑰交換方法指定一條曲線,因此一旦協商特定方法,密鑰交換消息僅包含點 Q_S 和 Q_C。用於 EdDSA 認證rfc8709曲線標識符再次包含在“算法”名稱中,其單個值是來自 rfc8032 的 Edwards 的固定格式中的點;對於 Bernstein-X 密鑰交換 rfc8731類似,但使用來自 rfc7748 的 Montgomery 的固定格式。

OpenSSH 可以將 X9/NIST 的私鑰處理為 PEM 中的 OpenSSL“傳統”(即 SEC1)或 PKCS8,或者 OpenSSH 自己的“新”格式,看起來像 PEM,但內部是 XDR 樣式而不是 ASN.1;對於 Ed25519,它只能使用最後一個(伯恩斯坦算法沒有 OpenSSL 傳統格式)。為與 OpenSSH 兼容而編寫的其他一些東西通常可以做同樣的事情,但並不總是完全同步。一個值得注意的例外是 Putty(以及 WinSCP 和 FileZilla),它有自己不同的“PPK”格式,但 puttygen 實用程序可以在 OpenSSH 格式和 PPK 之間進行轉換。我不了解 Tectia,儘管 puttygen 可以導出它聲稱與 Tectia 兼容的文件,您可能會看到這些文件。

OpenPGP有自己的格式,用於加密消息中的靜態密鑰(以發布/傳輸形式)和臨時公鑰,使用 PGP 的數據包編碼樣式;對於 NIST/brainpool,請參閱rfc6637,主要是第 9 節和第 10 節。它使用 OID(嵌入在 PGP 欄位中)來辨識公共 SEC1/X9.62 點和私有標量所使用的曲線和 PGP 格式的“數字”。GnuPG 也支持 Ed25519 和 X25519,但是我沒有找到任何關於它們的文件;--list-packets顯示了一個公共欄位,大概是 263 位或 33 字節的點,比 rfc7748 和 rfc8032 格式多一個。

**S/MIME(和 CMS)**使用 X.509 證書作為公鑰;實現可能因私鑰而異。

XMLDSIG現在(v1.1v2)將 ECDSA 公鑰的顯式表示定義為一個 XML 結構,其中包含曲線 OID 的 URI 和實際上是 X9.62/SEC1 未壓縮點的 base64,雖然沒有這樣標識,但是較早的版本rfc4050使用 XML 將 X、Y 分別表示為數字 $ F_p $ 曲線(和十六進制 $ F_{2^m} $ 曲線,最初被認為是一個好主意,但現在幾乎每個人都放棄了)。XMLENC v1.1將其重用於 ECDH。然而,這兩個標準都支持提供或引用密鑰的其他幾種方式,包括傳輸實際的 X.509 證書或提供允許獲取或選擇一個的引用,其中 IME 更常用(或幾年前)。端點中使用的私鑰可能會有所不同。

JSON Web 算法 ( JWA ) rfc7518 第 6.2 節為所選 X9/NIST 曲線上的 EC 公鑰定義了基於 JSON 的表示,可用於 JSON Web 密鑰 (JWK) rfc7517,後者又用於 JSON Web 簽名、加密和代幣。JWK(因此 JWS JWE JWT)可以改為使用 X.509 證書,在這裡我不知道在實踐中選擇了哪些選項,或者端點對私鑰做了什麼。

PKCS11 主要使用 X9.62 編碼的密鑰,但其他硬體設備可能會有所不同;但是,它們都被設計為僅限本地介面,因此可能不符合您的標準。

libsodium(如評論)僅支持 Ed25519 和 X25519 並為它們使用“裸”鍵格式;同樣, Signal僅使用裸 X25519。 比特幣最初使用裸 X9.62 點和 SEC1 編號(I2OSP),因為它不需要任何元數據來辨識 EC 或曲線(總是 secp256k1);它還為使用者界面創建了一個經過調整的帶有校驗和的 base58 編碼,當應用於 SEC1 私鑰(即無符號的 bigendian 數字)時,它被稱為錢包導入格式 (WIF)。在最早的日子之後,比特幣過渡到主要使用“地址”,這是一個雜湊公鑰而不是實際的公鑰,並且不能反轉,因此它作為一種表示並不有趣。隨著時間的推移,它還開發了更複雜的密鑰管理方案,這些方案使用幾種不同的表示來將實際的 EC 密鑰與各種相關數據結合起來。其他我不知道的加密貨幣。

這足以讓你開始嗎?

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