ECDSA 的 PEM 格式
我一直在查看Coinapult 的 API 文件,其中詳細介紹了 PEM 格式在*python-ecdsa*中的使用。具體來說,私鑰和公鑰需要使用 PEM 進行格式化。
讓我們使用 Coinapult 指定的公鑰:
-----BEGIN PUBLIC KEY----- MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEWp9wd4EuLhIZNaoUgZxQztSjrbqgTT0w LBq8RwigNE6nOOXFEoGCjGfekugjrHWHUi8ms7bcfrowpaJKqMfZXg== -----END PUBLIC KEY-----
使用 python-ecdsa:
vk = ecdsa.VerifyingKey.from_pem(ECC_COINAPULT_PUB) s = vk.to_string() s.encode('hex') >>> "5a9f7077812e2e121935aa14819c50ced4a3adbaa04d3d302c1abc4708a0344ea738e5c51281828c67de92e823ac7587522f26b3b6dc7eba30a5a24aa8c7d95e"
或者,如果它是比特幣公鑰,那就是
045a9f7077812e2e121935aa14819c50ced4a3adbaa04d3d302c1abc4708a0344ea738e5c51281828c67de92e823ac7587522f26b3b6dc7eba30a5a24aa8c7d95e
好的,這是有道理的,但是當我們在前導和尾隨之間獲取 base64 編碼數據時
-----BEGIN-----
:base64_data = "".join(ECC_COINAPULT_PUB[27:-26 ].split('\n')) s = base64.b64decode(base64_data) result = s.encode("hex") >>> "3056301006072a8648ce3d020106052b8104000a034200045a9f7077812e2e121935aa14819c50ced4a3adbaa04d3d302c1abc4708a0344ea738e5c51281828c67de92e823ac7587522f26b3b6dc7eba30a5a24aa8c7d95e" # WTF is this??
請注意,PEM 格式解碼為某種 DER 字元串,
3056301006072a8648ce3d020106052b8104000a034200045a9f7077812e2e121935aa14819c50ced4a3adbaa04d3d302c1abc4708a0344ea738e5c51281828c67de92e823ac7587522f26b3b6dc7eba30a5a24aa8c7d95e
但是這個 DER 字元串到底是什麼?我看到5a9f7077....a8c7d95e
在那個字元串中,那麼前導字節是什麼意思?問題: 1. 如何在不使用 python-ecdsa 的情況下將pubkey 編碼為 PEM 格式?2.私鑰與公鑰的過程是否相同?
#0 格式是什麼?****
SubjectPublicKeyInfo
正如您部分猜到的那樣,這是來自 X.509 的 ASN.1 類型的 DER 編碼的“PEM”裝甲,作為RFC5280 第 4.1 節特別是 4.1.2.7重新發布以供 Internet 使用。為了支持多種算法,包括將來的新算法,這個結構是一個SEQUENCE
標識AlgorithmIdentifier
算法的(使用OBJECT IDENTIFIER
算法和各種類型的參數,取決於算法),後跟一個BIT STRING
包含以某種格式編碼的鍵值的這取決於算法。特定於 ECDSA(和 ECDH)的 AlgId 和密鑰格式在RFC3279 第 2.3.5 節中,儘管您可以忽略關於ECParameters
因為實際上每個人都使用更簡單的namedCurve OBJECT IDENTIFIER
選項,而密鑰格式只是 SEC1/X9.62 點。這
301006072a8648ce3d020106052b8104000a
是 AlgId 並解碼為0:d=0 hl=2 l= 16 cons: SEQUENCE 2:d=1 hl=2 l= 7 prim: OBJECT :id-ecPublicKey 11:d=1 hl=2 l= 5 prim: OBJECT :secp256k1
(正如您已經知道的,“PEM”只是 DER 的 base64,有間隔的換行符,加上
----BEGIN whatever-----
頂部的-----END whatever-----
一行和底部的一行。)**#1 沒有 python 編碼?**除了自己實現(部分)DER(如果你願意的話,這並不難),我看到你連結到的頁面談論了很多關於 OpenSSL 兼容性:對於 C 或可以(輕鬆)呼叫 C 的語言的程序,這是許多,OpenSSL 可以生成、讀取、寫入和使用這種格式的 ECC 密鑰(以及未裝甲的 DER 形式)。Java 7+ 密碼學可以做到,但標準提供者僅在 DER 中;對於 PEM,您必須自己解除/解除裝甲或使用<http://www.BouncyCastle.org>反而。我希望 dot-NET 可以做到,但我不使用它,也不能肯定地說。我知道我已經看到了 DER 的 perl 模組,但不知何故,即使那是它的目的,我也永遠無法在 CPAN 中找到東西。如果您想要更具體的答案,請修改您的問題(或者如果它足夠不同,請提出一個新問題)。
**#2 私鑰?該頁面說它使用
-----BEGIN EC PRIVATE KEY-----
的可能是OpenSSL 中的兩種“傳統”格式之一:**未加密或加密。由於範例沒有顯示任何密碼,我將假設前者。如果您查看密鑰文件並看到行Proc-type
之後但在 base64 數據之前插入的行DEK-info
,則它是傳統加密的,並且更複雜。-----BEGIN
沒有它,它是由 C.4 中http://www.secg.org/的 SEC1 文件定義的私鑰結構,其中包含一個
OCTET STRING
用於私鑰(實際上是一個整數,但沒有這樣編碼),定義的參數在 C.2 中,如果您仔細檢查,它基本上等同於 RFC 3279 中的內容,並且再次BIT STRING
包含公鑰(一個點)。OpenSSL 還支持私鑰的“新”(大約 2000 年!)PKCS#8 格式。與用於公鑰的 X.509 SPKI 非常相似,這是一個通用包裝器,基本上是
AlgorithmIdentifier
算法加上OCTET STRING
包含取決於算法的密鑰值,除了 PKCS#8 還具有在 PKCS#8 級別進行加密的選項(相對於“PEM”級別)。我不知道 python 模組是否處理這些格式,如果沒有,您是否想使用它們從而與 python 模組不兼容。如果您不想使用 PKCS#8 並且確實想使用 OpenSSL,請小心使用特定的 EC 常式,而不是通用的常式。