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

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

ただいまの
回答率

90.35%

  • C#

    7662questions

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

  • .NET Core

    2questions

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

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 307

daiki002

score 25

 質問

.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の暗号化、複合をするにはどうすれば良いでしょうか。

 プログラム

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace Rijndael256Test
{
    class Program
    {
        static byte[] RijndaelEncrypt(byte[] bytes)
        {
            var key = Encoding.UTF8.GetBytes("aaaaaaaabbbbbbbbccccccccdddddddd");
            var iv = Encoding.UTF8.GetBytes("aaaaaaaabbbbbbbbccccccccdddddddd");

            var aes = Rijndael.Create();
            aes.Padding = PaddingMode.PKCS7;
            aes.Mode = CipherMode.CBC;
            aes.KeySize = 256;
            aes.BlockSize = 256;

            using (var decryptor = aes.CreateEncryptor(key, iv))
            {
                return decryptor.TransformFinalBlock(bytes, 0, bytes.Length);
            }
        }

        static byte[] RijndaelDecrypt(byte[] bytes)
        {
            var key = Encoding.UTF8.GetBytes("aaaaaaaabbbbbbbbccccccccdddddddd");
            var iv = Encoding.UTF8.GetBytes("aaaaaaaabbbbbbbbccccccccdddddddd");

            var aes = Rijndael.Create();
            aes.Padding = PaddingMode.PKCS7;
            aes.Mode = CipherMode.CBC;
            aes.KeySize = 256;
            aes.BlockSize = 256;

            using (var decryptor = aes.CreateDecryptor(key, iv))
            {
                return decryptor.TransformFinalBlock(bytes, 0, bytes.Length);
            }
        }

        static void Main(string[] args)
        {
            var bytes = Encoding.UTF8.GetBytes("helloworld");
            bytes = RijndaelEncrypt(bytes);
            bytes = RijndaelDecrypt(bytes);

            Console.WriteLine(Encoding.UTF8.GetString(bytes));

        }
    }
}

 .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
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+2

こんにちは。

.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/26 09:21 編集

    回答ありがとうございます。

    ■公式ドキュメントについて
    リンク先が.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の指定ができなければならない所、
    指定ができない現状は明らかに仕様に従っていない実装になっています。

    この点を放置してリリースした点がわかりかねます。

    キャンセル

  • 2018/07/26 10:22

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

    キャンセル

  • 2018/07/26 11:56

    私がRijndaelにこだわる理由は「私が手を加えることが出来ない他のアプリケーションで利用されている暗号方式がRijndaelでブロック長が256bitだった為」です。

    私もtamoto様が仰られるのと同意見でRijndaelにあえてこだわる理由はありません。。。が今回は他のアプリケーションの仕様に合わせる必要がありました。

    OpenSSL等もRijndaelをサポートしていないとの事なのでモダンな業界標準に合わせたという点もありそうですね。

    Rijndaelクラスが実はRijndaelではない点はうーむ...という感じですし、
    かといってRijndaelクラスをDeprecatedにするのは意味合いが違う気もしますし、
    そのあたりは少しもやもやしますが。。。

    メリットがあるとすれば、開発者がAESの色々な背景を知らなくとも自ずとブロック長128bitを選択する事になる為、互換性を維持できるという点ぐらいが思いつきます。

    とはいえ私個人が今更どうこう考えても仕方ないので現状を理解し受け入れる事にします。

    最終的にこのような形にはなりましたが、
    tamotoさんのコメントで考えを深める事ができました。
    ありがとうございました。

    ベストアンサーはすみませんが、自己回答でまとめたものとさせていただきます。
    Google等で検索してきた方がそれを読み、すぐ理解できるようにする為です。

    キャンセル

  • 2018/07/26 14:19

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

    キャンセル

check解決した方法

+1

 Q1

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

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

internal sealed class RijndaelImplementation : Rijndael
{
  internal RijndaelImplementation()
  {
    // This class wraps Aes
    _impl = Aes.Create();
  }
}

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クラスについて

 (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 等のライブラリを利用するしかありません。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

2Toad/Rijndael256

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/24 14:06 編集

    回答有り難うございます。ライブラリのソースコードを見ると残念ながら.NET Coreの場合はAesクラスが利用されていたのでブロック長256bitをサポートしているライブラリではありませんでした。

    追記
    このライブラリ開発者はブロック長256bitをサポートする気は無いようです。
    https://github.com/2Toad/Rijndael256/issues/13

    キャンセル

同じタグがついた質問を見る

  • C#

    7662questions

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

  • .NET Core

    2questions