每次AES256 pinvoke C#都有不同的输出

时间:2016-01-28 09:49:47

标签: c# c++ encryption pinvoke

想法是我有4个字节[512]数组,我从C#中获取密钥,并用AES256加密一些信息。比我的同事,使用完全相同的4字节数组,使用相同的密钥派生过程,解密消息。

除了首先,它投掷"不良数据" C ++中的异常,与我不同的是可以预料,C#中的加密输出每次都不同。为什么会这样?

常量:

    const uint ALG_CLASS_DATA_ENCRYPT = (3 << 13);
    const uint ALG_TYPE_BLOCK = (3 << 9);
    const uint ALG_SID_AES_256 = 16;
    const uint CALG_AES_256 = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_AES_256);

    const uint KEYLENGTH = 0x01000000;
    const uint CRYPT_EXPORTABLE = 0x00000001;

    const uint ALG_CLASS_HASH = (4 << 13);
    const uint ALG_TYPE_ANY = 0;
    const uint ALG_SID_SHA_256 = 12;
    const uint CALG_SHA_256 = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_256);
    const uint ENCRYPT_HASH_ALG = CALG_SHA_256;

    const uint PROV_RSA_AES = 24;
    const uint CRYPT_VERIFYCONTEXT = 0xF0000000;
    const string MS_ENH_RSA_AES_PROV = @"Microsoft Enhanced RSA and AES Cryptographic Provider";

    const uint CRYPT_MODE_CBC = 1;
    const uint KP_MODE = 4;
    const uint KP_IV = 1;

我的代码:

    IntPtr _hProv = new IntPtr();
    IntPtr _phHash = new IntPtr();
    IntPtr _phKey = new IntPtr();

    bool result = CryptAcquireContext(ref _hProv, null, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT);
    result = CryptCreateHash(_hProv, ENCRYPT_HASH_ALG, IntPtr.Zero, 0, ref _phHash);
    byte[] bbb = new ASCIIEncoding().GetBytes("Test hash!");
    result = CryptHashData(_phHash, bbb, (uint)bbb.Length, 0);
    result = CryptDeriveKey(_hProv, CALG_AES_256, _phHash, KEYLENGTH, ref _phKey);
    byte[] cryptMode = BitConverter.GetBytes(CRYPT_MODE_CBC);
    result = SetXKeyParamKey(_phKey, KP_MODE, cryptMode);
    byte[] ivBuff = new byte[16]{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
    result = SetXKeyParamKey(_phKey, KP_IV, ivBuff);

    uint lenght = (uint)data.Length;
    byte[] cln = new byte[data.Length + 128];
    Array.Copy(data, cln, data.Length);


    result = CryptEncrypt(_phKey, IntPtr.Zero, 1, 0, cln, ref lenght, (uint)(cln.Length + 128));

    data = new byte[lenght];
    Array.Copy(cln, data, lenght);

    result = CryptReleaseContext(_hProv, 0);
    return lenght;

签名:

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool CryptAcquireContext(ref IntPtr hProv, string pszContainer, string pszProvider, UInt32 dwProvType, UInt32 dwFlags);

    [DllImport("Advapi32.dll", EntryPoint = "CryptReleaseContext", CharSet = CharSet.Unicode, SetLastError = true)]
    static extern bool CryptReleaseContext(IntPtr hProv, Int32 dwFlags); //dwFlags   Reserved. Must be 0.

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool CryptCreateHash(IntPtr hProv, uint algId, IntPtr hKey, uint dwFlags, ref IntPtr phHash);

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool CryptHashData(IntPtr hHash, byte[] pbData, uint dataLen, uint flags);

    [DllImport("advapi32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool CryptDeriveKey(IntPtr hProv, uint Algid, IntPtr hBaseData, uint flags, ref IntPtr phKey);

    [DllImport(@"advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool CryptEncrypt(IntPtr hKey, IntPtr hHash, int Final, uint dwFlags, byte[] pbData, ref uint pdwDataLen, uint dwBufLen);

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    static extern bool CryptGetHashParam(IntPtr hHash, uint dwParam, [Out] IntPtr pbData, [In, Out] uint pdwDataLen, uint dwFlags);

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool CryptSetKeyParam(IntPtr Key, uint Param, IntPtr Data, uint Flags);

    private static bool SetXKeyParamKey(IntPtr Key, uint KeyParam, byte[] Data)
    {
        bool Result = false;

        if (Data == null)                                                   // special case, e.g. for KP_X
        {
            Result = CryptSetKeyParam(Key, KeyParam, IntPtr.Zero, 0);
            return Result;
        }
        IntPtr holder = Marshal.AllocHGlobal(12);                            // the same as DATA_BLOB
        Marshal.WriteInt32(holder, 0, Data.Length);                         // first 4 bytes is the length of the buffer
        IntPtr buffPtr = Marshal.AllocHGlobal(Data.Length);                 // ptr to buffer
        Marshal.Copy(Data, 0, buffPtr, Data.Length);                        // copy real data to a newly-allocated buffer
        Marshal.WriteInt64(holder, 4, (Int64)buffPtr);                        // holder now contains both size and ptr; assume that ptr takes 4 bytes
        Result = CryptSetKeyParam(Key, KeyParam, holder, 0);                // instead of real buffer, we must pass the holder
        Marshal.FreeHGlobal(buffPtr); Marshal.FreeHGlobal(holder);

        return Result;
    }

0 个答案:

没有答案