我可以在 ZeroMQ 中交换私钥和公钥吗

标签 c encryption zeromq

目前,我正在研究使用 ZeroMQ 和 Curve 来保护我的发布者和订阅者之间的流量的可能性。

我已经成功地实现了一个使用 CZMQ 的发布子系统。

目前,我的发布者正在使用他的私钥加密他想发送的数据,而订阅者可以使用发布者的公钥解密这些数据。这是比“加密”数据更“认证”的数据。因为当中间人存在时,他仍然可以解密所有数据,因为发布者的公钥是公开的。

我正在使用最新版本的 ZeroMQ 和 CZMQ 用 C 编写代码。

我的发布者.c

zctx_t* zmq_context = zctx_new();

zauth_t* auth = zauth_new (zmq_context);
zauth_set_verbose (auth, true);
zauth_configure_curve (auth, "*", CURVE_ALLOW_ANY);

zcert_t* pub_cert = zcert_load("cert.key"); // private key of publisher
void* socket = zsocket_new(zmq_context, ZMQ_PUB);
zcert_apply(pub_cert, socket);
zsocket_set_curve_server(socket, true);

//start publishing from here

我的订阅者.c

zctx_t* zmq_context = zctx_new();

zcert_t* sub_cert = zcert_new();
zcert_t* pub_cert = zcert_load("cert.pub"); // public key of publisher
char* pub_key = zcert_public_txt(pub_cert);

void* zmq_s = zsocket_new(zmq_context, ZMQ_SUB);
zcert_apply(sub_cert, zmq_s);
zsocket_set_curve_serverkey(zmq_s, pub_key);

//start subscribing to topics and receiving messages from here

从这一点开始,发布者使用他的私钥加密所有数据,订阅者使用发布者的公钥解密所有数据。我想交换这个系统。

所以,我想用发布者的公钥加密所有数据,用发布者的私钥解密所有数据。

我已经对其进行了测试,并将我的 publisher.c 中的 zcert_load("cert.key") 更改为 zcert_load("cert.pub")

我还在我的 subscriber.c 中更改了这段代码:

zcert_t* pub_cert = zcert_load("cert.pub"); // public key of publisher
char* pub_key = zcert_public_txt(pub_cert);

此代码:

zcert_t* pub_cert = zcert_load("cert.key"); // private key of publisher
char* pub_key = zcert_secret_txt(pub_cert);

当我使用这些代码更改运行我的发布者和订阅者时,发布者不断给我消息:CURVE I: cannot open client HELLO -- wrong server key?

我的问题:是否可以使用 ZeroMQ 和 CZMQ 的架构使用公钥加密数据(发布者套接字)和私钥解密数据(订阅者套接字)?

非常感谢,
罗伊

最佳答案

我认为您误解了 ZeroMQ CURVE 机制。 Pieter Hintjens 写了两篇很棒的文章,one is theoretical ,在哪里可以找到:

Clients and servers have long-term permanent keys, and for each connection, they create and securely exchange short-term transient keys. Each key is a public/secret keypair, following the elliptic curve security model.

To start a secure connection the client needs the server permanent public key. It then generates a transient key pair and sends a HELLO command to the server that contains its short term public key. The HELLO command is worthless to an attacker; it doesn't identify the client.

The server, when it gets a HELLO, generates its own short term key pair (one connection uses four keys in total), and encodes this new private key in a "cookie", which it sends back to the client as a WELCOME command. It also sends its short term public key, encrypted so only the client can read it. It then discards this short term key pair.

At this stage, the server hasn't stored any state for the client. It has generated a keypair, sent that back to the client in a way only the client can read, and thrown it away.

The client comes back with an INITIATE command that provides the server with its cookie back, and the client permanent public key, encrypted as a "vouch" so only the server can read it. As far as the client is concerned, the server is now authenticated, so it can also send back metadata in the command.

The server reads the INITIATE and can now authenticate the client permanent public key. It also unpacks the cookie and gets its short term key pair for the connection. As far as the server is now concerned, the client is now authenticated, so the server can send its metadata safely. Both sides can then send messages and commands.

因此您在此处生成的 key 不会直接用于加密数据,它们仅用于验证各方。客户端和服务器之间的握手过程产生用于加密数据的真实加密(和 MAC 中的身份验证) key 。因此,如果您唯一担心的是 MITM,那么您已经受到保护。

但是您也可能担心流氓客户端,您当前的方案允许任何人连接。这是the second article的地方Pieter Hintjens 的文章可以帮助您了解“The Ironhouse Pattern”。关键部分是禁用 CURVE_ALLOW_ANY 并告诉服务器在哪里寻找客户端公共(public)证书:

//  Tell authenticator to use the certificate store in .curve
zauth_configure_curve (auth, "*", ".curve");

然后您在客户端生成客户端 key (一次!不是为每个连接调用 zcert_new()),将其公共(public)部分传输到服务器的“.curve”目录并加载(在客户端)该 key 而不是调用 zcert_new()

如果你想让生活更轻松一点(不需要为每个客户端将公钥从客户端传输到服务器),你可以创建一个“黄金”客户端 key 对,将其公共(public)部分放入“.curve”存储然后(当然是通过安全通道)在每个需要连接到您的发布者的客户端上复制 key 。

关于我可以在 ZeroMQ 中交换私钥和公钥吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40016463/

相关文章:

c - 为什么作者在这个链表插入操作中要使用双指针呢?

python - 将加密文件存储在数据库中

node.js - 如何在 nodejs 请求中禁用 Tls 1.3

c++ - 零MQ/ZMQPP : Forward metadata with message

c - fread 从 Linux 磁盘读取扇区时返回 0

检查矩阵是否对称,我总是得到相同的结果

encryption - 要编码的 RSA 最大块大小是多少?

python - zeroRPC 多处理的奇怪问题

zeromq - ZMQ 是否公开任何内部日志记录?如果是这样,你如何使用它?

c - C 中 INT_MAX 宏和未初始化值的使用