英文:
How to bind openssl c binding via CGO in golang
问题
情况:
任务:
- 在Go中解密和验证有效载荷
操作:
- 在Rust中使用了josekit-rs,可以解决这个问题
- 通过safer_ffi创建了C API
- 通过CGO在Go中绑定了该库
结果:
- 当使用简单函数(不使用openssl)时,整个绑定过程都可以工作
$ go build .
# go-jose-kit/jose-kit-ffi
Undefined symbols for architecture arm64:
"_AES_ige_encrypt", referenced from:
openssl::aes::aes_ige::h356a909c3f173638 in libjose_kit_ffi.a(openssl-83ba33f9169f6e94.openssl.2a7d90ad-cgu.15.rcgu.o)
"_AES_set_decrypt_key", referenced from:
openssl::aes::AesKey::new_decrypt::h6be3702416d4e43e in libjose_kit_ffi.a(openssl-83ba33f9169f6e94.openssl.2a7d90ad-cgu.15.rcgu.o)
"_AES_set_encrypt_key", referenced from:
openssl::aes::AesKey::new_encrypt::heb205e6bc2f989db in libjose_kit_ffi.a(openssl-83ba33f9169f6e94.openssl.2a7d90ad-cgu.15.rcgu.o)
"_AES_unwrap_key", referenced from:
. . .
. . .
enssl-83ba33f9169f6e94.openssl.2a7d90ad-cgu.13.rcgu.o)
"_i2d_X509_REQ", referenced from:
openssl::x509::X509ReqRef::to_der::h5e65612242296419 in libjose_kit_ffi.a(openssl-83ba33f9169f6e94.openssl.2a7d90ad-cgu.13.rcgu.o)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
看起来CGO无法找到Rust二进制文件使用的外部方法(符号)。
尝试创建静态库,但无法将openssl
链接到Rust编译的对象中。
在main.go文件中添加了以下头文件。
#cgo CFLAGS: -I/opt/homebrew/opt/openssl@3/include
#cgo LDFLAGS: -L/opt/homebrew/opt/openssl@3/lib -L ./target/debug -l jose_kit_ffi -l pthread -l dl -lm
#include "./jose_kit_ffi.h"
$ go env
GO111MODULE=""
GOARCH="arm64"
GOBIN=""
GOCACHE="/Users/{USERNAME}/Library/Caches/go-build"
GOENV="/Users/{USERNAME}/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/{USERNAME}/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/{USERNAME}/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/opt/homebrew/Cellar/go/1.18.1/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/opt/homebrew/Cellar/go/1.18.1/libexec/pkg/tool/darwin_arm64"
GOVCS=""
GOVERSION="go1.18.1"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/{PATH}/go.mod"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/8l/_xp4ll7n4c3dqjxrs8klhkqh0000gn/T/go-build3058634703=/tmp/go-build -gno-record-gcc-switches -fno-common"
英文:
Situation:
- Need to use EdDSA 448 JSON web encryption in GoLang, ref
- Couldn't find JWT library which supports this in GoLang
- We are using jwcrypto in Python, need similar lib in GO
# Example header
{
"alg": "ECDH-ES",
"enc": "A256CBC-HS512",
"epk": {
"crv": "X448",
"kty": "OKP",
"x": "PNJPrNo7grr4y9m9CaxetWdMWA91aAkBf9xM2bsaJHzcLx5RZWyaBfOMhaGDioPEnOT6alPJ0sE"
}
}
Task:
- Decrypt and verify payload in GO
Actions:
- Used josekit-rs in Rust which can solve this
- Created C API via safer_ffi
- Bind the library via CGO in Golang
Result:
- Whole binding thing works when used simple function (without openssl)
$ go build .
# go-jose-kit/jose-kit-ffi
Undefined symbols for architecture arm64:
"_AES_ige_encrypt", referenced from:
openssl::aes::aes_ige::h356a909c3f173638 in libjose_kit_ffi.a(openssl-83ba33f9169f6e94.openssl.2a7d90ad-cgu.15.rcgu.o)
"_AES_set_decrypt_key", referenced from:
openssl::aes::AesKey::new_decrypt::h6be3702416d4e43e in libjose_kit_ffi.a(openssl-83ba33f9169f6e94.openssl.2a7d90ad-cgu.15.rcgu.o)
"_AES_set_encrypt_key", referenced from:
openssl::aes::AesKey::new_encrypt::heb205e6bc2f989db in libjose_kit_ffi.a(openssl-83ba33f9169f6e94.openssl.2a7d90ad-cgu.15.rcgu.o)
"_AES_unwrap_key", referenced from:
. . .
. . .
enssl-83ba33f9169f6e94.openssl.2a7d90ad-cgu.13.rcgu.o)
"_i2d_X509_REQ", referenced from:
openssl::x509::X509ReqRef::to_der::h5e65612242296419 in libjose_kit_ffi.a(openssl-83ba33f9169f6e94.openssl.2a7d90ad-cgu.13.rcgu.o)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
It seems CGO is unable to find external methods (symbols) used by rust binary.
Tried to create static lib but it isn't possible to link openssl
within rust compiled object.
In main.go file have added these headers.
#cgo CFLAGS: -I/opt/homebrew/opt/openssl@3/include
#cgo LDFLAGS: -L/opt/homebrew/opt/openssl@3/lib -L ./target/debug -l jose_kit_ffi -l pthread -l dl -lm
#include "./jose_kit_ffi.h"
$ go env
GO111MODULE=""
GOARCH="arm64"
GOBIN=""
GOCACHE="/Users/{USERNAME}/Library/Caches/go-build"
GOENV="/Users/{USERNAME}/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/{USERNAME}/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/{USERNAME}/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/opt/homebrew/Cellar/go/1.18.1/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/opt/homebrew/Cellar/go/1.18.1/libexec/pkg/tool/darwin_arm64"
GOVCS=""
GOVERSION="go1.18.1"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/{PATH}/go.mod"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/8l/_xp4ll7n4c3dqjxrs8klhkqh0000gn/T/go-build3058634703=/tmp/go-build -gno-record-gcc-switches -fno-common"
答案1
得分: 1
通过创建动态链接库(dylib)而不是静态库(static lib)来解决了这个问题。
[package]
name = "jose-kit-ffi"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
# crate-type = ["staticlib"] -> 不起作用
crate-type = ["dylib"] ->
# ^ 它不会在二进制文件中包含openssl符号。
[dependencies]
safer-ffi = { version = "0.0.10", features = ["proc_macros"] }
josekit = "0.8.1"
serde_json = "1.0"
[features]
c-headers = ["safer-ffi/headers"]
结果
go run .
2022/08/21 22:19:14 Hello, from GO!
JwkSecret { priv_key: "--", pub_key: "--" }
Encrypted JWT: eyJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiZXBrIjp7Imt0eSI6Ik9LUCIsImNydiI6Ilg0NDgiLCJ4IjoiTmdjRlE4bFY3WWtjUWMtNXR6RlhuUnZvcEI0NlZVTnhPWHFKajgwSzNLQnR4YWh1al9zM3ZNRVY4WVA0cnVvNkttS0FNR0FCN1M4In0sImFsZyI6IkVDREgtRVMifQ..q9BgTEh2UPjiSgLNfu0BTw.rLDyrLQYwtWpi4Qyo43csmERW-VNXowQQBPmqu7zj7U.epX8cMdNA9o9xzMTVdaxJALdtgruVyox5JaPYxKpwZ8
Some("eyJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiZXBrIjp7Imt0eSI6Ik9LUCIsImNydiI6Ilg0NDgiLCJ4IjoiTmdjRlE4bFY3WWtjUWMtNXR6RlhuUnZvcEI0NlZVTnhPWHFKajgwSzNLQnR4YWh1al9zM3ZNRVY4WVA0cnVvNkttS0FNR0FCN1M4In0sImFsZyI6IkVDREgtRVMifQ..q9BgTEh2UPjiSgLNfu0BTw.rLDyrLQYwtWpi4Qyo43csmERW-VNXowQQBPmqu7zj7U.epX8cMdNA9o9xzMTVdaxJALdtgruVyox5JaPYxKpwZ8")
英文:
Solved it via creating dylib instead of static lib.
[package]
name = "jose-kit-ffi"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
# crate-type = ["staticlib"] -> Doesn't work
crate-type = ["dylib"] ->
# ^ It won't include openssl symbols in binary.
[dependencies]
safer-ffi = { version = "0.0.10", features = ["proc_macros"] }
josekit = "0.8.1"
serde_json = "1.0"
[features]
c-headers = ["safer-ffi/headers"]
Result
go run .
2022/08/21 22:19:14 Hello, from GO!
JwkSecret { priv_key: "--", pub_key: "--" }
Encrypted JWT: eyJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiZXBrIjp7Imt0eSI6Ik9LUCIsImNydiI6Ilg0NDgiLCJ4IjoiTmdjRlE4bFY3WWtjUWMtNXR6RlhuUnZvcEI0NlZVTnhPWHFKajgwSzNLQnR4YWh1al9zM3ZNRVY4WVA0cnVvNkttS0FNR0FCN1M4In0sImFsZyI6IkVDREgtRVMifQ..q9BgTEh2UPjiSgLNfu0BTw.rLDyrLQYwtWpi4Qyo43csmERW-VNXowQQBPmqu7zj7U.epX8cMdNA9o9xzMTVdaxJALdtgruVyox5JaPYxKpwZ8
Some("eyJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiZXBrIjp7Imt0eSI6Ik9LUCIsImNydiI6Ilg0NDgiLCJ4IjoiTmdjRlE4bFY3WWtjUWMtNXR6RlhuUnZvcEI0NlZVTnhPWHFKajgwSzNLQnR4YWh1al9zM3ZNRVY4WVA0cnVvNkttS0FNR0FCN1M4In0sImFsZyI6IkVDREgtRVMifQ..q9BgTEh2UPjiSgLNfu0BTw.rLDyrLQYwtWpi4Qyo43csmERW-VNXowQQBPmqu7zj7U.epX8cMdNA9o9xzMTVdaxJALdtgruVyox5JaPYxKpwZ8")
答案2
得分: 0
嗨,我建议你使用github.com/golang-jwt/jwt/v4库。我认为这是很受欢迎的。如果你需要更多选择,你可以在https://jwt.io上找到其他推荐的JWT库。
英文:
Hei, I suggest u using github.com/golang-jwt/jwt/v4 lib. this popular i think. And Recommended as the one in https://jwt.io or if u need more, u can see another recommendation library JWT in there.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论