跳到主要内容

wolfssl

简介

使用 wolfssl 对 socket 进行加密 目前使用的 wolfssl 版本为: 4.7.0

使用 OpenSSL 生成自签名证书:

安装 OpenSSL:

确保系统上已经安装了 OpenSSL。大多数 UNIX 系统已经预装了 OpenSSL。如果没有,可以通过包管理工具安装。例如,在 Ubuntu 上可以使用命令 sudo apt-get install openssl。

生成私钥:

使用以下命令生成一个 2048 位长度的 RSA 私钥:

   openssl genrsa -out private.key 2048

生成证书签名请求 (CSR):

CSR 是发送给证书颁发机构(CA)的请求,但对于自签名证书,这个过程是本地完成的。运行以下命令,并按照提示输入信息,例如国家、州、省市、组织名以及常用名称(通常为域名):

   openssl req -new -key private.key -out certificate.csr

生成自签名证书:

使用 CSR 和私钥生成一个自签名证书。通常有效期设置为一年(365 天),可以通过 -days 参数调整:

   openssl x509 -req -in certificate.csr -signkey private.key -out self-signed-certificate.crt -days 365

查看生成的证书(可选):

可以使用以下命令来查看生成的自签名证书的信息:

   openssl x509 -in self-signed-certificate.crt -text -noout

文件输出说明:

  • private.key:你的私钥,必须安全存储,不要泄露。用于解密通过该证书加密的数据。

  • certificate.csr:证书签名请求文件,可以公开。

  • self-signed-certificate.crt:自签名证书,公共部分,可提供给任何需要信任该证书的客户端。

注意事项:

  • 安全性:自签名证书缺乏第三方信任,因此只能在内部网络或私有环境中使用。在生产环境中,最好使用由受信任的 CA 签发的证书。

  • 更新及管理:注意证书到期时间。如果证书到期,请重新生成。 保护私钥:务必保护你的私钥,勿将其与证书一同传播。

组件接口

server_transmit.gs

函数原型函数作用
int init(socket _fd, string cert, string key)初始化服务器连接
bool send(mixed data)发送消息
array recv(int max_size, buffer ret_buf, int offset, int timeout)接收消息

ssl_transmit.gs

函数原型函数作用
bool init(socket _fd, int timeout, string host, string cert)初始化 ssl, 并将 socket 交给 wolfssl 管理
bool send(mixed data, int timeout)通过 wolfssL 发送信息
buffer recv(int max_size, int timeout)接收消息
ErrorCode get_socket_code()获取 socket 错误码
string get_wolfssl_error_string()获取 wolfssl 错误信息
int get_wolfssl_error_code()获取 wolfssl 错误码

wolfssl.gs

函数原型函数作用
object new_transmit(domain d, bool is_server)创建 socket 的 wolfssl 代理
string error_string(int err)获取 wolfssl 的错误信息
void enable_wolfssl_log(bool able)是否开启 wolfssl 日志, 默认关闭

样例

// 客户端代码
public void client_connect(string host = "m68gitlab.g-bits.com", string ca = nil, int port = 443, string send_data = nil)
{
sockaddr addr = socket.resolve(host)[0];

auto fd = socket.create(SockDomain.AF_INET, SockType.SOCK_STREAM);
if (fd.connect(addr, port))
error("can't connect to %s", host);

object transmit = wolfssl.new_transmit(this_domain());
// wolfssl.enable_wolfssl_log(true);

// Auto close object when failed
if (!transmit.init(fd, 3, host, ca))
{
transmit.close();
error("can't init wolfssl, " + (transmit.get_wolfssl_error_string() ?? ""));
}
if (send_data != nil)
transmit.send(send_data);
transmit.close();
fd.close();
writeln("Client done");
}

public parallel void server_listen(int port = 443)
{
socket _sfd = socket.create(SockDomain.AF_INET, SockType.SOCK_STREAM);
_sfd.set_opt(SockOptLevel.SOCKET, SockOpt.REUSEADDR, 1);
mixed start_statue = _sfd.bind("0.0.0.0", port);
if (start_statue != ErrorCode.OK)
{
error("%O: it usually caused by port reuse! Current port is: %d", start_statue, port);
}

if (_sfd.listen(256) < 0)
{
error("Failed to listen on port, can't start http server.\n");
return;
}
while(true)
{
array cfd = _sfd.accept();
object socket_proxy = ssl_handshake(cfd[0]);
if (socket_proxy == nil)
{
error("ssl handshake failed");
return;
}
buffer buf = buffer.allocate(1024);
let int l, mixed _ = socket_proxy.recv(1024, buf, 0, 3);
writeln("receive from client: ", (string)buf[0..l]);
cfd[0].close();
}
}

// ssl 握手
parallel mixed ssl_handshake(socket cfd)
{
string from = (string)cfd.info().ip + ":" + (string)cfd.info().port;
object transmit = wolfssl.new_transmit(this_domain(), true);
int code = transmit.init(cfd, "./self_sign/self-signed-certificate.crt", "./self_sign/private.key");
if (code < 0)
{
if (code == -1)
writeln("error cert file:" + from);
if (code == -2)
writeln("error key file:" + from);
else
writeln("maybe it is not a https require, or cetify error, or unknown error!!: " + from);
cfd.close();
return nil;
}
return transmit;
}
coroutine.create_in_thread(nil, domain.create(), (: server_listen :));
coroutine.sleep(1);
client_connect("localhost", nil, 443, "send without certificate");
client_connect("localhost", "./self_sign/self-signed-certificate.crt", 443, "send with certificate");
catch {
// client_connect("localhost", "./ca/DigiCert.cer", 443, "send with wrong certificate"); // ASN no signer error to confirm failure
}