読者です 読者をやめる 読者になる 読者になる

備忘録

備忘録

C# でBouncyCastleを使ってRijndael で暗号化する

C#

Ⅰ. はじめに

現時点の.NET Core(1.0.3)には Rijndael に関するクラスは含まれていません。
ブロック長が 256bit 以外 かつ PaddingModeにISO10126等を使用しないのであれば Aes クラスを利用すればokです。※詳細

ブロック長が 256bit のRijndael を利用したい場合は、
公式のリリースではありませんが、それなりに利用数が多いBouncyCastleを利用するのがベターかと思います。

Q. いつ.NET Coreに Rijndael 関係のクラスが実装されるの?

A. 2017年 Q1の終わりの見込み。
corefxのリポジトリには既に Rijndael に関するクラスがpull requestされ、Mergeされていますが、※1
.NET Standard 2.0 に含まれる予定なので、
.NET Coreに Rijndael が実装されるのは早くても2017 Q1の終わりの見込みだそうです。※2

※1
https://github.com/dotnet/corefx/pull/12843

※2
https://www.infoq.com/jp/news/2016/12/dotnet-standard-20-goals

Ⅱ. やり方

1. NuGetで Portable.BouncyCastle をインストールする

2. Rijndael の暗号化、複合のサンプル

using System;
using System.Text;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Paddings;
using Org.BouncyCastle.Crypto.Parameters;

namespace RijndaelTest
{
    class BouncyCastleRijndael
    {
        static byte[] key;
        static byte[] iv;
        static PaddedBufferedBlockCipher cipher;
        static ParametersWithIV parametersWithIV;

        static BouncyCastleRijndael()
        {
            key = Encoding.UTF8.GetBytes("13e990b91d7e48b89e6b04372900d3b6");
            iv = Encoding.UTF8.GetBytes("2aab0b4007de49f8aa9f9a4fd3286067");
            
            // Rijndael
            // Mode = CBC
            // BlockSize = 256bit
            // PaddingMode = Zero
            var cbcBlockCipher = new CbcBlockCipher(new RijndaelEngine(256));
            cipher = new PaddedBufferedBlockCipher(cbcBlockCipher, new ZeroBytePadding());
            parametersWithIV = new ParametersWithIV(new KeyParameter(key), iv);
        }

        public static string Encrypt(string str)
        {
            var data = Encoding.UTF8.GetBytes(str);

            cipher.Init(true, parametersWithIV);
            var bytes = new byte[cipher.GetOutputSize(data.Length)];
            var length = cipher.ProcessBytes(data, bytes, 0);
            cipher.DoFinal(bytes, length);

            return Convert.ToBase64String(bytes);
        }

        public static string Decrypt(string str)
        {
            var data = Convert.FromBase64String(str);

            cipher.Init(false, parametersWithIV);
            var bytes = new byte[cipher.GetOutputSize(data.Length)];
            var length = cipher.ProcessBytes(data, bytes, 0);
            cipher.DoFinal(bytes, length);

            return Encoding.UTF8.GetString(bytes);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var encryptedString = BouncyCastleRijndael.Encrypt("abc123");
            Console.WriteLine(encryptedString);
            // K7vBcS3Wbh2H7jGrXe4XfoLDGRDIOZ2zk9qqScpxzYU=

            var decryptedString = BouncyCastleRijndael.Decrypt(encryptedString);
            Console.WriteLine(decryptedString);
            // abc123
        }
    }
}