-1

当我使用四个字母的单词作为输入时,我有以下代码可以正常工作,例如“测试”。当输入不是 4 的倍数时,它会失败,例如“MyTest”。

异常:Base-64 字符数组的长度无效。

问题

  1. 是否保证加密的结果将始终与 Unicode 字符串兼容(没有任何损失)。如果是,我可以使用 UTF 编码而不是 Base64 吗?UTF8/UTF16和Base64在编码方面有什么区别
  2. 即使输入不是 4 的倍数,如何添加填充以便我们得到正确的结果(解密后)?

主要程序

class Program
{
    static void Main(string[] args)
    {
        string valid128BitString = "AAECAwQFBgcICQoLDA0ODw==";
        string inputValue = "MyTest";
        string keyValue = valid128BitString;


        byte[] byteValForString = Convert.FromBase64String(inputValue);
        EncryptResult result = Aes128Utility.EncryptData(byteValForString, keyValue);
        EncryptResult encyptedValue = new EncryptResult();
        string resultingIV = "4uy34C9sqOC9rbV4GD8jrA==";
        if (String.Equals(resultingIV,result.IV))
        {
            int x = 0;
        }

        encyptedValue.IV = resultingIV;
        encyptedValue.EncryptedMsg = result.EncryptedMsg;

        string finalResult = Convert.ToBase64String(Aes128Utility.DecryptData(encyptedValue, keyValue));
        Console.WriteLine(finalResult);

        if (String.Equals(inputValue, finalResult))
        {
            Console.WriteLine("Match");
        }
        else
        {
            Console.WriteLine("Differ");
        }

        Console.ReadLine();
    }
}

AES 加密实用程序

public static class Aes128Utility
{
    private static byte[] key;

    public static EncryptResult EncryptData(byte[] rawData, string strKey)
    {
        EncryptResult result = null;
        if (key == null)
        {
            if (!String.IsNullOrEmpty(strKey))
            {
                key = Convert.FromBase64String((strKey));
                result = Encrypt(rawData);
            }
        }
        else
        {
            result = Encrypt(rawData);
        }

        return result; 

    }

    public static byte[] DecryptData(EncryptResult encryptResult, string strKey)
    {
        byte[] origData = null;
        if (key == null)
        {
            if (!String.IsNullOrEmpty(strKey))
            {
                key = Convert.FromBase64String(strKey);
                origData = Decrypt(Convert.FromBase64String(encryptResult.EncryptedMsg), Convert.FromBase64String(encryptResult.IV));
            }
        }
        else
        {
            origData = Decrypt(Convert.FromBase64String(encryptResult.EncryptedMsg), Convert.FromBase64String(encryptResult.IV));
        }

        return origData; 
    }

    private static EncryptResult Encrypt(byte[] rawData)
    {
        using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
        {
            aesProvider.Key = key;
            aesProvider.Mode = CipherMode.CBC;
            aesProvider.Padding = PaddingMode.PKCS7;
            aesProvider.IV = Convert.FromBase64String("4uy34C9sqOC9rbV4GD8jrA==");
            using (MemoryStream memStream = new MemoryStream())
            {
                CryptoStream encStream = new CryptoStream(memStream, aesProvider.CreateEncryptor(), CryptoStreamMode.Write);
                encStream.Write(rawData, 0, rawData.Length);
                encStream.FlushFinalBlock();
                EncryptResult encResult = new EncryptResult();
                encResult.EncryptedMsg = Convert.ToBase64String(memStream.ToArray());
                encResult.IV = Convert.ToBase64String(aesProvider.IV);
                return encResult;
            }
        }
    }

    private static byte[] Decrypt(byte[] encryptedMsg, byte[] iv)
    {
        using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
        {
            aesProvider.Key = key;
            aesProvider.IV = iv;
            aesProvider.Mode = CipherMode.CBC;
            aesProvider.Padding = PaddingMode.PKCS7;
            using (MemoryStream memStream = new MemoryStream())
            {
                CryptoStream decStream = new CryptoStream(memStream, aesProvider.CreateDecryptor(), CryptoStreamMode.Write);
                decStream.Write(encryptedMsg, 0, encryptedMsg.Length);
                decStream.FlushFinalBlock();
                return memStream.ToArray();
            }
        }
    }

 }

DTO

public class EncryptResult
{
    public string EncryptedMsg { get; set; }
    public string IV { get; set; }
}

参考文献

  1. 如何使用 FromBase64String 创建长度为 16 的字节 []
  2. 使用 AesCryptoServiceProvider 获取不正确的解密值
4

2 回答 2

2

Base64 是一种将二进制值表示为文本的方法,这样您就不会与常见的控制代码(如\x0A换行符或\0字符串终止符)发生冲突。它不适用于将输入的文本转换为二进制。

以下是您应该如何传递文本并将其取回。您可以替换UTF8为您想要的任何编码,但您需要确保Encoding.Whatever.GetBytesEncoding.Whatever.GetString

class Program
{
    static void Main(string[] args)
    {
        string valid128BitString = "AAECAwQFBgcICQoLDA0ODw==";
        string inputValue = "MyTest";
        string keyValue = valid128BitString;

        //Turns our text in to binary data
        byte[] byteValForString = Encoding.UTF8.GetBytes(inputValue);

        EncryptResult result = Aes128Utility.EncryptData(byteValForString, keyValue);
        EncryptResult encyptedValue = new EncryptResult();

        //(Snip)

        encyptedValue.IV = resultingIV;
        encyptedValue.EncryptedMsg = result.EncryptedMsg;

        string finalResult = Encoding.UTF8.GetString(Aes128Utility.DecryptData(encyptedValue, keyValue));
        Console.WriteLine(finalResult);

        if (String.Equals(inputValue, finalResult))
        {
            Console.WriteLine("Match");
        }
        else
        {
            Console.WriteLine("Differ");
        }

        Console.ReadLine();
    }
}
于 2013-02-19T08:11:01.877 回答
1

如果您正在加密,那么为我编码 Base64 不会增加任何有用的东西,反而会带来您面临的问题。

至于填充,我看到的一个解决方案是创建一个确实是 4 的倍数的新字节 [],并将源字节 [] 复制到该新字节 []。

所以,像这样:

 if (rawdata.Length % 16 !=0)
 {
      newSource = new byte[source.Length + 16 - source.Length % 16];
      Array.Copy(source, newSource, source.Length);
 }
于 2013-02-19T08:06:05.010 回答