修复Lua版ECDH密钥交换,使其与Go、NodeJS结果一致
修复Lua版ECDH共享密钥不匹配问题
问题概述
Go与NodeJS实现的P256(prime256v1)椭圆曲线密钥交换(ECDH)生成的共享密钥结果一致,但Lua版本输出不匹配,需调整Lua代码使其输出相同结果。
参考实现代码
Go实现
package main import ( "crypto/ecdh" "encoding/base64" "log" "os" "github.com/joho/godotenv" ) func main() { _ = godotenv.Load() aDecodedPrivateKey, _ := base64.StdEncoding.DecodeString(os.Getenv("A_PRIVATE_KEY")) bDecodedPrivateKey, _ := base64.StdEncoding.DecodeString(os.Getenv("B_PRIVATE_KEY")) aPrivateKey, _ := ecdh.P256().NewPrivateKey(aDecodedPrivateKey) bPrivateKey, _ := ecdh.P256().NewPrivateKey(bDecodedPrivateKey) sharedSecret, _ := aPrivateKey.ECDH(bPrivateKey.PublicKey()) log.Println(base64.StdEncoding.EncodeToString(sharedSecret)) }
NodeJS实现
require('dotenv').config() import { createECDH } from 'crypto' const aKey = createECDH('prime256v1') const bKey = createECDH('prime256v1') aKey.setPrivateKey(Buffer.from(String(process.env.A_PRIVATE_KEY), 'base64')) bKey.setPrivateKey(Buffer.from(String(process.env.B_PRIVATE_KEY), 'base64')) console.log(aKey.computeSecret(bKey.getPublicKey()).toString('base64'))
原Lua实现问题分析
原Lua代码存在两处关键问题:
- 私钥BN对象创建格式错误:使用
openssl_bn.new(a_decoded_key, 2)时,参数2表示解析0/1组成的二进制文本字符串,但实际a_decoded_key是base64解码后的原始字节流,格式不匹配导致私钥加载错误。 - 公钥处理冗余:将私钥对象转为PEM格式后再重新解析为公钥对象,虽不直接导致错误,但增加不必要的开销。
修改后的Lua实现代码
local openssl_pkey = require "resty.openssl.pkey" local openssl_bn = require "resty.openssl.bn" local ngx = require "ngx" local function ecdh() -- 解码base64格式的私钥(需确保a_private_key、b_private_key已从环境变量加载) local a_decoded_key = ngx.decode_base64(a_private_key) local b_decoded_key = ngx.decode_base64(b_private_key) -- 从原始二进制字节创建BN私钥对象,指定"binary"格式 local a_bn = openssl_bn.new(a_decoded_key, "binary") local b_bn = openssl_bn.new(b_decoded_key, "binary") -- 初始化EC私钥 local a_key = openssl_pkey.new({ type = "EC", params = { private = a_bn, group = "prime256v1" } }) local b_key = openssl_pkey.new({ type = "EC", params = { private = b_bn, group = "prime256v1" } }) -- 直接从私钥对象获取公钥,避免PEM转换开销 local b_public_key = b_key:public_key() -- 派生共享密钥,返回结果为原始32字节x坐标,与Go/NodeJS一致 local shared_secret = a_key:derive(b_public_key) return ngx.encode_base64(shared_secret) end
环境变量配置
A_PRIVATE_KEY="w2UwuwmF9h5p02fnr3MkxtKoDTl8aTtJXqLbsPwbqPg=" B_PRIVATE_KEY="ZyoPMal0TZzNwDyUUE30iThXCKgPOthPaIN2qnOhkNs="
测试环境
- Go 1.23.4
- NodeJS v22.12.0
- Lua 5.1
内容的提问来源于stack exchange,提问作者user29212913
相关产品推荐
相关产品推荐

