3

C# で (128 ビット AES) を使用してランダム IV で CBC をテストしようとしています。

解決する私の質問では、12 バイトの入力メッセージがあります。条件は、PlainText がブロック サイズ (16 バイト) 未満である場合、使用されるパディングが 0x01 で始まり、次に 6 個の 0x00 までであるということです。

例:

in ASCII PT     = Pay Bob 100%

in hex PT       = 50 61 79 20 42 6f 62 20 31 30 30 24

PT with Padding = 50 61 79 20 42 6f 62 20 31 30 30 24 01 00 00 00

RijndaelManagedでこのPaddingModeを見つけることができないようです。

次のことを行う方法を教えてもらえますか?

  • 可変長パディング

編集:

public class CBC
{
    public CBC()
    {

    }

    private static readonly byte[] SALT = new byte[]
        {0x26, 0xdc, 0xff, 0x00, 0xad, 0xed, 0x7a, 0xee, 0xc5, 0xfe, 0x07, 0xaf, 0x4d, 0x08, 0x22, 0x3c};

    public static byte[] EncryptCBC(string plainText, string passPhrase, PaddingMode paddingMode )
    {
        byte[] result;
        using (RijndaelManaged cryptoProvider = new RijndaelManaged())
        {
            Rfc2898DeriveBytes derivedKey = new Rfc2898DeriveBytes(passPhrase, SALT);
            cryptoProvider.Mode = CipherMode.CBC;
            cryptoProvider.GenerateIV(); // generate random IV

            cryptoProvider.Padding = paddingMode;

            cryptoProvider.Key = derivedKey.GetBytes(cryptoProvider.KeySize / 8);

            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (ICryptoTransform encryptor = cryptoProvider.CreateEncryptor(cryptoProvider.Key, cryptoProvider.IV))
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {
                            swEncrypt.Write(plainText);
                        }
                    }
                }
                // concatenate iv to ciphertext
                result = cryptoProvider.IV.Concat(msEncrypt.ToArray()).ToArray();
            }
            cryptoProvider.Clear();
        }
        return result;
    }

    public static string DecryptCBC(byte[] cipherTextBytes, string passPhrase, PaddingMode paddingMode)
    {
        string result = null;
        using (RijndaelManaged cryptoProvider = new RijndaelManaged())
        {
            Rfc2898DeriveBytes derivedKey = new Rfc2898DeriveBytes(passPhrase, SALT);
            cryptoProvider.Mode = CipherMode.CBC;
            // take the iv off the beginning of the ciphertext message
            cryptoProvider.IV = cipherTextBytes.Take(cryptoProvider.BlockSize / 8).ToArray();


            cryptoProvider.Padding = paddingMode;//PaddingMode.ANSIX923;



            cryptoProvider.Key = derivedKey.GetBytes(cryptoProvider.KeySize / 8);

            using (MemoryStream msEncrypt = new MemoryStream(cipherTextBytes.Skip(cryptoProvider.BlockSize / 8).ToArray())) // skip the IV bytes
            {
                using (ICryptoTransform encryptor = cryptoProvider.CreateDecryptor(cryptoProvider.Key, cryptoProvider.IV))
                {
                    using (CryptoStream cryptoStream = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Read))
                    {
                        byte[] plainTextBytes = new byte[cipherTextBytes.Length - cryptoProvider.BlockSize / 8];
                        int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);

                        result = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
                        cryptoStream.Close();
                    }
                }
            }

            cryptoProvider.Clear();
        }
        return result;
    }

}

マイパディング機能

        private byte[] PaddPlainTextBytes(byte[] plainTextBytes )
    {
        byte[] padding = utils.HexToBytes("01000000");
        MemoryStream s = new MemoryStream();

        s.Write(plainTextBytes, 0, plainTextBytes.Length);
        s.Write(padding, 0, padding.Length);

        byte[] paddedPt = s.ToArray();

        return paddedPt;
    }

私のCBCをテストする方法

        private void btnTestCBC_Click(object sender, EventArgs e)
    {
        string plainText = "Pay Bob 100%";

        string passPhrase = "Thisismypassphrase";
        ShowMessage(@"Plain Text = " + plainText);

        byte[] pBytes = PaddPlainTextBytes(Encoding.ASCII.GetBytes(plainText));

        string message = Encoding.ASCII.GetString(pBytes);

        byte[] encryptedBytes = CBC.EncryptCBC(plainText: message, passPhrase: passPhrase, paddingMode: PaddingMode.None);

        ShowMessage("Encrypted String = " + Encoding.ASCII.GetString(encryptedBytes));
        ShowMessage("Encrypted HEX = " + utils.BytesToHex(encryptedBytes));


        string decryptedString = CBC.DecryptCBC(encryptedBytes, passPhrase, PaddingMode.None);
        ShowMessage("Deccrypted String = " + decryptedString);
    }
4

2 に答える 2

5

私はあなたのパディングスキームに精通していませんが、確かに.netに組み込まれていません. を に設定し、パッドを入力メッセージにポストペンドすることができるはずPaddingModeですNone。それを復号化するものに対して同じ結果が得られるはずです。解読する場合は、自分でパッドを削除する必要があります。

于 2012-12-31T17:14:46.500 に答える
1

あなたが説明したパディング スキームは、"ISO/IEC 7816-4 パディング"によく似ています。パディング方法については、ウィキペディアのパディング (編集したばかり) のページを参照してください。通常、バイトではなく 1 に設定された単一のビットから開始するため、最初のバイトは 0x01 ではなく 0x80 になります。

このパディング ノードはおそらく組み込まれていません。試してみたい場合は、Bouncy Castle ライブラリをお勧めします。それ以外の場合は、ほぼどこにでもある PKCS#7 パディングに切り替えてください。

于 2013-01-01T16:34:34.363 に答える