有沒有辦法從CryptoAPI獲得非確定性輸出?換句話說,加密字符串時會輸出不同的字符串。總是得到與CryptoAPI相同的加密字符串
例如,獲得與「密碼」密碼加密密鑰和字符串加密的「A」在使用CALG_AES_256,它總是返回「SnÆwÞ¢大號\ X1E?6FÏLþw」
我有點的n00b使用CryptoAPI,所以任何幫助表示讚賞。
編輯: 下面是來自微軟的示例代碼密碼系統的代碼decrypte和encrypt這是相同的代碼,只是縮短/壓實。此代碼作爲Win32控制檯應用程序在VS 2017中編譯。 pszSource和pszDest是C:\ temp文件夾中的兩個文件。 source.txt有我們試圖加密的信件。
時遇到的問題是從的CryptoAPI 這隱窩/解密代碼不允許某些字符串來進行加密,然後解密後的(即,n,T,L,P,AA,AB,AC,AD ,ae等)。如果有人能告訴我爲什麼,那會非常有幫助。
#include <windows.h>
#include <tchar.h>
#include <wincrypt.h>
#define KEYLENGTH 0x00800000
#define ENCRYPT_BLOCK_SIZE 8
bool MyDecryptFile(LPTSTR szSource,LPTSTR szDestination,LPTSTR szPassword);
bool MyEncryptFile(LPTSTR szSource,LPTSTR szDestination,LPTSTR szPassword);
int _tmain(int argc, _TCHAR* argv[])
{
LPTSTR pszSource = L"c:\\temp\\source.txt";
LPTSTR pszDestination = L"c:\\temp\\dest.txt";
LPTSTR pszPassword = L"t";
if (MyEncryptFile(pszSource, pszDestination, pszPassword))
{
_tprintf(TEXT("Encryption of the file %s was successful. \n"),pszSource);
_tprintf(TEXT("The encrypted data is in file %s.\n"),pszDestination);
}
if (MyDecryptFile(pszSource, pszDestination, pszPassword))
{
_tprintf(TEXT("Encryption of the file %s was successful. \n"),pszSource);
_tprintf(TEXT("The encrypted data is in file %s.\n"),pszDestination);
}
return 0;
}
bool MyEncryptFile(LPTSTR pszSourceFile,LPTSTR pszDestinationFile,LPTSTR pszPassword)
{
bool fReturn = false;
HANDLE hSourceFile = INVALID_HANDLE_VALUE, hDestinationFile = INVALID_HANDLE_VALUE;
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hKey = NULL, hXchgKey = NULL;
HCRYPTHASH hHash = NULL;
PBYTE pbBuffer = NULL;
DWORD dwBlockLen, dwBufferLen, dwCount;
hSourceFile = CreateFile(pszSourceFile,FILE_READ_DATA,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if (INVALID_HANDLE_VALUE == hSourceFile)
goto Exit_MyEncryptFile;
hDestinationFile = CreateFile(pszDestinationFile,FILE_WRITE_DATA,FILE_SHARE_READ,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
if (INVALID_HANDLE_VALUE == hDestinationFile)
goto Exit_MyEncryptFile;
CryptAcquireContext(&hCryptProv,NULL,MS_ENH_RSA_AES_PROV,PROV_RSA_AES,0);
CryptCreateHash(hCryptProv,CALG_SHA_256,0,0,&hHash);
CryptHashData(hHash,(BYTE *)pszPassword,lstrlen(pszPassword),0);
CryptDeriveKey(hCryptProv,CALG_AES_256,hHash,CRYPT_EXPORTABLE,&hKey);
dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
if (ENCRYPT_BLOCK_SIZE > 1)
dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;
else
dwBufferLen = dwBlockLen;
pbBuffer = (BYTE *)malloc(dwBufferLen);
bool fEOF = FALSE;
do
{
if (ReadFile(hSourceFile,pbBuffer,dwBlockLen,&dwCount,NULL))
{
if (dwCount < dwBlockLen)
fEOF = TRUE;
if (CryptEncrypt(hKey,NULL,fEOF,0,pbBuffer,&dwCount,dwBufferLen))
WriteFile(hDestinationFile,pbBuffer,dwCount,&dwCount,NULL);
}
}
while (!fEOF);
fReturn = true;
Exit_MyEncryptFile:
if (hSourceFile) CloseHandle(hSourceFile);
if (hDestinationFile) CloseHandle(hDestinationFile);
if (pbBuffer) free(pbBuffer);
if (hHash) {CryptDestroyHash(hHash);hHash = NULL;}
if (hKey) CryptDestroyKey(hKey);
if (hCryptProv) CryptReleaseContext(hCryptProv, 0);
return fReturn;
}
bool MyDecryptFile(LPTSTR pszSourceFile,LPTSTR pszDestinationFile,LPTSTR pszPassword)
{
bool fReturn = false;
HANDLE hSourceFile = INVALID_HANDLE_VALUE, hDestinationFile = INVALID_HANDLE_VALUE;
HCRYPTKEY hKey = NULL;
HCRYPTHASH hHash = NULL;
HCRYPTPROV hCryptProv = NULL;
PBYTE pbBuffer = NULL;
DWORD dwCount, dwBlockLen, dwBufferLen;
hSourceFile = CreateFile(pszDestinationFile,FILE_READ_DATA,FILE_SHARE_READ,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
if (INVALID_HANDLE_VALUE == hSourceFile)
goto Exit_MyDecryptFile;
hDestinationFile = CreateFile(pszSourceFile,FILE_WRITE_DATA,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if (INVALID_HANDLE_VALUE == hDestinationFile)
goto Exit_MyDecryptFile;
CryptAcquireContext(&hCryptProv,NULL,MS_ENH_RSA_AES_PROV,PROV_RSA_AES,0);
CryptCreateHash(hCryptProv,CALG_SHA_256,0,0,&hHash);
CryptHashData(hHash,(BYTE *)pszPassword,lstrlen(pszPassword),0);
CryptDeriveKey(hCryptProv,CALG_AES_256,hHash,CRYPT_EXPORTABLE,&hKey);
dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
dwBufferLen = dwBlockLen;
pbBuffer = (PBYTE)malloc(dwBufferLen);
bool fEOF = false;
do
{
if (!ReadFile(hSourceFile,pbBuffer,dwBlockLen,&dwCount,NULL))
goto Exit_MyDecryptFile;
if (dwCount <= dwBlockLen)
fEOF = TRUE;
LONG rv = CryptDecrypt(hKey,0,fEOF,0,pbBuffer,&dwCount);
if (rv==0)
{
DWORD dwErr = GetLastError(); // <--- fails if password and string are n, t, L, p, aa, ab, ac, ad , ae
goto Exit_MyDecryptFile;
}
if (!WriteFile(hDestinationFile,pbBuffer,dwCount,&dwCount,NULL))
goto Exit_MyDecryptFile;
}
while (!fEOF);
fReturn = true;
Exit_MyDecryptFile:
if (pbBuffer) free(pbBuffer);
if (hSourceFile) CloseHandle(hSourceFile);
if (hDestinationFile) CloseHandle(hDestinationFile);
if (hHash) {CryptDestroyHash(hHash);hHash = NULL;}
if (hKey) CryptDestroyKey(hKey);
if (hCryptProv) CryptReleaseContext(hCryptProv, 0);
return fReturn;
}
如何使用它來獲得KP_IV選項?
BOOL bRV;
bRV = CryptAcquireContextW(&hCryptProv, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, 0);
bRV = CryptGenKey(hCryptProv, CALG_AES_256,0,&hKey);
DWORD dwMode = CRYPT_MODE_CBC;
bRV = CryptSetKeyParam(hKey,KP_MODE,(BYTE*)&dwMode,0);
BYTE pbData[16];
memcpy(pbData,"n",sizeof("n")); // <--- Hard coded password
bRV = CryptSetKeyParam(hKey,KP_IV,pbData,0);
enter code here
當保存密碼驗證程序只是使用哈希函數是不夠的,只是添加鹽對提高安全性沒有多大作用。相反,用隨機鹽迭代HMAC約100ms持續時間,然後用散列表保存鹽。更好的是使用諸如'PBKDF2','Rfc2898DeriveBytes','password_hash','Bcrypt','passlib.hash'或類似函數的函數。關鍵是要讓攻擊者花費大量時間通過暴力破解密碼。 – zaph
散列函數是確定性的,這是它們的一個主要屬性,爲了獲得一個隨機輸出,你需要提供一個通常用密碼安全僞隨機數生成器[CSPRNG]獲得的隨機輸入(https://en.wikipedia。組織/維基/ Cryptographically_secure_pseudorandom_number_generator)。 – zaph
謝謝。舊的capicom.dll文件做了256個並且每次都給出了不同的字符串,但每次都正確解密。 – JeffR