5

こんにちはこれは2年前に尋ねられたのと同じ質問です: Java / JCE:RSAで暗号化された「長い」メッセージの復号化

大きなバイト配列とrsaキーペアがあり、値1024で開始されました。rsa暗号化を使用し、キーの指定されたサイズが強い要件であるため、変更できません。そのため、非対称暗号化対称鍵で対称暗号化を使用することはできません。他のキーは使えません。バイト配列があり、暗号化されたバイト配列を返す必要があります。この問題に対処できる準備ができているツールがあるかどうか疑問に思います。

このような素人っぽい質問で申し訳ありませんが、私は本当に助けが必要です。

4

2 に答える 2

14

述べたように、あなたの質問には単一の答えがあり、それは「いいえ」です。RSA暗号化は、キーサイズに応じて、指定されたサイズまでメッセージを暗号化するアルゴリズムです。1024ビットのRSAキーを使用し、標準でRSAに記載されている場合、最大サイズは117バイトで、それ以上はありません。RSAだけで大きなメッセージを暗号化する方法はありません。これは、数学的に確実です。

本当に長いメッセージを処理する必要がある場合は、必然的に何か他のものを追加する必要があります。その場合は、データを小さなブロックに分割するなど、独自の工夫を凝らしてはいけませんその道は運命につながります。コンパイルして実行しているように見えるものを作成する場合がありますが、暗号化に関する他のほとんどすべての自家製のバリエーションのように、何らかの方法で常に弱いものになります。これは、セキュリティをテストできないためです。「機能する」または「機能しない」の場合ではありません。

したがって、非対称暗号化のよく知られたパスは次のようになります。

  1. 128ビット(16バイト)など、適切な長さのバイトのランダムシーケンスを選択します。それをKと呼びましょう。
  2. KをRSA公開鍵で暗号化します。これによりEが得られます。
  3. 対称暗号化アルゴリズム()を使用して、Kでメッセージを暗号化します"AES/CBC/PKCS5Padding"。これはワンショットキーであるため、すべてゼロのIVを使用できます。これにより、大量のバイトが生成されます。これをFと呼びましょう。
  4. 暗号化されたメッセージは、EFの連結です。

復号化は逆の順序で進行します。RSA秘密鍵を使用してEからKを回復し、次にKを使用してFを元のメッセージに復号化します。キーKはどこにも保存されず、新しいキーKが毎回生成されます(同じメッセージを2回暗号化した場合でも)。それは重要です。自分が何をしているのかを理解していない限り、それを変更しないでください(理解している場合は、すでにそれを知っています)。

問題について述べていることを考えると、「RSAだけ」以外のことをしなければなりません私が上で説明した手順は、セキュリティの観点から、あなたが思いつくことができる最高の「何か他のもの」についてです。

いくつかの暗号化要素をそのようなプロトコルにアセンブルすることは落とし穴に満ちたプロセスであるため、すでに定義されたフォーマットとサポートライブラリを使用する方が幸運かもしれません。非対称暗号化の2つの一般的な形式は、CMSOpenPGPです。両方をサポートし、評判の良いライブラリは、弾力がある城です。

于 2010-04-16T15:54:39.167 に答える
3

RSAを使用して長い文字列を暗号化/復号化する必要がある場合は、バイトを小さな「チャンク」に分割し、結果をByteBufferに格納しながら、暗号を介してバイトの各チャンクを一度に1つずつ処理できます。

暗号化:

byte[] encData = null;
try {

    // create public key
    X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(key);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    PublicKey pk = kf.generatePublic(publicKeySpec);

    Cipher pkCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    pkCipher.init(Cipher.ENCRYPT_MODE, pk);

    int chunkSize = 117; // 1024 / 8 - 11(padding) = 117
    int encSize = (int) (Math.ceil(data.length/117.0)*128);
    int idx = 0;
    ByteBuffer buf = ByteBuffer.allocate(encSize);
    while (idx < data.length) {
        int len = Math.min(data.length-idx, chunkSize);
        byte[] encChunk = pkCipher.doFinal(data, idx, len);
        buf.put(encChunk);
        idx += len;
    }

    // fully encrypted data     
    encData = buf.array();
} catch (Exception e) {
    e.printStackTrace();

復号化

Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
rsaCipher.init(Cipher.DECRYPT_MODE, rsaPk);

int chunkSize = 128;
int idx = 0;
ByteBuffer buf = ByteBuffer.allocate(data.length);
while(idx < data.length) {
    int len = Math.min(data.length-idx, chunkSize);
    byte[] chunk = rsaCipher.doFinal(data, idx, len);
    buf.put(chunk);
    idx += len;
}

// fully decrypted data
byte[] decryptedData = buf.array();
于 2014-05-18T15:15:03.020 に答える