Php 使用libnaid进行安全密钥交换

Php 使用libnaid进行安全密钥交换,php,cryptography,libsodium,nacl-cryptography,Php,Cryptography,Libsodium,Nacl Cryptography,我想做一个测试应用程序,它使用libnaid从客户机到服务器进行通信 有多种语言的多个端口: , 还有一个例子是“鲍勃”和“爱丽丝”。 这很好,但是他们从来没有展示过如何以安全的方式在网络上交换公钥 那么,建议如何将公钥交换为“alice/client”和“bob/server” 它们总是使用相同的文件或相同的机器来生成密钥对 以下是libnaid php扩展的摘录: $alice_kp = crypto_box_keypair(); $alice_secretkey = crypto_box

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

有多种语言的多个端口: ,

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

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

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

以下是libnaid 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);

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

  • 通过防篡改的“带外通信”传递公钥,或者如果com通道对侦听器是安全的,则传递共享秘密。(例如BittorrentSync,一种二维码,包含从一个设备扫描到另一个设备的共享秘密)

  • 在公钥未加密发送之前,请受信任的第三方对其进行签名。(SSL/TLS中的证书颁发机构除外)

  • 证书固定(例如,用于谷歌URL的谷歌浏览器)

  • 如果你控制着客户 因为您可能不想重新实现SSL/TLS,所以第一个或第三个选项可能是最好的。然而,第一种在客户机/服务器格式中有点困难,因为PHP服务器可能只有internet可以通过它进行通信

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

    例如,Alice使用Bob的公钥和她自己的私钥加密某些数据,并将其(连同唯一的nonce和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码显示客户端可以通过向操作系统注册自己作为uri协议的处理程序来扫描或链接自定义协议

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

    请注意,共享密钥/公钥在传输过程中可能应该是base64、base32或十六进制编码,因为密钥中的某些字节可能会被不同的字符编码弄乱

    如果服务器私钥泄漏怎么办? 如果您希望防止私钥泄漏,则初始公钥/私钥对应仅用于交换第二轮公钥,这些公钥永远不会保存到永久存储介质(本质上,没有磁盘或数据库)。因为您的案例只是一个测试应用程序,所以前向保密可能不是很重要

    第二轮密钥每隔一段时间(如每24小时)就会被丢弃一次,从而降低了过去的数据因OpenSSL的Heartbleed等错误而变得易受攻击的风险

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

    libnaid现在有