weidai11 / cryptopp

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

Speck implemententation not matching test vector from wiki #932

Closed dercdev closed 4 years ago

dercdev commented 4 years ago

Hello,

i am new to cryptopp and currently getting familiar with the lib. I am testing with the speck cipher and want to reproduce the example from the wiki shown here:

https://www.cryptopp.com/wiki/SPECK

I am refering to the following lines on the wiki:

Key: F36D4289293A07A0C1E3D8EAFBF83C6F IV: 50650B834D62457D3D5CBFE9708EC927 plain text: CBC Mode Test Cipher text: 952FB25AF03C17F972BEB9357AA48719 recovered text: CBC Mode Test

I started implementing with the code shown in the wiki and wanted to repoduce the test vector shown above. So see my example program:

CryptoPP::AutoSeededRandomPool prng;

//CryptoPP::SecByteBlock key(CryptoPP::SPECK128::DEFAULT_KEYLENGTH);
//prng.GenerateBlock(key, key.size());

const string ivstr = "50650B834D62457D3D5CBFE9708EC927";

string ivdecoded;
CryptoPP::StringSource ss(ivstr, true,
    new CryptoPP::HexDecoder(
        new CryptoPP::StringSink(ivdecoded)
    )
);

CryptoPP::SecByteBlock iv(reinterpret_cast<const CryptoPP::byte*>(&ivdecoded[0]), ivdecoded.size());     

const string k = "F36D4289293A07A0C1E3D8EAFBF83C6F";

string decoded;
CryptoPP::StringSource ss2(k, true,
                          new CryptoPP::HexDecoder(
                              new CryptoPP::StringSink(decoded)
                          ) // HexDecoder
); // StringSource
CryptoPP::SecByteBlock key(reinterpret_cast<const CryptoPP::byte*>(&decoded[0]), decoded.size());

std::cout << "Key: ";
CryptoPP::StringSource(key, key.size(), true, new CryptoPP::HexEncoder(new CryptoPP::FileSink(std::cout)));
std::cout << std::endl;

std::cout << "IV: ";
CryptoPP::StringSource(iv, sizeof(iv), true, new CryptoPP::HexEncoder(new CryptoPP::FileSink(std::cout)));
std::cout << std::endl;

string plain = "CBC Mode Test";
string cipher, encoded, recovered;

/*********************************\
\*********************************/

try
{
    std::cout << "plain text: " << plain << std::endl;

    CryptoPP::CBC_Mode<CryptoPP::SPECK128 >::Encryption e;
    e.SetKeyWithIV(key, key.size(), iv);

    // The StreamTransformationFilter adds padding
    //  as required. ECB and CBC Mode must be padded
    //  to the block size of the cipher.
    CryptoPP::StringSource(plain, true,
                           new CryptoPP::StreamTransformationFilter(e, new CryptoPP::StringSink(cipher), CryptoPP::BlockPaddingSchemeDef::DEFAULT_PADDING) // StreamTransformationFilter
    ); // StringSource

}
catch (const CryptoPP::Exception & e)
{
    std::cerr << e.what() << std::endl;
    //exit(1);
}

/*********************************\
\*********************************/

// Pretty print
std::cout << "Cipher text: ";
CryptoPP::StringSource(cipher, true, new CryptoPP::HexEncoder(new CryptoPP::FileSink(std::cout)));
std::cout << std::endl;

/*********************************\
\*********************************/

try
{
    CryptoPP::CBC_Mode<CryptoPP::SPECK128 >::Decryption d;
    d.SetKeyWithIV(key, key.size(), iv);

    // The StreamTransformationFilter removes
    //  padding as required.
    CryptoPP::StringSource s(cipher, true,
                             new CryptoPP::StreamTransformationFilter(d,
                                                                      new CryptoPP::StringSink(recovered), CryptoPP::BlockPaddingSchemeDef::DEFAULT_PADDING
                             ) // StreamTransformationFilter
    ); // StringSource

    std::cout << "recovered text: " << recovered << std::endl;
}
catch (const CryptoPP::Exception & e)
{
    cerr << e.what() << std::endl;
    //exit(1);
}

As a summary what my program does: I am using a fixed IV and key (with the values from the wiki) instead of randomly generated values. My expectation is, that the program produces as cipher text "952FB25AF03C17F972BEB9357AA48719" (value from the wiki). But it generetes the following cipher text instead: "D3937748C4A9D3B215E930F41C6AD76B" which differs from the value of the wiki. In my opinion there is an error in my implementation or the test vector is wrong. May be someone can help?

OS: Windows 10 x64 with VS 2019 Crypto++ library: 8.2 Release from the website

noloader commented 4 years ago

In my opinion there is an error in my implementation or the test vector is wrong. May be someone can help?

It is probably your implementation. The specification for SIMON and SPECK caused a lot of confusion when first released because the authors were a bit vague about endianess and presentation of test vectors. The kernel and Crypto++ had to change their implementations to align with what the authors stated in their paper (and not what they showed in their test vectors).

The NSA folks published an implementation guide at SIMON and SPECK Implementation Guide. It removed confusion for the implementors. You can find it at the NSA's GitHub.

You can also test the library's implementation using:

$ ./cryptest.exe tv simon
Using seed: 1581266323      

Testing SymmetricCipher algorithm SIMON-64/ECB.
................
Testing SymmetricCipher algorithm SIMON-64/CBC.
..............
Testing SymmetricCipher algorithm SIMON-64/CTR.
..............
Testing SymmetricCipher algorithm SIMON-128/ECB.
........................
Testing SymmetricCipher algorithm SIMON-128/CBC.
.....................
Testing SymmetricCipher algorithm SIMON-128/CTR.
.....................
Tests complete. Total tests = 110. Failed tests = 0.

$ ./cryptest.exe tv speck
Using seed: 1581266328      

Testing SymmetricCipher algorithm SPECK-64/ECB.
................
Testing SymmetricCipher algorithm SPECK-64/CBC.
..............
Testing SymmetricCipher algorithm SPECK-64/CTR.
..............
Testing SymmetricCipher algorithm SPECK-128/ECB.
........................
Testing SymmetricCipher algorithm SPECK-128/CBC.
.....................
Testing SymmetricCipher algorithm SPECK-128/CTR.
.....................
Tests complete. Total tests = 110. Failed tests = 0.
dercdev commented 4 years ago

I am familiar with the problem of endianness with speck. But in my opinion should my usage produce the exact same value shown in the wiki, but it does not.

dercdev commented 4 years ago

any ideas?

noloader commented 4 years ago

I think this was cleared under Issue #945