如何为Base64应用填充

时间:2013-02-19 08:00:13

标签: c# .net encryption cryptography

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

  

Eexception:Base-64 char数组的长度无效。

问题

  1. 是否保证加密结果始终与Unicode字符串兼容(没有任何损失)。如果是,我可以使用UTF编码而不是Base64? What's the difference between UTF8/UTF16 and Base64 in terms of encoding
  2. 即使输入不是4的倍数,如何添加填充以便我们得到正确的结果(解密后)?
  3. MAIN PRGORAM

    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. How to create byte[] with length 16 using FromBase64String
    2. Getting incorrect decryption value using AesCryptoServiceProvider

2 个答案:

答案 0 :(得分:2)

Base64是一种将二进制值表示为文本的方法,这样您就不会与新行的\x0A或字符串终止符\0等公共控制代码冲突。将键入的文字转换为二进制文件 NOT

以下是您应该如何传递文本并将其取回。您可以使用您想要的任何编码替换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();
    }
}

答案 1 :(得分:1)

如果您正在加密,那么为我编码Base64不会添加任何有用的内容,而是会带来您遇到的问题。

至于填充,我看到的解决方案是创建一个新的byte [],它实际上是4的倍数,并将源byte []复制到新的byte []。

所以,像这样:

 if (rawdata.Length % 16 !=0)
 {
      newSource = new byte[source.Length + 16 - source.Length % 16];
      Array.Copy(source, newSource, source.Length);
 }