Aes使用base64数据编码解密java文件

Aes使用base64数据编码解密java文件,java,encryption,openssl,base64,sha1,Java,Encryption,Openssl,Base64,Sha1,我提到并尝试使用base64解码进行文件解密 我的要求是在加密期间使用base64编码数据,在解密期间使用base64解码数据 但我面临以下错误: javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher at java.base/com.sun.crypto.provider.CipherCore.doFinal(Unkno

我提到并尝试使用base64解码进行文件解密

我的要求是在加密期间使用base64编码数据,在解密期间使用base64解码数据

但我面临以下错误:

javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
    at java.base/com.sun.crypto.provider.CipherCore.doFinal(Unknown Source)
    at java.base/com.sun.crypto.provider.CipherCore.doFinal(Unknown Source)
    at java.base/com.sun.crypto.provider.AESCipher.engineDoFinal(Unknown Source)
    at java.base/javax.crypto.Cipher.doFinal(Unknown Source)
    at aes.DecryptNew.decryptNew(DecryptNew.java:124)
    at aes.DecryptNew.main(DecryptNew.java:32)
另外,我对如何在块中执行解密感到困惑。 请向我建议此代码中的问题

import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.util.Arrays;
import java.util.Base64;

public class DecryptNew {
    public static void main(String[] args) {
        String plaintextFilename = "D:\\\\plaintext.txt";
        String ciphertextFilename = "D:\\\\plaintext.txt.crypt";
        String decryptedtextFilename = "D:\\\\plaintextDecrypted.txt";
        String password = "testpass";

        writeToFile();
        String ciphertext = encryptfile(plaintextFilename, password);
        System.out.println("ciphertext: " + ciphertext);
        decryptNew(ciphertextFilename, password, decryptedtextFilename);
    }

    static void writeToFile() {
        BufferedWriter writer = null;
        try
        {
            writer = new BufferedWriter( new FileWriter("D:\\\\plaintext.txt"));
            byte[] data = Base64.getEncoder().encode("hello\r\nhello".getBytes(StandardCharsets.UTF_8));
            writer.write(new String(data)); 
        }
        catch ( IOException e)
        {
        }
        finally
        {
            try
            {
                if ( writer != null)
                writer.close( );
            }
            catch ( IOException e)
            {
            }
        }
    }
    
    public static String encryptfile(String path, String password) {
        try {
            FileInputStream fis = new FileInputStream(path);
            FileOutputStream fos = new FileOutputStream(path.concat(".crypt"));
            final byte[] pass = Base64.getEncoder().encode(password.getBytes());
            final byte[] salt = (new SecureRandom()).generateSeed(8);
            fos.write(Base64.getEncoder().encode("Salted__".getBytes()));
            fos.write(salt);
            final byte[] passAndSalt = concatenateByteArrays(pass, salt);
            byte[] hash = new byte[0];
            byte[] keyAndIv = new byte[0];
            for (int i = 0; i < 3 && keyAndIv.length < 48; i++) {
                final byte[] hashData = concatenateByteArrays(hash, passAndSalt);
                final MessageDigest md = MessageDigest.getInstance("SHA-1");
                hash = md.digest(hashData);
                keyAndIv = concatenateByteArrays(keyAndIv, hash);
            }
            final byte[] keyValue = Arrays.copyOfRange(keyAndIv, 0, 32);
            final byte[] iv = Arrays.copyOfRange(keyAndIv, 32, 48);
            final SecretKeySpec key = new SecretKeySpec(keyValue, "AES");
            final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
            CipherOutputStream cos = new CipherOutputStream(fos, cipher);
            int b;
            byte[] d = new byte[8];
            while ((b = fis.read(d)) != -1) {
                cos.write(d, 0, b);
            }
            cos.flush();
            cos.close();
            fis.close();
            System.out.println("encrypt done " + path);
        } catch (IOException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        }
        return path;
    }

    static void decryptNew(String path,String password, String outPath) {
        byte[] SALTED_MAGIC = Base64.getEncoder().encode("Salted__".getBytes());
        try{
            FileInputStream fis = new FileInputStream(path);
            FileOutputStream fos = new FileOutputStream(outPath);
            final byte[] pass = password.getBytes(StandardCharsets.US_ASCII);
            final byte[] inBytes = Files.readAllBytes(Paths.get(path));
            final byte[] shouldBeMagic = Arrays.copyOfRange(inBytes, 0, SALTED_MAGIC.length);
            if (!Arrays.equals(shouldBeMagic, SALTED_MAGIC)) {
                throw new IllegalArgumentException("Initial bytes from input do not match OpenSSL SALTED_MAGIC salt value.");
            }
            final byte[] salt = Arrays.copyOfRange(inBytes, SALTED_MAGIC.length, SALTED_MAGIC.length + 8);
            final byte[] passAndSalt = concatenateByteArrays(pass, salt);
            byte[] hash = new byte[0];
            byte[] keyAndIv = new byte[0];
            for (int i = 0; i < 3 && keyAndIv.length < 48; i++) {
                final byte[] hashData = concatenateByteArrays(hash, passAndSalt);
                MessageDigest md = null;
                md = MessageDigest.getInstance("SHA-1");
                hash = md.digest(hashData);
                keyAndIv = concatenateByteArrays(keyAndIv, hash);
            }
            final byte[] keyValue = Arrays.copyOfRange(keyAndIv, 0, 32);
            final SecretKeySpec key = new SecretKeySpec(keyValue, "AES");
            final byte[] iv = Arrays.copyOfRange(keyAndIv, 32, 48);
            final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
            final byte[] clear = cipher.doFinal(inBytes, 16, inBytes.length - 16);
            String contentDecoded = new String(Base64.getDecoder().decode(clear));
            fos.write(contentDecoded.getBytes());
            fos.close();
            System.out.println("Decrypt is completed");
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    

    public static byte[] concatenateByteArrays(byte[] a, byte[] b) {
        return ByteBuffer
                .allocate(a.length + b.length)
                .put(a).put(b)
                .array();
    }
}
导入javax.crypto.Cipher;
导入javax.crypto.CipherOutputStream;
导入javax.crypto.NoSuchPaddingException;
导入javax.crypto.spec.IvParameterSpec;
导入javax.crypto.spec.SecretKeySpec;
导入java.io.BufferedWriter;
导入java.io.FileInputStream;
导入java.io.FileOutputStream;
导入java.io.FileWriter;
导入java.io.IOException;
导入java.nio.ByteBuffer;
导入java.nio.charset.StandardCharset;
导入java.nio.file.Files;
导入java.nio.file.path;
导入java.security.*;
导入java.util.array;
导入java.util.Base64;
公共类解密新{
公共静态void main(字符串[]args){
String plaintextFilename=“D:\\\\plaintext.txt”;
字符串ciphertextFilename=“D:\\\\plaintext.txt.crypt”;
String decryptedtextFilename=“D:\\\\plaintextDecrypted.txt”;
字符串password=“testpass”;
writeToFile();
字符串密文=加密文件(明文文件名,密码);
System.out.println(“密文:+ciphertext”);
decryptNew(ciphertextFilename、密码、decryptedtextFilename);
}
静态void writeToFile(){
BufferedWriter=null;
尝试
{
writer=new BufferedWriter(新文件编写器(“D:\\\\plaintext.txt”);
byte[]data=Base64.getEncoder().encode(“hello\r\nhello.getBytes(StandardCharsets.UTF_8));
write(新字符串(数据));
}
捕获(IOE异常)
{
}
最后
{
尝试
{
if(writer!=null)
writer.close();
}
捕获(IOE异常)
{
}
}
}
公共静态字符串加密文件(字符串路径、字符串密码){
试一试{
FileInputStream fis=新的FileInputStream(路径);
FileOutputStream fos=新的FileOutputStream(path.concat(“.crypt”);
最终字节[]pass=Base64.getEncoder().encode(password.getBytes());
最后一个字节[]salt=(new SecureRandom()).generateSeed(8);
fos.write(Base64.getEncoder().encode(“Salted__u;”.getBytes());
写作(salt);
最后一个字节[]passAndSalt=串联字节数组(pass,salt);
字节[]哈希=新字节[0];
字节[]keyAndIv=新字节[0];
对于(int i=0;i<3&&keyAndIv.length<48;i++){
最后一个字节[]hashData=concatenateByteArray(散列,passAndSalt);
final MessageDigest md=MessageDigest.getInstance(“SHA-1”);
hash=md.digest(hashData);
keyAndIv=串联字节数组(keyAndIv,散列);
}
最后一个字节[]keyValue=Arrays.copyOfRange(keyAndIv,0,32);
最后一个字节[]iv=Arrays.copyOfRange(keyAndIv,32,48);
最终SecretKeySpec密钥=新SecretKeySpec(keyValue,“AES”);
final Cipher=Cipher.getInstance(“AES/CBC/PKCS5Padding”);
cipher.init(cipher.ENCRYPT_模式,密钥,新的IvParameterSpec(iv));
CipherOutputStream cos=新的CipherOutputStream(fos,密码);
int b;
字节[]d=新字节[8];
而((b=fis.read(d))!=-1){
cos.write(d,0,b);
}
cos.flush();
cos.close();
fis.close();
System.out.println(“加密完成”+路径);
}捕获(IOException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException e){
e、 printStackTrace();
}
返回路径;
}
静态void decryptNew(字符串路径、字符串密码、字符串输出路径){
字节[]SALTED_umagic=Base64.getEncoder().encode(“SALTED_uuu.getBytes());
试一试{
FileInputStream fis=新的FileInputStream(路径);
FileOutputStream fos=新的FileOutputStream(输出路径);
final byte[]pass=password.getBytes(StandardCharsets.US\u ASCII);
final byte[]inBytes=Files.readAllBytes(path.get(path));
最后一个字节[]应该是MAGIC=Arrays.copyOfRange(以字节为单位,0,SALTED_MAGIC.length);
if(!Arrays.equals(shouldBeMagic,salt_MAGIC)){
抛出新的IllegalArgumentException(“输入的初始字节与OpenSSL SALTED_MAGIC salt值不匹配”);
}
最后一个字节[]salt=Arrays.copyOfRange(以字节为单位,SALTED_MAGIC.length,SALTED_MAGIC.length+8);
最后一个字节[]passAndSalt=串联字节数组(pass,salt);
字节[]哈希=新字节[0];
字节[]keyAndIv=新字节[0];
对于(int i=0;i<3&&keyAndIv.length<48;i++){
最后一个字节[]hashData=concatenateByteArray(散列,passAndSalt);
MessageDigest md=null;
md=MessageDigest.getInstance(“SHA-1”);
hash=md.digest(hashData);
keyAndIv=串联字节数组(keyAndIv,散列);
}
最后一个字节[]keyValue=Arrays.copyOfRange(keyAndIv,0,32);
最终SecretKeySpec密钥=新SecretKeySpec(keyValue,“AES”);
最后一个字节[]iv=Arrays.copyOfRange(keyAndIv,32,48);
final Cipher=Cipher.getInstance(“AES/CBC/PKCS5Padding”);
cipher.init(cipher.DECRYPT_模式,密钥,新的IvParameterSpec(iv));
final byte[]clear=cipher.doFinal(以字节为单位,16,以字节为单位,长度为-16);
String contentDecoded=新字符串(Base64.getDecoder().decode(clear));
fos.write(contentDecoded.getBytes());
fos.close();
System.out.pri
...
byte[] pass = password.getBytes(StandardCharsets.US_ASCII);
byte[] SALTED_MAGIC = "Salted__".getBytes(StandardCharsets.US_ASCII);
byte[] salt = (new SecureRandom()).generateSeed(8);
fos.write(SALTED_MAGIC);
fos.write(salt);
...
...
byte[] pass = password.getBytes(StandardCharsets.US_ASCII);
byte[] SALTED_MAGIC = "Salted__".getBytes(StandardCharsets.US_ASCII);
byte[] prefix = fis.readNBytes(8);
byte[] salt = fis.readNBytes(8);
...
openssl enc -aes-256-cbc -base64 -pass pass:testpass -p -in sample.txt -out sample.crypt
static void decrypt(String path, String password, String outPath) {

    try (FileInputStream fis = new FileInputStream(path);
         Base64InputStream bis = new Base64InputStream(fis, false, 64, "\r\n".getBytes(StandardCharsets.US_ASCII))) { // from Apache Commons Codec
        
        // Read prefix and salt
        byte[] SALTED_MAGIC = "Salted__".getBytes(StandardCharsets.US_ASCII);
        byte[] prefix = bis.readNBytes(8);
        if (!Arrays.equals(prefix, SALTED_MAGIC)) {
            throw new IllegalArgumentException("Initial bytes from input do not match OpenSSL SALTED_MAGIC salt value.");
        }
        byte[] salt = bis.readNBytes(8);

        // Derive key and IV
        byte[] pass = password.getBytes(StandardCharsets.US_ASCII);
        byte[] passAndSalt = concatenateByteArrays(pass, salt);
        byte[] hash = new byte[0];
        byte[] keyAndIv = new byte[0];
        for (int i = 0; i < 3 && keyAndIv.length < 48; i++) {
            byte[] hashData = concatenateByteArrays(hash, passAndSalt);
            MessageDigest md = null;
            md = MessageDigest.getInstance("SHA-1");   // Use digest from encryption
            hash = md.digest(hashData);
            keyAndIv = concatenateByteArrays(keyAndIv, hash);
        }
        byte[] keyValue = Arrays.copyOfRange(keyAndIv, 0, 32);
        SecretKeySpec key = new SecretKeySpec(keyValue, "AES");
        byte[] iv = Arrays.copyOfRange(keyAndIv, 32, 48);

        // Decrypt
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
        try (CipherInputStream cis = new CipherInputStream(bis, cipher);
             FileOutputStream fos = new FileOutputStream(outPath)) {

            int length;
            byte[] buffer = new byte[1024];
            while ((length = cis.read(buffer)) != -1) {
                fos.write(buffer, 0, length);
            }
        }
        System.out.println("Decrypt is completed");
        
    } catch (Exception e) {
        e.printStackTrace();
    }
}
static void decryptfile(String path, String password, String outPath) {

    try (FileInputStream fis = new FileInputStream(path)) {

        // Read prefix and salt
        byte[] SALTED_MAGIC = Base64.getEncoder().encode("Salted__".getBytes());
        byte[] prefix = new byte[SALTED_MAGIC.length];
        fis.readNBytes(prefix, 0, prefix.length);
        if (!Arrays.equals(prefix, SALTED_MAGIC)) {
            throw new IllegalArgumentException("Initial bytes from input do not match OpenSSL SALTED_MAGIC salt value.");
        }
        byte[] salt = new byte[8];
        fis.readNBytes(salt, 0, salt.length);

        // Derive key and IV
        final byte[] pass = Base64.getEncoder().encode(password.getBytes());
        byte[] passAndSalt = concatenateByteArrays(pass, salt);
        byte[] hash = new byte[0];
        byte[] keyAndIv = new byte[0];
        for (int i = 0; i < 3 && keyAndIv.length < 48; i++) {
            byte[] hashData = concatenateByteArrays(hash, passAndSalt);
            MessageDigest md = null;
            md = MessageDigest.getInstance("SHA-1");   // Use digest from encryption
            hash = md.digest(hashData);
            keyAndIv = concatenateByteArrays(keyAndIv, hash);
        }
        byte[] keyValue = Arrays.copyOfRange(keyAndIv, 0, 32);
        SecretKeySpec key = new SecretKeySpec(keyValue, "AES");
        byte[] iv = Arrays.copyOfRange(keyAndIv, 32, 48);

        // Decrypt
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
        try (CipherInputStream cis = new CipherInputStream(fis, cipher);
             Base64InputStream bis = new Base64InputStream(cis, false, -1, null); // from Apache Commons Codec  
             FileOutputStream fos = new FileOutputStream(outPath)) {

            int length;
            byte[] buffer = new byte[1024];
            while ((length = bis.read(buffer)) != -1) {
                fos.write(buffer, 0, length);
            }
        }
        System.out.println("Decrypt is completed");
        
    } catch (Exception e) {
        e.printStackTrace();
    }
}