.NET(C#)でデータ暗号化（主にAES）を利用する時のメモ


.NETを使った暗号化の実装について気になることがあったので、メモ。

## 気になったこと

オンラインドキュメントの日本語訳が無茶苦茶だったので、英語から引用です。
要するに、`AesCryptoServiceProvider`や`AesManaged`とかは普通は使わないでよくて、`Aes`を使うとよい、というように読めます。ネットのサイトを色々見てると作り方が色々のようで、どのクラスを使うのか迷ったのだけれど。どうも見ていると、基本は`Aes.Create()`でインスタンスを作れば設定値は推奨のものが自動で入るっぽいですね（そんな風に読めた）。

>In most cases, you don't need to directly reference an algorithm implementation class, such as AesCryptoServiceProvider. The methods and properties you typically need are on the base algorithm class, such as Aes.

- [.NET Cryptography Model](https://docs.microsoft.com/en-us/dotnet/standard/security/cryptography-model)

確かに、MSサイトの例を見ると、`Aes aes = Aes.Create()`という例が多いですね。ちなみに、この`Create`のFactoryメソッドの引数にはアルゴリズム（AES、AesManaged、AesCryptoServiceProvider）が指定できるので、何の型が返ってくるのか調べてみました。

検証コード、出力結果は以下です。


```csharp:検証プログラム
using System;
using System.Security.Cryptography;

Aes def = Aes.Create();
Aes aes = Aes.Create("AES");
Aes aesManaged = Aes.Create("AesManaged");
Aes aesCSP = Aes.Create("AesCryptoServiceProvider");

AesManaged managed = new AesManaged();
AesCryptoServiceProvider CSP = new AesCryptoServiceProvider();

Console.WriteLine(def.GetType().Name);
Console.WriteLine(aes.GetType().Name);
Console.WriteLine(aesManaged.GetType().Name);
Console.WriteLine(aesCSP.GetType().Name);
Console.WriteLine(managed.GetType().Name);
Console.WriteLine(CSP.GetType().Name);
```

```plaintext:出力結果
AesImplementation
AesCryptoServiceProvider
AesManaged
AesCryptoServiceProvider
AesManaged
AesCryptoServiceProvider
```

![testAES.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323247/a365a9dc-e204-ea2f-b530-60456a8e245c.png)


"AES"の場合はAesImplementationなので、AesManagedとは別のクラスが使用されているようですね。下にも書いていますが、AesCryptoServiceProviderはWindowsの実装を呼び出すためのラッパーです。


## Managedが付くやつはFIPS認定されていない

アルゴリズムの名称にMagagedが付くものは文字通り完全なマネージドとして記述されているものなのですが、MSのドキュメントによるとFIPS認定されていません。FIPS (Federal Information Processing Standards)は、アメリカの政府調達に関する標準です（FIPS 140-2については暗号化モジュールが満たすべき要件について定義している）。要するに、FIPS認定がないものは第三者のお墨付きがないから、それ以外を使った方が無難ということでしょうか（むしろ詳しい方がいれば教えてほしい）。

- [AesManaged.cs (GitHub)](https://github.com/microsoft/referencesource/blob/master/System.Core/System/Security/Cryptography/AesManaged.cs)

```csharp
if (CryptoConfig.AllowOnlyFipsAlgorithms) {
    if (LocalAppContextSwitches.UseLegacyFipsThrow) {
        throw new InvalidOperationException(SR.GetString(SR.Cryptography_NonCompliantFIPSAlgorithm));
    }
```

`AesCryptoServiceProvider`は、Windowsの機能（CAPI）のラッパーのようです。このソースを見ると、`AllowOnlyFipsAlgorithms`は見ていないようです。FIPS認証されているということでいいんですかね？

- [AesCryptoServiceProvider.cs](https://github.com/microsoft/referencesource/blob/master/System.Core/System/Security/Cryptography/AesCryptoServiceProvider.cs)
 
## Rijndael

.NETのRijndael (とそれを継承したRijndaelManaged)は、`SymmetricAlgorithm`クラスを継承していますが、`Aes`も同様に`SymmetricAlgorithm`を継承しています。

RijndaelはAESと比べ、ブロック長が256bitまでの32bitの倍数で選べるが（鍵長についても同様）、AESは鍵長が128bit、192bit、256bitの3種類のみ。あと、ブロック長が128bitしか選べない。

要するに、AESとは別クラス。どちらが良いか…は何ともいえないけれど、AESは秘密鍵暗号方式としては標準と言ってよいほど色んなプログラムで実装されていて、今のところ危殆化とかそういう話題は見ない（今のところ）。むしろ、あれば大騒ぎになるはず。広く使われているので。

## 補足：WindowsにFIPS認定の使用を強制させる方法

MSの記事で、こんなのを見つけた（英語ですが）。

- [FIPs and .NET Core] (https://techcommunity.microsoft.com/t5/windows-dev-appconsult/fips-and-net-core/ba-p/1454638)

上で書いたFIPS認定の使用を強制させることができるらしいが、グループポリシーの編集で可能になるらしい。ただ、変更した後にどうなるかが怖いので、検証はしていません。

半ばメモなので、Qiitaの記事っぽくないかもしれませんが、ご了承下さい。