Bouncy Castle (.NETFramework) の使い方

## はじめに

[Bouncy Castle](http://www.bouncycastle.org/csharp/) は、Javaで実装されたさまざまな暗号ライブラリの.NETFrameworkへのポーティングである。

この使い方のメモ。

## 基本

基本的に、[本家](http://www.bouncycastle.org/csharp/)のAPIリファレンスで事足りるとは思うけど、私なりのメモ。

しかしながら、VisualStudioのオブジェクトブラウザは、便利♪

関数/メソッドの引数の型とかで、大体の使い方が分かると思う。

## 共通鍵暗号

鍵が一つの暗号だよ。

## 共通鍵暗号

### ブロック暗号

暗号の単位が、数バイトのやつ。

まずは、アルゴリズムを選択する。

Org.BouncyCastle.Crypto.Engines 以下の Org.BouncyCastle.Crypto.IBlockCipher インターフェイスを実装しているやつがそれ。

大抵の場合で、AES を選択すればいいでしょうけど、[Bouncy Castle](http://www.bouncycastle.org/csharp/)にはさまざまなアルゴリズムが用意されている(すごい!!!)。

大抵は、引数のないコンストラクタがあると思うので、それでオブジェクトを生成(インスタンス)する

#### 暗号モード

ブロックごとの関係がないと、つまり独立の場合は、ブロックごとに個別に解読される危険性があるので、ブロック間で関係(例えば、一つ前のブロックとキーをxorしてから次のブロックの暗号にとりかかるとか)が必要。
それが暗号モードというやつ。

##### 暗号モードの選択

Org.BouncyCastle.Crypto.Modes 以下で、コンストラクタの引数に Org.BouncyCastle.Crypto.IBlockCipher インターフェイスがあるやつを選択すればいい。
といっても Org.BouncyCastle.Crypto.Modes 以下の全てのクラスがこの条件を満たしていると思う。

##### 暗号モードによるストリーム暗号化

Org.BouncyCastle.Crypto.Modes.CtsBlockCipher と Org.BouncyCastle.Crypto.Modes.KCtrBlockCipher は、ブロック暗号をストリーム暗号として使えるようにするモードなので、
これらのオブジェクトは、Org.BouncyCastle.Crypto.IBlockCipher インターフェイスを実装していないことに注意されたし。

また、ストリーム暗号化するので、これらのモードにパディングが不要になることも分かると思う。

##### [AEAD暗号モード](https://ja.wikipedia.org/wiki/%E8%AA%8D%E8%A8%BC%E4%BB%98%E3%81%8D%E6%9A%97%E5%8F%B7)

いくつかの暗号モードは、AEAD モードという最近の暗号モードなので、注意されたし。
なので、それらのオブジェクトは、Org.BouncyCastle.Crypto.IBlockCipher インターフェイスを実装せず、Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher インターフェイスを実装しているので注意されたし。

#### パディング

次は、データの末端がブロック全体を満たさなかった場合は、なにかで満たす必要があるわけで、それがパディングというアルゴリズム。

足りなかったら 0x00 で満たせばいいじゃん。って簡単に考えがちだけど、それ以外にもいろいろな満たし方(パディングアルゴリズム)があるということ。

##### パディングの選択

Org.BouncyCastle.Crypto.Paddings 以下で、コンストラクタの引数に Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding インターフェイスを実装しているやつを選択すればいい。
といっても Org.BouncyCastle.Crypto.Paddings 以下の全てのクラス(PaddedBufferedBlockCipherを除く)がこの条件を満たしていると思う。

そして、Org.BouncyCastle.Crypto.Paddings.PaddedBufferedBlockCipher クラスを、モードも含めた IBlockCipher と、直前に作った IBlockCipherPadding でオブジェクトを作成(インスタンス)すればいい。

### ストリーム暗号

暗号の単位が、1Bit(1Byte)のやつ。

まずは、アルゴリズムを選択する。

Org.BouncyCastle.Crypto.Engines 以下の Org.BouncyCastle.Crypto.IStreamCipher インターフェイスを実装しているやつがそれ。

RC4 とか ChaChaが有名だと思う。

#### ストリーム暗号のモードとパディング

ストリーム暗号は、1Bit(1Byte)単位なので、モードもパディングも不要だというのは分かるでしょう。

#### ストリーム暗号のまとめ

アルゴリズムのインスタンスを作って終了。以上

### ブロック暗号とストリーム暗号の初期化(Org.BouncyCastle.Crypto.ICipherParameters インターフェイス)

#### 共通鍵

Org.BouncyCastle.Crypto.Parameters 以下の ICipherParameters インターフェイスを実装したクラスが対象なのだが、ブロック暗号/ストリーム暗号共に、鍵は一つなので、まずは Org.BouncyCastle.Crypto.Parameters.KeyParameter クラスを生成(インスタンス)しておく。

#### IVが必要なら

そして、IVが必要なら、Org.BouncyCastle.Crypto.Parameters.ParametersWithIV クラスを、直前の KeyParameter のオブジェクトと IV(Byte配列)のコンストラクタで、オブジェクトとして生成(インスタンス)する

#### そして、初期化

あとは、init(Org.BouncyCastle.Crypto.ICipherParameters) 関数に与えれば、初期化が完了する

#### いくつか例外

アルゴリズムごとに専用の Org.BouncyCastle.Crypto.ICipherParameters インターフェイスを実装したオプションを収めたオブジェクトがある

Org.BouncyCastle.Crypto.Parameters.DesEdeParameters
Org.BouncyCastle.Crypto.Parameters.DesParameters
Org.BouncyCastle.Crypto.Parameters.RC5Parameters
Org.BouncyCastle.Crypto.Parameters.RC2Parameters

あたりがそうだと思う。

また、AEAD 専用のパラメータオブジェクトとして、

Org.BouncyCastle.Crypto.Parameters.AeadParameters
Org.BouncyCastle.Crypto.Parameters.CcmParameters

があるよ。

##### いくつか例外(AEAD)

AEADモード時は、Org.BouncyCastle.Crypto.Parameters.AeadParameters オブジェクトをパラメータに init しなきゃいけないのだけど、Org.BouncyCastle.Crypto.ParametersWithIV クラスでもよい。

## ハッシュ

Org.BouncyCastle.Crypto.Digests 以下がそれ。

基本的には、引数のないコンストラクタばかりだと思うけど、一部のコンストラクタは IBlockCipher が必要だったりする。
詳しくは、オブジェクトブラウザーで見るとよいと思う。

Org.BouncyCastle.Crypto.Digests.ShortenedDigest クラスは、他のハッシュオブジェクトで生成したハッシュ値をさらにも短くするハッシュオブジェクト。
こういうのもあるので、オブジェクトブラウザで眺めるだけでも面白い。

## Mac

ハッシュと鍵を使って、鍵の知らない人にはハッシュ値が生成できないようにしたもの。

Org.BouncyCastle.Crypto.Macs 以下がそれ。


ハッシュを作って、それを引数にするコンストラクタとか、暗号(IBlockCipher)を引数にするコンストラクタとか、いろいろあるよ。

Org.BouncyCastle.Crypto.Macs.HMac は、ハッシュを使った MAC

Org.BouncyCastle.Crypto.Macs.CMac は、暗号を使った MAC

Org.BouncyCastle.Crypto.Macs.CbcBlockCipherMac は、共通鍵のブロック暗号の CBC モード暗号を使った MAC なので、モードなしの IBlockCipher を与えるべきだと思う。

Org.BouncyCastle.Crypto.Macs.CfbBlockCipherMac は、共通鍵のブロック暗号の CFB モード暗号を使った MAC なので、モードなしの IBlockCipher を与えるべきだと思う。

Org.BouncyCastle.Crypto.Macs.GMac は、共通鍵のブロック暗号の GCM モード暗号を使った MAC
(コンストラクタの引数には Org.BouncyCastle.Crypto.Modes.GcmBlockCipher オブジェクトが必要)

## ストリーム([System.IO.Stream](https://docs.microsoft.com/en-us/dotnet/api/system.io.stream?view=netframework-4.8))

Org.BouncyCastle.Crypto.IO.CipherStream
Org.BouncyCastle.Crypto.IO.DigestStream
Org.BouncyCastle.Crypto.IO.MacStream

がある

## 公開鍵暗号

鍵として、公開鍵と秘密鍵で、二つ必要な暗号だよ。

Org.BouncyCastle.Crypto.Engines 以下の Org.BouncyCastle.Crypto.IAsymmetricBlockCipher インターフェイスを実装しているやつがそれ。

RSA が有名だと思う。

### 公開鍵暗号....

未稿



## 以上