OpenSSL生成的Ed25519密钥对与NaCl.net不匹配?求排查原因
问题:OpenSSL生成的Ed25519密钥对与NaCl.net验证不匹配
我尝试用OpenSSL生成Ed25519密钥的自签名证书,执行命令:
openssl req -new -newkey ed25519 -noenc -config root.cnf -section root_req -out RootCA.csr -keyout RootCA.key -passout file:password.txt -batch
相关配置段:
[root_req] default_bits = 256 encrypt_key = no default_md = sha256 utf8 = yes string_mask = utf8only prompt = no distinguished_name = root_dn req_extensions = root_ext [root_ext] basicConstraints = critical,CA:true keyUsage = critical,keyCertSign subjectKeyIdentifier = hash
生成的请求和签名证书中公钥为:
BFDC8F370A5B5CA66E5FA55A6CFBC6D10963B2D6EFFCB86C006E08F64A0654D8
RootCA.key解码后的私钥为:
99302B2E03C55D957BAA38C64BED90321B535BDC2864A32AB18BED6F11C7159D
但用NaCl.net实现的Ed25519验证时出现问题:Curve25519XSalsa20Poly1305加密解密失败,且通过Curve25519.ScalarMultiplicationBase从私钥重建的公钥为:
5089A9E4FBFF67D9419713FC0267C1540091E0126607BF903F4996E03EC79F29
该密钥对可正常签名,请问为何OpenSSL输出的密钥对不匹配?是生成操作有误还是格式差异导致?
原因分析与解决办法
核心问题:Ed25519和X25519的算法用途差异
你混淆了两种基于同一条椭圆曲线但用途完全不同的密钥:- OpenSSL生成的是Ed25519密钥对,专门用于签名/验签(比如证书场景),公钥是Ed25519算法定义的格式。
- NaCl.net里的
Curve25519.ScalarMultiplicationBase是X25519密钥交换的方法,它会从Ed25519私钥衍生出X25519专用的公钥——这两个公钥本身就不一样,因为Ed25519和X25519对密钥的处理逻辑、应用场景完全分开:一个管签名,一个管加密协商。
OpenSSL密钥格式的细节
OpenSSL输出的Ed25519私钥是原始32字节种子,Ed25519的公钥是通过种子哈希、截断等步骤生成的。但X25519不能直接用Ed25519的原始种子,需要先对种子做SHA-512哈希,取前32字节再做比特位调整,才能生成X25519的私钥,进而得到对应的公钥。所以直接用Ed25519私钥调用X25519方法,得到的公钥自然和Ed25519公钥不匹配。具体解决办法
- 若要做Curve25519XSalsa20Poly1305加密解密,直接生成X25519密钥对(OpenSSL 1.1.1及以上版本支持):
openssl genpkey -algorithm X25519 -out x25519.key - 若必须复用现有Ed25519私钥做X25519密钥交换,需先转换格式:对Ed25519私钥种子做SHA-512哈希,取前32字节,将第32字节的最高位清零、第25位设为1,再用处理后的字节串调用
ScalarMultiplicationBase,得到的才是正确的X25519公钥。 - 签名场景继续用Ed25519密钥,加密协商场景用X25519密钥,不要跨场景混用两种算法的密钥。
- 若要做Curve25519XSalsa20Poly1305加密解密,直接生成X25519密钥对(OpenSSL 1.1.1及以上版本支持):
内容的提问来源于stack exchange,提问作者MikkelBybjerg
相关产品推荐
相关产品推荐

