5

いくつかのファイルを暗号化するアプリを作っています。gnuのcryptixライブラリを使用したい。2005年以降は開発されていないとのことですが、必要なものはすべて揃っていると思います...他のものを使用する必要がありますか?

また、単一のファイルの暗号化について質問があります。今、私はこのようなループでそれを行います:

for(int i=0; i+block_size < bdata.length; i += block_size)
    cipher.encryptBlock(bdata, i, cdata, i);

だから私の質問は、block_sizeと同じサイズではないかもしれない最後のブロックを暗号化する方法です。最後のブロックにデータを追加する必要があるかもしれないと思っていましたが、それを復号化する方法がわかりません...

4

4 に答える 4

7

AES暗号化を使用することを強くお勧めします。これもJAVASDKに付属しています。ご覧ください:JavaテクノロジーでのAESの使用。これにより、いくつかの優れた例が得られます。AESの詳細については、AdvancedEncryptionStandard-Wikipediaを参照してください。

独自の暗号化スキームまたは古い形式の暗号化スキームを使用しないでください。AESは、その分野で私たちよりもはるかに多くの知識を持つ人々によって試され、テストされているので、あなたはそれが機能することを知っています。独自の暗号化スキームや古い暗号化スキームと同様に、データを攻撃にさらす致命的なループホールを見逃す可能性があります。

暗号化スキームの違いについては、こちらの質問を参照してください:DES、トリプルDES、AES、データのblowfish暗号化の比較

補遺:

JavaのAESは、192ビットキーと256ビットキーで問題なく動作しますが、新しいJCEポリシーファイルをインストールする必要があります。ここここを参照してください。また、ファイルをJDKに配置する必要があります。そうしないと、IDEから実行したときに機能しません。

注:Javaのバージョン(1.4、1.5 1.6、または7)に応じて、正しいJCEポリシーファイルをダウンロードしてください。

ただし、128ビットキーを使用する場合は、新しいJCEファイルをインストールする必要はありません。

これは、Javaでの安全なAES使用のテンプレートであり、CBC / AES/PKCS5Paddingとを使用したランダムIVを使用しRandomSecureます。

復号化にはキーとIVの両方が必要であることに注意してください。

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * This program generates a AES key, retrieves its raw bytes, and then
 * reinstantiates a AES key from the key bytes. The reinstantiated key is used
 * to initialize a AES cipher for encryption and decryption.
 */
public class AES {

    /**
     * Encrypt a sample message using AES in CBC mode with a random IV genrated
     * using SecyreRandom.
     *
     */
    public static void main(String[] args) {
        try {
            String message = "This string contains a secret message.";
            System.out.println("Plaintext: " + message + "\n");

            // generate a key
            KeyGenerator keygen = KeyGenerator.getInstance("AES");
            keygen.init(128);  // To use 256 bit keys, you need the "unlimited strength" encryption policy files from Sun.
            byte[] key = keygen.generateKey().getEncoded();
            SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");

            // build the initialization vector (randomly).
            SecureRandom random = new SecureRandom();
            byte iv[] = new byte[16];//generate random 16 byte IV AES is always 16bytes
            random.nextBytes(iv);
            IvParameterSpec ivspec = new IvParameterSpec(iv);

            // initialize the cipher for encrypt mode
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivspec);

            System.out.println("Key: " + new String(key, "utf-8") + " This is important when decrypting");
            System.out.println("IV: " + new String(iv, "utf-8") + " This is important when decrypting");
            System.out.println();

            // encrypt the message
            byte[] encrypted = cipher.doFinal(message.getBytes());
            System.out.println("Ciphertext: " + asHex(encrypted) + "\n");

            // reinitialize the cipher for decryption
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivspec);

            // decrypt the message
            byte[] decrypted = cipher.doFinal(encrypted);
            System.out.println("Plaintext: " + new String(decrypted) + "\n");
        } catch (IllegalBlockSizeException | BadPaddingException | UnsupportedEncodingException | InvalidKeyException | InvalidAlgorithmParameterException | NoSuchPaddingException | NoSuchAlgorithmException ex) {
            ex.printStackTrace();
        }
    }

    /**
     * Turns array of bytes into string
     *
     * @param buf   Array of bytes to convert to hex string
     * @return  Generated hex string
     */
    public static String asHex(byte buf[]) {
        StringBuilder strbuf = new StringBuilder(buf.length * 2);
        int i;
        for (i = 0; i < buf.length; i++) {
            if (((int) buf[i] & 0xff) < 0x10) {
                strbuf.append("0");
            }
            strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
        }
        return strbuf.toString();
    }
}
于 2012-07-29T10:36:03.273 に答える
5

