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
}