weidai11 / cryptopp

free C++ class library of cryptographic schemes
https://cryptopp.com
Other
4.67k stars 1.47k forks source link

xchacha20 incompatible with libsodium and golang.org/x/crypto #1183

Closed pa-sowa closed 1 year ago

pa-sowa commented 1 year ago

Crypto++ XChaCha20 implementation cannot decrypt data that both libsodium and Go's golang.org/x/crypto decrypt correctly. Do I need to do it differently with Crypto++? I couldn't find a way to make it work.

Below is a proof of concept program that uses libsodium to encrypt and Crypto++ to decrypt, which doesn't work as expected:

Crypto++ version: 8.6.0-2ubuntu1 Operating system: Ubuntu 22.04 x86_64

#include <cryptopp/chacha.h>
#include <cryptopp/cryptlib.h>
#include <sodium.h>

#include <array>
#include <cstdint>
#include <iostream>

int main(int argc, char *argv[])
{
    using namespace CryptoPP;

    const size_t keySize = 32;
    const size_t ivSize = 24;
    const uint8_t key[keySize + 1] = "12345678901234567890123456789012";
    const uint8_t iv[ivSize + 1] = "123456789012345678901234";
    std::array<byte, 4> origin = {'t', 'e', 's', 't'};

    std::array<byte, origin.size()> encrypted;
    crypto_stream_xchacha20_xor(encrypted.data(), origin.data(), origin.size(), iv, key);

    std::array<byte, encrypted.size()> decrypted;
    XChaCha20::Decryption dec;
    dec.SetKeyWithIV(key, keySize, iv, ivSize);
    dec.ProcessData(decrypted.data(), encrypted.data(), encrypted.size());

    for (byte b : decrypted) {
        std::cout << b;
    }
    std::cout << std::endl;

    return 0;
}

Build: g++ -o test test.cpp -lsodium -lcrypto++

noloader commented 1 year ago

Please run the test program for ChaCha and XChaCha. The ChaCha test vectors were generated using Bernstein's reference implementation. The XChaCha were taken from the RFC, if I recall correctly.

$ ./cryptest.exe tv chacha
Using seed: 1672061537

Testing SymmetricCipher algorithm ChaCha.
..............................................................................
Tests complete. Total tests = 78. Failed tests = 0.

Also note that the IETF changed Bernstein's algorithm and called it ChaCha, too. As far as I know, Bernstein's ChaCha and the IETF's ChaCha are not always compatible. The IETF should have used a different name to avoid confusing users.

Also see https://www.cryptopp.com/wiki/ChaCha20, https://www.cryptopp.com/wiki/ChaChaTLS and https://www.cryptopp.com/wiki/XChaCha20 .