У меня есть код класса, использующий cryptoApi для шифрованя/дешифрования по DES и RSA. когда я запускаю его под WinXp все работает нормально, но когда запускаю под Win2000 шифрование по RSA перестает работать, при попытке зашифровать последовательность выпадает сообщение "Плохой ключ". Непонятно, почему так происходит — ключи инициализируются нормально без ошибок. Может кто поможет?
Код класса:
CZCrypt::CZCrypt()
{
m_hRSACryptProv = NULL;
m_hRSAKey = NULL;
m_hDESKey = NULL;
}
CZCrypt::~CZCrypt()
{
ReleaseRSA();
}
DWORD CZCrypt::InitRSA(char *UserName)
{
DWORD err = 0;
if(!CryptAcquireContext(&m_hRSACryptProv, UserName, MS_DEF_PROV, PROV_RSA_FULL, 0))
{
err = GetLastError();
if(err != 0x80090016)
return err;
if(!CryptAcquireContext(&m_hRSACryptProv, UserName, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET))
return GetLastError();
}
return 0;
}
DWORD CZCrypt::GenDESKey()
{
if(m_hRSACryptProv == NULL)
return 1;
if(m_hDESKey)
CryptDestroyKey(m_hDESKey);
m_hDESKey = NULL;
if(!CryptGenKey(m_hRSACryptProv, CALG_DES, CRYPT_EXPORTABLE, &m_hDESKey)) //64 bit
return GetLastError();
return 0;
}
void CZCrypt::ReleaseRSA()
{
if(m_hRSACryptProv)
CryptReleaseContext(m_hRSACryptProv, 0);
m_hRSACryptProv = NULL;
if(m_hRSAKey)
CryptDestroyKey(m_hRSAKey);
m_hRSAKey = NULL;
if(m_hDESKey)
CryptDestroyKey(m_hDESKey);
m_hDESKey = NULL;
}
DWORD CZCrypt::GenRSAKeys()
{
if(m_hRSACryptProv == NULL)
return 1;
if(m_hRSAKey)
CryptDestroyKey(m_hRSAKey);
m_hRSAKey = NULL;
if(!CryptGenKey(m_hRSACryptProv, AT_KEYEXCHANGE, CRYPT_EXPORTABLE|0x04000000, &m_hRSAKey)) //1024 bit
return GetLastError();
return 0;
}
DWORD CZCrypt::GetRSAPublicKey(RSAPublicKey1024* pkey)
{
if(m_hRSACryptProv==NULL || m_hRSAKey==NULL)
return 1;
DWORD actual_data_length = sizeof(RSAPublicKey1024);
if(!CryptExportKey(m_hRSAKey, NULL, PUBLICKEYBLOB, 0, (BYTE*)pkey, &actual_data_length))
return GetLastError();
return 0;
}
DWORD CZCrypt::GetDESKey(DESKEY* dkey)
{
if(m_hRSACryptProv==NULL || m_hDESKey==NULL)
return 1;
DWORD actual_data_length = sizeof(DESKEY);
if(!CryptExportKey(m_hDESKey, NULL, PLAINTEXTKEYBLOB, 0, (BYTE*)dkey, &actual_data_length))
return GetLastError();
return 0;
}
DWORD CZCrypt::EncryptRSA(BYTE* plainbuf, int plainbufsize, DWORD* actual_data_length)
{
if(m_hRSACryptProv==NULL || m_hRSAKey==NULL)
return 1;
if(plainbufsize < 1024/8)
return 1;
if(!CryptEncrypt(m_hRSAKey, NULL, TRUE, 0, (BYTE*)plainbuf, actual_data_length, plainbufsize))
return GetLastError();
return 0;
}
DWORD CZCrypt::DecryptRSA(BYTE* cipherbuf, DWORD* actual_data_length)
{
if(m_hRSACryptProv==NULL || m_hRSAKey==NULL)
return 1;
if(!CryptDecrypt(m_hRSAKey, NULL, TRUE, 0, (BYTE*)cipherbuf, actual_data_length))
return GetLastError();
return 0;
}
DWORD CZCrypt::ImportRSAKey(BYTE* plainRSAkey, DWORD dwExp)
{
if(m_hRSACryptProv==NULL)
return 1;
if(m_hRSAKey != NULL)
{
if(!CryptDestroyKey(m_hRSAKey))
return 1;
m_hRSAKey = NULL;
}
RSAPublicKey1024 rkey;
CopyMemory(rkey.modulus, plainRSAkey, 1024/8);
rkey.publickeystruc.aiKeyAlg = ALG_TYPE_RSA|ALG_CLASS_KEY_EXCHANGE;
rkey.publickeystruc.bType = PUBLICKEYBLOB;
rkey.publickeystruc.bVersion = CUR_BLOB_VERSION;
rkey.publickeystruc.reserved = 0;
rkey.rsapubkey.bitlen = 1024;
rkey.rsapubkey.magic = 0x31415352; //RSA1
rkey.rsapubkey.pubexp = dwExp;
if(!CryptImportKey(m_hRSACryptProv, (BYTE*)&rkey, sizeof(rkey), NULL, CRYPT_EXPORTABLE, &m_hRSAKey))
return GetLastError();
return 0;
}
DWORD CZCrypt::ImportDESKey(BYTE* plainDESkey)
{
if(m_hRSACryptProv==NULL)
return 1;
if(m_hDESKey != NULL)
{
if(!CryptDestroyKey(m_hDESKey))
return 1;
m_hDESKey = NULL;
}
DESKEY dkey;
CopyMemory(dkey.keydata, plainDESkey, 8);
dkey.pubkey.bType = PLAINTEXTKEYBLOB;
dkey.pubkey.bVersion = CUR_BLOB_VERSION;
dkey.pubkey.reserved = 0;
dkey.pubkey.aiKeyAlg = CALG_DES;
dkey.keysize = 8;
if(!CryptImportKey(m_hRSACryptProv, (BYTE*)&dkey, sizeof(dkey), NULL, CRYPT_EXPORTABLE, &m_hDESKey))
return GetLastError();
return 0;
}
DWORD CZCrypt::EncryptDES(BYTE* plainbuf, int plainbufsize, DWORD* pActual_data_length)
{
int blocksize = 64/8;
if(m_hRSACryptProv==NULL || m_hDESKey==NULL)
return 1;
//Check for minimum buffer length (it is necessary to have one additional empty block at the end of buffer)
//cout<<"Init Ok"<<endl;
if((DWORD)plainbufsize < (*pActual_data_length&7)+8)
return 1;
DWORD bnSize = 0;
for(DWORD icx=0; icx<*pActual_data_length; icx+=blocksize)
{
DWORD block_sz = blocksize;
BOOL bLast = FALSE;
if(icx+blocksize >= *pActual_data_length)
{
block_sz = *pActual_data_length - icx;
bLast = TRUE;
}
if(!CryptEncrypt(m_hDESKey, NULL, bLast, 0, (BYTE*)plainbuf+icx, &block_sz, plainbufsize-icx))
return GetLastError();
bnSize += block_sz;
}
*pActual_data_length = bnSize;
return 0;
}
DWORD CZCrypt::DecryptDES(BYTE* cipherbuf, DWORD* pActual_data_length)
{
int blocksize = 64/8;
if(m_hRSACryptProv==NULL || m_hDESKey==NULL)
return 1;
DWORD bnSize = 0;
for(DWORD icx=0; icx<*pActual_data_length; icx+=blocksize)
{
DWORD block_sz = blocksize;
BOOL bLast = FALSE;
if(icx+blocksize >= *pActual_data_length)
{
block_sz = *pActual_data_length - icx;
bLast = TRUE;
}
if(!CryptDecrypt(m_hDESKey, NULL, bLast, 0, (BYTE*)cipherbuf+icx, &block_sz))
return GetLastError();
bnSize += block_sz;
}
*pActual_data_length = bnSize;
return 0;
}