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

Can I swap the private and public key within ZeroMQ

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

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

目前,我的发布者正在使用他的私钥加密他要发送的数据,订阅者可以使用发布者的 public 密钥解密此数据。这是比 'encrypting' 数据更多的 'authenticating' 数据。因为当中间人存在时,他仍然可以解密所有数据,因为发布者的 public 密钥是 public.

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

我的publisher.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

我的subscriber.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

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

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

我已经测试过了,并且在我的 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 的体系结构中,是否可以使用 public 密钥加密数据(发布者套接字)和使用私钥解密数据(订阅者套接字)?

非常感谢,
罗伊

我认为您误解了 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.

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

但是您也可以担心流氓客户端,您当前的方案允许任何人连接。这是 Pieter Hintjens 的 the second article 可以帮助您解决“铁屋模式”的地方。关键部分是禁用 CURVE_ALLOW_ANY 并告诉服务器在哪里寻找客户端 public 证书:

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

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

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