0

SHA-256 キーで AES を使用してファイルを暗号化しようとしています。IV を生成するときは、暗号化されたファイルの先頭に追加し、残りを追加します。

IV を復元して比較すると (IV のプロセス後とその後)、それらは同じです。問題は、ファイルを復号化しようとしたときです。

javax.crypto.BadPaddingException: 最終ブロックが適切にパディングされていない場合

次のバイトを正しく読み取っていないことが原因である可能性があると思いますが、コードを修正すると、問題ないようです。

暗号クラス:

private static String password;
private static String salt;
private static int pswdIterations = 65536  ;
private static int keySize = 256;
private byte[] ivBytes;

public void encryptOfFile(byte[] bytes, File out) throws Exception {  

    byte[] saltBytes = salt.getBytes("UTF-8");

    System.out.println("Salt bfre:" +salt);

    // Derive the key
    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    PBEKeySpec spec = new PBEKeySpec(
            password.toCharArray(),
            saltBytes,
            pswdIterations,
            keySize
            );

    SecretKey secretKey = factory.generateSecret(spec);
    SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");

    //encrypt the message
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, secret);
    AlgorithmParameters params = cipher.getParameters();
    ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV();

    //First copy the IVBytes at the beginning  of the file
    System.out.println("IvBytes Bfore: "  + DatatypeConverter.printHexBinary(ivBytes));
    FileOutputStream os = new FileOutputStream(out, true);
    os.write(ivBytes);

    CipherOutputStream cos = new CipherOutputStream(os, cipher);
    cos.write(bytes);

    os.close();
    cos.close();

}

public byte[] decryptToBytes(File in) throws Exception {  
    byte[] saltBytes = salt.getBytes("UTF-8");
    System.out.println("Salt afetr:" +salt);

    // Derive the key
    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    PBEKeySpec spec = new PBEKeySpec(
            password.toCharArray(),
            saltBytes,
            pswdIterations,
            keySize
            );

    SecretKey secretKey = factory.generateSecret(spec);
    SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");


    //Get IVBytes of the first 16 bytes of the file
    System.out.println("File Size: "  + in.length());

    FileInputStream is = new FileInputStream(in);
    byte [] ivBytesRecovered = new byte [16];
    if (is.read(ivBytesRecovered) != ivBytesRecovered.length) {
        //is.close();
        throw new IllegalStateException("Too short file");
    }
    System.out.println("IvBytes After: "  + DatatypeConverter.printHexBinary(ivBytesRecovered));

    // Decrypt the message
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(ivBytesRecovered));        

    byte[] encBytes = new byte[(int) in.length()-16];
    is.read(encBytes);

    byte[] decryptedBytes = null;
    try {
        decryptedBytes = cipher.doFinal(encBytes);
    } catch (IllegalBlockSizeException | BadPaddingException e) {
        e.printStackTrace();
    }

    is.close();

    return decryptedBytes;

}

エラーメッセージが表示されました...最初の16バイト以降のバイトを正しく読み取っていないためでしょうか? それとも、byte[] encBytes の適切なサイズを指定していないためでしょうか?

ソルトの生成に使用:

public String generateSalt() {
    SecureRandom random = new SecureRandom();
    byte bytes[] = new byte[20];
    random.nextBytes(bytes);
    String s = new String(bytes);
    return s;
}
4

1 に答える 1

1

問題は暗号化/書き込み側にあります。cos (CipherOutputStream) を閉じる前に os (FileOutputStream) を閉じるため、最後に暗号化されたブロックがファイルに書き込まれません。代わりに、 javadoccos.close();ごとに whichを指定する必要があり ます (os.close() を処理することに注意してください):

このメソッドは、カプセル化された暗号オブジェクトの doFinal メソッドを呼び出します。これにより、カプセル化された暗号によってバッファリングされたすべてのバイトが処理されます。結果は、この出力ストリームの flush メソッドを呼び出すことによって書き出されます。

このメソッドは、カプセル化された暗号オブジェクトを初期状態にリセットし、基になる出力ストリームの close メソッドを呼び出します。

または、プレーンテキストが 1 つのバッファーに収まるため (読み取り側でそれが必要な場合)、CipherOutputStream をスキップして、os.write (cipher.doFinal(bytes)); os.close();

(file,true)また、識別されたファイルが既に存在し、空でない場合 (および保護されていないため例外がスローされる場合)、新しいデータが最後に追加されることを意味するFileOutputStream を構築しますが、読み取り側はそれが最初にあることを期待します。

そして、あなたはが何であるかを示していませんが、人間が覚えているよりも多くのエントロピーが含まれていない場合、おそらくその目的を果たしていません. 人間が適切なソルトを覚えて入力することは期待できないため、通常はそれをファイル/メッセージ/データベース/その他に含めます。

于 2015-04-09T18:04:14.910 に答える