Hôm nay tôi đã cố gắng cả ngày để tìm ra cách đọc tệp nhị phân và giải mã nó.
Trong tệp của tôi, 4 byte đầu tiên mô tả định dạng tệp và 32 byte cuối cùng là tiêu đề, được mã hóa bằng Blowfish.
Vì vậy, tôi đã viết mã này để làm điều đó:
file chuỗi = "C:\\test.bin";
byte *tiêu đề = byte mới[32];
TẬP TIN *data = fopen(file.c_str(), "r");
nếu(dữ liệu == NULL)
{
return 1; //Lỗi khi mở file!
}
kiểu char[6];
gõ[5] = 0;
if(fread(type, sizeof(type) - 1, 1, data) < 1)
{
trở lại 2;
}
if(strcmp(type, "ABCD") != 0)
{
trở lại 3;
}
if(fread(tiêu đề, sizeof(tiêu đề), 1, dữ liệu) < 1)
{
return 2; //Lỗi đọc file!
}
khóa vector;
key.push_back(0xAA);
key.push_back(0xBB);
key.push_back(0xCC);
key.push_back(0xDD);
key.push_back(0xAA);
key.push_back(0xBB);
key.push_back(0xCC);
key.push_back(0xDD);
ECB_Mode::Giải mã giải mã(key.data(), key.size());
hết byte[32];
decryption.ProcessData(out, header, 32);
TẬP_TIN *outer = fopen("C:\\out.bin", "w");
fwrite (out, sizeof(byte), sizeof(out), bên ngoài);
Nhưng điều này không giải mã dữ liệu một cách chính xác.
Tôi đã làm gì sai?
Ở đây có nhiều thứ bốc mùi quá
fopen
nên sử dụng "rb"
Và "wb"
chế độ nhị phân
- bạn nên sử dụng
memcmp
thay vì strcmp
- Bạn chưa xác minh
bánh mì
4 byte thực sự đã được đọc
- Đối với dữ liệu nhị phân bạn nên ưu tiên
ký tự không dấu
(Ít cạm bẫy hơn liên quan đến phần mở rộng ký hiệu và hành vi không xác định khi tràn)
- Nếu bạn đang sử dụng C++, tại sao bạn lại sử dụng cstdlib, cstdio và cstring ngay từ đầu?
đây là một错误
if(fread(tiêu đề, sizeof(tiêu đề), 1, dữ liệu) < 1)
kích thước(tiêu đề)
đây làkích thước(byte*)
, hơn là những gì bạn có vẻ mong đợi32
Dưới đây là đánh giá nhanh về mã kiểu C++:Cập nhật Đã thêm trường độ dài để thử nghiệm chuyến đi khứ hồi thực sự của tôi (xem bên dưới).
bộ giải mã.cpp
:
#include
#include
#include
#include
#include
static std::vector khóa const { 's','e','c','r','e','t' };
byte tĩnh const CHỮ KÝ[] = "ABCD"; //{ 'A','B','C','D' };
int chính()
{
if (std::ifstream data {"test.bin", std::ios::binary})
{
kiểu char[] = { 0, 0, 0, 0 };
if (!data.read(loại, 4))
{
trở lại 2;
}
tự động không khớp = std::mismatch(std::begin(SIGNATURE), std::end(SIGNATURE), std::begin(type));
if (không khớp.first != std::end(SIGNATURE))
{
trở lại 3;
}
chiều dài uint32_t = 0;
if (!data.read(reinterpret_cast(&length), sizeof(length))) // TODO sử dụng thứ tự byte di động
{
trả về 4;
}
std::vector const bản mã { std::istreambuf_iterator(data), {} };
// để đọc 32 byte:
// std::copy_n(std::istreambuf_iterator(data), 32, std::back_inserter(ciphertext));
khẳng định(data.good() || data.eof());
khẳng định(ciphertext.size() >= length);
khẳng định(ciphertext.size() % CryptoPP::Blowfish::BLOCKSIZE == 0);
CryptoPP::ECB_Mode::Giải mã giải mã(key.data(), key.size());
std::vector bản rõ(ciphertext.size());
decryption.ProcessData(reinterpret_cast(plaintext.data()), ciphertext.data(), plaintext.size());
plaintext.resize(length); // cắt phần đệm
std::ofstream out("out.bin", std::ios::binary);
out.write(plaintext.data(), plaintext.size());
} khác
{
return 1; //Lỗi mở file
}
}
Tôi chưa có tài liệu để kiểm tra nó.
gia hạn Vì vậy, tôi đã làm MỘT mã hóa.cpp
Ngay cả bây giờ.
echo "Xin chào thế giới" ./encryptor
Kết quả là file 40 byte (sig + length + ciphertext = 4 + 4 + 32 = 40), base64:
test base64.bin
QUJDRAwAAABCaDMrpG0WEYePd7fI0wsHAQoNkUl1CjIBCg2RSXUKMg==
Bây giờ, kết quả kiểm tra giải mã là tốt. Lưu ý rằng tôi thấy rằng tôi cần đảm bảo rằng BLOCKSIZE đã được đệm, vì vậy tôi đã thêm một chiều dài
để lưu trữ kích thước thực tế của bản rõ nhằm tránh để lại rác sau khi giải mã.
Bạn có thể xem chuyến đi khứ hồi bằng cách thực hiện
echo 'Tạm biệt thế giới!!' ./encryptor && ./decryptor && cat out.bin
Lời chào sẽ được in sau khi giải mã.
đặc biệt chú ýVIỆC CẦN LÀM
. có lẽ bạn nên sử dụng Bộ lọc chuyển đổi luồng
trong đó thêm phần đệm theo yêu cầu.
Tôi là một lập trình viên xuất sắc, rất giỏi!