-->

CryptAPI native Interop with .NET Code

2019-08-13 01:48发布

问题:

I have managed to encrypt data in native code using the Crypto API and decrypt this in .NET (C#) code, using RC2 algorithm and SHA for creating a key.

This is the native code (Delphi in this case):

// Get handle to CSP
If Not CryptAcquireContext(hCryptProv, nil, nil, PROV_RSA_FULL, 0) Then
    If Not CryptAcquireContext(hCryptProv, nil, nil, PROV_RSA_FULL, CRYPT_NEWKEYSET) Then
        ShowMessage('CryptAcquireContext '+IntToStr(GetLastError()));

// Create a hash object
If Not CryptCreateHash(hCryptProv, CALG_SHA, 0, 0, hHash) Then
        ShowMessage('CryptCreateHash '+IntToStr(GetLastError()));

// Hash the password
If Not CryptHashData(hHash,PByte(as_password), Length(as_password), 0) Then
        ShowMessage('CryptHashData '+IntToStr(GetLastError()));

// Derive a session key from the hash object
If Not CryptDeriveKey(hCryptProv, CALG_RC2, hHash, CRYPT_EXPORTABLE, hKey) Then
        ShowMessage('CryptDeriveKey '+IntToStr(GetLastError()));

// allocate buffer space
lul_datalen := Length(ablob_data);
lblob_buffer := ablob_data + '        ';
lul_buflen := Length(lblob_buffer);

If ab_encrypt Then
    // Encrypt data
    If CryptEncrypt(hKey, 0, True, 0, PByte(lblob_buffer), lul_datalen, lul_buflen) Then
        lblob_value := Copy(lblob_buffer, 1, lul_datalen)
  else
        ShowMessage('CryptEncrypt '+IntToStr(GetLastError()))
Else
    // Decrypt data
    If CryptDecrypt(hKey, 0, True, 0, PByte(lblob_buffer), lul_datalen) Then
        lblob_value := Copy(lblob_buffer, 1, lul_datalen)
    Else
        ShowMessage('CryptDecrypt '+IntToStr(GetLastError()));

// Destroy session key
If hKey > 0 Then
    CryptDestroyKey(hKey);

// Destroy hash object
If hHash > 0 Then
    CryptDestroyHash(hHash);

// Release CSP handle
If hCryptProv > 0 Then
    CryptReleaseContext(hCryptProv, 0);

  Result := lblob_value;

This the .NET code:

CspParameters cspParams = new CspParameters(1);
PasswordDeriveBytes deriveBytes = new PasswordDeriveBytes(aPassword, null, "SHA-1", 1, cspParams);
byte[] rgbIV = new byte[8];
byte[] key = deriveBytes.CryptDeriveKey("RC2", "SHA1", 0, rgbIV);

var provider = new RC2CryptoServiceProvider();
provider.Key = key;
provider.IV = rgbIV;

ICryptoTransform transform = provider.CreateDecryptor();

byte[] decyptedBlob = transform.TransformFinalBlock(arData, 0, arData.Length);

Now I want to use want to use the newer and better AES encryption, so in the native code I want to use PROV_RSA_AES instead of PROV_RSA_FULL, CALG_SHA_256 instead of CALG_SHA and CALG_AES_256 instead of CALG_RC2. That works fine on the native site.

But I can't get it to work on the .NET site. Of course I need to change RC2CryptoServiceProvider to AESCryptoServiceProvider and CspParameters must be initialized with 24 instead of 1. My problem is how to get working the PasswordDerivedBytes, what are the exact parameter value needed?

Thanks for any hints.

回答1:

PasswordDerivedBytes.CryptDeriveKey does not support AES. See: CryptDeriveKey fails for AES algorithm name