Я играл с AES и записать в.в. и производный ключ к файлу, так что я использую его позже для расшифровки ...AES шифрования C++ (не может расшифровать зашифрованный файл)
Следующая функция шифрует файл и сохраняет в.в. и полученный ключ в файл, он также сохраняет зашифрованный текст в отдельный файл:
void MainWindow::on_button_encrypt() try
{
using namespace std;
using namespace Gtk;
using namespace CryptoPP;
fstream file;
file.open(m_file_name + ".aes", std::ios::out | std::ios::trunc);
if (file.is_open())
{
// get the plain password:
SecByteBlock password;
password_dialog get_passwd(password);
get_passwd.run();
// generate random salt
const int SALT_SIZE = 32;
SecByteBlock salt(SALT_SIZE);
AutoSeededRandomPool prng;
prng.GenerateBlock(salt.BytePtr(), SALT_SIZE);
// derive a key from password and salt:
SecByteBlock key(AES::DEFAULT_KEYLENGTH);
PKCS5_PBKDF2_HMAC<SHA512> gen;
gen.DeriveKey(key.BytePtr(), key.size(), 1, password.BytePtr(), password.size(), salt.BytePtr(), salt.size(), 200);
// genereate random iv:
SecByteBlock iv(AES::BLOCKSIZE);
OS_GenerateRandomBlock(false, iv.BytePtr(), AES::BLOCKSIZE);
// encrypt plain text:
AES::Encryption enc(key.BytePtr(), AES::DEFAULT_KEYLENGTH);
CBC_Mode_ExternalCipher::Encryption mode(enc, iv);
string cipher_text;
StringSink* sink = new StringSink(cipher_text);
StreamTransformationFilter encryptor(mode, sink);
string plain_text = m_file_buffer->get_text();
encryptor.Put(reinterpret_cast<const byte*>(plain_text.c_str()), plain_text.length() + 1);
encryptor.MessageEnd();
// write the result:
file << cipher_text.c_str();
file.close();
file.open(m_file_name + ".key", std::ios::out | std::ios::trunc);
file << key << '\n' << iv;
file.close();
}
}
// catch ...
выше функция записывает в.в. и производный ключ к файлу.
0000000002F9F140
0000000002F9F4E0
Следующая функция должна прочитать файл и расшифровать его, используя * .key файл:
void MainWindow::on_button_decrypt()
{
using namespace std;
using namespace CryptoPP;
Gtk::MessageDialog info("Info");
fstream file;
file.open("decrypted.txt", ios::out | ios::trunc);
if (file.is_open())
{
// read the key:
fstream stream;
string input;
SecByteBlock key(AES::DEFAULT_KEYLENGTH);
SecByteBlock iv(AES::BLOCKSIZE);
stream.open("test.txt.key", std::ios::in);
if (stream.is_open())
{
getline(stream, input);
key.Assign(reinterpret_cast<const byte*>(input.c_str()), input.size());
input.clear();
getline(stream, input);
iv.Assign(reinterpret_cast<const byte*>(input.c_str()), input.size());
}
else
{
info.set_secondary_text("can't read key file");
info.run();
return;
}
// decrypt:
AES::Decryption dec(key, AES::DEFAULT_KEYLENGTH);
CBC_Mode_ExternalCipher::Decryption mode(dec, iv);
string plain_text;
StringSink* sink = new StringSink(plain_text);
StreamTransformationFilter decryptor(mode, sink);
try
{
// get encrypted text from buffer (obtained from other function):
string cipher_text = m_file_buffer->get_text();
decryptor.Put(reinterpret_cast<const byte*>(cipher_text.c_str()), cipher_text.size());
decryptor.MessageEnd();
file << plain_text;
file.close();
}
catch (CryptoPP::Exception& ex)
{
info.set_secondary_text(ex.what());
info.run();
}
}
}
CryptoPP trows исключение при дешифрования заявив это:
FileTransformationFilter: длина зашифрованного текста не кратная размеру блока.
Как никогда он ничего не бросает, если процесс дешифрования выполняется в первой функции (on_btn_encrypt()) там нет файла, поэтому, похоже, у меня проблема с чтением зашифрованного файла, но понятия не имею, как это сделать?
Это содержимое зашифрованного файла: & `OôÍoYjÜMe × Q ° Þ
открытый текст: некоторый текст
Вы видите, что я здесь отсутствует? большое спасибо!
EDIT:
вот переделки, которые решили эту проблему, как мотивационные по Qmick и Artjom:
ENCRYPTION
// encrypt the file:
AES::Encryption enc(key.BytePtr(), AES::DEFAULT_KEYLENGTH);
CBC_Mode_ExternalCipher::Encryption mode(enc, iv);
string file = m_file_name + ".aes";
FileSink* sink = new FileSink(file.c_str());
StreamTransformationFilter encryptor(mode, sink);
string plain_text = m_file_buffer->get_text();
encryptor.Put(reinterpret_cast<const byte*>(plain_text.c_str()), plain_text.length());
encryptor.MessageEnd();
// write the key:
file = m_file_name + ".key";
FileSink* out = new FileSink(file.c_str());
Base64Encoder* base64_enc = new Base64Encoder;
base64_enc->Attach(out);
base64_enc->Put(key.BytePtr(), key.size());
base64_enc->MessageEnd();
// write the iv:
file = m_file_name + ".iv";
FileSink* out2 = new FileSink(file.c_str());
Base64Encoder* base64_enc2 = new Base64Encoder;
base64_enc2->Attach(out2);
base64_enc2->Put(iv.BytePtr(), iv.size());
base64_enc2->MessageEnd();
РАСШИФРОВЫВАНИЕ:
//
// read key
//
string store_key;
StringSink* string_key_in = new StringSink(store_key);
Base64Decoder* base64_key_dec = new Base64Decoder(string_key_in);
string file = "test.txt.key";
FileSource* file_key_in = new FileSource(file.c_str(), true, base64_key_dec);
SecByteBlock key(AES::DEFAULT_KEYLENGTH);
key.Assign(reinterpret_cast<const byte*>(store_key.c_str()), store_key.size());
//
// read iv
//
string store_iv;
StringSink* string_iv_in = new StringSink(store_iv);
Base64Decoder* base64_iv_dec = new Base64Decoder(string_iv_in);
file = "test.txt.iv";
FileSource* file_iv_in = new FileSource(file.c_str(), true, base64_iv_dec);
SecByteBlock iv(AES::BLOCKSIZE);
iv.Assign(reinterpret_cast<const byte*>(store_iv.c_str()), store_iv.size());
// read ciphertext:
string store_ciphertext;
StringSink* ciphertext_in = new StringSink(store_ciphertext);
file = m_file_name;
FileSource* file_ciphertext_in = new FileSource(file.c_str(), true, ciphertext_in);
SecByteBlock cipher_text;
cipher_text.Assign(reinterpret_cast<const byte*>(store_ciphertext.c_str()), store_ciphertext.size());
//
// decrypt:
//
AES::Decryption dec(key, AES::DEFAULT_KEYLENGTH);
CBC_Mode_ExternalCipher::Decryption mode(dec, iv);
file = "decrypted.txt";
FileSink* sink = new FileSink(file.c_str());
StreamTransformationFilter decryptor(mode, sink);
decryptor.Put(cipher_text.BytePtr(), cipher_text.size());
decryptor.MessageEnd();
Проблема заключается в том, что длина зашифрованного текста не кратная размеру блока. (Duh). Прочитайте о блочных и вспомогательных режимах – deviantfan
@deviantfan, спасибо, я сделал, и, как я сказал в своем сообщении выше, такой проблемы нет, если дешифрование выполняется без чтения файла. – codekiddy
Вы должны прочитать его в двоичном формате, потому что зашифрованный текст может содержать всевозможные непечатаемые и пробельные символы, такие как '\ n' и' \ 0'. –