DES加密解密
使用Base64(加密字符串)
import cn.hzjykj.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.security.Key;
import java.security.Security;
private static byte[] iv = new byte[8];
private static String _KEY = "Jinyi-hz";
public static String encryptDES(String encryptString) throws Exception{
IvParameterSpec zoreIv = new IvParameterSpec(iv);
SecretKeySpec key = new SecretKeySpec(_KEY.getBytes(),"DES");
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE,key,zoreIv);
byte[] encryptedData = cipher.doFinal(encryptString.getBytes("UTF-8"));
return Base64.encode(encryptedData);
}
public static String decryptDES(String decryptString) throws Exception{
new Base64();
byte[] byteMi = Base64.decode(decryptString);
IvParameterSpec zeroIv = new IvParameterSpec(iv);
SecretKeySpec key = new SecretKeySpec(_KEY.getBytes("UTF-8"),"DES");
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE,key,zeroIv);
byte decryptedData[] = cipher.doFinal(byteMi);
return new String(decryptedData,"UTF-8");
}
public static void main(String[] args) throws Exception {
String gbkStr = new String("������GBK���ַ�".getBytes("GBK"), "GBK");
System.out.println("GBK:" + gbkStr);
String utf8Str = new String(gbkStr.getBytes("GBK"), "ISO8859_1");
utf8Str = new String(utf8Str.getBytes("ISO8859_1"), "UTF-8");
System.out.println("UTF-8:" + utf8Str);
String t = new String(utf8Str.getBytes("UTF-8"), "ISO8859_1");
t = new String(t.getBytes("ISO8859_1"), "GBK");
System.out.println("GBK:" + t);
String tt = encryptDES(t);
System.out.println(tt);
System.out.println(decryptDES(tt));
}
new String,通过String.getBytes(加密文件)
import javax.crypto.Cipher;
import java.io.*;
import java.security.Key;
import java.security.Security;
/**
* 获取秘钥
* @author zrx
* @date 2020/4/22
*/
public class MySecurity {
private static String strDefaultKey = "hnztzwma";
private Cipher encryptCipher = null;
private Cipher decryptCipher = null;
private Key getKey(byte[] arrBTmp) throws Exception{
// 创建一个空的8位字节数组,默认值为0
byte[] arrB = new byte[8];
// 将原始字节数组转化为8位
for (int i=0;i<arrBTmp.length;i++){
arrB[i] = arrBTmp[i];
}
// 生成秘钥
Key key = new javax.crypto.spec.SecretKeySpec(arrB,"DES");
return key;
}
public MySecurity() throws Exception{
this(strDefaultKey);
}
public MySecurity(String strKey) throws Exception{
Security.addProvider(new com.sun.crypto.provider.SunJCE());
Key key = getKey(strKey.getBytes());
encryptCipher = Cipher.getInstance("DES");
encryptCipher.init(Cipher.ENCRYPT_MODE,key);
decryptCipher = Cipher.getInstance("DES");
decryptCipher.init(Cipher.DECRYPT_MODE,key);
}
public byte[] encrypt(byte[] arrB) throws Exception{
return encryptCipher.doFinal(arrB);
}
public byte[] decrypt(byte[] arrB) throws Exception{
return decryptCipher.doFinal(arrB);
}
/**
* 文件加密
* @param file
* @return
* @throws Exception
*/
public static byte[] getBytesFromFile(java.io.File file) throws Exception{
InputStream is = new FileInputStream(file);
// 获取文件大小
long length = file.length();
// 限制要读取的文件的大小不能能超过Integer.MAX_VALUE
if (length>Integer.MAX_VALUE){
return null; // 文件太大,退出程序
}
// 创建字节数组
byte[] bytes = new byte[(int)length];
// 将文件信息读入数组
int offset = 0;
int numRead = 0;
while (offset<bytes.length && (numRead = is.read(bytes,offset,bytes.length-offset))>=0){
offset+=numRead;
}
// 确认是否将所有信息读入数组
if (offset<bytes.length){
throw new IOException("Could not completely read file "+file.getName());
}
// 关闭流
is.close();
return bytes;
}
/**
* 将字节数组写入文件
* @param inByte
* @param pathAndNameString
* @return
* @throws IOException
*/
public static File writeBytesToFile(byte[] inByte,String pathAndNameString) throws IOException{
File file = null;
try {
file = new File(pathAndNameString);
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
fos.write(inByte);
fos.close();
}catch (Exception e){
e.printStackTrace();
}
return file;
}
/**
* 文件加密
* @param srcFile 要加密的源文件
* @param destFile 加密后的文件
* @throws Exception
*/
public void encryptFile(String srcFile,String destFile) throws Exception{
File infile = new File(srcFile); // 加密前文件
byte[] myFileA = getBytesFromFile(infile);
writeBytesToFile(encrypt(myFileA),destFile);
}
/**
* 文件解密
* @param srcFile 要解密的源文件
* @param destFile 解密后的文件
* @throws Exception
*/
public void decryptFile(String srcFile,String destFile) throws Exception{
File infile = new File(srcFile);
byte[] myfileA = getBytesFromFile(infile);
writeBytesToFile(decrypt(myfileA),destFile);
}
public static void main(String[] args) throws Exception {
try {
MySecurity des = new MySecurity();
// 加密文件测试
des.encryptFile("D:\\file.txt","D:\\enFile.txt");
// 解密文件测试
des.decryptFile("D:\\enFile.txt","D:\\deFile.txt");
}catch (Exception e){
e.printStackTrace();
}
}
}
错误: Input length must be multiple of 8 when decrypting with padded cipher
- 为什么数组转字符串,字符串然后转数组会出现前后两个字节数组的值会有不同,因为并不是每个字节数和编码集上的字符都有对应关系,如果一个字节数在编码集上没有对应编码,new String(byte[])后,往往解出来的会是一些乱码无意义的符号,例如:��
但是解码的时候�这个字符也是一个字符,在编码表中也有固定的字节数用来表示,所有解码出来的值必定是编码表中对应的值,除非你的字节数组中的字节数正好在编码表中有对应的值,否则编码解码后的字节数组会不一样。
【解决办法】
- 可以用base64对参生成的数组进行编码,然后再解码,这样不会想new String(byte[]).getBytes()那样造成数组前后不一致,base64对数据的处理是不会造成误差的。
- 直接返回数组,然后再用数组解密