0

它接缝令人困惑,但我会尽力解释它!

我正在尝试在我的 C# 代码上运行 C++ DLL。

在这个 DLL 上,我有一个方法应该返回 20 个字符的 unsigned char*。代表 4 个字节的 5 个“字”。(sha-1 算法的输出)

我在我的 C# 项目中使用 DLLIMPORT,如下所示:

    [DllImport("hashLibrary.dll", CharSet = CharSet.Ansi)]
    static private extern string CallReturnString(IntPtr pHashClassObject);

这应该返回 5 WORDS 字符串。

这是我应该放弃字符串的 C++ 方法:

unsigned char* SHA1::Result(/*unsigned *message_digest_array*/)
{
int i;                                  // Counter
int j = 0;
static int s_chString[5];
static unsigned char s_out[20]; // 4 * 5 + 10 de bob
if (Corrupted)
{
    return false;
}

if (!Computed)
{
    PadMessage();
    Computed = true;
}

unsigned int a = 0;
a = H[0];
s_out[0] = (a >> (8*0)) & 0xff;
a = H[0];
s_out[1] = (a >> (8*1)) & 0xff;
a = H[0];
s_out[2] = (a >> (8*2)) & 0xff;
a = H[0];
s_out[3] = (a >> (8*3)) & 0xff;

a = H[1];
s_out[4] = (a >> (8*0)) & 0xff;
s_out[5] = (a >> (8*1)) & 0xff;
s_out[6] = (a >> (8*2)) & 0xff;
s_out[7] = (a >> (8*3)) & 0xff;

a = H[2];
s_out[8] = (a >> (8*0)) & 0xff;
s_out[9] = (a >> (8*1)) & 0xff;
s_out[10] = (a >> (8*2)) & 0xff;
s_out[11] = (a >> (8*3)) & 0xff;

a = H[3];
s_out[12] = (a >> (8*0)) & 0xff;
s_out[13] = (a >> (8*1)) & 0xff;
s_out[14] = (a >> (8*2)) & 0xff;
s_out[15] = (a >> (8*3)) & 0xff;

a = H[4];
s_out[16] = (a >> (8*0)) & 0xff;
s_out[17] = (a >> (8*1)) & 0xff;
s_out[18] = (a >> (8*2)) & 0xff;
s_out[19] = (a >> (8*3)) & 0xff;
s_out[20] = '\0';



return s_out;
}

在这段代码中,我尝试从 H 获取所有字节并放入一个将传递给 C# 代码的字符。

H 声明是: unsigned H[5];

它几乎可以工作,但由于某种原因,某些组合给了我疯狂的结果,比如 C# 上的 22 个成员字符串,并且值都错误。

我认为这与 C# 和 C++ 上的一些不同类型的变量有关。如果我只能从 char* 中获取所有字节,就像它们在 C++ 代码中一样,那就太棒了。

有谁知道该怎么做?

非常感谢你们!

编辑 :

一般的工作流程是:

  1. 我的 Windows 窗体应用程序从 C++ 类创建一个新类:HashWrapper hash = new HashWrapper();
  2. 我的 windows 窗体应用程序将种子发送到 C++(这是一个 SHA-1 算法类):hash.SendInput("abc");
  3. 我的 windows 窗体应用程序要求 c++ 算法的结果:string output = hash.ReturnString();

在这里,我将把我调用的方法放在最上面:

 public HashWrapper()
    {
        // We have to Create an instance of this class through an exported function
        this.m_pNativeObject = CreateSHA1Class();
    }

public void SendInput(string inp )
    {
        CallInput(this.m_pNativeObject, inp, inp.Length);
    }

public string ReturnString()
    {

        string ans = CallReturnString(this.m_pNativeObject);

        return ConvertStringToHex(ans); // Converts to Hex
    }
 public string ConvertStringToHex(string asciiString)
    {
        string hex = "";
        foreach (char c in asciiString)
        {
            int tmp = c;
            hex += String.Format("{0:x2}", (uint)System.Convert.ToUInt32(tmp.ToString()));
        }
        return hex;
    }
4

2 回答 2

0

不要重新发明轮子

你有什么理由不能使用微软提供的类吗?您的答案存在一些问题,例如重新创建memcpy允许您在大约 6 行代码中执行内存复制功能的函数,或者尝试将数据字符串编组为空终止字符串。您应该只使用 .NET 提供的 SHA1 实现,除非有要求说您必须自己制作。

如何在 .NET 中解决您的问题

您尝试解决的问题实际上需要 .NET 中的 3 行代码,除非您需要使用 .NET 制作自己的 SHA1 实现更有意义。

public static byte[] HashString(string inputString)
{
    inputData = Encoding.ASCII.GetBytes("abc");
    var sha1 = new SHA1Managed();

    return sha1.ComputeHash(inputData);
}
于 2013-07-19T21:24:47.160 回答
0

不幸的是,您不能简单地从返回值中编组数组。如果您需要多次调用它,我将从自定义编组器开始:

private class ReturnArrayMarshaller : ICustomMarshaler
{

    public static ICustomMarshaler GetInstance(string cookie)
    {
        return new ReturnArrayMarshaller(cookie);
    }

    private readonly int byteCount;

    private ReturnArrayMarshaller(string cookie)
    {
        byteCount = int.Parse(cookie);
    }

    public void CleanUpManagedData(object ManagedObj) { throw new NotImplementedException(); }

    public void CleanUpNativeData(IntPtr pNativeData)
    {
        // release unmanaged return value if needed
    }

    public int GetNativeDataSize() { throw new NotImplementedException(); }

    public IntPtr MarshalManagedToNative(object ManagedObj) { throw new NotImplementedException(); }

    public object MarshalNativeToManaged(IntPtr pNativeData)
    {
        byte[] data = new byte[byteCount];
        Marshal.Copy(pNativeData, data, 0, data.Length);
        return data;
    }

}

并在签名声明中使用它:

[DllImport(@"hashLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(ReturnArrayMarshaller), MarshalCookie = "20")]
public static extern byte[] CallReturnString(IntPtr pHashClassObject);

不要忘记指定CallingConvention.Cdeclin DllImport,因为您没有__stdcall在 C++ 代码中使用修饰符。

PS 我相信你使用非托管库不仅仅是因为 SHA1 哈希,因为大多数密码学都可以作为托管类使用。

于 2013-07-20T00:47:58.423 回答