8

私はアプリケーションサーバーを作成していますが、AES128/CTR/NoPadding を使用して接続を保護することにしました。これは、バイトをブロック境界に拡張する必要なく十分に安全であると考えられており、TCP に適していると考えたからです。論理的にシームレスなストリームです。

問題は、CTR が基本的にストリーム暗号をシミュレートしているにもかかわらず、CTR がブロック暗号に基づいているため、Cipher.update() が完全な 16 バイトのブロックになるまで暗号化されたブロックを返さないことです。tcp ソケットからデータを読み取り、メッセージが到着したらすぐに処理する必要がありますが、最新のブロックはまだ構築中であり、サイズが 16 バイト未満であるため、取得できません。そして、次のメッセージがいつ送信されるかわからないので、ただ待つことはできません。もちろん、Cipher.doFinal() を呼び出して残りを取得することもできますが、それはストリーム (接続) の終わりを意味し、Cipher オブジェクトが再初期化されます。

キャリーオーバーを覗く方法があればいいなと思いました。CTR はプレーン テキストとキーストリームを XOR するだけなので、ブロック内の残りのバイトに関係なく、暗号化されたデータを取得できるはずです。この問題に対する適切な回避策はありますか? 偽のプレーンテキストをゼロで暗号化してキーストリームを事前に取得し、XOR を手動で行うラッパーを作成することを考えていますが、他の人がこの問題をどのように解決したのだろうか。

アップデート

私は Android アプリケーションを開発していますが、これは Dalvik VM の問題であることが判明しました。Robert と monnand が以下で指摘したように、Java SE には、少なくともデフォルトのプロバイダーではこの問題はありません。この問題を回避するには、ラッパー クラスを作成するか、モードを CFB8 に変更する必要があると思います。(CTR8 は機能しませんでした) すべての応答に感謝します!

4

3 に答える 3

5

Oracle Java 1.7を使用してCTRモードでAESをテストしましたが、あなたの観察を検証できません:

Cipher c = Cipher.getInstance("AES/CTR/NoPadding");
KeyGenerator kg = KeyGenerator.getInstance("AES");
c.init(Cipher.ENCRYPT_MODE, kg.generateKey());
System.out.println(c.update(new byte[1]).length);  // output: 1
System.out.println(c.update(new byte[20]).length); // output: 20

「AES128/CTR/NoPadding」は私のシステムでは既知の暗号ではないため、欠陥のあるサードパーティの実装を使用している可能性があります。

于 2013-04-30T11:19:56.877 に答える
4

私は今日まったく同じ問題を抱えていて、今それを修正しました。

問題はプロバイダーであり、おそらくBouncy Castleです。を呼び出すときgetInstance()は、アルゴリズムの名前を指定するだけです (私の場合は「AES/CTR/NoPadding」です)。プロバイダーを指定しないでください。

コード自体を説明しましょう。

@Robertが言ったように、次のコードは正しく機能します:

Cipher c = Cipher.getInstance("AES/CTR/NoPadding");
KeyGenerator kg = KeyGenerator.getInstance("AES");
c.init(Cipher.ENCRYPT_MODE, kg.generateKey());
System.out.println(c.update(new byte[1]).length);  // output: 1
System.out.println(c.update(new byte[20]).length); // output: 20

ただし、代わりにプロバイダーを「BC」と指定すると、正しくなくなります。

Cipher c = Cipher.getInstance("AES/CTR/NoPadding", "BC");
KeyGenerator kg = KeyGenerator.getInstance("AES");
c.init(Cipher.ENCRYPT_MODE, kg.generateKey());
System.out.println(c.update(new byte[20]).length); // output: 16
System.out.println(c.update(new byte[1]).length);  // null pointer exception

これは、Bouncy Castle のバグ、または一種の (奇妙だが合理的な) 機能と見なすことができます。

于 2013-04-30T20:19:39.233 に答える