使用java加密/解密文件在使用填充时返回错误的字节数

使用java加密/解密文件在使用填充时返回错误的字节数,java,encryption,aes,encryption-symmetric,Java,Encryption,Aes,Encryption Symmetric,我正在尝试制作一个加密/解密的应用程序,当我使用无填充的密码模式时,它工作正常。有了填充,块的数量是不可预测的,我找不到问题的根源 我正在使用以下代码进行测试: private static final int KEY_LEN = 16; private static final String ENCRYPTION_ALGO = "AES"; private static final String HASHING_ALGO = "SHA-256"; private static final S

我正在尝试制作一个加密/解密的应用程序,当我使用无填充的密码模式时,它工作正常。有了填充,块的数量是不可预测的,我找不到问题的根源

我正在使用以下代码进行测试:

private static final int KEY_LEN = 16;
private static final String ENCRYPTION_ALGO = "AES";
private static final String HASHING_ALGO = "SHA-256"; 
private static final String CIPHER_MODE = "AES/CFB/PKCS5Padding";
private static final String ENCODING = "UTF-8";

static private byte[] initVector;
static private SecretKey key;
static Cipher cipher;

private static SecretKey generateKey(byte[] password) {
    MessageDigest md = MessageDigest.getInstance(HASHING_ALGO);

    byte[] hashedKey = md.digest(password);

    return new SecretKeySpec(hashedKey, 0, KEY_LEN, ENCRYPTION_ALGO);
}

public static byte[] getIV() {
    return initVector;
}

public static void setup(String password) 
{

    key = generateKey(password.getBytes(ENCODING));

    cipher = Cipher.getInstance (CIPHER_MODE);
    cipher.init (Cipher.ENCRYPT_MODE, key);
    AlgorithmParameters params = cipher.getParameters ();

    initVector = params.getParameterSpec (IvParameterSpec.class).getIV();
}

public static void setup(String password, byte[] iv)
{
    key = generateKey(password.getBytes(ENCODING));

    cipher = Cipher.getInstance (CIPHER_MODE);

    // define init vector that was used for encryption
    cipher.init (Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
}

private static byte[] crypt(byte[] plaintext, boolean hasNext) 
    if (hasNext) {
        return cipher.update(plaintext);
    }else {
        return cipher.doFinal(plaintext);
    }
}

public static void main(String [] args)
{
    try {
        File input = new File ("input.txt");
        File eoutput = new File ("output.enc");
        File doutput = new File ("decrypted.txt");

        FileInputStream fin = new FileInputStream(input);
        FileOutputStream fout = new FileOutputStream (eoutput);

        byte [] buffer = new byte [32];
        int nBytes;

        //encrypt
        setup("password");

        while ((nBytes = fin.read(buffer))!=-1) {
            byte[] cyphertext;
            if (nBytes < buffer.length) {
                byte[] trimbuffer = new byte [nBytes];
                System.arraycopy(buffer, 0, trimbuffer, 0, nBytes);
                cyphertext = crypt(trimbuffer, false);
            }else {
                cyphertext = crypt(buffer, true);
            }
            fout.write(cyphertext);
        }
        fin.close();
        fout.close();

        FileInputStream fin2 = new FileInputStream(eoutput);
        FileOutputStream fout2 = new FileOutputStream (doutput);            

        byte[] iv = getIV();

        // decrypt
        setup("password",iv);
        while ((nBytes = fin2.read(buffer))!=-1) {
            byte[] plaintext;
            if (nBytes < buffer.length) {
                byte[] trimbuffer = new byte [nBytes];
                System.arraycopy(buffer, 0, trimbuffer, 0, nBytes);

                plaintext = crypt(trimbuffer, false);
            }else {
                plaintext = crypt(buffer, true);
            }
            fout2.write(plaintext);
        }

        fin2.close();
        fout2.close();

  }
private static final int KEY_LEN=16;
私有静态最终字符串加密\u ALGO=“AES”;
私有静态最终字符串哈希_ALGO=“SHA-256”;
私有静态最终字符串密码\u MODE=“AES/CFB/pkcs5ppadding”;
私有静态最终字符串编码=“UTF-8”;
静态专用字节[]initVector;
静态私钥;
静态密码;
专用静态加密密钥生成器密钥(字节[]密码){
MessageDigest md=MessageDigest.getInstance(哈希算法);
字节[]hashedKey=md.digest(密码);
返回新的SecretKeySpec(hashedKey,0,KEY\u LEN,ENCRYPTION\u ALGO);
}
公共静态字节[]getIV(){
返回初始向量;
}
公共静态无效设置(字符串密码)
{
key=generateKey(password.getBytes(ENCODING));
cipher=cipher.getInstance(cipher\u模式);
cipher.init(cipher.ENCRYPT_模式,密钥);
AlgorithmParameters params=cipher.getParameters();
initVector=params.getParameterSpec(IvParameterSpec.class).getIV();
}
公共静态无效设置(字符串密码,字节[]iv)
{
key=generateKey(password.getBytes(ENCODING));
cipher=cipher.getInstance(cipher\u模式);
//定义用于加密的初始向量
cipher.init(cipher.DECRYPT_模式,密钥,新的IvParameterSpec(iv));
}
专用静态字节[]密码(字节[]明文,布尔hasNext)
如果(下一步){
返回密码更新(明文);
}否则{
返回cipher.doFinal(纯文本);
}
}
公共静态void main(字符串[]args)
{
试一试{
文件输入=新文件(“input.txt”);
File eoutput=新文件(“output.enc”);
File doutput=新文件(“decrypted.txt”);
FileInputStream fin=新的FileInputStream(输入);
FileOutputStream fout=新的FileOutputStream(输出输出);
字节[]缓冲区=新字节[32];
整数字节;
//加密
设置(“密码”);
而((nBytes=fin.read(buffer))!=-1){
字节[]密码文本;
if(N字节<缓冲区长度){
字节[]trimbuffer=新字节[N字节];
System.arraycopy(缓冲区,0,trimbuffer,0,N字节);
cyphertext=crypt(trimbuffer,false);
}否则{
cyphertext=crypt(缓冲区,true);
}
fout.write(密码文本);
}
fin.close();
fout.close();
FileInputStream fin2=新的FileInputStream(Output);
FileOutputStream fout2=新的FileOutputStream(doutput);
字节[]iv=getIV();
//解密
设置(“密码”,iv);
而((nBytes=fin2.read(buffer))!=-1){
字节[]明文;
if(N字节<缓冲区长度){
字节[]trimbuffer=新字节[N字节];
System.arraycopy(缓冲区,0,trimbuffer,0,N字节);
明文=密码(trimbuffer,false);
}否则{
明文=密码(缓冲区,真);
}
fout2.书写(纯文本);
}
fin2.close();
fout2.close();
}

我忘了提及解密方面的问题。

我只是在经过大量测试后发现了问题。问题是,当我读取文件时,最后一个块的缓冲区大小完全相同,我总是调用crypt(buffer,true),它执行cipher.update()而不是cipher.doFinal()

经过大量测试,我才发现问题。问题是,当我读取文件时,最后一个块的缓冲区大小完全相同,我总是调用crypt(buffer,true),它执行cipher.update()而不是cipher.doFinal()

这段代码似乎不完整?getIV()?cipher?key?是为了简化,但我会添加它。代码似乎不完整?getIV()?cipher?key?是为了简化,但我也会添加它