16

次のスレッドを読み、少しは役に立ちましたが、もう少し情報を探しています。

BlackBerry の初期化ベクトル パラメータを使用して AES/CBC/PKCS5Padding 暗号化と復号化を記述する方法

Java 256 ビット AES 暗号化

基本的に、私がやっていることは、TCP/IP 経由で送信される要求を暗号化し、サーバー プログラムによって復号化するプログラムを作成することです。暗号化は AES である必要があり、調査の結果、CBC と PKCS5Padding を使用する必要があることがわかりました。したがって、基本的には秘密鍵と IV も必要です。

私が開発しているアプリケーションは携帯電話用なので、Java セキュリティ パッケージを使用してサイズを抑えたいと考えています。設計は完了しましたが、IV と共有キーの実装がわかりません。

ここにいくつかのコードがあります:

// My user name
byte[] loginId = "login".getBytes();

byte[] preSharedKey128 = "ACME-1234AC".getBytes();
byte[] preSharedKey192 = "ACME-1234ACME-1234A".getBytes();
// 256 bit key
byte[] preSharedKey256 = "ACME-1234ACME-1234ACME-1234".getBytes();
byte[] preSharedKey = preSharedKey256;

// Initialization Vector
// Required for CBC
byte[] iv ={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
IvParameterSpec ips = new IvParameterSpec(iv);


byte[] encodedKey = new byte[loginId.length + preSharedKey.length];

System.arraycopy(loginId, 0, encodedKey, 0, loginId.length);
System.arraycopy(preSharedKey, 0, encodedKey, loginId.length, preSharedKey.length);

// The SecretKeySpec provides a mechanism for application-specific generation
// of cryptography keys for consumption by the Java Crypto classes.

// Create a key specification first, based on our key input.
SecretKey aesKey = new SecretKeySpec(encodedKey, "AES");

// Create a Cipher for encrypting the data using the key we created.
Cipher encryptCipher;

encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// Initialize the Cipher with key and parameters
encryptCipher.init(Cipher.ENCRYPT_MODE, aesKey, ips);

// Our cleartext
String clearString = "33,8244000,9999,411,5012022517,0.00,0,1,V330";
byte[] cleartext = clearString.getBytes();

// Encrypt the cleartext
byte[] ciphertext = encryptCipher.doFinal(cleartext);

// Now decrypt back again...
// Decryption cipher
Cipher decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// Initialize PBE Cipher with key and parameters
decryptCipher.init(Cipher.DECRYPT_MODE, aesKey, ips);

// Decrypt the cleartext
byte[] deciphertext = decryptCipher.doFinal(ciphertext);

簡単に言えば、サーバーが電話からキーまたは IV を取得する必要なく、サーバーによって復号化できるメッセージを暗号化することです。電話でIVとキーを保護し、サーバーでもキーとIVを認識できるようにする方法はありますか? そうでない場合は、物事をより明確にするように遠慮なく言ってください。

4

2 に答える 2

12

コードにはいくつかの問題があります。まず、秘密鍵を生成するには鍵ジェネレーターを使用する必要があります。一部のテキストを直接使用するだけで、一部のアルゴリズムでは機能する場合がありますが、テストが必要な弱いキーなどがあるアルゴリズムもあります。

パスワードベースの暗号化を行いたい場合でも、すでに引用した質問に対する私の回答に示されているように、パスワードをキー導出アルゴリズムを介して実行してキーを生成する必要があります。

getBytes()また、 の引数なしメソッドを使用しないでStringください。これはプラットフォームに依存します。エンコードするすべての文字列に US-ASCII 文字セットの文字のみが含まれている場合は、そのエンコードを明示的に指定して明確にします。そうしないと、電話とサーバーのプラットフォームで異なる文字エンコーディングが使用されている場合、キーと IV が一致しなくなります。

CBC モードでは、送信するメッセージごとに新しい IV を使用することをお勧めします。通常、CBC IV はランダムに生成されます。CFB や OFB などの他のモードでは、メッセージごとに固有の IV が必要です。IV は通常、暗号文とともに送信されます。IV を秘密にしておく必要はありませんが、予測可能な IV を使用すると、多くのアルゴリズムが壊れます。

サーバーは、シークレットや IV を電話から直接取得する必要はありません。秘密鍵 (または秘密鍵の派生元のパスワード) を使用してサーバーを構成できますが、多くのアプリケーションでは、これは不適切な設計となります。

たとえば、アプリケーションを複数の人の電話に展開する場合、同じ秘密鍵を使用することはお勧めできません。1 人の悪意のあるユーザーがキーを回復し、全員のシステムを破壊することができます。

より良い方法は、電話で新しい秘密鍵を生成し、鍵合意アルゴリズムを使用してサーバーと鍵を交換することです。これには Diffie-Hellman 鍵協定を使用できます。または、秘密鍵を RSA で暗号化してサーバーに送信することもできます。


アップデート:

サーバーの公開鍵がアプリケーションに組み込まれている限り、サーバーから電話への最初のメッセージなしで、「ephemeral-static」モード (および「static-static」モードも、あまり望ましくありません) の Diffie-Hellman が可能です。 .

サーバーの公開鍵は、電話に共通の秘密鍵を埋め込む場合と同じリスクをもたらしません。これは公開鍵であるため、脅威となるのは、攻撃者が電話を手に入れて (またはリモートでハッキングして)、実際の公開鍵を偽の鍵に置き換えて、サーバーになりすますことができるようにすることです。

静的 - 静的モードを使用することもできますが、実際にはより複雑で安全性が少し低くなります。すべての電話には独自の一意の鍵ペアが必要です。そうしないと、秘密鍵の問題に陥ります。少なくとも、どの電話がどのキーを持っているかをサーバーが追跡する必要はありません (アプリケーション レベルで、パスワードなどの認証メカニズムがあると仮定します)。

電話の速さはわかりません。私のデスクトップでは、エフェメラル キー ペアの生成に約 1/3 秒かかります。Diffie-Hellman パラメータの生成は非常に低速です。サーバーキーのパラメーターを再利用することは間違いありません。

于 2009-09-17T17:22:48.517 に答える
2

以前にミッドレットで同様のプロジェクトを行ったことがありますが、次のアドバイスがあります。

  1. 電話に共有秘密を保存する安全な方法はありません。使用できますが、これはSecurity through Obscurityと呼ばれるカテゴリに分類されます。「マットの下の鍵」のようなセキュリティです。
  2. 広く利用されていない 256 ビット AES は使用しないでください。別の JCE をインストールする必要がある場合があります。128 ビットの AES または TripleDES は引き続き安全と見なされます。#1を考えると、これについて心配する必要はありません。
  3. パスワード (ユーザーごとに異なる) を使用した暗号化は、はるかに安全です。ただし、例で示しているように、パスワードをキーとして使用しないでください。キーの生成には PBEKeySpec (パスワードベースの暗号化) を使用してください。
  4. MITM (man-in-the-middle) 攻撃が心配な場合は、SSL を使用してください。
于 2009-09-17T17:47:50.033 に答える