Reputation: 579
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
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
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
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