将 go-jasypt 编译成静态库给 C++ 调用
编辑使用的 go-jasypt
https://github.com/Mystery00/go-jasypt
首先写一个go项目,引入 go-jasypt
先写 go.mod
module c-jasypt
go 1.21
require github.com/Mystery00/go-jasypt v1.0.3
require golang.org/x/crypto v0.22.0 // indirect
截止到现在,
go-jasypt
的版本是1.0.3
,里面有一个crypto
的依赖有漏洞,因此这里强制指定了它的版本为0.22.0
然后再写一个 main.go
文件,我们在这个文件里面暴露出来加密解密函数
package main
import (
"C"
"fmt"
"github.com/Mystery00/go-jasypt"
"github.com/Mystery00/go-jasypt/iv"
"github.com/Mystery00/go-jasypt/salt"
)
const (
// specify the algorithm
algorithm = "PBEWithHMACSHA512AndAES_256"
)
//export Encrypt
func Encrypt(password, message *C.char) *C.char {
// create a new instance of jasypt
encryptor := jasypt.New(algorithm, jasypt.NewConfig(
jasypt.SetPassword(C.GoString(password)),
jasypt.SetSaltGenerator(salt.RandomSaltGenerator{}),
jasypt.SetIvGenerator(iv.RandomIvGenerator{}),
))
// encrypt the message
encrypted, err := encryptor.Encrypt(C.GoString(message))
if err != nil {
return C.CString(fmt.Sprintf("Error: %s", err.Error()))
}
return C.CString(encrypted)
}
//export Decrypt
func Decrypt(password, encode *C.char) *C.char {
// create a new instance of jasypt
encryptor := jasypt.New(algorithm, jasypt.NewConfig(
jasypt.SetPassword(C.GoString(password)),
jasypt.SetSaltGenerator(salt.RandomSaltGenerator{}),
jasypt.SetIvGenerator(iv.RandomIvGenerator{}),
))
// decrypt the message
decrypted, err := encryptor.Decrypt(C.GoString(encode))
if err != nil {
return C.CString(fmt.Sprintf("Error: %s", err.Error()))
}
return C.CString(decrypted)
}
func main() {
}
有几个地方需要注意一下:
package 必须是main,因为我们这里需要编译成静态库,不是main的话会报错
-buildmode=c-archive requires exactly one main package
同上,需要一个main方法,没有逻辑无所谓,必须要存在
在需要暴露的方法上增加
//export
标识import中也要带上
import "C"
这个库接收的都是 go 的string类型参数,但是直接使用string类型似乎会导致go的内存管理出现问题,运行时会报错 oom,所以使用
*C.char
来接收返回数据也是同理,使用
*C.char
编译静态库
编写好源码之后,执行以下命令进行编译
go build -buildmode=c-archive -o jasypt.a
我没有指定
GOOS
和GOARCH
这些,需要交叉编译的话请自行指定
编译通过之后会生成两个文件,一个是 jasypt.a
,也就是编译命令中我们指定的输出文件名,这个就是静态库,同时还有一个 jasypt.h
头文件,这个是给C++引用的。
编写 C++ 代码
代码如下,仅仅是调用一下,里面的输入都是测试数据
#include <iostream>
extern "C" {
const char* Encrypt(const char* password, const char* message);
const char* Decrypt(const char* password, const char* encode);
}
int main() {
const char* result = Decrypt("password", "yBC5Tt8PFp+mIoxY69zYfW2f/wxV6ofYMuHGIxd8fxMra/riH78DyMz4zNTCcQ9z");
std::cout << result << std::endl;
const char* encode = Encrypt("password", result);
std::cout << encode << std::endl;
return 0;
}
按照我上面的代码是可以正常运行的,或许在大型项目里面需要单独去引入头文件啥的
但是我的C++是10年前学的了,已经全部忘记完了,这里就留给C++大佬去自行修改吧
不行了,要长脑子了
编译 C++ 代码
执行一下命令
g++ -o test _test.cpp jasypt.a
我的 cpp 代码与go代码放到了一起,为了避免go拿去编译静态库了,就加了_前缀
参数没啥好说的,照着写就编译出来一个 test 文件
直接运行这个 test 文件,就得到输出内容了
./test
1234567890
A4l0hahtfc4S4q586c6xEAVvzButDaXrwNyQ5NhhC1A64IxBbkE7NHU2gDYvHvwN
其中第一行是我们用测试数据解密的结果,是正确的
第二行是我们用解密结果再做了一次加密之后的密文
因为jasypt的效果,每一次加密我们得到的密文都是不同的,因此如果你的第二行输出和我不一样并不是代码原因,只要输出的内容不带 Error:
前缀,都是正确的
- 0
- 0
-
分享