繁体   English   中英

C#AES CFB与第三方C实现的兼容性

[英]C# AES CFB compatibility with 3rd party C implementation

我有一个用于C的第三方AES库(来自Lantronix)。 我从C#的托管代码中包装了他们的API,如下所示,并且可以正常工作:

    [DllImport("cbx_enc.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
    static extern unsafe void VC_blockEncrypt(char* iv, char* key, int length, char* text, int RDkeyLen);

    /// <summary>
    /// Managed Encrypt Wrapper     
    /// </summary>
    /// <param name="buffer">provides the plain text and receives the same length cipher text</param>
    static readonly string key = "abcdef0123456789";
    static readonly string iv = "0123456789ABCDEF";
    public static void Encrypt(ref byte[] buffer)
    {
        var keyPtr = Marshal.StringToHGlobalAnsi(key);
        var ivPtr = Marshal.StringToHGlobalAnsi(iv);

        byte[] temp = new byte[16];
        Marshal.Copy(ivPtr, temp, 0, 16);
        int index = 0; 
        for (int i = 0; i < buffer.Length; i++)
        {
            if (index == 0)
            {
                Marshal.Copy(temp, 0, ivPtr, 16);
                unsafe
                {
                    VC_blockEncrypt((char*) ivPtr, (char*) keyPtr, 0, (char*) ivPtr, 128);
                }
                Marshal.Copy(ivPtr, temp, 0, 16);
                index = 16;
            }

            temp[16 - index] ^= buffer[i];
            buffer[i] = temp[16 - index];
            index--;
        }

        Marshal.FreeHGlobal(ivPtr);
        Marshal.FreeHGlobal(keyPtr);
    }

现在,当我编写自己的文件时,使用System.Security.Cryptography完全避免使用其不受管的DLL,我的最终密文似乎与它们不同! 我使用相同的模式,相同的键,相同的iv和相同的纯文本,但是算法不兼容。 下面显示的是RijndaelManaged对象和代码的属性设置; 我是否缺少引起这种不兼容的东西?

    /// <summary>
    /// Managed Encrypt     
    /// </summary>
    /// <param name="buffer">provides the plain text and receives the same length cipher text</param>
    static readonly string key = "abcdef0123456789";
    static readonly string iv = "0123456789ABCDEF";
    public static void Encrypt(ref byte[] buffer)
    {
        using (RijndaelManaged cipher = new RijndaelManaged())
        {
            cipher.Mode = CipherMode.CFB;
            cipher.Key = Encoding.ASCII.GetBytes(key);
            cipher.IV = Encoding.ASCII.GetBytes(iv);
            cipher.Padding = PaddingMode.None;
            cipher.FeedbackSize = 128;

            ICryptoTransform encryptor = cipher.CreateEncryptor(cipher.Key, cipher.IV);
            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    using (BinaryWriter swEncrypt = new BinaryWriter(csEncrypt))
                    {
                        swEncrypt.Write(buffer);
                    }
                    buffer = msEncrypt.ToArray();
                }
            }
        }
    }

另外,我从Lantronix架构中阐明的算法看起来非常简单-API进行加密,然后将输出与纯文本进行异或操作是在调用方法中完成的。 而使用.NET库,我无权访问中间加密的输出(或者有一个?),因此我可以对Lantronix加密后手动执行的方式进行XOR ...

最终目标是停止使用非托管代码,但应该能够使用完全托管的.NET代码生成相同的密文。

感谢您的帮助。

ps如果需要,我可以提供第三方C库cbx_enc.dll。

编辑 :@Topaco,这是一些要求的示例数据。 还没有从供应商那里得到关于分发DLL的消息。 正在努力...

CFB的常见输入:

byte[] buffer = Encoding.ASCII.GetBytes("AAAAAAAAAAAAAABBBBBBBBBBBBBBBBBD"); //plain text string key = "abcdef0123456789"; string iv = "0123456789ABCDEF";

从包装器到非托管DLL的I / O:

PlainText Hex: 4141414141414141414141414141424242424242424242424242424242424244 CipherText Hex: C9094F820428E07AE035B6749E18546C62F9D5FD4A78480215DA3625D376A271

