Any code I tried that uses AES encryption, fails to link (but the code
that uses decryption is fine - go figure). Other primitives don't seem
to cause problems. Code stopped linking with the move from 5.5.2 to
5.6.0. It applies only to the code that uses AES encryption (CBC in my
case), AES decryption does not seem to be affected. Replacing AES with
e.g. MARS also cures the problem - the issue is definitely with the
new code for AES/Rijndael in 5.6.0.
Mac OS X 10.5.6 Leopard, gcc-4.2.1 (tried with 4.0.1 with the same
result). Everything works fine with 5.5.2.
Here's the command line and the error messages:
$ g++ -I/usr/include/cryptopp -o t1 t1.cpp -lcryptopp -lstdc++
Undefined symbols:
"CryptoPP::Rijndael::Enc::AdvancedProcessBlocks(unsigned char
const*, unsigned char const*, unsigned char*, unsigned long, unsigned
int) const", referenced from:
vtable for CryptoPP::BlockCipherFinal<(CryptoPP::CipherDir)0,
CryptoPP::Rijndael::Enc>in ccYwjfFL.o
vtable for CryptoPP::ClonableImpl<CryptoPP::BlockCipherFinal<
(CryptoPP::CipherDir)0, CryptoPP::Rijndael::Enc>,
CryptoPP::Rijndael::Enc>in ccYwjfFL.o
"non-virtual thunk to CryptoPP::Rijndael::Enc::AdvancedProcessBlocks
(unsigned char const*, unsigned char const*, unsigned char*, unsigned
long, unsigned int) const", referenced from:
vtable for CryptoPP::BlockCipherFinal<(CryptoPP::CipherDir)0,
CryptoPP::Rijndael::Enc>in ccYwjfFL.o
vtable for CryptoPP::ClonableImpl<CryptoPP::BlockCipherFinal<
(CryptoPP::CipherDir)0, CryptoPP::Rijndael::Enc>,
CryptoPP::Rijndael::Enc>in ccYwjfFL.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
Here's the actual code taken from the FAQ Web page <http://
www.cryptopp.com/fom-serve/cache/79.html> (lest people think that it's
my code that's at fault :-):
#include <iostream>
#include <iomanip>
#include "modes.h"
#include "aes.h"
#include "filters.h"
int main(int argc, char* argv[]) {
//
// Key and IV setup
//
byte key[ CryptoPP::AES::DEFAULT_KEYLENGTH ], iv
[ CryptoPP::AES::BLOCKSIZE ];
memset( key, 0x00, CryptoPP::AES::DEFAULT_KEYLENGTH );
memset( iv, 0x00, CryptoPP::AES::BLOCKSIZE );
//
// String and Sink setup
//
std::string plaintext = "Now is the time for all good men to come
to the aide...";
std::string ciphertext;
std::string decryptedtext;
//
// Dump Plain Text
//
std::cout << "Plain Text (" << plaintext.size() << " bytes)" <<
std::endl;
std::cout << plaintext;
std::cout << std::endl << std::endl;
//
// Create Cipher Text
//
CryptoPP::AES::Encryption aesEncryption(key,
CryptoPP::AES::DEFAULT_KEYLENGTH);
CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcEncryption
( aesEncryption, iv );
CryptoPP::StreamTransformationFilter stfEncryptor(cbcEncryption,
new CryptoPP::StringSink( ciphertext ) );
stfEncryptor.Put( reinterpret_cast<const unsigned char*>
( plaintext.c_str() ), plaintext.length() + 1 );
stfEncryptor.MessageEnd();
//
// Dump Cipher Text
//
std::cout << "Cipher Text (" << ciphertext.size() << " bytes)" <<
std::endl;
for( int i = 0; i < ciphertext.size(); i++ ) {
std::cout << "0x" << std::hex << (0xFF & static_cast<byte>
(ciphertext[i])) << " ";
}
std::cout << std::endl << std::endl;
//
// Decrypt
//
CryptoPP::AES::Decryption aesDecryption(key,
CryptoPP::AES::DEFAULT_KEYLENGTH);
CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption
( aesDecryption, iv );
CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption,
new CryptoPP::StringSink( decryptedtext ) );
stfDecryptor.Put( reinterpret_cast<const unsigned char*>
( ciphertext.c_str() ), ciphertext.size() );
stfDecryptor.MessageEnd();
//
// Dump Decrypted Text
//
std::cout << "Decrypted Text: " << std::endl;
std::cout << decryptedtext;
std::cout << std::endl << std::endl;
return 0;
}