Jeggu
Jeggu

Reputation: 579

ciphertext length is not a multiple of block size in cryptopp

My program could encrypt text and save it in a file, and decrypt the cipher text after getting from the file.

But I keep on getting this error

terminate called after throwing an instance of 'CryptoPP::InvalidCiphertext'
what(): StreamTransformationFilter: ciphertext length is not a multiple of block size

While reading data from file i am getting file size as ciphertext length but content size is less what might be the wrong.

code:

std::string key = "0123456789abcdef";
std::string plaintext = "name macmilan age 24 ciy bonn country germany";
std::string ciphertext;
std::string decryptedtext;

CryptoPP::AES::Encryption aesEncryption((byte *)key.c_str(), CryptoPP::AES::DEFAULT_KEYLENGTH);
CryptoPP::ECB_Mode_ExternalCipher::Encryption cbcEncryption( aesEncryption);

CryptoPP::StreamTransformationFilter stfEncryptor(cbcEncryption, new CryptoPP::StringSink( ciphertext ) );
stfEncryptor.Put( reinterpret_cast<const unsigned char*>( plaintext.c_str() ), plaintext.length() + 1 );
stfEncryptor.MessageEnd();

CryptoPP::AES::Decryption aesDecryption((byte *)key.c_str(), CryptoPP::AES::DEFAULT_KEYLENGTH);
CryptoPP::ECB_Mode_ExternalCipher::Decryption cbcDecryption( aesDecryption);

std::cout << "ciphertext Text:"<<ciphertext.c_str()<<"length"<<ciphertext.length()<< std::endl;

FILE *ptr = fopen("temp.txt", "w");

if(ptr){
    fprintf(ptr, "%s",ciphertext.c_str());
    fclose(ptr);
    ptr = NULL;
}

ptr = fopen("temp.txt", "r");
if(ptr){
    fseek(ptr, 0, SEEK_END);
    size_t size = ftell(ptr);
    std::cout << "file size"<<size<< std::endl;
    char* temp = new char[size];
    rewind(ptr);
    fscanf(ptr,"%s",temp);
    ciphertext = temp;
    delete[] temp;
    ptr = NULL;
}

std::cout << "ciphertext Text:"<<ciphertext.c_str()<<"length"<<ciphertext.length() << std::endl;
try{
    CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink( decryptedtext ) );
    stfDecryptor.Put( reinterpret_cast<const unsigned char*>( ciphertext.c_str() ), ciphertext.size() );
    stfDecryptor.MessageEnd();
}
catch(CryptoPP::Exception &e)
{
    std::cout << "Decrypted Text:"<<e.what();

}
std::cout << "Decrypted Text: " << std::endl;
std::cout << decryptedtext;
std::cout << std::endl << std::endl;

system("pause");

return 0;

output:

ciphertext Text:î4¬■◄vqù┼Ä╢óΣ*₧z┐É;'!ìy─ªú√@╕╡Oh∙2♠ε\→ktáäì╘aÄδ▌length48
file size48
ciphertext Text:î4¬■◄vqù┼Ä╢óΣ*₧z┐É;'!ìy─ªú√@╕╡Oh∙2♠ε\length37
Decrypted Text:StreamTransformationFilter: ciphertext length is not a multiple o
f block sizeDecrypted Text:
name macmilan ag

Upvotes: 0

Views: 7268

Answers (3)

JGC
JGC

Reputation: 12997

In encryption various characters may appear including null (0). So when you write encrypted string in file you write null too. When you are retrieving encrypted value reader gets null character and assumes that string has been terminated. so it will be shorter. For resolve you have to use coding like Base64 or MD5 or open file and read in binary mode

Upvotes: 4

TonyK
TonyK

Reputation: 17124

When reading and writing binary files, the mode parameter to fopen must be "rb" or "wb", otherwise non-printable characters in the file may be interpreted as control characters. Here it looks like you have a Ctrl-Z (hex 0x1a) in your data, which is an end-of-file marker in a text file.

Upvotes: 1

Alan Stokes
Alan Stokes

Reputation: 18974

You probably want to read and write your file in binary mode - use "wb" and "rb" in your calls to fopen.

Also you might want to use fwrite and fread. fscanf will stop on whitespace which wouldn't help you.

Upvotes: 2

Related Questions