Search code examples
.netcopensslpbkdf2

Using OpenSSL's PKCS5_PBKDF2_HMAC from .NET


I am attempting to utilize the PKCS5_PBKDF2_HMAC function from OpenSSL within a .NET application by utilizing a DllImport attribute as shown below. The .NET wrapper library OpenSSL.NET (http://openssl-net.sourceforge.net/) does not currently expose this OpenSSL function, so I have attempted to do so in a similar fashion but am failing due to my lack of experience with C.

[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public extern static int PKCS5_PBKDF2_HMAC(string pass, int passlen, byte[] salt, int saltlen, int iter, IntPtr digest, int keylen, out byte[] outBytes);

Here is the function signature from the OpenSSL source code:

int PKCS5_PBKDF2_HMAC(const char *pass, int passlen, const unsigned char *salt, int saltlen, int iter, const EVP_MD *digest, int keylen, unsigned char *out)

I am attempting to call this using the method below, but clearly have something wrong because I consistently get "Attempted to read or write protected memory" on the call to PKCS5_PBKDF2_HMAC.

public byte[] DeriveKey(MessageDigest digest, string password, byte[] salt, int iterations)
{                     
    var keyBuffer = new byte[digest.Size];
    Native.ExpectSuccess(Native.PKCS5_PBKDF2_HMAC(password, password.Length, salt, salt.Length, iterations, digest.Handle, digest.Size, out keyBuffer));

    return keyBuffer;
}

If someone else has been successful in doing this, or sees an error in my attempt I would appreciate any advice.


Solution

  • After a bit of trial and error I found that I didn't need the "out" prefix on the outBytes parameter. The external function definition that is working for me is:

    [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
    public extern static int PKCS5_PBKDF2_HMAC(string pass, int passlen, byte[] salt, int saltlen, int iter, IntPtr digest, int keylen, byte[] outBytes);