java - 无法从 Java 读取 OpenSSL 生成的 ECDSA key : InvalidKeySpecException

标签 java openssl cryptography ecdsa

我创建了 ECDSA key 对并使用 OpenSSL 导出了公钥,但我无法从 Java 读取公钥。

OpenSSL 中的 key 生成:

$ openssl ecparam -name secp256k1 -genkey -noout -outform DER | openssl ec -inform DER -pubout -outform DER > secp256k1.public.der

从文件中读取 key 的 Clojure 代码,以 [org.bouncycaSTLe/bcprov-jdk15on "1.56"] 作为依赖项:

(ns adhoc.ecdsa-mismatch
  (:import (java.nio.file Files Paths)
           (java.security Security KeyFactory)
           (java.security.spec X509EncodedKeySpec)))

(when (nil? (Security/getProvider "BC"))
  (Security/addProvider (org.bouncycastle.jce.provider.BouncyCastleProvider.)))

(defn read-bytes
  "Read file from path as byte array."
  [^String path]
  (Files/readAllBytes (Paths/get path (into-array String []))))

(defn read-pubkey
  [^String path]
  (.generatePublic (KeyFactory/getInstance "ECDSA" "BC")
                   (X509EncodedKeySpec. (read-bytes path))))
(require '[adhoc.ecdsa-mismatch :as mm])

(mm/read-pubkey "secp256k1.public.der")
;; InvalidKeySpecException java.lang.NullPointerException  org.bouncycastle.jce.provider.JDKKeyFactory$EC.engineGeneratePublic (:-1)

(.printStackTrace *e)
;; java.security.spec.InvalidKeySpecException: java.lang.NullPointerException
;;  at org.bouncycastle.jce.provider.JDKKeyFactory$EC.engineGeneratePublic(Unknown Source)
;;  at java.security.KeyFactory.generatePublic(KeyFactory.java:328)
;;  at adhoc.ecdsa_mismatch$read_pubkey.invokeStatic(ecdsa_mismatch.clj:16)
;;  at adhoc.ecdsa_mismatch$read_pubkey.invoke(ecdsa_mismatch.clj:14)
<小时/>

其他信息

使用 NIST P-256 曲线生成 key :

$ openssl ecparam -name prime256v1 -genkey -noout -outform DER | openssl ec -inform DER -pubout -outform DER > prime256v1.public.der

从磁盘加载 prime256v1:

(println (mm/read-pubkey "prime256v1.public.der"))
;; #object[org.bouncycastle.jce.provider.JCEECPublicKey 0x72369051 EC Public Key
;;             X: 5a690a647dc4b7e80f71f15212b08686c1f717ada7198fa8a0b8c93cec16ecb
;;             Y: 30be46137f328766ef8686675f118760ab0c96c52275bf00cf56097333ea6487
;; ]

公钥的内容:

$ base64 secp256k1.public.der 
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEsipNgzBpQ0CLgZNw+LhASmh4KmGXnJsOC2dfzq5cVwMn
HfsfHGphaGvZTNoc/lUVrr+ICFK/2D/9up9hHHHHWg==
$ base64 prime256v1.public.der 
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEBaaQpkfcS36A9x8VISsIaGwfcXracZj6iguMk87B
bsswvkYTfzKHZu+GhmdfEYdgqwyWxSJ1vwDPVglzM+pkhw==

最佳答案

解决方案是 Java(或者可能是此版本的 BouncyCaSTLe)不支持 secp256k1 椭圆曲线!在 openssl 调用中使用更常见的曲线 prime256v1 (NIST P-256) 会生成一个我可以读取的 key 。

成功输出示例:

#<JCEECPublicKey EC Public Key
            X: 89cfd7dfb455e6ea51e578e9ea3505ba1e44a0a5f126e3b280611cf6bb467653
            Y: 565eb189ef15b8ff1b72824a7f0418a7df205797a86c8f30961e9bf0deaaa0c3
>

关于java - 无法从 Java 读取 OpenSSL 生成的 ECDSA key : InvalidKeySpecException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42234685/

相关文章:

openssl - 如何配置 openssl 的默认后端引擎?

java - 在 Node js 中通过 AES/GCM/NoPadding 算法使用 key 和 iv 加密有效负载并在 java 中解密

java - 如何等待所有线程(可变数量的线程)完成并继续 Main?

windows - 通过 OpenSSL 使用来自 Windows 证书库的证书和私钥

ssl - TLS 1.3 早期数据放置 $ssl_early_data 的位置

svn - 针对本地符号的错误而重定位R_X86_64_32

java - Python 到 Java 加密 (RSA)

java - Java 应用程序的 Web 界面

java - Arrays.asList() 在java中的实现

java - 应用程序完成工作后如何删除 ICEpdf 临时文件?