Encryption 始终使用CryptoAPI获取相同的加密字符串

Encryption 始终使用CryptoAPI获取相同的加密字符串,encryption,cryptoapi,Encryption,Cryptoapi,有没有办法从CryptoAPI获取非确定性输出?换句话说,加密字符串时会输出不同的字符串 例如,当使用CALG_AES_256导出密码为“password”且字符串为“a”的加密密钥时,它总是返回“SnÆwÞ、L\x1e?6FÏLþw” 我在使用CryptoAPI方面有点像n00b,因此非常感谢您的帮助 编辑: 这是微软示例代码中的加密代码,这是相同的代码,只是缩短/压缩了。此代码在VS2017中编译为Win32控制台应用程序。pszSource和pszDest是C:\temp文件夹中的两个文件

有没有办法从CryptoAPI获取非确定性输出?换句话说,加密字符串时会输出不同的字符串

例如,当使用CALG_AES_256导出密码为“password”且字符串为“a”的加密密钥时,它总是返回“SnÆwÞ、L\x1e?6FÏLþw”

我在使用CryptoAPI方面有点像n00b,因此非常感谢您的帮助

编辑: 这是微软示例代码中的加密代码,这是相同的代码,只是缩短/压缩了。此代码在VS2017中编译为Win32控制台应用程序。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;
}
#包括
#包括
#包括
#定义键长度0x00800000
#定义加密块大小8
bool mydecrypt文件(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(“文件%s的加密成功。\n”)、pszSource);
_tprintf(TEXT(“加密数据在文件%s中。\n”)、pszDestination;
}
if(MyDecryptFile(pszSource、pszDestination、pszPassword))
{
_tprintf(TEXT(“文件%s的加密成功。\n”)、pszSource);
_tprintf(TEXT(“加密数据在文件%s中。\n”)、pszDestination;
}
返回0;
}
bool MyEncryptFile(LPTSTR pszSourceFile、LPTSTR pszDestinationFile、LPTSTR pszPassword)
{
bool-fReturn=false;
HANDLE hSourceFile=无效的\u HANDLE\u值,hDestinationFile=无效的\u HANDLE\u值;
HCRYPTPROV HCRYPTPROV=NULL;
HCRYPTKEY hKey=NULL,hXchgKey=NULL;
HCRYPTHASH hHash=NULL;
PBYTE pbBuffer=NULL;
DWORD dwBlockLen、dwBufferLen、dwCount;
hSourceFile=CreateFile(pszourcefile,文件读取数据,文件共享读取,NULL,打开现有,文件属性正常,NULL);
if(无效的\u句柄\u值==hSourceFile)
转到退出文件;
hDestinationFile=CreateFile(pszDestinationFile,文件写入数据,文件共享读取,NULL,总是打开,文件属性正常,NULL);
if(无效的\u句柄\u值==hDestinationFile)
转到退出文件;
CryptAcquireContext(&hCryptProv,NULL,MS_ENH_RSA_AES_PROV,PROV_RSA_AES,0);
CryptCreateHash(hCryptProv、CALG_SHA_256,0,0和hHash);
CryptHashData(hHash,(字节*)pszPassword,lstrlen(pszPassword),0);
CryptDeriveKey(hCryptProv、CALG_AES_256、hHash、CRYPT_EXPORTABLE和hKey);
dwBlockLen=1000-1000%加密块大小;
如果(加密块大小>1)
dwBufferLen=dwBlockLen+加密块大小;
其他的
dwBufferLen=dwBlockLen;
pbBuffer=(字节*)malloc(dwBufferLen);
bool-fEOF=FALSE;
做
{
if(ReadFile(hSourceFile、pbBuffer、dwBlockLen和dwCount,NULL))
{
if(dwCount如果(dwCount如果您想在使用相同密钥加密相同的明文时获得不同的cypertext,则必须使用CBC操作模式

为了使用CBC正确加密,您需要每次生成不同的随机初始化向量(IV)。 为了解密,您需要知道加密过程中使用的IV。 因此,IV必须(清晰地)与密码文本相关联

参考您的示例,在调用CryptDeriveKey函数时,CBC是默认模式,但它使用设置为零的IV,这使CBC操作模式的实用程序无效:

为了设置random IV,需要调用CryptSetKeyParam函数w
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