首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >与libsodium的安全密钥交换

与libsodium的安全密钥交换
EN

Stack Overflow用户
提问于 2014-03-21 07:05:02
回答 1查看 3.3K关注 0票数 6

我想做一个测试应用程序,它使用client从客户端到服务器进行通信。

有许多语言的端口:C#PHP,.

“鲍勃”和“爱丽丝”总是有一个例子。这很好,但是他们从来没有展示过如何以安全的方式通过网络交换公钥。

那么,建议如何将公钥交换为"alice/client“和"bob/server”。

他们总是使用同一个文件或同一台机器来生成密钥对。

下面是libsodium扩展的摘录:

代码语言:javascript
复制
$alice_kp = crypto_box_keypair();
$alice_secretkey = crypto_box_secretkey($alice_kp);
$alice_publickey = crypto_box_publickey($alice_kp);

$bob_kp = crypto_box_keypair();
$bob_secretkey = crypto_box_secretkey($bob_kp);
$bob_publickey = crypto_box_publickey($bob_kp);

$alice_to_bob_kp = crypto_box_keypair_from_secretkey_and_publickey
  ($alice_secretkey, $bob_publickey);

$bob_to_alice_kp = crypto_box_keypair_from_secretkey_and_publickey
  ($bob_secretkey, $alice_publickey);

$alice_to_bob_message_nonce = randombytes_buf(CRYPTO_BOX_NONCEBYTES);

$alice_to_bob_ciphertext = crypto_box('Hi, this is Alice',
                                      $alice_to_bob_message_nonce,
                                      $alice_to_bob_kp);

$alice_message_decrypted_by_bob = crypto_box_open($alice_to_bob_ciphertext,
                                                  $alice_to_bob_message_nonce,
                                                  $bob_to_alice_kp);

$bob_to_alice_message_nonce = randombytes_buf(CRYPTO_BOX_NONCEBYTES);

$bob_to_alice_ciphertext = crypto_box('Hi Alice! This is Bob',
                                      $bob_to_alice_message_nonce,
                                      $bob_to_alice_kp);

$bob_message_decrypted_by_alice = crypto_box_open($bob_to_alice_ciphertext,
                                                  $bob_to_alice_message_nonce,
                                                  $alice_to_bob_kp);
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-04-08 23:23:23

direct不提供任何直接的密钥交换方法。您可以通过几种不同的方式安全地进行密钥交换:

  1. 通过防篡改的“带外通信”传递一个公钥,或者如果com通道对听众是安全的,则是一个共享的秘密。(例如BittorrentSync,一种QR代码,包含从一个设备扫描到另一个设备的共享秘密)
  2. 让可信的第三方在未加密的公钥发送之前对其签名。(例如SSL/TLS中的证书颁发机构)
  3. 证书钉扎(出口)( Google Chrome for Google URL)

如果您控制了客户端

由于您可能不希望重新实现SSL/TLS,第一个或第三个选项可能是最好的。但是,在客户机/服务器格式中,第一种方式有点困难,因为PHP服务器可能只有互联网才能进行通信。

但是,如果控制客户端,则可以执行证书固定。也就是说,将Bob的公钥嵌入Alice的可执行文件中。然后,Alice只会用Bob的公钥加密消息。

例如,Alice使用Bob的公钥和自己的私钥对一些数据进行加密,并将其发送给Bob(连同惟一的nonce和Alice的公钥)。

Bob使用他收到的公钥和他自己的私钥来解密和验证加密的数据包。对于Bob来说,使用任何数据都是安全的,因为只有他和Alice才能解密。

中间的男人呢?

好吧,伊芙可以屏蔽爱丽丝的信息并发送伊芙的公钥,但她可能是瞎了,因为爱丽丝只会发送用爱丽丝的私钥和鲍勃的公钥加密的信息。

在鲍勃看来,她只是另一个客户。在爱丽丝的眼里,她会很沮丧,因为鲍勃似乎没有反应。

如果Eve发送Alice消息,它们总是被标记为无效,因为Alice使用Alice的私钥,Bob的公钥试图解密它们,这将失败,因为Eve没有Bob的私钥。

如果Alice没有经过验证的可执行文件,Eve可能会在下载时修改它(并插入Eve的公钥而不是Bob的公钥)。验证可以通过她的包管理器,应用商店(大多数使用一些用于代码签名& SSL/TLS下载)或签名的可执行文件/源tarball。

有关泄露私钥的说明见此答案的最后一节.

防篡改分布

在客户端的用户以某种方式(使用特定于用户的密码或将来使用SQRL)验证自己之后,您可以在HTTPS网站上提供QR代码。QR代码显示,客户端可以通过在OS中注册自己作为uri协议的处理程序来扫描或链接自定义协议。

上述QR代码/ uri方法的一个不那么复杂的替代方法是让用户复制粘贴上面提到的HTTPS站点的共享秘密,该秘密将用于使用钠的crypto_secretbox()方法进行初始公钥交换。

请注意,共享密钥/公钥可能应该是在传输期间编码的base64、base32或十六进制,因为密钥中的一些字节可能会被不同的字符编码破坏。

如果服务器的私钥被泄露了怎么办?

如果您希望在私钥泄漏时使用前向保密,那么初始的公钥/私钥对应该只用于交换从未保存到永久存储介质(本质上是没有磁盘或数据库)的第二轮公钥。因为您的情况只是一个测试应用程序,所以前向保密可能并不是很重要。

第二轮密钥每隔一段时间就会被丢弃(就像每24小时一样),减少过去的数据由于诸如OpenSSL的心脏出血之类的错误而变得脆弱的风险。

在传统的使用PHP的are服务器中,这可能很难做到,因为每个HTTP请求都会重置所有变量。适当配置的memcached实例可能是一个选项,但有泄漏临时私钥的风险。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22552341

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档