当前位置:  开发笔记 > 编程语言 > 正文

与libsodium保持密钥交换

如何解决《与libsodium保持密钥交换》经验,为你挑选了1个好方法。

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

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

并且总有一个例子"bob"和"alice".这很好,但他们从未表明如何以安全的方式通过网络交换公钥.

那么如何推荐交换"alice/client"和"bob/server"的公钥.

它们总是使用相同的文件或同一台机器来生成密钥对.

以下是libsodium-php扩展的摘录:

$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);

小智.. 9

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

    通过防篡改的"带外通信"提供公钥或者如果通道对听众是安全的,则是共享秘密.(例如BittorrentSync,包含从设备到设备扫描的共享密钥的QR代码)

    让受信任的第三方在未加密发送公钥之前对其进行签名.(例如SSL/TLS中的证书颁发机构)

    证书固定(例如Google Chrome for Google URL)

如果您掌控着客户

由于您可能不想重新实现SSL/TLS,因此第一个或第三个选项可能是最佳选择.然而,第一种在客户端/服务器格式上有点难,因为PHP服务器可能只有互联网进行通信.

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

例如,Alice使用Bob的公钥和她自己的私钥来加密某些数据,并将其(以及唯一的随机数和Alice的公钥)发送给Bob.

Bob使用他收到的公钥和他自己的私钥来解密和验证加密的数据包.Bob可以安全地使用其中的任何数据,因为只有他和Alice可以解密它.

中间人怎么样?

好吧,Eve可以阻止Alice的消息并发送Eve的公钥,但她会盲目工作,因为Alice只发送用Alice的私钥和Bob的公钥加密的消息.

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

如果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或hex编码,因为密钥中的某些字节可能会因不同的字符编码而受到损坏.

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

如果您想在私钥泄漏的情况下保密,那么初始公钥/私钥对只应用于交换永远不会保存到永久存储介质的第二轮公钥(实质上,没有磁盘或数据库) ).由于您的案例只是一个测试应用程序,因此Forward Secrecy可能不是很重要.

第二轮密钥每隔一段时间(例如每24小时)被丢弃,从而降低过去数据由于OpenSSL的Heartbleed等漏洞而变得脆弱的风险.

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



1> 小智..:

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

    通过防篡改的"带外通信"提供公钥或者如果通道对听众是安全的,则是共享秘密.(例如BittorrentSync,包含从设备到设备扫描的共享密钥的QR代码)

    让受信任的第三方在未加密发送公钥之前对其进行签名.(例如SSL/TLS中的证书颁发机构)

    证书固定(例如Google Chrome for Google URL)

如果您掌控着客户

由于您可能不想重新实现SSL/TLS,因此第一个或第三个选项可能是最佳选择.然而,第一种在客户端/服务器格式上有点难,因为PHP服务器可能只有互联网进行通信.

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

例如,Alice使用Bob的公钥和她自己的私钥来加密某些数据,并将其(以及唯一的随机数和Alice的公钥)发送给Bob.

Bob使用他收到的公钥和他自己的私钥来解密和验证加密的数据包.Bob可以安全地使用其中的任何数据,因为只有他和Alice可以解密它.

中间人怎么样?

好吧,Eve可以阻止Alice的消息并发送Eve的公钥,但她会盲目工作,因为Alice只发送用Alice的私钥和Bob的公钥加密的消息.

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

如果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或hex编码,因为密钥中的某些字节可能会因不同的字符编码而受到损坏.

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

如果您想在私钥泄漏的情况下保密,那么初始公钥/私钥对只应用于交换永远不会保存到永久存储介质的第二轮公钥(实质上,没有磁盘或数据库) ).由于您的案例只是一个测试应用程序,因此Forward Secrecy可能不是很重要.

第二轮密钥每隔一段时间(例如每24小时)被丢弃,从而降低过去数据由于OpenSSL的Heartbleed等漏洞而变得脆弱的风险.

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

推荐阅读
LEEstarmmmmm
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有