Go and NodeJS produced the same result, but not Lua. I want Lua to produce the same one.
package main
import (
"crypto/ecdh"
"encoding/base64"
"log"
"os"
"github/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))
}
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(aKeyputeSecret(bKey.getPublicKey()).toString('base64'))
local openssl_pkey = require "resty.openssl.pkey"
local openssl_bn = require "resty.openssl.bn"
local ngx = require "ngx"
local function ecdh()
local a_decoded_key = ngx.decode_base64(a_private_key)
local b_decoded_key = ngx.decode_base64(b_private_key)
local a_bn = openssl_bn.new(a_decoded_key, 2)
local b_bn = openssl_bn.new(b_decoded_key, 2)
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"
}
})
local b_public_key = openssl_pkey.new(b_key:to_PEM('public'))
return ngx.encode_base64(a_key:derive(b_public_key))
end
Please help me create the Lua version that produces the same result as Go and NodeJS.
In case you need environment variables, take this .env
.
A_PRIVATE_KEY="w2UwuwmF9h5p02fnr3MkxtKoDTl8aTtJXqLbsPwbqPg="
B_PRIVATE_KEY="ZyoPMal0TZzNwDyUUE30iThXCKgPOthPaIN2qnOhkNs="
Here is my testing environment.
- Go 1.23.4
- NodeJS v22.12.0
- Lua 5.1
References that might help.
- #restyopensslpkey
- .lua
Thank you in advance.
Go and NodeJS produced the same result, but not Lua. I want Lua to produce the same one.
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))
}
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'))
local openssl_pkey = require "resty.openssl.pkey"
local openssl_bn = require "resty.openssl.bn"
local ngx = require "ngx"
local function ecdh()
local a_decoded_key = ngx.decode_base64(a_private_key)
local b_decoded_key = ngx.decode_base64(b_private_key)
local a_bn = openssl_bn.new(a_decoded_key, 2)
local b_bn = openssl_bn.new(b_decoded_key, 2)
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"
}
})
local b_public_key = openssl_pkey.new(b_key:to_PEM('public'))
return ngx.encode_base64(a_key:derive(b_public_key))
end
Please help me create the Lua version that produces the same result as Go and NodeJS.
In case you need environment variables, take this .env
.
A_PRIVATE_KEY="w2UwuwmF9h5p02fnr3MkxtKoDTl8aTtJXqLbsPwbqPg="
B_PRIVATE_KEY="ZyoPMal0TZzNwDyUUE30iThXCKgPOthPaIN2qnOhkNs="
Here is my testing environment.
- Go 1.23.4
- NodeJS v22.12.0
- Lua 5.1
References that might help.
- https://github.com/fffonion/lua-resty-openssl?tab=readme-ov-file#restyopensslpkey
- https://github.com/fffonion/lua-resty-openssl/blob/master/examples/x25519-dh.lua
Thank you in advance.
Share Improve this question edited 2 days ago user29212913 asked 2 days ago user29212913user29212913 271 silver badge2 bronze badges New contributor user29212913 is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.1 Answer
Reset to default 1I see at least three problems:
- X25519 and prime256v1 are totally different curves. You need to pick one or the other and use it consistently.
- That's not the right syntax to make a pkey with existing key material. Here's how you'd modify that part of your code to do that correctly:
local openssl_bn = require "resty.openssl.bn"
local a_bn = openssl_bn.new(a_decoded_key, 2)
local a_key = openssl_pkey.new({
type = "EC",
params = {
private = a_bn,
group = "prime256v1"
}
})
- OpenSSL doesn't automatically calculate the public key from the private key, so you have to do that yourself, as How do I obtain the public key from an ECDSA private key in OpenSSL? explains. Unfortunately, lua-resty-openssl doesn't expose a lot of necessary functions for this, e.g.,
EC_POINT_mul
, so you'd have to either switch libraries or write a lot of C FFI code yourself to do this.