質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
.NET Core

.NET Coreは、マネージソフトウェアフレームワークでオープンソースで実装されています。クロスプラットフォームを前提に考えられており、Windows/Mac/Linuxで動くアプリケーションを作成することが可能です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

3回答

1791閲覧

.NET CoreのRijndaelのブロック長256bitについて

daiki002

総合スコア68

.NET Core

.NET Coreは、マネージソフトウェアフレームワークでオープンソースで実装されています。クロスプラットフォームを前提に考えられており、Windows/Mac/Linuxで動くアプリケーションを作成することが可能です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

1クリップ

投稿2018/07/24 04:50

編集2018/07/26 05:01

質問

.NET Framework と .NET Coreでの実行結果が違います。

Q1. corefxのRijndaelImplementation.csを見ると以下のように書かれていました。
なぜ.NET Coreではブロック長256bitがサポートされていないのでしょうか?

Values which were legal in desktop RijndaelManaged but not here in this wrapper type

https://github.com/dotnet/corefx/blob/master/src/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RijndaelImplementation.cs#L36

Q2. .NET Core標準クラスを利用してブロック長256bitの暗号化、複合をするにはどうすれば良いでしょうか。

プログラム

cs

1using System; 2using System.IO; 3using System.Security.Cryptography; 4using System.Text; 5 6namespace Rijndael256Test 7{ 8 class Program 9 { 10 static byte[] RijndaelEncrypt(byte[] bytes) 11 { 12 var key = Encoding.UTF8.GetBytes("aaaaaaaabbbbbbbbccccccccdddddddd"); 13 var iv = Encoding.UTF8.GetBytes("aaaaaaaabbbbbbbbccccccccdddddddd"); 14 15 var aes = Rijndael.Create(); 16 aes.Padding = PaddingMode.PKCS7; 17 aes.Mode = CipherMode.CBC; 18 aes.KeySize = 256; 19 aes.BlockSize = 256; 20 21 using (var decryptor = aes.CreateEncryptor(key, iv)) 22 { 23 return decryptor.TransformFinalBlock(bytes, 0, bytes.Length); 24 } 25 } 26 27 static byte[] RijndaelDecrypt(byte[] bytes) 28 { 29 var key = Encoding.UTF8.GetBytes("aaaaaaaabbbbbbbbccccccccdddddddd"); 30 var iv = Encoding.UTF8.GetBytes("aaaaaaaabbbbbbbbccccccccdddddddd"); 31 32 var aes = Rijndael.Create(); 33 aes.Padding = PaddingMode.PKCS7; 34 aes.Mode = CipherMode.CBC; 35 aes.KeySize = 256; 36 aes.BlockSize = 256; 37 38 using (var decryptor = aes.CreateDecryptor(key, iv)) 39 { 40 return decryptor.TransformFinalBlock(bytes, 0, bytes.Length); 41 } 42 } 43 44 static void Main(string[] args) 45 { 46 var bytes = Encoding.UTF8.GetBytes("helloworld"); 47 bytes = RijndaelEncrypt(bytes); 48 bytes = RijndaelDecrypt(bytes); 49 50 Console.WriteLine(Encoding.UTF8.GetString(bytes)); 51 52 } 53 } 54} 55

.NET Framework 4.6.1での実行結果

helloworld

.NET Core 2.1.201 での実行結果

Unhandled Exception: System.PlatformNotSupportedException: BlockSize must be 128 in this implementation. at Internal.Cryptography.RijndaelImplementation.set_BlockSize(Int32 value) at Rijndael256Test.Program.RijndaelEncrypt(Byte[] bytes) in Program.cs:line 19 at Rijndael256Test.Program.Main(String[] args) in Program.cs:line 47

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

こんにちは。

.NET Coreはその成り立ちからして、「過去の負債を清算しよう」ということを推進していたフシがあります。まあ、NETStandard2.0でその野望も潰えたわけなのですが……
そこら辺が関係するのかは推測でしかないですが、公式ドキュメント[Rijndael Class (System.Security.Cryptography) | Microoft Docs]に書いてあるとおり、「RijndaelなんてのはAesの先行品だから今更使ってんじゃねえ!Aesを使え!」ってことなので、つまりAesを使えってことなんじゃないでしょうか。

リンク先にありますが、こっちのBlogも参考までに。
The Differences Between Rijndael and AES – .NET Security Blog

投稿2018/07/25 16:05

tamoto

総合スコア4103

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

daiki002

2018/07/26 00:26 編集

回答ありがとうございます。 ■公式ドキュメントについて リンク先が.NET Framework 4.7.2になっていたので .NET Core 2.1のURLを一応残しておきます。 https://docs.microsoft.com/ja-jp/dotnet/api/system.security.cryptography.rijndael?view=netcore-2.1#remarks 上記公式ドキュメントを見ましたが間違っていました。 「This algorithm supports block sizes of 128, 192, or 256 bits; defaulting to 128 bits (Aes-compatible).」 と書かれていますが正確には今回質問した通り.NET CoreのRijndaelではブロック長256bitはサポートされていない実装になっています。 (詳細が明らかになり次第修正のプルリクを送りたいと思います。) ■公式ブログについて 今回の質問とはあまり関係がなく、AesとRijndaelのブロック長の違い等について書かれた記事でした。 ■個人的な意見 私はRijndaelを過去のものと捉えておらず、RijndaelとAESは仕様上異なる点から別物であると考えています。 (例えばブロック長の指定が仕様上違う点) なので、もしRijndaelをdeprecatedにするような動きがあり、今のような実装したのであれば正直意味が分かりません。 また、AESとしてRijndaelが採用された歴史も考えると、RijndaelがAesのラッパーである点が意味が分かりません。 AesがRijndaelのラッパーで、ブロック長を制限しているのであれば意味がわかります。 (厳密な仕様上はブロック長だけでなく、他にも違いがあるかもしれませんが。) 本来Rijndaelの仕様上ブロック長256bitの指定ができなければならない所、 指定ができない現状は明らかに仕様に従っていない実装になっています。 この点を放置してリリースした点がわかりかねます。
tamoto

