4

我已经通过 libsodium 测试了公钥密码学并遇到了一个奇怪的行为。加密的消息在没有私钥的情况下被解密。

来自官方网站libsodium的示例

#include "sodium.h"

#define MESSAGE         "test"
#define MESSAGE_LEN     4
#define CIPHERTEXT_LEN (crypto_box_MACBYTES + MESSAGE_LEN)

static bool TestSodium()
{
    unsigned char alice_publickey[crypto_box_PUBLICKEYBYTES];
    unsigned char alice_secretkey[crypto_box_SECRETKEYBYTES];
    crypto_box_keypair(alice_publickey, alice_secretkey);

    unsigned char bob_publickey[crypto_box_PUBLICKEYBYTES];
    unsigned char bob_secretkey[crypto_box_SECRETKEYBYTES];
    crypto_box_keypair(bob_publickey, bob_secretkey);

    unsigned char nonce[crypto_box_NONCEBYTES];
    unsigned char ciphertext[CIPHERTEXT_LEN];
    randombytes_buf(nonce, sizeof nonce);

    // message alice -> bob
    if (crypto_box_easy(ciphertext, (const unsigned char*)MESSAGE, MESSAGE_LEN, nonce, bob_publickey, alice_secretkey) != 0)
    {
        return false;
    }

    unsigned char decrypted[MESSAGE_LEN + 1];
    decrypted[MESSAGE_LEN] = 0;

    // Original!
    //if (crypto_box_open_easy(decrypted, ciphertext, CIPHERTEXT_LEN, nonce, alice_publickey, bob_secretkey) != 0)

    // Whis works without Bobs secret key!
    if (crypto_box_open_easy(decrypted, ciphertext, CIPHERTEXT_LEN, nonce, bob_publickey, alice_secretkey) != 0)
    {
        return false;
    }

    if(strcmp((const char*)decrypted, MESSAGE) != 0) return false;

    return true;
}

使用公钥认证加密,Alice 可以使用 Bob 的公钥加密专门为 Bob 发送的机密消息。

使用 Alice 的公钥,Bob 可以在最终解密之前验证加密消息实际上是由 Alice 创建的并且没有被篡改。

Bob 只需要 Alice 的公钥、nonce 和密文。

为了向 Bob 发送消息,Alice 只需要 Bobs 的公钥。

在原始示例中,Bob 使用自己的密钥解密来自 Alice 的消息,并使用 Alice 的公钥对其进行验证。我在代码中犯了一个错误,并且在没有 Bob 的私钥的情况下正确解密了消息!

怎么可能?我的错误在哪里?谢谢

4

1 回答 1

2

是的,有可能

在 libsodium 中,公钥认证加密分三个独立的阶段完成,顺序如下:

  1. 密钥交换— 使用椭圆曲线 Diffie-Hellman算法 (X25519)从我的私钥和您的公钥生成共享密钥。

  2. 加密— 使用在步骤 1 中生成的共享密钥对明文消息应用对称密钥加密 (XSalsa20)。

  3. 身份验证— 生成 MAC (Poly1305),再次依赖于上述步骤中生成的密钥。

在步骤 2-3 中使用对称加密意味着Alice 和 Bob 必须可以计算相同的密钥,即

shared_key_computed_by_alice = crypto_box_beforenm(bob_pk, slice_sk)
shared_key_computed_by_bob = crypto_box_beforenm(alice_pk, bob_sk) 
assert(shared_key_computed_by_alice == shared_key_computed_by_bob)

由于我们要求两个密钥对生成相同的共享密钥,因此不难看出两个密钥对也可以解密相同的消息。

这很好

请注意,在您执行“错误”解密的过程中,您不仅使用了 Bob 的公钥,还使用了 Alice 的私钥(只有 Alice 知道)。

由于是 Alice 想要将加密消息发送给 Bob,这意味着 Alice 首先应该已经知道纯文本消息。因此,她可以使用自己的私钥解密该消息,这不是安全问题。

如果您将 Bob 的公钥与另一个人 (Eve) 的私钥一起使用,那么解密程序真的会失败。

 

如果您认为 Alice 能够解密她自己的消息是一个问题,您可以强制 Alice 在对话后销毁她的私钥,所以现在只有 Bob 可以解密它(并且不能从 Alice 发送更多消息)。

事实上,libsodium 提供了密封盒 API来执行此操作(生成一个临时密钥对并在加密后立即销毁它)。

于 2016-09-30T19:31:49.697 回答