CryptDeriveKey für AES
-
Hallo zusammen,
ich möchte aus einem Passwort einen Session Key für AES Verschlüsselung erzeugen. Der Algorithmus ist CALG_AES, die Schlüssellänge ist 128 bit. Der Aufruf von
CryptDeriveKey
schlägt mit der Fehlermeldung "Ungültiger Algorithmus angegeben" fehl (Fehlercode 0x80090008). Wenn ich statt CALG_AES CALG_RC4 benutze funktioniert alles ohne Probleme.#include <windows.h> #include <wincrypt.h> #include <string> #include <algorithm> using namespace std; HCRYPTPROV create_provider( ALG_ID CryptAlgo ) { string ProviderNameNew = "Microsoft Enhanced RSA and AES Cryptographic Provider"; string ProviderNameOld = "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"; HCRYPTPROV retVal; if( ::CryptAcquireContext( &retVal, nullptr, nullptr, PROV_RSA_AES, 0 ) ) { return retVal; } if( ::CryptAcquireContext( &retVal, nullptr, ProviderNameNew.c_str(), PROV_RSA_AES, CRYPT_VERIFYCONTEXT ) ) { return retVal; } else if( ::CryptAcquireContext( &retVal, nullptr, ProviderNameOld.c_str(), PROV_RSA_AES, CRYPT_VERIFYCONTEXT ) ) { return retVal; } else if( ::CryptAcquireContext( &retVal, nullptr, nullptr, PROV_RSA_FULL, 0 ) ) { return retVal; } return 0; } bool update_hash( HCRYPTHASH Hash, const string& Data ) { if( Data.empty() ) return true; else return ::CryptHashData( Hash, reinterpret_cast<const BYTE*>( Data.data() ), Data.size(), 0 ); } HCRYPTHASH create_session_hash( HCRYPTPROV CryptProvider, ALG_ID HashAlgo, const string& Pass ) { HCRYPTHASH retVal; if( ::CryptCreateHash( CryptProvider, HashAlgo, 0, 0, &retVal ) ) { if( update_hash( retVal, Pass ) ) { return retVal; } else { ::CryptDestroyHash( CryptHash ); } } return 0; } HCRYPTKEY create_session_key( HCRYPTPROV Provider, ALG_ID CryptAlgo, const string& Pass ) { HCRYPTHASH CryptHash = create_session_hash( Provider, CALG_MD5, Pass ); if( CryptHash ) { HCRYPTKEY retVal; DWORD KeyLength = 128; DWORD Flags = CRYPT_EXPORTABLE | (KeyLength << 16); BOOL Result = ::CryptDeriveKey( Provider, CryptAlgo, CryptHash, Flags, &retVal ); ::CryptDestroyHash( CryptHash ); return retVal; } return 0; } vector<unsigned char> encrypt( ALG_ID CryptAlgo, const string& Pass, void const* Data, unsigned int Size ) { vector<unsigned char> retVal; if( Data && Size > 0 ) { HCRYPTPROV CryptProvider = create_provider( CryptAlgo ); if( !CryptProvider ) { WIN32_RAISE_LAST_ERROR; } HCRYPTKEY CryptKey = create_session_key( CryptProvider, CryptAlgo, Pass ); if( !CryptKey ) { ::CryptReleaseContext( CryptProvider, 0 ); WIN32_RAISE_LAST_ERROR; } const char* CharBuf = reinterpret_cast<const char*>( Data ); unsigned char CryptMem[BUFFER_SIZE]; for( int BytesLeft = Size; BytesLeft > 0; BytesLeft -= BLOCK_SIZE ) { BOOL FinalBlock = BytesLeft <= BLOCK_SIZE ? TRUE : FALSE; unsigned long BlockSize = BytesLeft <= BLOCK_SIZE ? BytesLeft : BLOCK_SIZE; copy( CharBuf, CharBuf + BlockSize, CryptMem ); if( !::CryptEncrypt( CryptKey, 0, FinalBlock, 0, CryptMem, &BlockSize, BUFFER_SIZE ) ) { ::CryptDestroyKey( CryptKey ); ::CryptReleaseContext( CryptProvider, 0 ); WIN32_RAISE_LAST_ERROR; } CharBuf += BlockSize; retVal.insert( retVal.end(), CryptMem, CryptMem + BlockSize ); } ::CryptDestroyKey( CryptKey ); ::CryptReleaseContext( CryptProvider, 0 ); } return retVal; }
CryptDeriveKey
in Zeile 72 liefert mir fürCALG_RC4
1 zurück, aber 0 fürCALG_AES
. Kann/darf ich für AES keinen Session Key aus einem Passwort generieren? Oder mache ich da irgendwas grundsätzlich falsch?Edit:
Zeilennummer korrigiert