package test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import org.apache.commons.codec.binary.Base64;
public class DESUtils {
private final static String KEY_ALGORITHM = "DES";
private final static String CIPER_ALGORITHM = "DES";
public static void encrypt(File inFile, String outFilePath, String outFileName, String key){
FileInputStream fis = null;
FileOutputStream fos = null;
if(! inFile.exists()){
System.out.println("要加密的文件不存在");
return;
}
File dir = new File(outFilePath);
if(!dir.exists()){
dir.mkdir();
}
File outFile = new File(dir, outFileName);
byte[] buffer = new byte[1024*10];
int length;
SecureRandom random = new SecureRandom();
try {
DESKeySpec desKey = new DESKeySpec(key.getBytes());
//创建一个密匙工厂,然后用它把DESKeySpec转换成SecretKey对象
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
SecretKey secretKey = keyFactory.generateSecret(desKey);
//Cipher对象实际完成解密操作
Cipher cipher = Cipher.getInstance(CIPER_ALGORITHM);
//用密匙初始化Cipher对象
cipher.init(Cipher.ENCRYPT_MODE, secretKey, random);
fis = new FileInputStream(inFile);
fos = new FileOutputStream(outFile);
//开始加密操作
while((length = fis.read(buffer)) != -1){
buffer = Arrays.copyOf(buffer, length);
System.out.println(buffer.length);
byte[] byteArray = cipher.doFinal(buffer);
byte[] base64Array = Base64.encodeBase64(byteArray);
fos.write(base64Array, 0, base64Array.length);
}
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeySpecException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(fis != null){
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(fos != null){
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void decrypt(File inFile, String outFilePath, String outFileName, String key){
FileInputStream fis = null;
FileOutputStream fos = null;
if(! inFile.exists()){
System.out.println("要解密的文件不存在");
return;
}
File dir = new File(outFilePath);
if(!dir.exists()){
dir.mkdir();
}
File outFile = new File(dir, outFileName);
byte[] buffer = new byte[1024*10];
int length;
SecureRandom random = new SecureRandom();
try {
DESKeySpec desKey = new DESKeySpec(key.getBytes());
//创建一个密匙工厂,然后用它把DESKeySpec转换成SecretKey对象
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
SecretKey secretKey = keyFactory.generateSecret(desKey);
//Cipher对象实际完成解密操作
Cipher cipher = Cipher.getInstance(CIPER_ALGORITHM);
//用密匙初始化Cipher对象
cipher.init(Cipher.DECRYPT_MODE, secretKey, random);
fis = new FileInputStream(inFile);
fos = new FileOutputStream(outFile);
//开始解密操作
while((length = fis.read(buffer)) != -1){
buffer = Arrays.copyOf(buffer, length);
System.out.println(buffer.length);
byte[] base64Array = Base64.decodeBase64(buffer);
byte[] byteArray = cipher.doFinal(base64Array);
fos.write(byteArray, 0, byteArray.length);
}
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeySpecException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(fis != null){
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(fos != null){
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
DESUtils des = new DESUtils();
File file = new File("D:\\moms.sql");
String filePath = "D:\\";
String key = "12345678";
DESUtils.encrypt(file, "D:\\", "copy1", key);
DESUtils.decrypt(new File("D:\\copy1"), "D:\\", "copy2", key);
}
}
javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
at com.sun.crypto.provider.DESCipher.engineDoFinal(DESCipher.java:314)
at javax.crypto.Cipher.doFinal(Cipher.java:2087)
at test.DESUtils.decrypt(DESUtils.java:155)
at test.DESUtils.main(DESUtils.java:209)
2 个解决方案
#1
10K的数据加密出来还是10K吗
你在加密的时候打印一下这个
System.out.println(base64Array.length); 如果原始是10k,加密的结果是13644
这个原始数据的长度与加密结果的长度是有规律的,一般是以8为单位
比如
原始长度 加密后长度(解密长度)
1~15 24
16~23 32
24~31 44
32~39 56
40~47 64
48~55 76
512 696
所以你分段加密的时候原始分段加密读取的长度与解密分段读取的长度要对应
你在加密的时候打印一下这个
System.out.println(base64Array.length); 如果原始是10k,加密的结果是13644
这个原始数据的长度与加密结果的长度是有规律的,一般是以8为单位
比如
原始长度 加密后长度(解密长度)
1~15 24
16~23 32
24~31 44
32~39 56
40~47 64
48~55 76
512 696
所以你分段加密的时候原始分段加密读取的长度与解密分段读取的长度要对应
#2
加解密的pad方式可能不一样。。
DES 、AES加密模式和填充方式(其实还有还几种填充方式没写上,开始时候也在这里绕了一下)
16 算法/模式/填充 16字节加密后数据长度 不满16字节加密后长度
AES/CBC/NoPadding 16 不支持
AES/CBC/PKCS5Padding 32 16
AES/CBC/ISO10126Padding 32 16
AES/CFB/NoPadding 16 原始数据长度
AES/CFB/PKCS5Padding 32 16
AES/CFB/ISO10126Padding 32 16
AES/ECB/NoPadding 16 不支持
AES/ECB/PKCS5Padding 32 16
AES/ECB/ISO10126Padding 32 16
AES/OFB/NoPadding 16 原始数据长度
AES/OFB/PKCS5Padding 32 16
AES/OFB/ISO10126Padding 32 16
AES/PCBC/NoPadding 16 不支持
AES/PCBC/PKCS5Padding 32 16
AES/PCBC/ISO10126Padding 32 16
DES 、AES加密模式和填充方式(其实还有还几种填充方式没写上,开始时候也在这里绕了一下)
16 算法/模式/填充 16字节加密后数据长度 不满16字节加密后长度
AES/CBC/NoPadding 16 不支持
AES/CBC/PKCS5Padding 32 16
AES/CBC/ISO10126Padding 32 16
AES/CFB/NoPadding 16 原始数据长度
AES/CFB/PKCS5Padding 32 16
AES/CFB/ISO10126Padding 32 16
AES/ECB/NoPadding 16 不支持
AES/ECB/PKCS5Padding 32 16
AES/ECB/ISO10126Padding 32 16
AES/OFB/NoPadding 16 原始数据长度
AES/OFB/PKCS5Padding 32 16
AES/OFB/ISO10126Padding 32 16
AES/PCBC/NoPadding 16 不支持
AES/PCBC/PKCS5Padding 32 16
AES/PCBC/ISO10126Padding 32 16
#1
10K的数据加密出来还是10K吗
你在加密的时候打印一下这个
System.out.println(base64Array.length); 如果原始是10k,加密的结果是13644
这个原始数据的长度与加密结果的长度是有规律的,一般是以8为单位
比如
原始长度 加密后长度(解密长度)
1~15 24
16~23 32
24~31 44
32~39 56
40~47 64
48~55 76
512 696
所以你分段加密的时候原始分段加密读取的长度与解密分段读取的长度要对应
你在加密的时候打印一下这个
System.out.println(base64Array.length); 如果原始是10k,加密的结果是13644
这个原始数据的长度与加密结果的长度是有规律的,一般是以8为单位
比如
原始长度 加密后长度(解密长度)
1~15 24
16~23 32
24~31 44
32~39 56
40~47 64
48~55 76
512 696
所以你分段加密的时候原始分段加密读取的长度与解密分段读取的长度要对应
#2
加解密的pad方式可能不一样。。
DES 、AES加密模式和填充方式(其实还有还几种填充方式没写上,开始时候也在这里绕了一下)
16 算法/模式/填充 16字节加密后数据长度 不满16字节加密后长度
AES/CBC/NoPadding 16 不支持
AES/CBC/PKCS5Padding 32 16
AES/CBC/ISO10126Padding 32 16
AES/CFB/NoPadding 16 原始数据长度
AES/CFB/PKCS5Padding 32 16
AES/CFB/ISO10126Padding 32 16
AES/ECB/NoPadding 16 不支持
AES/ECB/PKCS5Padding 32 16
AES/ECB/ISO10126Padding 32 16
AES/OFB/NoPadding 16 原始数据长度
AES/OFB/PKCS5Padding 32 16
AES/OFB/ISO10126Padding 32 16
AES/PCBC/NoPadding 16 不支持
AES/PCBC/PKCS5Padding 32 16
AES/PCBC/ISO10126Padding 32 16
DES 、AES加密模式和填充方式(其实还有还几种填充方式没写上,开始时候也在这里绕了一下)
16 算法/模式/填充 16字节加密后数据长度 不满16字节加密后长度
AES/CBC/NoPadding 16 不支持
AES/CBC/PKCS5Padding 32 16
AES/CBC/ISO10126Padding 32 16
AES/CFB/NoPadding 16 原始数据长度
AES/CFB/PKCS5Padding 32 16
AES/CFB/ISO10126Padding 32 16
AES/ECB/NoPadding 16 不支持
AES/ECB/PKCS5Padding 32 16
AES/ECB/ISO10126Padding 32 16
AES/OFB/NoPadding 16 原始数据长度
AES/OFB/PKCS5Padding 32 16
AES/OFB/ISO10126Padding 32 16
AES/PCBC/NoPadding 16 不支持
AES/PCBC/PKCS5Padding 32 16
AES/PCBC/ISO10126Padding 32 16