-1

次のコードは、「Test」などの 4 文字の単語を入力として使用すると正常に動作します。入力が 4 の倍数でない場合、たとえば「MyTest」は失敗します。

例外: Base-64 char 配列の長さが無効です。

質問

  1. 暗号化された結果が常に Unicode 文字列と互換性があることが保証されています (損失なし)。はいの場合、Base64 の代わりに UTF エンコーディングを使用できますか? エンコーディングに関して、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 の byte[] を作成する方法
  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の倍数である新しいbyte []を作成し、ソースbyte []をその新しいbyte []に​​コピーすることです。

したがって、次のようなものです。

 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 に答える