如何 PInvoke 到 CommonCrypto CCKeyDerivationPBKDF?

How Do I PInvoke Into CommonCrypto CCKeyDerivationPBKDF?

我正在尝试 PInvoke 到 CCKeyDerivationPBKDF here

方法签名如下所示:

int 
CCKeyDerivationPBKDF( CCPBKDFAlgorithm algorithm, const char *password, size_t passwordLen,
                      const uint8_t *salt, size_t saltLen,
                      CCPseudoRandomAlgorithm prf, uint rounds, 
                      uint8_t *derivedKey, size_t derivedKeyLen)
                      __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA);

目前我正在尝试:

[DllImport(ObjCRuntime.Constants.libSystemLibrary, EntryPoint = "CCKeyDerivationPBKDF")]
public extern static void CCKeyCerivationPBKDF(int algorithm, string password, int passwordLen,
    string salt, int saltLen, int prf, int rounds, out byte[] derivedKey, int derivedKeyLength);

我收到错误:

malloc: *** error for object 0xb9374fc61e8f9d1e: pointer being freed was not allocated

这是我第一次尝试 PInvoke。我相当确定我的签名可能已经过时了。它需要是什么?

由于 derivedKey 参数上的 out 标志,您收到 pointer being freed was not allocated 错误,只需将其作为 IntPtr (byte[]) 和 Mono 传递将正确编组:

CCKeyCerivationPBKDF 签名:

[DllImport(ObjCRuntime.Constants.libSystemLibrary, EntryPoint = "CCKeyDerivationPBKDF")]
public extern static int CCKeyCerivationPBKDF(
    int algorithm, 
    string password, 
    nint passwordLen,
    string salt, 
    nint saltLen, 
    UInt32 prf, 
    int rounds, 
    byte[] derivedKey, 
    int derivedKeyLength);

示例:

var passwordEntry = "Whosebug";
var saltEntry = "SaltyMcSalty";
var keyBytes = new byte[32 + 1];
Array.Clear(keyBytes, 0, keyBytes.Length);
var result = CCKeyCerivationPBKDF(2, passwordEntry, passwordEntry.Length, saltEntry, saltEntry.Length, 3, 1, keyBytes, keyBytes.Length);

使用 "native" 个对象/减少编组:

(不得不以这种方式通过 military/aerospace certification/review)

[DllImport(ObjCRuntime.Constants.libSystemLibrary, EntryPoint = "CCKeyDerivationPBKDF")]
public extern static int CCKeyCerivationPBKDF(
    int algorithm, 
    IntPtr password, 
    nuint passwordLen,
    IntPtr salt, 
    nuint saltLen, 
    UInt32 prf, 
    nuint rounds, 
    IntPtr derivedKey, 
    nuint derivedKeyLength);

示例(带 Base64):

var passwordEntry = "Whosebug";
var passwordBytes = System.Text.Encoding.UTF8.GetBytes(passwordEntry);
var passwordBase64 =  Convert.ToBase64String(passwordBytes);
var passwordNSStringBase64 = new NSString(passwordBase64);
var passwordNSData = new NSData(passwordNSStringBase64, NSDataBase64DecodingOptions.None);

var saltEntry = "SaltyMcSalty";
var saltBytes = System.Text.Encoding.UTF8.GetBytes(saltEntry);
var saltBase64 = Convert.ToBase64String(saltBytes);
var saltNSStringBase64 = new NSString(saltBase64);
var saltNSData = new NSData(saltNSStringBase64, NSDataBase64DecodingOptions.None);

var keyBytes = new NSMutableData();
keyBytes.Length = 33;
var result = CCKeyCerivationPBKDF(2, passwordNSData.Bytes, passwordNSData.Length, saltNSData.Bytes, saltNSData.Length, 3, 1, keyBytes.MutableBytes, keyBytes.Length - 1);