私はいつもBouncyCastleを使います

また、あなたが説明したforループの代わりにストリーミングフレームワークを使用します。これは、提起された問題を処理します。暗号化(およびスレッド化)に関しては、自分のコードを信頼することはめったにないので、ほとんどの場合、これを使用します。生きている人々がそれを食べて呼吸することを信頼します。これが、「ガッシュ」暗号化が必要なときに使用するコードです。つまり、私は特定の脅威モデルを持っておらず、「少し安全な」ものが欲しいだけです。

キーの16進エンコーディングにより、キーの操作/保存などがはるかに簡単になります。私は「makeKey」を使用して...まあ...キーを作成し、暗号化および復号化メソッドでそのキーを使用できます。byte[]明らかに、キーに16進文字列の代わりに使用することに戻ることができます。

    private static boolean initialised;
    private static void init() {
      if (initialised)
        return;
      Security.addProvider(new BouncyCastleProvider());
      initialised = true;
    }
    public static String makeKey() {
        init();
        KeyGenerator generator = KeyGenerator.getInstance(algorithm, provider);
        generator.init(keySize);
        Key key = generator.generateKey();
        byte[] encoded = key.getEncoded();
        return Strings.toHex(encoded);
}

public static String aesDecrypt(String hexKey, String hexCoded) {
        init();
        SecretKeySpec key = new SecretKeySpec(Strings.fromHex(hexKey), algorithm);
        Cipher cipher = Cipher.getInstance(algorithm + "/ECB/PKCS5Padding", provider);
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] codedBytes = Strings.fromHex(hexCoded);
        CipherInputStream inputStream = new CipherInputStream(new ByteArrayInputStream(codedBytes), cipher);
        byte[] bytes = getBytes(inputStream, 256);
        String result = new String(bytes, "UTF-8");
        return result;
}

public static String aesEncrypt(String hexKey, String input) {
        init();
        SecretKeySpec key = new SecretKeySpec(Strings.fromHex(hexKey), algorithm);

        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding", "BC");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(input.length());
        CipherOutputStream outputStream = new CipherOutputStream(byteArrayOutputStream, cipher);
        setText(outputStream, input);
        byte[] outputBytes = byteArrayOutputStream.toByteArray();
        String output = new String(Strings.toHex(outputBytes));
        return output;
}
public static void setText(OutputStream outputStream, String text, String encoding) {
    try {
        outputStream.write(text.getBytes(encoding));
        outputStream.flush();
    } finally {
            outputStream.close();
    }
}
public static byte[] getBytes(InputStream inputStream, int bufferSize) {
    try {
        List<ByteArrayAndLength> list = Lists.newList();
        while (true) {
            byte[] buffer = new byte[bufferSize];
            int count = inputStream.read(buffer);
            if (count == -1) {
                byte[] result = new byte[ByteArrayAndLength.length(list)];
                int index = 0;
                for (ByteArrayAndLength byteArrayAndLength : list) {
                    System.arraycopy(byteArrayAndLength.bytes, 0, result, index, byteArrayAndLength.length);
                    index += byteArrayAndLength.length;
                }
                assert index == result.length;
                return result;
            }
            list.add(new ByteArrayAndLength(buffer, count));
        }
    } finally {
            inputStream.close();
    }
}
    static class ByteArrayAndLength {
    byte[] bytes;
    int length;

    public ByteArrayAndLength(byte[] bytes, int length) {
        super();
        this.bytes = bytes;
        this.length = length;
    }

    static int length(List<ByteArrayAndLength> list) {
        int result = 0;
        for (ByteArrayAndLength byteArrayAndLength : list) {
            result += byteArrayAndLength.length;
        }
        return result;
    }
}

コードのサイズを小さくするために例外キャッチの一部を削除しStrings.fromHex、文字列をに戻しましたbyte[]

于 2012-07-29T09:43:48.830 に答える
2

たぶん、javax.cryptoパッケージの使用を検討する必要があります。暗号の使用方法の例を次に示します。

DES暗号化

お役に立てれば

于 2012-07-29T09:13:00.713 に答える
0

このルートに行く前に、私は真剣に考え直します。標準的な代替手段が存在するため、ソフトウェアの開発は中止されました。メーリングリストを見ると、2009年以降、重要な活動はありません。私の本では、ソフトウェアが放棄されたことを意味し、放棄されたソフトウェアは多かれ少なかれあなたが自分で。

ここでSOを見てください。これを気に入ってもらうのに役立つ、いくつかの質問と回答があります。物事を単純化できる(ただし、標準のJCEインフラストラクチャを使用している)一見興味深いパッケージは、jasyptです。

于 2012-07-29T09:17:47.803 に答える