来自托管代码的I / O,其中FeedbackSize = 128; //CFB128 FeedbackSize = 128; //CFB128

PlainText Hex: 4141414141414141414141414141424242424242424242424242424242424244 CipherText Hex: 6A1A5088ACDA505B47192093DD06CD987868BFD85278A4D7D3120CC85FCD3D83

来自托管代码的I / O,其中FeedbackSize = 8 //CFB8

PlainText Hex: 4141414141414141414141414141424242424242424242424242424242424244 CipherText Hex: 6ACA3B1159D38568504248CDFF159C87BB2D3850EDAEAD89493BD91087ED7507

我还使用ECB进行了附加测试,以查看其API的行为是否类似于ECB(因此需要外部XORing)。 因此,我将IV作为纯文本传递给我的ECB代码,如下所示,然后将其与第一次XOR之前的输出进行了比较-它们都不匹配!

将IV作为PlainText传递给ECB: 30313233343536373839414243444546 CipherText Hex: 2B5B11C9ED9B111A065861D29C478FDA

非托管DLL中的CipherText Hex(在第一个XOR之前): 88480EC34569A13BA174F735DF59162E

最后,这是上述测试的ECB实施:

   static readonly string key = "abcdef0123456789";
    static readonly string iv = "0123456789ABCDEF";
    public static void Encrypt(ref byte[] buffer)
    {
        buffer = Encoding.ASCII.GetBytes(iv);
        Console.WriteLine($"PlainText:  {HexHelper.ToHexString(buffer)}");

        var aes = new AesManaged
        {
            KeySize = 128,
            Key = Encoding.ASCII.GetBytes(key),
            BlockSize = 128,
            Mode = CipherMode.ECB,
            Padding = PaddingMode.None,
            IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
        };

        ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
        buffer = encryptor.TransformFinalBlock(buffer, 0, buffer.Length);

        Console.WriteLine($"CipherText: {HexHelper.ToHexString(buffer)}");
    } 

谢谢。

在此,我要感谢所有的帮助,尤其是@Topaco,非常感谢-您对根据文档HEX中的纯文本进行编码的见解提供了帮助! 这是修改后的包装器代码; 如您所见,其密码现在与托管代码的密码匹配! 完善!!

    static readonly string key = "61626364656630313233343536373839"; //"abcdef0123456789";
    static readonly string iv = "0123456789ABCDEF";
    public static void Encrypt(ref byte[] buffer)
    {
        Console.WriteLine($"PlainText: {HexHelper.ToHexString(buffer)}");

        var keyPtr = Marshal.StringToHGlobalAnsi(key);
        var ivPtr = Marshal.StringToHGlobalAnsi(iv);
        byte[] temp = new byte[16];
        Marshal.Copy(ivPtr, temp, 0, 16);
        int index = 0; 
        for (int i = 0; i < buffer.Length; i++)
        {
            if (index == 0)
            {
                Marshal.Copy(temp, 0, ivPtr, 16);
                unsafe
                {
                    VC_blockEncrypt((char*) ivPtr, (char*) keyPtr, 0, (char*) ivPtr, 128);
                }
                Marshal.Copy(ivPtr, temp, 0, 16);
                index = 16;
                Console.WriteLine($"CipherText BeforeXOR: {HexHelper.ToHexString(temp)}");
            }

            temp[16 - index] ^= buffer[i];
            buffer[i] = temp[16 - index];
            index--;
        }

        Marshal.FreeHGlobal(ivPtr);
        Marshal.FreeHGlobal(keyPtr);

        Console.WriteLine($"CipherText: {HexHelper.ToHexString(buffer)}");

    }

修改后的包装器代码的I / O:PlainText: 4141414141414141414141414141424242424242424242424242424242424244 CipherText: 6A1A5088ACDA505B47192093DD06CD987868BFD85278A4D7D3120CC85FCD3D83

来自托管代码的I / O:PlainText: 4141414141414141414141414141424242424242424242424242424242424244 CipherText: 6A1A5088ACDA505B47192093DD06CD987868BFD85278A4D7D3120CC85FCD3D83

干杯!!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM