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

罗伊·伦弗林克

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

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

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

我使用最新版本的ZeroMQ和CZMQ用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

我的订户

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

从这一点来看,发布者正在使用其私有密钥加密所有数据,而订阅正在使用发布者的公共密钥解密所有数据。我想交换这个系统。

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

我测试了它,并改变了zcert_load("cert.key")zcert_load("cert.pub")我的publisher.c。

我也在我的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曲线机制。Pieter Hintjens写了两篇伟大的文章,其中一篇是理论文章,您可以在其中找到:

客户端和服务器具有长期永久密钥,并且对于每个连接,它们都会创建并安全地交换短期临时密钥。每个密钥都是公共/秘密密钥对,遵循椭圆曲线安全性模型。

要启动安全连接,客户端需要服务器永久公共密钥。然后,它生成一个临时密钥对,并将包含其短期公共密钥的HELLO命令发送到服务器。HELLO命令对攻击者毫无价值。它不能识别客户。

服务器在获得HELLO后,将生成其自己的短期密钥对(一个连接总共使用四个密钥),并将此新的私钥编码为“ cookie”,并将其作为WELCOME命令发送回客户端。它还发送经过加密的短期公共密钥,因此只有客户端可以读取它。然后,它将丢弃此短期密钥对。

在此阶段,服务器尚未为客户端存储任何状态。它生成了一个密钥对,以仅客户端可以读取的方式将其发送回客户端,然后将其丢弃。

客户端返回一个INITIATE命令,该命令向服务器提供其cookie返回,并且客户端永久性公共密钥被加密为“凭证”,因此只有服务器才能读取它。就客户端而言,服务器现在已通过身份验证,因此它也可以在命令中发送回元数据。

服务器读取INITIATE,现在可以验证客户端永久公共密钥。它还解压缩cookie并获取其连接的短期密钥对。就服务器而言,客户端现在已通过身份验证,因此服务器可以安全地发送其元数据。双方然后可以发送消息和命令。

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

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

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

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

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章