3

我正在尝试解密用 Rijndael 算法加密的字符串。如果密钥和 IV 的长度少于 16 个字符,这种类型的加密会在密钥和 IV 的右侧使用“#”填充。要解密的字符串是从将它和密钥以 XML SOAP 格式发送给我的 Web 服务接收的。IV 是我机器的 Mac 地址(服务器用作 IV 来加密字符串)。当我尝试解密收到的字符串时,我的程序在此指令处崩溃:

while ((num5 = stream3.ReadByte()) != -1)

它给了我这个错误“填充无效并且无法删除”。我在 MSDN 上搜索了这个错误,它说当用于加密的 IV 与用于解密的 IV 不同时会发生这种情况,但是,我再说一遍,IV 是 MacAddress 并且每次都相同。

这是加密和解密函数的源代码:

public static string Decrypt(string strInputString, string strKeyString, string myIV)
{
        if ((strInputString == null) || (strInputString.Length == 0))
        {
            return strInputString;
        }
        try
        {
            int num5;
            int keySize = 0x100;
            int blockSize = 0x100;
            int length = keySize / 0x10;
            if (strKeyString.Length > length)
            {
                strKeyString = strKeyString.Substring(0, length);
            }
            if (strKeyString.Length < length)
            {
                strKeyString = strKeyString.PadRight(length, '#');
            }
            Encoding.Unicode.GetBytes(strKeyString);
            if (myIV.Length > length)
            {
                myIV = myIV.Substring(0, length);
            }
            if (myIV.Length < length)
            {
                myIV = myIV.PadRight(length, '#');
            }
            Encoding.Unicode.GetBytes(myIV);
            byte[] bytes = Encoding.Unicode.GetBytes(strKeyString);
            byte[] rgbIV = Encoding.Unicode.GetBytes(myIV);
            RijndaelManaged managed = new RijndaelManaged {
                BlockSize = blockSize,
                KeySize = keySize
            };
            MemoryStream stream = new MemoryStream();
            for (int i = 0; i < strInputString.Length; i += 2)
            {
                stream.WriteByte(byte.Parse(strInputString.Substring(i, 2), NumberStyles.AllowHexSpecifier));
            }
            stream.Position = 0L;
            MemoryStream stream2 = new MemoryStream();
            CryptoStream stream3 = new CryptoStream(stream, managed.CreateDecryptor(bytes, rgbIV), CryptoStreamMode.Read);
            while ((num5 = stream3.ReadByte()) != -1)
            {
                stream2.WriteByte((byte) num5);
            }
            stream3.Close();
            stream2.Close();
            stream.Close();
            byte[] buffer3 = stream2.ToArray();
            return Encoding.Unicode.GetString(buffer3);
        }
        catch (Exception exception)
        {
            Log.Error(exception.Message);
        }
}

public static string Encrypt(string strInputString, string strKeyString, string myIV)
{
        if ((strInputString == null) || (strInputString.Length == 0))
        {
            return strInputString;
        }
        try
        {
            int num4;
            int keySize = 0x100;
            int blockSize = 0x100;
            int length = keySize / 0x10;
            if (strKeyString.Length > length)
            {
                strKeyString = strKeyString.Substring(0, length);
            }
            if (strKeyString.Length < length)
            {
                strKeyString = strKeyString.PadRight(length, '#');
            }
            Encoding.Unicode.GetBytes(strKeyString);
            if (myIV.Length > length)
            {
                myIV = myIV.Substring(0, length);
            }
            if (myIV.Length < length)
            {
                myIV = myIV.PadRight(length, '#');
            }
            Encoding.Unicode.GetBytes(myIV);
            byte[] bytes = Encoding.Unicode.GetBytes(strKeyString);
            byte[] rgbIV = Encoding.Unicode.GetBytes(myIV);
            string str = "";
            RijndaelManaged managed = new RijndaelManaged {
                BlockSize = blockSize,
                KeySize = keySize
            };
            MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(strInputString));
            MemoryStream stream2 = new MemoryStream();
            CryptoStream stream3 = new CryptoStream(stream2, managed.CreateEncryptor(bytes, rgbIV), CryptoStreamMode.Write);
            while ((num4 = stream.ReadByte()) != -1)
            {
                stream3.WriteByte((byte) num4);
            }
            stream3.Close();
            stream2.Close();
            stream.Close();
            foreach (byte num5 in stream2.ToArray())
            {
                str = str + num5.ToString("X2");
            }
            return str;
        }
        catch (Exception exception)
        {
            Log.Error(exception.Message);
        }
    }

}

4

4 回答 4

0

我不认为IV是问题。这是密码本身。我怀疑服务器用来加密的密码不是客户端用来解密的密码。

我可以重现 OP 报告的崩溃的唯一方法是将错误的密码传递给 Decrypt() 方法。传入一个稍微不正确的 IV 不会引发异常。例如,我使用 IV 作为 MAC 地址进行加密,大写字母并使用冒号,然后使用 IV 作为相同的 MAC 地址以小写字母和破折号进行解密。-- 前几个字节被打乱了,但到了大约 16 字节,一切都开始与纯文本原件匹配。

