首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java使用CBC 256/CBC/PKCS7Padd加密文件

Java使用CBC 256/CBC/PKCS7Padd加密文件
EN

Stack Overflow用户
提问于 2016-07-28 12:07:30
回答 1查看 2.2K关注 0票数 3

我正在尝试使用美学256-CBC-PKCS7Padd加密一个文件。我在使用弹跳城堡库,但我得到了例外

代码语言:javascript
复制
java.lang.IllegalArgumentException: invalid parameter passed to AES init - org.bouncycastle.crypto.params.ParametersWithIV
at org.bouncycastle.crypto.engines.AESEngine.init(Unknown Source)
at org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher.init(Unknown Source)

在这里,源代码:

代码语言:javascript
复制
public class Crypto {

    public static final int AES_Key_Size = 256;
    public static int blockSize = 16;
    private final BlockCipher AESCipher = new AESEngine();
    private PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(AESCipher, new PKCS7Padding());
    private byte[] IV;
    private KeyParameter key;

    public Crypto() throws NoSuchAlgorithmException {
        KeyGenerator kg = KeyGenerator.getInstance("AES");
        kg.init(AES_Key_Size);
        SecretKey sk = kg.generateKey();
        key = new KeyParameter(sk.getEncoded());


    }
    public void CryptoZip(File plikZip, File plikAES) throws IOException, DataLengthException, IllegalStateException, InvalidCipherTextException {

        byte[] input = Files.readAllBytes(plikZip.toPath());
        byte[] cryptOut = encrypt(input);
        FileOutputStream fos = new FileOutputStream(plikAES);
        fos.write(cryptOut);
        fos.close();



    }


    private byte[] encrypt(byte[] input) throws DataLengthException, IllegalStateException, InvalidCipherTextException {



        IV = new byte[blockSize];
        SecureRandom random = new SecureRandom();
        random.nextBytes(IV);

        cipher.init(true, new ParametersWithIV(key, IV)); // problem here


        byte[] output = new byte[cipher.getOutputSize(input.length)];
        int bytesWrittenOut = cipher.processBytes(
            input, 0, input.length, output, 0);

        cipher.doFinal(output, bytesWrittenOut);

        return output;

    }
}

任何建议,如何解决它,并解释我做错了什么,将是真正有帮助的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-07-30 14:35:59

你所缺少的是模式的指示。如果这是缺失,那么欧洲央行模式是假设的,而欧洲央行模式不需要一个IV。因此,PaddedBufferedBlockCipher确实进行缓冲,但对欧洲央行模式。因此init模式只是将参数传递给AESEngine,而AESEngine拒绝IV,因为它只接受键。

在您的代码中,以下是解决问题的直接方法:

代码语言:javascript
复制
private final CBCBlockCipher AESCipherCBC = new CBCBlockCipher(AESCipher);
private final PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(AESCipherCBC, new PKCS7Padding());

我将包括下面的重写,以向您展示一种不同的记录方式。请注意,我没有正确地处理IV或异常。显然,对于大型文件,您可能需要流内容和/或映射您的文件。

代码语言:javascript
复制
// renamed as crypto is a horrible name
public class FileEncryptor {

    // lets use all uppercase constant names
    public static final int AES_KEY_SIZE = 256;

    // only field needed, the rest can be generated on the fly
    private final KeyParameter key;

    public FileEncryptor() throws NoSuchAlgorithmException {
        key = generateKey();
    }

    private static KeyParameter generateKey() {
        // removed KeyGenerator as that's dependent on JCA crypto-API 
        SecureRandom keyRNG = new SecureRandom();
        byte[] keyData = new byte[AES_KEY_SIZE / Byte.SIZE];
        keyRNG.nextBytes(keyData);
        return new KeyParameter(keyData);
    }

    // the code doesn't do anything with zip itself, so no need to include it in the method name
    public void encryptFile(File plaintextFile, File ciphertextFile) throws IOException, DataLengthException, IllegalStateException, InvalidCipherTextException {
        byte[] plaintext = Files.readAllBytes(plaintextFile.toPath());
        byte[] ciphertext = encrypt(plaintext);
        // try and be symmetric, use Files functionality for reading *and writing*
        Files.write(ciphertextFile.toPath(), ciphertext);
    }


    private byte[] encrypt(byte[] plaintext) throws DataLengthException, IllegalStateException, InvalidCipherTextException {
        // create cipher
        final BlockCipher aes = new AESFastEngine();
        CBCBlockCipher aesCBC = new CBCBlockCipher(aes);
        PaddedBufferedBlockCipher aesCBCPadded =
                new PaddedBufferedBlockCipher(aesCBC, new PKCS7Padding());

        // create IV
        byte[] iv = new byte[aes.getBlockSize()];
        SecureRandom random = new SecureRandom();
        random.nextBytes(iv);

        // initialize cipher with IV
        ParametersWithIV paramsWithIV = new ParametersWithIV(key, iv);
        aesCBCPadded.init(true, paramsWithIV); // problem here

        // encrypt
        byte[] ciphertext = new byte[aesCBCPadded.getOutputSize(plaintext.length)];
        int bytesWrittenOut = aesCBCPadded.processBytes(
            plaintext, 0, plaintext.length, ciphertext, 0);
        aesCBCPadded.doFinal(ciphertext, bytesWrittenOut);

        // that's great, but where is your IV now? you need to include it in the returned ciphertext!
        return ciphertext;
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38635920

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档