筆者嘗試 VCKBASE 上「加密之星」工具,發現其加密效果不佳:文字檔僅前段加密、MP3 加密後仍可正常播放。遂自行設計一種簡單卻能完整加密任意檔案、支援同密碼多次加密的方法。
將檔案從頭到尾逐位元組讀取並加密:
for (int i = 0; i < flen; i++) {
data[i] ^= m_password;
data[i] ^= flen; // 檔案長度參與運算,使同密碼多次加密結果不同
}
m_path)、密碼 (m_pass)__int64 epass(); // 密碼初始化
BOOL ecfile(LPCTSTR fpath); // 加密
BOOL dcfile(LPCTSTR fpath); // 解密
__int64 CEcfileDlg::epass() {
DWORD plen;
char *ppass;
__int64 mc = 8757735233305; // 固定種子
UpdateData(TRUE);
ppass = m_pass.GetBuffer(0);
plen = strlen(ppass);
for (int i = 0; i < (int)plen; i++) {
mc ^= ppass[i] | 128;
}
return mc;
}
BOOL CEcfileDlg::ecfile(LPCTSTR fpath) {
char *data;
CFile *file;
DWORD flen;
m_password = epass();
file = new CFile;
if (!file->Open(fpath, CFile::shareDenyNone | CFile::modeReadWrite))
return FALSE;
flen = file->GetLength();
data = new char[(int)flen];
file->SeekToBegin();
file->Read(data, flen);
// 逐位元組加密
for (int i = 0; i < (int)flen; i++) {
data[i] ^= m_password;
data[i] ^= flen;
}
file->SeekToBegin();
file->Write(data, flen);
delete[] data;
// 附加密碼驗證碼 (5 bytes "love" 加密後)
char cpass[5] = "love";
for (int j = 0; j < 5; j++)
cpass[j] ^= m_password;
file->SeekToEnd();
file->Write(&cpass, 5); // 檔案長度增加 5 bytes
file->Close();
delete file;
return TRUE;
}
BOOL CEcfileDlg::dcfile(LPCTSTR fpath) {
char *data;
CFile *file;
DWORD flen;
char love[5];
file = new CFile;
if (!file->Open(fpath, CFile::shareDenyNone | CFile::modeReadWrite))
return FALSE;
flen = file->GetLength();
data = new char[(int)flen];
// 驗證密碼:讀取末尾 5 bytes
file->Seek(-5, CFile::end);
file->Read(&love, 5);
m_password = epass();
for (int i = 0; i < 5; i++)
love[i] ^= m_password;
if (strcmp(love, "love") != 0) // 密碼錯誤
return FALSE;
// 解密(XOR 可逆,須用原始長度 flen-5)
file->SeekToBegin();
file->Read(data, flen);
for (int j = 0; j < (int)flen; j++) {
data[j] ^= m_password;
data[j] ^= (flen - 5);
}
file->SeekToBegin();
file->Write(data, flen);
file->SetLength(flen - 5); // 移除驗證碼
file->Close();
delete[] data;
delete file;
return TRUE;
}
Windows XP 下編譯通過並實測有效。