于 2012-06-05T09:09:29.247 回答
0

填充可能是 Pkcs#5。而不是#,用一个字节值填充,该字节值是要填充的字节数。

因此,如果您有 5 个字节要填充,则填充字节将为0505050505,如果您需要填充 2 个字节,则填充字节将为0202

于 2012-05-17T12:02:36.580 回答
0

您是否在加密时使用与原始字符串相同的字符编码?

我有一个类似的问题......最后的区别在于我如何传递要加密的数据(字符串)。如果我复制/粘贴到文本框中,加密不同于我硬编码到程序中。所以简而言之......原始数据的编码有很大的不同。虽然字符可能看起来相同,但实际上它们的表示方式可能完全不同(8 字节、16 字节等)。

找出原始字符串在加密算法之前是如何编码的(也许还要检查 IV 参数编码。

于 2013-03-18T15:13:10.783 回答
0

使用下面的测试代码对我来说可以正常工作-您确定要传递加密字符串进行解密吗?

static void Main(string[] args)
    {

        string strInputString = "test";
        string strKeyString = "test123";
        string myIV = GetMacAddress();

        string encryptedString = Encrypt(strInputString, strKeyString, myIV);
        string decryptedString = Decrypt(encryptedString, strKeyString, myIV);

    }

    public static string Decrypt(string strInputString, string strKeyString, string myIV)
    {
        if ((strInputString == null) || (strInputString.Length == 0))
        {
            return strInputString;
        }

            int num5;
            int keySize = 0x100;
            int blockSize = 0x100;
            int length = keySize / 0x10;
            if (strKeyString.Length > length)
            {
                strKeyString = strKeyString.Substring(0, length);
            }
            if (strKeyString.Length < length)
            {
                strKeyString = strKeyString.PadRight(length, '#');
            }
            Encoding.Unicode.GetBytes(strKeyString);
            if (myIV.Length > length)
            {
                myIV = myIV.Substring(0, length);
            }
            if (myIV.Length < length)
            {
                myIV = myIV.PadRight(length, '#');
            }
            Encoding.Unicode.GetBytes(myIV);
            byte[] bytes = Encoding.Unicode.GetBytes(strKeyString);
            byte[] rgbIV = Encoding.Unicode.GetBytes(myIV);
            RijndaelManaged managed = new RijndaelManaged
            {
                BlockSize = blockSize,
                KeySize = keySize
            };
            MemoryStream stream = new MemoryStream();
            for (int i = 0; i < strInputString.Length; i += 2)
            {
                stream.WriteByte(byte.Parse(strInputString.Substring(i, 2), NumberStyles.AllowHexSpecifier));
            }
            stream.Position = 0L;
            MemoryStream stream2 = new MemoryStream();
            CryptoStream stream3 = new CryptoStream(stream, managed.CreateDecryptor(bytes, rgbIV), CryptoStreamMode.Read);
            while ((num5 = stream3.ReadByte()) != -1)
            {
                stream2.WriteByte((byte)num5);
            }
            stream3.Close();
            stream2.Close();
            stream.Close();
            byte[] buffer3 = stream2.ToArray();
            return Encoding.Unicode.GetString(buffer3);

    }

    public static string Encrypt(string strInputString, string strKeyString, string myIV)
    {
        if ((strInputString == null) || (strInputString.Length == 0))
        {
            return strInputString;
        }           
            int num4;
            int keySize = 0x100;
            int blockSize = 0x100;
            int length = keySize / 0x10;
            if (strKeyString.Length > length)
            {
                strKeyString = strKeyString.Substring(0, length);
            }
            if (strKeyString.Length < length)
            {
                strKeyString = strKeyString.PadRight(length, '#');
            }
            Encoding.Unicode.GetBytes(strKeyString);
            if (myIV.Length > length)
            {
                myIV = myIV.Substring(0, length);
            }
            if (myIV.Length < length)
            {
                myIV = myIV.PadRight(length, '#');
            }
            Encoding.Unicode.GetBytes(myIV);
            byte[] bytes = Encoding.Unicode.GetBytes(strKeyString);
            byte[] rgbIV = Encoding.Unicode.GetBytes(myIV);
            string str = "";
            RijndaelManaged managed = new RijndaelManaged
            {
                BlockSize = blockSize,
                KeySize = keySize
            };
            MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(strInputString));
            MemoryStream stream2 = new MemoryStream();
            CryptoStream stream3 = new CryptoStream(stream2, managed.CreateEncryptor(bytes, rgbIV), CryptoStreamMode.Write);
            while ((num4 = stream.ReadByte()) != -1)
            {
                stream3.WriteByte((byte)num4);
            }
            stream3.Close();
            stream2.Close();
            stream.Close();
            foreach (byte num5 in stream2.ToArray())
            {
                str = str + num5.ToString("X2");
            }
            return str;

    }

    private static string GetMacAddress()
    {
        string macAddresses = "";

        foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
        {
            if (nic.OperationalStatus == OperationalStatus.Up)
            {
                macAddresses += nic.GetPhysicalAddress().ToString();
                break;
            }
        }
        return macAddresses;
    }
于 2012-05-17T08:59:09.020 回答