java基于Des对称加密算法实现的加密与解密功能详解
本文实例讲述了java基于Des对称加密算法实现的加密与解密功能。分享给大家供大家参考,具体如下:
Des加密相关类介绍:
SecureRandom 这个类是继承自java.util.Random这个类
SecureRandom这个类的构造器有三种,下面例举两种:
SecureRandom()构造一个实现默认随机数算法的安全随机数生成器(RNG)。
SecureRandom(byte[]seed)构造一个实现默认随机数算法的安全随机数生成器(RNG)。
DESKeySpec这个类是用来使用原始秘钥来生成秘钥的秘钥内容
DESKeySpec有两个构造函数:
DESKeySpec(byte[]key)创建一个DESKeySpec对象,使用key中的前8个字节作为DES密钥的密钥内容。
DESKeySpec(byte[]key,intoffset)创建一个DESKeySpec对象,使用key中始于且包含offset的前8个字节作为DES-EDE密钥的密钥内容。
SecretKeyFactory,密钥工厂用来将密钥(类型Key的不透明加密密钥)转换为密钥规范(底层密钥材料的透明表示形式),反之亦然。秘密密钥工厂只对秘密(对称)密钥进行操作。
SecretKey对象,秘钥对象,通过调用秘钥工厂的generateSecret(DESKeySpecdeskeyspace)方法来生成秘钥
Cipher类为加密和解密提供密码功能,通过调用Cipher的getInstance("des")来获取实例
Cipher对象调用init()方法进行对象的初始化,init()方法的具体参数按照具体情况而定,有加密的也有解密的常量
最后调用Cipher的doFinal()方法进行加密解密。
在这里请教大家一个问题,不管是第一种使用BASE64Encoder编码还是第二种org.apache.commons.codec.binary.Base64编码,在将String转化为byte以及将byte转化为String时需要UTF-8/GBK等编码来编码,解码吗?
一、使用了sun.misc.BASE64Decoder和BASE64Encoder进行解码,编码
packagecom.soufun.com;
importjava.io.IOException;
importjava.security.NoSuchAlgorithmException;
importjava.security.SecureRandom;
importjava.util.Date;
importjavax.crypto.Cipher;
importjavax.crypto.SecretKey;
importjavax.crypto.SecretKeyFactory;
importjavax.crypto.spec.DESKeySpec;
//导入sun的64位编码
importsun.misc.BASE64Decoder;
importsun.misc.BASE64Encoder;
/**
*@authorWHD
*
*即使导入sun.misc这个架包也会报错,这时首先把你的JRE架包移除再导入一次就可以了
*/
publicclassDesUtil{
//定义加密方式
privatefinalstaticStringDES="DES";
privatefinalstaticStringUTF8="GBK";
staticSecretKeyFactorykeyFactory=null;
static{
try{
keyFactory=SecretKeyFactory.getInstance("DES");
}catch(NoSuchAlgorithmExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
publicstaticvoidmain(String[]args)throwsException{
longbegin=newDate().getTime();
Stringdata="aaades加密测试";
//注意:DES加密和解密过程中,密钥长度都必须是8的倍数
Stringkey="qazwsxed";
System.err.println(encrypt(data,key));
System.err.println(decrypt(encrypt(data,key),key));
longend=newDate().getTime();
System.out.println(end-begin);
}
/**
*Description根据键值进行加密
*@paramdata
*@paramkey加密键byte数组
*@return
*@throwsException
*/
publicstaticStringencrypt(Stringdata,Stringkey)throwsException{
//使用指定的编码获取要加密的内容,一般秘钥都是字母或数字不用指定编码,但指定也可以
byte[]bt=encrypt(data.getBytes(UTF8),key.getBytes(UTF8));
//注意:在加密和解密的时候使用sun的BASE64Encoder()进行编码和解码不然会有乱码
//网上查看了很多实例,都没有编码和解码,也说没有乱码问题,而我这里出现了乱码,所以使用BASE64Encoder()进行了编码解码
Stringstrs=newBASE64Encoder().encode(bt);
returnstrs;
}
/**
*Description根据键值进行解密
*@paramdata
*@paramkey加密键byte数组
*@return
*@throwsIOException
*@throwsException
*/
publicstaticStringdecrypt(Stringdata,Stringkey)throwsIOException,
Exception{
if(data==null)
returnnull;
//注意:在加密和解密的时候使用sun的BASE64Encoder()进行编码和解码不然会有乱码
BASE64Decoderdecoder=newBASE64Decoder();
byte[]buf=decoder.decodeBuffer(data);
byte[]bt=decrypt(buf,key.getBytes());
returnnewString(bt,UTF8);
}
/**
*Description根据键值进行加密
*@paramdata
*@paramkey加密键byte数组
*@return
*@throwsException
*/
privatestaticbyte[]encrypt(byte[]data,byte[]key)throwsException{
//生成一个可信任的随机数源
SecureRandomsr=newSecureRandom();
//从原始密钥数据创建DESKeySpec对象,也就是创建秘钥的秘钥内容
DESKeySpecdks=newDESKeySpec(key);
//密钥工厂用来将密钥(类型Key的不透明加密密钥)转换为密钥规范(底层密钥材料的透明表示形式),反之亦然。秘密密钥工厂只对秘密(对称)密钥进行操作。
//这里改为使用单例模式
//SecretKeyFactorykeyFactory=SecretKeyFactory.getInstance(DES);
//根据提供的密钥规范(密钥材料)生成SecretKey(秘钥)对象。
SecretKeysecurekey=keyFactory.generateSecret(dks);
//Cipher对象实际完成加密操作,此类为加密和解密提供密码功能
Ciphercipher=Cipher.getInstance(DES);
//用密钥和随机源初始化此Cipher。ENCRYPT_MODE用于将Cipher初始化为加密模式的常量。
cipher.init(Cipher.ENCRYPT_MODE,securekey,sr);
//正式执行加密操作
returncipher.doFinal(data);
}
/**
*Description根据键值进行解密
*@paramdata
*@paramkey加密键byte数组
*@return
*@throwsException
*/
privatestaticbyte[]decrypt(byte[]data,byte[]key)throwsException{
//生成一个可信任的随机数源
SecureRandomsr=newSecureRandom();
//从原始密钥数据创建DESKeySpec对象,也就是创建秘钥的秘钥内容
DESKeySpecdks=newDESKeySpec(key);
//密钥工厂用来将密钥(类型Key的不透明加密密钥)转换为密钥规范(底层密钥材料的透明表示形式),反之亦然。秘密密钥工厂只对秘密(对称)密钥进行操作。
//这里改为使用单例模式
//SecretKeyFactorykeyFactory=SecretKeyFactory.getInstance(DES);
//根据提供的密钥规范(密钥材料)生成SecretKey(秘钥)对象。
SecretKeysecurekey=keyFactory.generateSecret(dks);
//Cipher类为加密和解密提供密码功能
Ciphercipher=Cipher.getInstance(DES);
//DECRYPT_MODE用于将Cipher初始化为解密模式的常量。
cipher.init(Cipher.DECRYPT_MODE,securekey,sr);
//正式进行解密操作
returncipher.doFinal(data);
}
}
二、使用org.apache.commons.codec.binary.Base64进行解码,编码
packagecom.soufun.com;
importjava.io.IOException;
importjava.security.NoSuchAlgorithmException;
importjava.security.SecureRandom;
importjava.util.Date;
importjavax.crypto.Cipher;
importjavax.crypto.SecretKey;
importjavax.crypto.SecretKeyFactory;
importjavax.crypto.spec.DESKeySpec;
importorg.apache.commons.codec.binary.Base64;
/**
*@authorWHD
*
*/
publicclassDesUtil{
//定义加密方式
privatefinalstaticStringDES="DES";
privatefinalstaticStringUTF8="GBK";
staticSecretKeyFactorykeyFactory=null;
static{
try{
keyFactory=SecretKeyFactory.getInstance("DES");
}catch(NoSuchAlgorithmExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
publicstaticvoidmain(String[]args)throwsException{
longbegin=newDate().getTime();
Stringdata="aaades加密测试";
//注意:DES加密和解密过程中,密钥长度都必须是8的倍数
Stringkey="qazwsxed";
System.err.println(encrypt(data,key));
System.err.println(decrypt(encrypt(data,key),key));
longend=newDate().getTime();
System.out.println(end-begin);
}
/**
*Description根据键值进行加密
*@paramdata
*@paramkey加密键byte数组
*@return
*@throwsException
*/
publicstaticStringencrypt(Stringdata,Stringkey)throwsException{
//使用指定的编码获取要加密的内容,一般秘钥都是字母或数字不用指定编码,但指定也可以
byte[]bt=encrypt(data.getBytes(UTF8),key.getBytes());
//第一个使用了sun.misc.BASE64Encoder;进行了编码,但网上说使用org.apache.commons.codec.binary.Base64比较好所以拿来试试
Stringstrs=Base64.encodeBase64String(bt);
returnstrs;
}
/**
*Description根据键值进行解密
*@paramdata
*@paramkey加密键byte数组
*@return
*@throwsIOException
*@throwsException
*/
publicstaticStringdecrypt(Stringdata,Stringkey)throwsIOException,
Exception{
if(data==null)
returnnull;
//使用org.apache.commons.codec.binary.Base64解码
byte[]buf=Base64.decodeBase64(data);
byte[]bt=decrypt(buf,key.getBytes());
returnnewString(bt,UTF8);
}
/**
*Description根据键值进行加密
*@paramdata
*@paramkey加密键byte数组
*@return
*@throwsException
*/
privatestaticbyte[]encrypt(byte[]data,byte[]key)throwsException{
//生成一个可信任的随机数源
SecureRandomsr=newSecureRandom();
//从原始密钥数据创建DESKeySpec对象,也就是创建秘钥的秘钥内容
DESKeySpecdks=newDESKeySpec(key);
//密钥工厂用来将密钥(类型Key的不透明加密密钥)转换为密钥规范(底层密钥材料的透明表示形式),反之亦然。秘密密钥工厂只对秘密(对称)密钥进行操作。
//这里改为使用单例模式
//SecretKeyFactorykeyFactory=SecretKeyFactory.getInstance(DES);
//根据提供的密钥规范(密钥材料)生成SecretKey(秘钥)对象。
SecretKeysecurekey=keyFactory.generateSecret(dks);
//Cipher对象实际完成加密操作,此类为加密和解密提供密码功能
Ciphercipher=Cipher.getInstance(DES);
//用密钥和随机源初始化此Cipher。ENCRYPT_MODE用于将Cipher初始化为加密模式的常量。
cipher.init(Cipher.ENCRYPT_MODE,securekey,sr);
//正式执行加密操作
returncipher.doFinal(data);
}
/**
*Description根据键值进行解密
*@paramdata
*@paramkey加密键byte数组
*@return
*@throwsException
*/
privatestaticbyte[]decrypt(byte[]data,byte[]key)throwsException{
//生成一个可信任的随机数源
SecureRandomsr=newSecureRandom();
//从原始密钥数据创建DESKeySpec对象,也就是创建秘钥的秘钥内容
DESKeySpecdks=newDESKeySpec(key);
//密钥工厂用来将密钥(类型Key的不透明加密密钥)转换为密钥规范(底层密钥材料的透明表示形式),反之亦然。秘密密钥工厂只对秘密(对称)密钥进行操作。
//这里改为使用单例模式
//SecretKeyFactorykeyFactory=SecretKeyFactory.getInstance(DES);
//根据提供的密钥规范(密钥材料)生成SecretKey(秘钥)对象。
SecretKeysecurekey=keyFactory.generateSecret(dks);
//Cipher类为加密和解密提供密码功能
Ciphercipher=Cipher.getInstance(DES);
//DECRYPT_MODE用于将Cipher初始化为解密模式的常量。
cipher.init(Cipher.DECRYPT_MODE,securekey,sr);
//正式进行解密操作
returncipher.doFinal(data);
}
}
一、二中使用到的架包下载地址:
下载:sun.misc.BASE64Decoder。
下载:apache的Base64编码、解码器。
三、未使用任何编码,解码架包
packagecom.soufun.com;
importjava.io.IOException;
importjava.security.NoSuchAlgorithmException;
importjava.util.Date;
importjava.util.HashMap;
importjava.util.Map;
importjavax.crypto.Cipher;
importjavax.crypto.SecretKey;
importjavax.crypto.SecretKeyFactory;
importjavax.crypto.spec.DESKeySpec;
importjavax.crypto.spec.IvParameterSpec;
/**
*@authorWHD
*
*/
publicclassDESCrypt{
staticSecretKeyFactorysecretKeyFactory=null;
//Cipher的“算法/模式/填充”
staticfinalStringCIPHER="DES/CBC/PKCS5Padding";
static{
try{
//在静态代码块中获取秘钥工程
secretKeyFactory=SecretKeyFactory.getInstance("DES");
}catch(NoSuchAlgorithmExceptione){
e.printStackTrace();
}
}
//定义常量,编码格式
privatestaticfinalStringUTF8="GBK";
/*
*对象缓存的容器
*/
staticabstractclassCache{
privatefinalMapinnerCache=newHashMap();
protectedabstractObjectcreateValue(Objectkey)throwsException;
publicObjectget(Objectkey)throwsException{
Objectvalue;
synchronized(innerCache){
value=innerCache.get(key);
if(value==null){
value=newCreationPlaceholder();
innerCache.put(key,value);
}
}
if(valueinstanceofCreationPlaceholder){
synchronized(value){
CreationPlaceholderprogress=(CreationPlaceholder)value;
if(progress.value==null){
progress.value=createValue(key);
synchronized(innerCache){
innerCache.put(key,progress.value);
}
}
returnprogress.value;
}
}
returnvalue;
}
staticfinalclassCreationPlaceholder{
Objectvalue;
}
}
/*
*hex->str&str->hex
*/
publicstaticbyte[]stringToHex(Stringss){
//字符串转化we
bytedigest[]=newbyte[ss.length()/2];
for(inti=0;i<digest.length;i++){
StringbyteString=ss.substring(2*i,2*i+2);
intbyteValue=Integer.parseInt(byteString,16);
digest[i]=(byte)byteValue;
}
returndigest;
}
publicstaticStringhexToString(byteb[]){
StringBufferhexString=newStringBuffer();
for(inti=0;i<b.length;i++){
StringplainText=Integer.toHexString(0xff&b[i]);
if(plainText.length()<2){
hexString.append("0");
}
hexString.append(plainText);
}
returnhexString.toString();
}
privatestaticbyte[]_convertKeyIv(Stringtext)throwsIOException{
if(text.length()==8){
returntext.getBytes(UTF8);
}
if(text.startsWith("0x")&&text.length()==32){
byte[]result=newbyte[8];
for(inti=0;i<text.length();i+=2){
if(text.charAt(i++)=='0'&&text.charAt(i++)=='x'){
try{
result[i/4]=(byte)Integer.parseInt(
text.substring(i,i+2),16);
}catch(Exceptione){
thrownewIOException("TXT'"+text+"'isinvalid!");
}
}
}
returnresult;
}
thrownewIOException("TXT'"+text+"'isinvalid!");
}
/*
*SecretKey&IvParameterSpec的缓存
*/
privatestaticCacheSecretKeySpecs=newCache(){
protectedObjectcreateValue(Objectkey)throwsException{
SecretKeysecretKeyObj=null;
try{
secretKeyObj=secretKeyFactory.generateSecret(newDESKeySpec(
_convertKeyIv((String)key)));
}catch(Exceptione){
e.printStackTrace();
}
returnsecretKeyObj;
}
};
privatestaticCacheIvParamSpecs=newCache(){
protectedObjectcreateValue(Objectkey)throwsException{
IvParameterSpecivObj=null;
ivObj=newIvParameterSpec(_convertKeyIv((String)key));
returnivObj;
}
};
/*
*加密&解密
*/
publicstaticStringencrypt(Stringtext,StringauthKey,StringauthIv){
SecretKeysecretKeyObj=null;
IvParameterSpecivObj=null;
try{
secretKeyObj=(SecretKey)SecretKeySpecs.get(authKey);
ivObj=(IvParameterSpec)IvParamSpecs.get(authIv);
}catch(Exceptione){
e.printStackTrace();
}
byte[]data=null;
try{
data=text.getBytes(UTF8);
}catch(Exceptione){
e.printStackTrace();
}
byte[]authToken=null;
try{
authToken=encrypt(data,secretKeyObj,ivObj);
}catch(Exceptione){
e.printStackTrace();
}
returnhexToString(authToken);
}
publicstaticbyte[]encrypt(byte[]data,SecretKeysecretKey,
IvParameterSpeciv)throwsException{
Ciphercipher=Cipher.getInstance(CIPHER);
cipher.init(Cipher.ENCRYPT_MODE,secretKey,iv);
returncipher.doFinal(data);
}
publicstaticStringdecrypt(StringhexString,StringauthKey,StringauthIv)
throwsException{
SecretKeysecretKeyObj=null;
IvParameterSpecivObj=null;
try{
secretKeyObj=(SecretKey)SecretKeySpecs.get(authKey);
ivObj=(IvParameterSpec)IvParamSpecs.get(authIv);
}catch(Exceptione){
e.printStackTrace();
}
Stringtext=decrypt(hexString,secretKeyObj,ivObj);
returntext;
}
publicstaticStringdecrypt(Stringmessage,SecretKeysecretKey,
IvParameterSpeciv)throwsException{
byte[]data=stringToHex(message);
returndecrypt(data,secretKey,iv);
}
publicstaticStringdecrypt(byte[]data,SecretKeysecretKey,
IvParameterSpeciv)throwsException{
Ciphercipher=Cipher.getInstance(CIPHER);
cipher.init(Cipher.DECRYPT_MODE,secretKey,iv);
byte[]retByte=cipher.doFinal(data);
returnnewString(retByte);
}
publicstaticvoidmain(String[]args)throwsException{
longbegin=newDate().getTime();
StringauthKey="w8f3k9c2";
StringauthIv="w8f3k9c2";
Stringtext="aaades加密测试";
//140CB412BA03869F
//140cb412ba03869f
//对原文进行加密
StringencryptedText=encrypt(text,authKey,authIv);
System.out.println("encryptedText:"+encryptedText);
//对密文进行还原
StringplainText=decrypt(encryptedText,authKey,authIv);
System.out.println("plainText:"+plainText);
//2a329740ce15f549be64190b183a5be2
longend=newDate().getTime();
System.out.println(end-begin);
}
}
PS:关于加密解密感兴趣的朋友还可以参考本站在线工具:
密码安全性在线检测:
http://tools.jb51.net/password/my_password_safe
高强度密码生成器:
http://tools.jb51.net/password/CreateStrongPassword
迅雷、快车、旋风URL加密/解密工具:
http://tools.jb51.net/password/urlrethunder
在线散列/哈希算法加密工具:
http://tools.jb51.net/password/hash_encrypt
在线MD5/hash/SHA-1/SHA-2/SHA-256/SHA-512/SHA-3/RIPEMD-160加密工具:
http://tools.jb51.net/password/hash_md5_sha
在线sha1/sha224/sha256/sha384/sha512加密工具:
http://tools.jb51.net/password/sha_encode
希望本文所述对大家java程序设计有所帮助。