赞
踩
项目中的加密算法
问题描述
在项目中使用了Des加密算法,我在本机增加用户加密了密码,实现了用户的登陆注册,然后将数据库备份给同事,同事再跑这个项目解密时就报错了。
分析原因
猜测:Des加密时和本机有联系,只有在本机加密的密码才能在本机解密。
更新:上面的猜测狗屁不通,DES是对称加密,只要秘匙相同就能正常加密解密。于是网上查了查,DES的入口参数有Data,model,填充模式。我使用的是"DES"它是采用默认的model和填充模式,在加密解密时会将其填充为8字节的整数倍。
尝试第一次解决
既然是这样,那我将加密解密都设置为"DES/ECB/NoPadding",结果报错说数据必须是8字节的整数倍。
尝试第二次解决
将输入的字符串格式化为8字节的整数倍,将输出的bytes[]数组截取出不为空的部分转为化String结果成功了。
简析加密算法原理
首先将64位的str进行顺序置换,然后分成32位的L0,R0两部分。然后L1=R(n-1),Rn=L(n-1)^f(keyN,L(n-1))这种算法计算16次得到L16和R16最后将他们合成64位输出。KeyN=C0+D0 C0=key的前28位循环左移一位或者两位,D0=key的后28位循环左移一位或者两位
DES Utils
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public class CryptionUtil {
public static Key DEFAULT_KEY = null;
//1qaz2wsx3edc$RFV%TGB^YHN&UJM
public static final String DEFAULT_SECRET_KEY = "1qaz2wsx3edc$RFV%TGB^YHN&UJM";
//不能写成DES,如果写成DES加密时会自动填充成64位,在解密时没有去除尾部就会发生问题。
public static final String DES_Content = "DES/ECB/NoPadding";
public static final String DES_Key= "DES";
static {
DEFAULT_KEY = obtainKey(DEFAULT_SECRET_KEY);
}
/**
* 获得key
**/
public static Key obtainKey(String key) {
if (key == null) {
return DEFAULT_KEY;
}
KeyGenerator generator = null;
try {
generator = KeyGenerator.getInstance(DES_Key);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
generator.init(new SecureRandom(key.getBytes()));
Key key1 = generator.generateKey();
generator = null;
return key1;
}
/**
* 加密
* String明文输入,String密文输出
*/
public static String encode(String str) {
return encode(null, str);
}
/**
* 加密
* String明文输入,String密文输出
*/
public static String encode(String key, String str) {
//将str补齐8字节的整数倍
byte[] bytes=formatData(str);
return Base64.encodeBase64URLSafeString(obtainEncode(key,bytes));
}
/**
* 解密
* 以String密文输入,String明文输出
*/
public static String decode(String str) {
return decode(null, str);
}
/**
* 解密
* 以String密文输入,String明文输出
*/
public static String decode(String key, String str) {
//通过DES算法解密得到正确的bytes[]
byte[] bytes=obtainDecode(key, Base64.decodeBase64(str));
//将bytes[]末尾补齐的空白去掉返回。
return formatByte(bytes);
}
/**
* 加密
* 以byte[]明文输入,byte[]密文输出
*/
private static byte[] obtainEncode(String key, byte[] str) {
byte[] byteFina = null;
Cipher cipher;
try {
Key key1 = obtainKey(key);
cipher = Cipher.getInstance(DES_Content);
cipher.init(Cipher.ENCRYPT_MODE, key1);
byteFina = cipher.doFinal(str);
} catch (Exception e) {
e.printStackTrace();
} finally {
cipher = null;
}
return byteFina;
}
@Override
public int hashCode() {
return super.hashCode();
}
/**
* 解密
* 以byte[]密文输入,以byte[]明文输出
*/
private static byte[] obtainDecode(String key, byte[] str) {
Cipher cipher;
byte[] byteFina = null;
try {
Key key1 = obtainKey(key);
cipher = Cipher.getInstance(DES_Content);
cipher.init(Cipher.DECRYPT_MODE, key1);
byteFina = cipher.doFinal(str);
} catch (Exception e) {
e.printStackTrace();
} finally {
cipher = null;
}
return byteFina;
}
//将str转为8的整数倍的byte[]
public static byte[] formatData(String str){
try{
byte[] data=str.getBytes("UTF-8");
int size=8-(data.length%8);
byte[] result=new byte[data.length+size];
for(int i=0;i
result[i]=data[i];
}
return result;
}catch (Exception e){
System.out.println(e.getMessage());
}
return null;
}
//将byte[]去掉空行转为Str
public static String formatByte(byte[] bytes){
int i=0;
for(;i
if(bytes[i]==0){
break;
}
}
byte[] result=new byte[i];
for(int j=0;j
result[j]=bytes[j];
}
try{
return new String(result,"UTF-8");
}catch (Exception e){
System.out.println(e.getMessage());
}
return null;
}
public static void main(String[] args) {
//String 中一个英文字符占一个字节,中文根据编码不同所占字节数不同。UFT-8占3个字节,GBK占两个字节。
String a = "admin1";
//encode的str必须是8字节的整数倍,key没做要求
String m = encode(a);
System.out.println(m);
String n = decode(m);
System.out.println(n);
// String str="abcdefg";
// byte[] bytes=formatData(str);
// String result=formatByte(bytes);
// System.out.println(result);
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。