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, int offset) 创建一个 deskeyspec 对象,使用 key 中始于且包含 offset 的前 8 个字节作为 des-ede 密钥的密钥内容。
secretkeyfactory , 密钥工厂用来将密钥(类型 key 的不透明加密密钥)转换为密钥规范(底层密钥材料的透明表示形式),反之亦然。秘密密钥工厂只对秘密(对称)密钥进行操作。
secretkey对象,秘钥对象,通过调用秘钥工厂的generatesecret(deskeyspec deskeyspace) 方法来生成秘钥
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 进行解码,编码
package com.soufun.com; import java.io.ioexception; import java.security.nosuchalgorithmexception; import java.security.securerandom; import java.util.date; import javax.crypto.cipher; import javax.crypto.secretkey; import javax.crypto.secretkeyfactory; import javax.crypto.spec.deskeyspec; // 导入sun的64位编码 import sun.misc.base64decoder; import sun.misc.base64encoder; /** *@author whd * *即使导入sun.misc这个架包也会报错,这时首先把你的jre架包移除再导入一次就可以了 */ public class desutil { // 定义加密方式 private final static string des = "des"; private final static string utf8="gbk"; static secretkeyfactory keyfactory = null; static { try { keyfactory=secretkeyfactory.getinstance("des"); } catch (nosuchalgorithmexception e) { // todo auto-generated catch block e.printstacktrace(); } } public static void main(string[] args) throws exception { long begin=new date().gettime(); string data = "aaades加密测试"; // 注意:des加密和解密过程中,密钥长度都必须是8的倍数 string key = "qazwsxed"; system.err.println(encrypt(data, key)); system.err.println(decrypt(encrypt(data, key), key)); long end =new date().gettime(); system.out.println(end-begin); } /** * description 根据键值进行加密 * @param data * @param key 加密键byte数组 * @return * @throws exception */ public static string encrypt(string data, string key) throws exception { // 使用指定的编码获取要加密的内容,一般秘钥都是字母或数字不用指定编码,但指定也可以 byte[] bt = encrypt(data.getbytes(utf8), key.getbytes(utf8)); //注意:在加密和解密的时候使用sun的base64encoder()进行编码和解码不然会有乱码 //网上查看了很多实例,都没有编码和解码,也说没有乱码问题,而我这里出现了乱码,所以使用base64encoder()进行了编码解码 string strs = new base64encoder().encode(bt); return strs; } /** * description 根据键值进行解密 * @param data * @param key 加密键byte数组 * @return * @throws ioexception * @throws exception */ public static string decrypt(string data, string key) throws ioexception, exception { if (data == null) return null; //注意:在加密和解密的时候使用sun的base64encoder()进行编码和解码不然会有乱码 base64decoder decoder = new base64decoder(); byte[] buf = decoder.decodebuffer(data); byte[] bt = decrypt(buf,key.getbytes()); return new string(bt,utf8); } /** * description 根据键值进行加密 * @param data * @param key 加密键byte数组 * @return * @throws exception */ private static byte[] encrypt(byte[] data, byte[] key) throws exception { // 生成一个可信任的随机数源 securerandom sr = new securerandom(); // 从原始密钥数据创建deskeyspec对象,也就是创建秘钥的秘钥内容 deskeyspec dks = new deskeyspec(key); // 密钥工厂用来将密钥(类型 key 的不透明加密密钥)转换为密钥规范(底层密钥材料的透明表示形式),反之亦然。秘密密钥工厂只对秘密(对称)密钥进行操作。 // 这里改为使用单例模式 //secretkeyfactory keyfactory = secretkeyfactory.getinstance(des); //根据提供的密钥规范(密钥材料)生成 secretkey(秘钥) 对象。 secretkey securekey = keyfactory.generatesecret(dks); // cipher对象实际完成加密操作,此类为加密和解密提供密码功能 cipher cipher = cipher.getinstance(des); // 用密钥和随机源初始化此 cipher。encrypt_mode用于将 cipher 初始化为加密模式的常量。 cipher.init(cipher.encrypt_mode, securekey, sr); //正式执行加密操作 return cipher.dofinal(data); } /** * description 根据键值进行解密 * @param data * @param key 加密键byte数组 * @return * @throws exception */ private static byte[] decrypt(byte[] data, byte[] key) throws exception { // 生成一个可信任的随机数源 securerandom sr = new securerandom(); // 从原始密钥数据创建deskeyspec对象,也就是创建秘钥的秘钥内容 deskeyspec dks = new deskeyspec(key); // 密钥工厂用来将密钥(类型 key 的不透明加密密钥)转换为密钥规范(底层密钥材料的透明表示形式),反之亦然。秘密密钥工厂只对秘密(对称)密钥进行操作。 // 这里改为使用单例模式 //secretkeyfactory keyfactory = secretkeyfactory.getinstance(des); //根据提供的密钥规范(密钥材料)生成 secretkey(秘钥)对象。 secretkey securekey = keyfactory.generatesecret(dks); // cipher类为加密和解密提供密码功能 cipher cipher = cipher.getinstance(des); // decrypt_mode用于将 cipher 初始化为解密模式的常量。 cipher.init(cipher.decrypt_mode, securekey, sr); // 正式进行解密操作 return cipher.dofinal(data); } }
二、使用org.apache.commons.codec.binary.base64 进行解码,编码
package com.soufun.com; import java.io.ioexception; import java.security.nosuchalgorithmexception; import java.security.securerandom; import java.util.date; import javax.crypto.cipher; import javax.crypto.secretkey; import javax.crypto.secretkeyfactory; import javax.crypto.spec.deskeyspec; import org.apache.commons.codec.binary.base64; /** *@author whd * */ public class desutil { // 定义加密方式 private final static string des = "des"; private final static string utf8="gbk"; static secretkeyfactory keyfactory = null; static { try { keyfactory=secretkeyfactory.getinstance("des"); } catch (nosuchalgorithmexception e) { // todo auto-generated catch block e.printstacktrace(); } } public static void main(string[] args) throws exception { long begin=new date().gettime(); string data = "aaades加密测试"; // 注意:des加密和解密过程中,密钥长度都必须是8的倍数 string key = "qazwsxed"; system.err.println(encrypt(data, key)); system.err.println(decrypt(encrypt(data, key), key)); long end =new date().gettime(); system.out.println(end-begin); } /** * description 根据键值进行加密 * @param data * @param key 加密键byte数组 * @return * @throws exception */ public static string encrypt(string data, string key) throws exception { // 使用指定的编码获取要加密的内容,一般秘钥都是字母或数字不用指定编码,但指定也可以 byte[] bt = encrypt(data.getbytes(utf8), key.getbytes()); // 第一个使用了sun.misc.base64encoder;进行了编码,但网上说使用org.apache.commons.codec.binary.base64比较好所以拿来试试 string strs = base64.encodebase64string(bt); return strs; } /** * description 根据键值进行解密 * @param data * @param key 加密键byte数组 * @return * @throws ioexception * @throws exception */ public static string decrypt(string data, string key) throws ioexception, exception { if (data == null) return null; // 使用org.apache.commons.codec.binary.base64解码 byte [] buf=base64.decodebase64(data); byte[] bt = decrypt(buf,key.getbytes()); return new string(bt,utf8); } /** * description 根据键值进行加密 * @param data * @param key 加密键byte数组 * @return * @throws exception */ private static byte[] encrypt(byte[] data, byte[] key) throws exception { // 生成一个可信任的随机数源 securerandom sr = new securerandom(); // 从原始密钥数据创建deskeyspec对象,也就是创建秘钥的秘钥内容 deskeyspec dks = new deskeyspec(key); // 密钥工厂用来将密钥(类型 key 的不透明加密密钥)转换为密钥规范(底层密钥材料的透明表示形式),反之亦然。秘密密钥工厂只对秘密(对称)密钥进行操作。 // 这里改为使用单例模式 //secretkeyfactory keyfactory = secretkeyfactory.getinstance(des); //根据提供的密钥规范(密钥材料)生成 secretkey(秘钥) 对象。 secretkey securekey = keyfactory.generatesecret(dks); // cipher对象实际完成加密操作,此类为加密和解密提供密码功能 cipher cipher = cipher.getinstance(des); // 用密钥和随机源初始化此 cipher。encrypt_mode用于将 cipher 初始化为加密模式的常量。 cipher.init(cipher.encrypt_mode, securekey, sr); //正式执行加密操作 return cipher.dofinal(data); } /** * description 根据键值进行解密 * @param data * @param key 加密键byte数组 * @return * @throws exception */ private static byte[] decrypt(byte[] data, byte[] key) throws exception { // 生成一个可信任的随机数源 securerandom sr = new securerandom(); // 从原始密钥数据创建deskeyspec对象,也就是创建秘钥的秘钥内容 deskeyspec dks = new deskeyspec(key); // 密钥工厂用来将密钥(类型 key 的不透明加密密钥)转换为密钥规范(底层密钥材料的透明表示形式),反之亦然。秘密密钥工厂只对秘密(对称)密钥进行操作。 // 这里改为使用单例模式 //secretkeyfactory keyfactory = secretkeyfactory.getinstance(des); //根据提供的密钥规范(密钥材料)生成 secretkey(秘钥)对象。 secretkey securekey = keyfactory.generatesecret(dks); // cipher类为加密和解密提供密码功能 cipher cipher = cipher.getinstance(des); // decrypt_mode用于将 cipher 初始化为解密模式的常量。 cipher.init(cipher.decrypt_mode, securekey, sr); // 正式进行解密操作 return cipher.dofinal(data); } }
一、二中使用到的架包下载地址:
下载: sun.misc.base64decoder 。
下载:apache的base64编码、解码器 。
三、未使用任何编码,解码架包
package com.soufun.com; import java.io.ioexception; import java.security.nosuchalgorithmexception; import java.util.date; import java.util.hashmap; import java.util.map; import javax.crypto.cipher; import javax.crypto.secretkey; import javax.crypto.secretkeyfactory; import javax.crypto.spec.deskeyspec; import javax.crypto.spec.ivparameterspec; /** *@author whd * */ public class descrypt { static secretkeyfactory secretkeyfactory = null; //cipher 的“算法/模式/填充” static final string cipher = "des/cbc/pkcs5padding"; static { try { // 在静态代码块中获取秘钥工程 secretkeyfactory = secretkeyfactory.getinstance("des"); } catch (nosuchalgorithmexception e) { e.printstacktrace(); } } // 定义常量 ,编码格式 private static final string utf8 = "gbk"; /* * 对象缓存的容器 */ static abstract class cache { private final map innercache = new hashmap(); protected abstract object createvalue(object key) throws exception; public object get(object key) throws exception { object value; synchronized (innercache) { value = innercache.get(key); if (value == null) { value = new creationplaceholder(); innercache.put(key, value); } } if (value instanceof creationplaceholder) { synchronized (value) { creationplaceholder progress = (creationplaceholder) value; if (progress.value == null) { progress.value = createvalue(key); synchronized (innercache) { innercache.put(key, progress.value); } } return progress.value; } } return value; } static final class creationplaceholder { object value; } } /* * hex->str & str->hex */ public static byte[] stringtohex(string ss) { // 字符串转化we byte digest[] = new byte[ss.length() / 2]; for (int i = 0; i < digest.length; i++) { string bytestring = ss.substring(2 * i, 2 * i + 2); int bytevalue = integer.parseint(bytestring, 16); digest[i] = (byte) bytevalue; } return digest; } public static string hextostring(byte b[]) { stringbuffer hexstring = new stringbuffer(); for (int i = 0; i < b.length; i++) { string plaintext = integer.tohexstring(0xff & b[i]); if (plaintext.length() < 2) { hexstring.append("0"); } hexstring.append(plaintext); } return hexstring.tostring(); } private static byte[] _convertkeyiv(string text) throws ioexception { if (text.length() == 8) { return text.getbytes(utf8); } if (text.startswith("0x") && text.length() == 32) { byte[] result = new byte[8]; for (int i = 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 (exception e) { throw new ioexception("txt '" + text + "' is invalid!"); } } } return result; } throw new ioexception("txt '" + text + "' is invalid!"); } /* * secretkey & ivparameterspec的缓存 */ private static cache secretkeyspecs = new cache() { protected object createvalue(object key) throws exception { secretkey secretkeyobj = null; try { secretkeyobj = secretkeyfactory.generatesecret(new deskeyspec( _convertkeyiv((string) key))); } catch (exception e) { e.printstacktrace(); } return secretkeyobj; } }; private static cache ivparamspecs = new cache() { protected object createvalue(object key) throws exception { ivparameterspec ivobj = null; ivobj = new ivparameterspec(_convertkeyiv((string) key)); return ivobj; } }; /* * 加密&解密 */ public static string encrypt(string text, string authkey, string authiv) { secretkey secretkeyobj = null; ivparameterspec ivobj = null; try { secretkeyobj = (secretkey) secretkeyspecs.get(authkey); ivobj = (ivparameterspec) ivparamspecs.get(authiv); } catch (exception e) { e.printstacktrace(); } byte[] data = null; try { data = text.getbytes(utf8); } catch (exception e) { e.printstacktrace(); } byte[] authtoken = null; try { authtoken = encrypt(data, secretkeyobj, ivobj); } catch (exception e) { e.printstacktrace(); } return hextostring(authtoken); } public static byte[] encrypt(byte[] data, secretkey secretkey, ivparameterspec iv) throws exception { cipher cipher = cipher.getinstance(cipher); cipher.init(cipher.encrypt_mode, secretkey, iv); return cipher.dofinal(data); } public static string decrypt(string hexstring, string authkey, string authiv) throws exception { secretkey secretkeyobj = null; ivparameterspec ivobj = null; try { secretkeyobj = (secretkey) secretkeyspecs.get(authkey); ivobj = (ivparameterspec) ivparamspecs.get(authiv); } catch (exception e) { e.printstacktrace(); } string text = decrypt(hexstring, secretkeyobj, ivobj); return text; } public static string decrypt(string message, secretkey secretkey, ivparameterspec iv) throws exception { byte[] data = stringtohex(message); return decrypt(data, secretkey, iv); } public static string decrypt(byte[] data, secretkey secretkey, ivparameterspec iv) throws exception { cipher cipher = cipher.getinstance(cipher); cipher.init(cipher.decrypt_mode, secretkey, iv); byte[] retbyte = cipher.dofinal(data); return new string(retbyte); } public static void main(string[] args) throws exception { long begin= new date().gettime(); string authkey = "w8f3k9c2"; string authiv = "w8f3k9c2"; string text = "aaades加密测试"; // 140cb412ba03869f // 140cb412ba03869f // 对原文进行加密 string encryptedtext = encrypt(text, authkey, authiv); system.out.println("encryptedtext:" + encryptedtext); // 对密文进行还原 string plaintext = decrypt(encryptedtext, authkey, authiv); system.out.println("plaintext:" + plaintext); //2a329740ce15f549be64190b183a5be2 long end =new date().gettime(); system.out.println(end-begin); } }
ps:关于加密解密感兴趣的朋友还可以参考本站在线工具:
密码安全性在线检测:
高强度密码生成器:
http://tools.jb51.net/password/createstrongpassword
迅雷、快车、旋风url加密/解密工具:
在线散列/哈希算法加密工具:
在线md5/hash/sha-1/sha-2/sha-256/sha-512/sha-3/ripemd-160加密工具:
在线sha1/sha224/sha256/sha384/sha512加密工具:
希望本文所述对大家java程序设计有所帮助。