BouncyCastle で公開鍵暗号標準(RSA)を扱う


# キーペアを用意する

openssl コマンドで秘密鍵、公開鍵のペアを作成する

秘密鍵

```
$ openssl genrsa > private.pem
```

秘密鍵を元にした公開鍵

```
$ openssl rsa -pubout < private.pem > public.pem
```

参考： [opensslでRSA暗号と遊ぶ - ろば電子が詰まっている](http://d.hatena.ne.jp/ozuma/20130510/1368114329)


# BouncyCastle のソースコードをプロジェクトに取り込む

以下のように Git リポジトリをクローンして必要な箇所をプロジェクトに取り込む。

```
$ git clone https://github.com/bcgit/bc-csharp.git
```


# 暗号化とその復号をやってみる

:::note info
コードに記載されている公開鍵・秘密鍵は、このサンプル用に用意したものです。実務で利用しているものではありません。念のため :wink: 
:::


```csharp:RSATest.cs
using UnityEngine;
using System.IO;
using System.Text;

using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Encodings;

public class APITestMain : MonoBehaviour {

	// （いろいろ省略）

		// RSA公開鍵で"hogehoge" を暗号化
		// その後、その公開鍵とペアとなる秘密鍵で復号する
		public void DoTest() {
			// 暗号化の対象となる文字列
			var originalText = "hogehoge";

			// 文字列からバイト列を取得
			var originalBytes = Encoding.UTF8.GetBytes(originalText);
			
			// ============
			// 暗号化
			// ============

			// 公開鍵のPEMフォーマット文字列(opensslで生成したPEM形式文字列をここに貼り付け)
			var publicKeyPem = new StringReader(@"-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAOTlsg0qJMptmM8LFqCWEC1bIcdvnzoH
xm+xscJb9qpAZhVluEKz+gTSlEGEDDHlOFjC8LcWrMfVK7vl+PR92RMCAwEAAQ==
-----END PUBLIC KEY-----
			");
			// PEMフォーマットの公開鍵を読み込んで KeyParam を生成
			var publicKeyReader = new PemReader(publicKeyPem);
			var publicKeyParam = (AsymmetricKeyParameter)publicKeyReader.ReadObject();

			// RSA暗号標準オブジェクト(PKCS#1)を生成
			var rsa = new Pkcs1Encoding(new RsaEngine());

			// RSA暗号オブジェクトを初期化（第１引数 true は「暗号化」を示す）
			rsa.Init(true, publicKeyParam);

			// 対象のバイト列を渡し暗号化した結果のバイト列を受け取る
			byte[] encrypted = rsa.ProcessBlock(originalBytes, 0, originalBytes.Length);

			// とりあえず結果を表示してみる（バイト列なので表示しきれないが一応）
			Debug.Log ("encrypted: " + encrypted);
			
			// ============
			// 復号
			// ============

			// 秘密鍵のPEMフォーマット文字列(opensslで生成したPEM形式文字列をここに貼り付け)
			var privateKeyPem = new StringReader(@"-----BEGIN RSA PRIVATE KEY-----
MIIBPAIBAAJBAOTlsg0qJMptmM8LFqCWEC1bIcdvnzoHxm+xscJb9qpAZhVluEKz
+gTSlEGEDDHlOFjC8LcWrMfVK7vl+PR92RMCAwEAAQJBANONg6ltKQG6l3/MFMao
yxzQXIDyJmzA4OM8jTlAO9MO4IOdhkkyqr4JW+2pj8ejBgyj0w55XPEir44/6ByO
ewkCIQD2SHPYKCeiEwSNo231LVqa1bK7mSDeOGuYaiKLjiwqlwIhAO3to/PuXpAc
bIAzF33A2f9pGLiIaO3jhBkDyan/GkDlAiEAyH0syQ/PS9Jdh4w+jDPyqU9D5BIB
PsYBWR81phQEAlsCIGWa7UAXVHSwXrlkmCyQtce3xuHPBxhH57qS/oTFNx3tAiEA
0PJgIm1jvfuWKN+JPcfiCRciSyO1A6LPYCQcbVRa934=
-----END RSA PRIVATE KEY-----
			");

			// PEMフォーマットの秘密鍵を読み込んで KeyPair オブジェクトを生成
			var privateKeyReader = new PemReader(privateKeyPem);
			var keyPair = (AsymmetricCipherKeyPair)privateKeyReader.ReadObject();

			// RSA暗号オブジェクトを初期化（第１引数 false は「復号」を示す）
			rsa.Init (false, keyPair.Private);

			// 暗号化されたバイト列を渡し、復号されたバイト列を受け取る
			byte[] decrypted = rsa.ProcessBlock(encrypted, 0, encrypted.Length);

			// "hogehoge" と表示されたら復号成功
			Debug.Log ("decrypted: " + Encoding.UTF8.GetString(decrypted));
		}	
	}
}
```

上記実装にあたっては、BouncyCastle自身のテストコードが参考になった

* [bc-csharp/crypto/test/src/crypto/test/RsaTest.cs at master · bcgit/bc-csharp](https://github.com/bcgit/bc-csharp/blob/master/crypto/test/src/crypto/test/RsaTest.cs#L393)



# 参考リンク

* [The Legion of the Bouncy Castle C# Cryptography APIs](http://www.bouncycastle.org/csharp/)
* [bcgit/bc-csharp](https://github.com/bcgit/bc-csharp)
* [PKCS - Wikipedia](http://ja.wikipedia.org/wiki/PKCS)