9

アリスが公開鍵と秘密鍵のペアを作成できるようにして、ボブが秘密のメッセージを送信できるようにしたいと考えています。しかし、アリスがどこからでもメッセージを確認できるようにしたいのですが、秘密鍵が入ったメモリースティックを持ち歩くのは面倒です。アリスが覚えているパスワードに基づいて公開鍵と秘密鍵のペアを作成する方法はありますか? このようにして、必要なときにいつでも簡単に秘密鍵 (および公開鍵) を生成できました。

この質問の短いバージョンは次のとおりです。 cryptico.jsに相当する Java はどこにありますか。

また、これはスタック オーバーフローに関する同じ質問ですが、javascript に関するものです。

編集:解決策への私の最初の試みは次のとおりです。

    SecureRandom saltRand = new SecureRandom(new byte[] { 1, 2, 3, 4 });
    byte[] salt = new byte[16];
    saltRand.nextBytes(salt);

    int keyLength = 3248;
    SecretKeyFactory factory = SecretKeyFactory
            .getInstance("PBKDF2WithHmacSHA1");
    KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 8192, keyLength);
    SecretKey key = factory.generateSecret(spec);

    SecureRandom keyGenRand = SecureRandom.getInstance("SHA1PRNG");
    keyGenRand.setSeed(key.getEncoded());

    KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
    gen.initialize(keyLength, keyGenRand);
    java.security.KeyPair p = gen.generateKeyPair();
4

6 に答える 6

5

RSAについて話すとき:PBKDF2の結果を使用して、疑似乱数ジェネレーターをシードできます。これを使用して、キーペアを生成できます。SecureRandomを使用すると、rngが完全に再初期化される代わりにシードがプールに追加されるため、機能しないことに注意してください。RSAは、ランダムな素数を見つけるためにPRNGを必要とします。

楕円曲線暗号を使用できる方がよいでしょう。F(p)よりも標準のNISTまたはBrainpool曲線を選択できます。次に、PBKDF2の32バイトの出力を秘密鍵として使用し、公開鍵を計算できます。ECCはランダムな秘密鍵のみを必要とし、PBKDF2の出力はランダムと区別できないはずなので、出力は問題ありません。追加のPRNGが必要なだけでなく、RSAキーペアを計算する時間を節約できます。これはかなりの量になる可能性があります。

上記の計算されたキーで暗号化されたものに対するブルートフォース攻撃を防ぐものは何もないことに注意してください。したがって、辞書にない単語、数字、記号を含む16文字以上のパスフレーズを要求することをお勧めします。特にユーザーが攻撃の可能性に気付いていない場合は、それ以下のものは失敗する可能性があります。ストレージがない場合、ランダムソルトを使用できないことに注意してください。ランダムソルトを使用できない場合は、レインボーテーブルに対して防御できません(特定のアプリケーションでは、もちろんアプリケーション固有のソルトを使用できます)。さらに、同じパスフレーズを持つ人は同じ秘密鍵を生成します

もちろん、デフォルトの方法(たとえば、PGP)は、パスワードベースの暗号化を使用して暗号化された秘密鍵を保存することです。ただし、これにはストレージが必要です。このアプローチの利点は、完全にランダムなキーを持つことができることです。つまり、キーストレージにアクセスできなければ、暗号テキストに対するブルートフォース攻撃は不可能です。重要な追加レイヤーを追加します。

于 2012-07-22T14:17:32.037 に答える
3

多くの詳細は提供しませんが、 を使用して鍵ペアを生成する場合は、java.security.KeyPairGeneratorを拡張する独自のクラスを定義する必要がありますがSecureRandom、提供されたパスワードのみをエントロピー ソースとして使用します。

クラスを実装する必要はありません。スーパークラスの保護されたコンストラクターを引数でSecureRandomSpi呼び出すだけです。(null, null)

于 2012-07-22T14:04:10.403 に答える
1

RSA キーの長さは通常、1024 ビットまたは 2048 ビットです。つまり、128 または 256 バイトになります。

通常、パスワードの長さは 8 バイトです (約 64 バイトしか使用しません)。

RSA キーがパスワードから派生した場合、アルゴリズムの強度の多くが失われます。攻撃者は、128 または 256 バイトの長さのキーではなく、8 バイトのパスワードを推測またはブルート フォースするだけで済みます。

于 2012-07-22T13:33:28.993 に答える
0

共有キーを使用します。

String encryptionKey = "53616d706c6550617373776f726453616d706c6550617373776f726453616d70"; // string to hex of "SamplePasswordSamplePasswordSamp"
String sampleText = "sampletext";
String encrypted = null;
String decrypted = null;

使用を暗号化するには:

Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(Hex.decodeHex(encryptionKey.toCharArray()), "AES"));
encrypted = Hex.encodeHexString(cipher.doFinal((sampleText.toString()).getBytes()));

使用を復号化するには:

   Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(Hex.decodeHex(encryptionKey.toCharArray()), "AES"));
    decrypted = new String(cipher.doFinal(Hex.decodeHex(enc.toCharArray())));

Note Hex は次のとおりです。 import org.apache.commons.codec.binary.Hex; Mavenで:

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.6</version>
</dependency>
于 2012-07-22T14:41:01.810 に答える
0

パスワードを使用して Web アプリへのアクセスを許可しないのはなぜでしょうか (実際にそうしているので)、単に https を使用しますか?

于 2012-07-22T14:09:46.250 に答える