如何进入CommonCrypto CCKeyDerivationPBKDF?

时间:2016-07-31 06:44:05

标签: xamarin mono xamarin.ios

我正试图进入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。我相当肯定我的签名可能已经过时了。它需要什么?

1 个答案:

答案 0 :(得分:1)

由于pointer being freed was not allocated参数上的out标记,您收到derivedKey错误,只需将其作为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 = "StackOverflow";
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);

使用“原生”对象/减少编组:

(不得不以这种方式通过军事/航空航天认证/审查)

[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);

示例(w / Base64):

var passwordEntry = "StackOverflow";
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);