我正在使用命令openssl ecparam -name secp256r1 -genkey -noout -out k1.pem
创建一个私有EC密钥。我正在尝试使用crypto.subtle.importKey
导入它,如这份文件中所描述的。
也就是说,在运行OpenSSL之后,我有一个私钥
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIOuQ2Du5Q3bE0wzYwqImGjbb6zASbof36MVeRQMTfOA5oAoGCCqGSM49
AwEHoUQDQgAErSz9FIO1sLPciJjHbj/EduYNClaeCBhQuU5ZPh24YRvHG5FXLNiV
1dPIB02KyKXiYjvLro586uYDkYzaPkzbOw==
-----END EC PRIVATE KEY-----
从Chrome控制台
let binary = atob("MHcCAQEEIOuQ2Du5Q3bE0wzYwqImGjbb6zASbof36MVeRQMTfOA5oAoGCCqGSM49AwEHoUQDQgAErSz9FIO1sLPciJjHbj/EduYNClaeCBhQuU5ZPh24YRvHG5FXLNiV1dPIB02KyKXiYjvLro586uYDkYzaPkzbOw==")
let der = str2ab(binary)
let key = crypto.subtle.importKey(
'pkcs8',
der,
{
name: 'ECDSA',
namedCurve: 'P-256',
},
false,
['sign']
);
从最后一个命令中获得一个Uncaught (in promise) Error
。
值得一提的是,当我通过Clojure使用Java库生成EC密钥时,我可以使用相同的js代码成功地导入它:
(ns vouch.crypto
(:import (java.security KeyPairGenerator SecureRandom KeyPair)
(org.bouncycastle.jce ECNamedCurveTable)
(java.util Base64)))
(defn generate-ec-key-pair
"Generate an Elliptic Curve Key Pair"
^KeyPair []
(let [ec-spec (ECNamedCurveTable/getParameterSpec "secp256r1")
^KeyPairGenerator generator (KeyPairGenerator/getInstance "ECDSA" "BC")]
(.initialize generator ec-spec (SecureRandom.))
(.generateKeyPair generator)))
(defn bytes->hex
"Convert a seq of bytes into a hex encoded string."
^String [^bytes bytes]
(apply str (for [b bytes] (format "%02x" b))))
(defn- base64-encode
^String [^bytes bytes-to-encode]
(-> (Base64/getEncoder)
(.encode bytes-to-encode)
(String. StandardCharsets/UTF_8)))
(comment
(let [key-pair (vouch.crypto/generate-ec-key-pair)
private-key (.getPrivate key-pair)
private-key-base64 (-> private-key .getEncoded vouch.crypto/base64-encode)]
(println (str "-----BEGIN EC PRIVATE KEY-----\n" private-key-base64 "\n-----END EC PRIVATE KEY-----"))))
发布于 2022-08-30 14:46:44
这是一个SEC1格式的私有EC密钥,支持的格式不受WebCrypto,s. 这里的支持。
WebCrypto为私钥支持的一种格式是PKCS#8 (顺便说一句,您已经在WebCrypto代码中使用它作为importKey()
调用中的第一个参数),因此可能的解决办法是将密钥转换为这种格式,例如使用OpenSSL:
openssl pkcs8 -topk8 -nocrypt -in <path to input-sec1-pem> -out <path to output-pkcs8-pem>
这意味着:
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg65DYO7lDdsTTDNjC
oiYaNtvrMBJuh/foxV5FAxN84DmhRANCAAStLP0Ug7Wws9yImMduP8R25g0KVp4I
GFC5Tlk+HbhhG8cbkVcs2JXV08gHTYrIpeJiO8uujnzq5gORjNo+TNs7
-----END PRIVATE KEY-----
这两种格式表示可以在ASN.1解析器(例如https://lapo.it/asn1js/)中验证的相同密钥(即封装相同的密钥参数,即相同的原始私钥和相同的原始公钥)。
使用PKCS#8格式的键导入是成功的:
(async () => {
function b642ab(base64_string){
return Uint8Array.from(window.atob(base64_string), c => c.charCodeAt(0));
}
let der = b642ab("MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg65DYO7lDdsTTDNjCoiYaNtvrMBJuh/foxV5FAxN84DmhRANCAAStLP0Ug7Wws9yImMduP8R25g0KVp4IGFC5Tlk+HbhhG8cbkVcs2JXV08gHTYrIpeJiO8uujnzq5gORjNo+TNs7")
let key = await crypto.subtle.importKey(
'pkcs8',
der,
{
name: 'ECDSA',
namedCurve: 'P-256',
},
false,
['sign']
);
console.log(key);
})();
https://stackoverflow.com/questions/73543963
复制相似问题