【问题标题】:Can I swap the private and public key within ZeroMQ我可以在 ZeroMQ 中交换私钥和公钥吗
【发布时间】:2016-10-13 20:45:21
【问题描述】:

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

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

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

我正在使用最新版本的 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 的架构下,是否可以使用公钥加密数据(发布者套接字)和私钥解密数据(订阅者套接字)?

非常感谢,
罗伊

【问题讨论】:

    标签: c encryption zeromq


    【解决方案1】:

    我认为您误解了 ZeroMQ CURVE 机制。 Pieter Hintjens 写了两篇关于它的精彩文章,one is theoretical,您可以在其中找到:

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

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

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

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

    客户端返回一个 INITIATE 命令,该命令向服务器提供它的 cookie,以及客户端永久公钥,加密为“保证”,因此只有服务器可以读取它。就客户端而言,服务器现在已经过身份验证,因此它也可以在命令中发回元数据。

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

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

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

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

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

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

    【讨论】:

    • 按回车键快速。我已经阅读了 Pieter Hintjens 的两篇文章。我正在处理的事情是两台或多台机器之间的安全性。您说我必须将客户的证书转移到我的服务器。但就我而言,我正在使用发布订阅模式,这意味着我的订阅者在我的发布者启动并运行之前已经启动并运行。我所拥有的是建立与服务器私钥的连接,并且订阅者可以通过公钥访问。
    • 当我把密钥放到网上时(它是一个公钥,所以它可以通过整个网络访问)每个人都可以授权给我的发布者。这就是为什么我们可以使用zauth_configure_curve (auth, "*", ".curve"),但我们不能使用这个,因为我需要通过不安全的网络将公钥发送给我的发布者。这就是为什么我考虑使用我的公钥来设置我的发布者套接字,并使用发布者私钥来保护连接。因为那时我可以分发我的公钥,只有订阅者才能解密已发送的数据。
    • @RoyLenferink:谁先开始并不重要,订阅者或发布者。您只需要让您的发布者知道订阅者的密钥,否则无法验证订阅者。您可以用来简化密钥分发的一个技巧是在每个客户端上使用单个密钥,并在需要时通过某个安全通道将其传输给客户端(我将用它来更新答案)。除此之外,没有带有 CA 的 PKI 或类似的东西来独立于服务器对客户端的密钥进行签名。
    • 好的,那么这就回答了我的问题,即实际上不可能交换密钥。唯一的选择是使用 .curve 目录作为发布者并对订阅者进行身份验证。谢谢罗马
    猜你喜欢
    • 2012-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-09
    • 2012-03-11
    相关资源
    最近更新 更多