【C#中級】 AES-256で暗号化・復号化する方法

C# AES暗号化

近年、世界的にセキュリティ意識が高まってきたのでC#でAES暗号するコードを実装してみました。

目次
スポンサーリンク

AES暗号とは?

AES(Advanced Encryption Standard)はRijndaelとも呼ばれています。

旧規格の対称鍵暗号であるDES(Data Encryption Standard)の安全性が低下したために、NIST(アメリカ国立標準技術研空所)が公募し、2000年に選定された対称暗号です。

そのため、DESは今となっては非推奨のレガシーテクノロジーとなっているため、AESが推奨とされています。

尚、AES以外にもDES/3DESRC 4などの暗号化技術がありますが、AESが一番強固と言われています。

AESの鍵長

AESは鍵長によって安全性が異なっており、長さはbit数で表されます。

鍵長が長くなるほどセキュリティは高くなりますが、計算量が増えるのでシステムのパフォーマンスによって鍵長を決定する必要があります。

  1. 128bit (AES-128)
  2. 192bit (AES-192)
  3. 256bit (AES-256)

AES-256暗号を実装してみた

それでは実際にAES暗号するためのコードを書いてみます。今回は鍵長が長めのAES-256を実装しました。

セキュリティに絡むことなので難しそうですが、C#ではSystem.Security.Cryptography.RijndaelManagedクラスを使うことで簡単に実装することができます。

サンプルコード

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace AesSample
{
    class Program
    {
        // 初期化ベクトル"<半角16文字(1byte=8bit, 8bit*16=128bit>"
        private const string AES_IV_256 = @"pf69DL6GrWFyZcMK";
        // 暗号化鍵<半角32文字(8bit*32文字=256bit)>
        private const string AES_Key_256 = @"5TGB&YHN7UJM(IK<5TGB&YHN7UJM(IK<";

        static void Main(string[] args)
        {
            // 平文の文字列
            string plainText = "Hello, World!";

            Console.WriteLine("PlainText : {0}\n", plainText);

            // 暗号化された文字列
            string cipher = Encrypt(plainText, AES_IV_256, AES_Key_256);
            Console.WriteLine("Cipher : {0}\n", cipher);

            Console.WriteLine("Decrypted : {0}\n", Decrypt(cipher, AES_IV_256, AES_Key_256));

            Console.ReadLine();
        }

        /// <summary>
        /// 対称鍵暗号を使って文字列を暗号化する
        /// </summary>
        /// <param name="text">暗号化する文字列</param>
        /// <param name="iv">対称アルゴリズムの初期ベクター</param>
        /// <param name="key">対称アルゴリズムの共有鍵</param>
        /// <returns>暗号化された文字列</returns>
        public static string Encrypt(string text, string iv, string key)
        {

            using (RijndaelManaged myRijndael = new RijndaelManaged())
            {
                // ブロックサイズ(何文字単位で処理するか)
                myRijndael.BlockSize = 128;
                // 暗号化方式はAES-256を採用
                myRijndael.KeySize = 256;
                // 暗号利用モード
                myRijndael.Mode = CipherMode.CBC;
                // パディング
                myRijndael.Padding = PaddingMode.PKCS7;

                myRijndael.IV = Encoding.UTF8.GetBytes(iv);
                myRijndael.Key = Encoding.UTF8.GetBytes(key);

                // 暗号化
                ICryptoTransform encryptor = myRijndael.CreateEncryptor(myRijndael.Key, myRijndael.IV);

                byte[] encrypted;
                using (MemoryStream mStream = new MemoryStream())
                {
                    using (CryptoStream ctStream = new CryptoStream(mStream, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter sw = new StreamWriter(ctStream))
                        {
                            sw.Write(text);
                        }
                        encrypted = mStream.ToArray();
                    }
                }
                // Base64形式(64種類の英数字で表現)で返す
                return (System.Convert.ToBase64String(encrypted));
            }
        }

        /// <summary>
        /// 対称鍵暗号を使って暗号文を復号する
        /// </summary>
        /// <param name="cipher">暗号化された文字列</param>
        /// <param name="iv">対称アルゴリズムの初期ベクター</param>
        /// <param name="key">対称アルゴリズムの共有鍵</param>
        /// <returns>復号された文字列</returns>
        public static string Decrypt(string cipher, string iv, string key)
        {
            using (RijndaelManaged rijndael = new RijndaelManaged())
            {
                // ブロックサイズ(何文字単位で処理するか)
                rijndael.BlockSize = 128;
                // 暗号化方式はAES-256を採用
                rijndael.KeySize = 256;
                // 暗号利用モード
                rijndael.Mode = CipherMode.CBC;
                // パディング
                rijndael.Padding = PaddingMode.PKCS7;

                rijndael.IV = Encoding.UTF8.GetBytes(iv);
                rijndael.Key = Encoding.UTF8.GetBytes(key);

                ICryptoTransform decryptor = rijndael.CreateDecryptor(rijndael.Key, rijndael.IV);

                string plain = string.Empty;
                using (MemoryStream mStream = new MemoryStream(System.Convert.FromBase64String(cipher)))
                {
                    using (CryptoStream ctStream = new CryptoStream(mStream, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader sr = new StreamReader(ctStream))
                        {
                            plain = sr.ReadLine();
                        }
                    }
                }
                return plain;
            }
        }
    }
}

実行結果

PlainText : Hello, World!

Cipher : /NYRDYOCN8ra6GiGEuzw/w==

Decrypted : Hello, World!

C#でみんなが買っている本

「C#の本」人気ランキングになります。

スクロールできます
ランク製品特徴と評価価格
1
1週間でC#の基礎が学べる本
7日間で基礎力が身に付く

評価
単行本 2,750円
Kindle 2,475円
2
なるほどなっとくC#入門
厳選した機能を学べる


評価
単行本 3,168円
Kindle 3,010円
各製品の比較

\仕事と資格に強いスクールを探す/

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

都内の精密機器を作っている会社に勤務している14年目のエンジニアです。趣味は美味しいものを食べることとゴルフ。プログラムについて今まで学んだことをわかりやすく発信するサイトを目指しています。

コメント

コメントする

目次