![](/img/trans.png)
[英]Unable to verify a public cert's modules with openssl (Unable to verify rsa public key came from a private key)
[英]Unable to import OpenSSL generated private key into web API crypto.subtle.importKey
我正在使用命令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-----"))))
这是 SEC1 格式的私有 EC 密钥,WebCrypto 不支持。 这里是支持的格式。
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); })();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.