我在 C DLL 中有一个执行 SCrypt key 派生的函数,但我在将这些值编码到我的 C# 程序中时遇到了真正的麻烦。
C中的函数声明如下:
__declspec(dllexport) int scrypt(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p,uint8_t * buf, size_t buflen);
passwd 和 salt 都通过指向 uint8 数组的指针传递,N、r 和 p 是算法的调整值。 Buflen 是您希望输出缓冲区的大小。 buf 是输出缓冲区(因此我认为需要是 ref 或 out);
我尝试了各种方法,最近的方法是 Marshal.Copy 将数据从 IntPtr 移到字节数组(反之亦然),但是因为这些是 UInt 指针而不是 IntPtr 我不知道如果那是对的。目前,当我尝试将数据从 buf IntPtr 复制回数组时,它会崩溃。
如果有任何帮助,我将不胜感激。
class Program
{
[DllImport("SCrypt.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
public static extern int scrypt(IntPtr passwd, UIntPtr passwdlen, IntPtr salt, UIntPtr saltlen, UInt64 N, UInt32 r, UInt32 p, out IntPtr buf, UIntPtr buflen);
static void Main(string[] args)
{
byte[] encoded = new byte[32];
IntPtr encodedptr;
byte[] password = System.Text.Encoding.Unicode.GetBytes("test");
byte[] salt = System.Text.Encoding.Unicode.GetBytes("ThisistheSaltweareusingforthiskey");
IntPtr passwordptr, saltptr;
passwordptr = Marshal.AllocHGlobal(password.Length);
Marshal.Copy(password, 0, passwordptr, password.Length);
saltptr = Marshal.AllocHGlobal(salt.Length);
Marshal.Copy(salt, 0, saltptr, salt.Length);
int returnVal = scrypt(passwordptr, (UIntPtr)password.Length, saltptr, (UIntPtr)salt.Length, 262144, 8, 1,out encodedptr,(UIntPtr) 32);
Marshal.Copy(encodedptr, encoded, 0, 32);
Console.WriteLine(BitConverter.ToString(encoded));
Console.ReadKey();
}
}
最佳答案
我可能会使用以下函数声明:
public static extern int scrypt(byte[] passwd, uint passwdlen, byte[] salt, uint saltlen, ulong N, uint r, uint p, byte[] buf, uint buflen).
请记住,有多种不同的方法来编码某些类型,但在这种情况下,上述变体可能是最清晰的,因为它直接映射到相应的类型。
您可以通过请求 Encoding
为您完成此操作,将 string
简单地转换为 byte[]
。对于密码,只要您将其转换为 Unicode,一切都应该没问题。但请确保在可能需要将密码转换为 byte[]
的每个地方使用相同的变体。
关于c# - 编码 native 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24799691/