Home > other >  How to bind openssl c binding via CGO in golang
How to bind openssl c binding via CGO in golang

Time:08-22

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"

CodePudding user response:

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")

CodePudding user response:

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.

  • Related