2018/07/26 01:22

そうですね。 「Rijndaelを使う」という前提がある以上は、現在のCore実装が仕様を満たしていないのは明白ですし、使えないという判断になることも解ります。 個人的に疑問なのは、そこまでして「なぜRijndaelにこだわるのか?」という点です。 ご存知の通り、RijndaelはAesに採用されました。言い換えると、「大々的に規格化された」ということです。 Aesの規格では、ブロック長を128に固定したことで規格自体を単純化しています。Rijndaelのように変更できるようにしたとして、それは鍵長ではなくブロック長なので、変えたところでセキュアになるものでもないです。それは、「規格を複雑にし、互換性担保の難度を上げてまで搭載するものではない」と判断されたのでしょう。インターフェースをシンプルに保つメリットは質問者さんもよく理解していることでしょう。 今の時代、Aesの規格に従う暗号化ロジックは普遍的に実装されているわけですが、「その強力な互換性を捨ててまで、Rijndaelにこだわる理由は何なのか?」という疑問が出てきます。 Coreライブラリ提供側の立場を想定すると、仮にRijndaelを使う場合でも、互換性を担保できるブロック長128しかどうせ使わないだろう(則ち、Aesのラッパーにしてしまう)という判断を下すのは理解できなくはないです。 それでも本来本物のRijndaelを使いたい、というのであれば、自前実装やコミュニティ実装の利用を検討するのが現実的かなと思います。
daiki002

2018/07/26 02:56

私がRijndaelにこだわる理由は「私が手を加えることが出来ない他のアプリケーションで利用されている暗号方式がRijndaelでブロック長が256bitだった為」です。 私もtamoto様が仰られるのと同意見でRijndaelにあえてこだわる理由はありません。。。が今回は他のアプリケーションの仕様に合わせる必要がありました。 OpenSSL等もRijndaelをサポートしていないとの事なのでモダンな業界標準に合わせたという点もありそうですね。 Rijndaelクラスが実はRijndaelではない点はうーむ...という感じですし、 かといってRijndaelクラスをDeprecatedにするのは意味合いが違う気もしますし、 そのあたりは少しもやもやしますが。。。 メリットがあるとすれば、開発者がAESの色々な背景を知らなくとも自ずとブロック長128bitを選択する事になる為、互換性を維持できるという点ぐらいが思いつきます。 とはいえ私個人が今更どうこう考えても仕方ないので現状を理解し受け入れる事にします。 最終的にこのような形にはなりましたが、 tamotoさんのコメントで考えを深める事ができました。 ありがとうございました。 ベストアンサーはすみませんが、自己回答でまとめたものとさせていただきます。 Google等で検索してきた方がそれを読み、すぐ理解できるようにする為です。
tamoto

2018/07/26 05:19

はわ……まさか、「Rijndaelなんて使うんじゃねえー!」の最も大きな理由そのものにぶち当たっていたとは…… やはり互換性のない暗号化方式はこれだからギルティですし、だから最初からサポートしないぜ!って姿勢は極めて正当である気もしてきますね……。
guest

0

自己解決

Q1

以下3点の内容をまとめると、
「もはやRijndaelは不要と判断され、実装されなかった。」という事かと思われます。
(推測です)

(1) .NET CoreのRijndaelはAesクラスのラッパーである事がわかりました。

cs

1internal sealed class RijndaelImplementation : Rijndael 2{ 3 internal RijndaelImplementation() 4 { 5 // This class wraps Aes 6 _impl = Aes.Create(); 7 } 8}

https://github.com/dotnet/corefx/blob/master/src/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RijndaelImplementation.cs#L25-L26

Aesはもともとブロック長256bitをサポートしていません。
128bitのみサポートしています。
ゆえにラッパーであるRijndaelクラスもブロック長256bitをサポートしていないという事がわかりました。

しかし、なぜ.NET CoreのRijndaelはAesのラッパーなのでしょうか。
その点が未だ不明です。回答を募集しております。

(2) .NET CoreのManagedクラスについて

  • .NET Coreでは Managedクラスを今後一切メンテナンスしないと決めている。

https://github.com/dotnet/corefx/issues/12064#issuecomment-251155477

(3) 現状の暗号ライブラリの実装について

CNG(Cryptography API: Next Generation), OpenSSL, Security Framework(Apple系)どれをみてもRijndaelをサポートしている物はない。
.NET FrameworkはRijndaelに関するManagedクラスがある。ブロック長256bitもサポートしている。
.NET CoreはManagedクラスをサポートしない。

https://github.com/dotnet/corefx/issues/12064#issuecomment-354495938

Q2

現状不可能です。
BouncyCastle 等のライブラリを利用するしかありません。

投稿2018/07/24 05:01

編集2018/07/26 03:08
daiki002

総合スコア68

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

2Toad/Rijndael256

使ったことはありません。
使えるかどうか調べてもいません。
調べてみてください。

投稿2018/07/24 05:01

Zuishin

総合スコア28660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

daiki002

2018/07/26 00:31 編集

回答有り難うございます。ライブラリのソースコードを見ると残念ながら.NET Coreの場合はAesクラスが利用されていたのでブロック長256bitをサポートしているライブラリではありませんでした。 追記 このライブラリ開発者はブロック長256bitをサポートする気は無いようです。 https://github.com/2Toad/Rijndael256/issues/13
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問