对称密钥加密,又称私钥加密,即信息的发送方和接收方用一个密钥去加密和解密数据。它的最大优点是加/解密速度快,适合于对大数据量进行加密。javascript
DES算法全称为Data Encryption Standard,即数据加密算法,它是IBM公司于1975年研究成功并公开发表的。DES算法的入口参数有三个:Key、Data、Mode。其中Key为8个字节共64位,是DES算法的工做密钥;Data也为8个字节64位,是要被加密或被解密的数据;Mode为DES的工做方式,有两种:加密或解密。java
项目里有个活,要求登陆的时候帐号密码加密传输,又不能使用SSL(真的坑),没办法,本身想了想,决定使用对称密匙来加密解密数据。git
可是密匙总不能是固定的吧,万一别人拿到了个人密匙就能够随意破解数据了(由于加密算法是固定的),因此个人实现思路是在用户访问login页面的时候,服务端生成一个40位(此算法的密匙必须是八的倍数)的随机密匙给浏览器,而后写一个JQ在浏览器同步加密用户输入的用户名及密码,当用户提交表单的时候再将加密好的用户名密码及密匙传到服务端解密出原始数据不就OK了?想到这里说干就干!!!算法
加密及解密算法的代码我已经写成一个工具类,不太懂的同窗能够去百度,百度上一大堆 щ(゚Д゚щ) ,代码以下:我也已经传到码云上:https://git.oschina.net/LKWai数据库
package cn.yy.util; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; 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; /** * DES加解密工具类 * * @author 二十岁之后 * * @date 2017年7月27日 */ public class DESUtil { private static final String DES_ALGORITHM = "DES"; /** * DES加密 * * @param plainData 原始字符串 * @param secretKey 加密密钥 * @return 加密后的字符串 * @throws Exception */ public static String encryption(String plainData, String secretKey) throws Exception { Cipher cipher = null; try { cipher = Cipher.getInstance(DES_ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, generateKey(secretKey)); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { } try { // 为了防止解密时报javax.crypto.IllegalBlockSizeException: Input length must // be multiple of 8 when decrypting with padded cipher异常, // 不能把加密后的字节数组直接转换成字符串 byte[] buf = cipher.doFinal(plainData.getBytes()); return Base64Utils.encode(buf); } catch (IllegalBlockSizeException e) { e.printStackTrace(); throw new Exception("IllegalBlockSizeException", e); } catch (BadPaddingException e) { e.printStackTrace(); throw new Exception("BadPaddingException", e); } } /** * DES解密 * @param secretData 密码字符串 * @param secretKey 解密密钥 * @return 原始字符串 * @throws Exception */ public static String decryption(String secretData, String secretKey) throws Exception { Cipher cipher = null; try { cipher = Cipher.getInstance(DES_ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, generateKey(secretKey)); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); throw new Exception("NoSuchAlgorithmException", e); } catch (NoSuchPaddingException e) { e.printStackTrace(); throw new Exception("NoSuchPaddingException", e); } catch (InvalidKeyException e) { e.printStackTrace(); throw new Exception("InvalidKeyException", e); } try { byte[] buf = cipher.doFinal(Base64Utils.decode(secretData.toCharArray())); return new String(buf); } catch (IllegalBlockSizeException e) { e.printStackTrace(); throw new Exception("IllegalBlockSizeException", e); } catch (BadPaddingException e) { e.printStackTrace(); throw new Exception("BadPaddingException", e); } } /** * 得到秘密密钥 * * @param secretKey * @return * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException * @throws InvalidKeyException */ private static SecretKey generateKey(String secretKey) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException { SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES_ALGORITHM); DESKeySpec keySpec = new DESKeySpec(secretKey.getBytes()); keyFactory.generateSecret(keySpec); return keyFactory.generateSecret(keySpec); } static private class Base64Utils { static private char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" .toCharArray(); static private byte[] codes = new byte[256]; static { for (int i = 0; i < 256; i++) codes[i] = -1; for (int i = 'A'; i <= 'Z'; i++) codes[i] = (byte) (i - 'A'); for (int i = 'a'; i <= 'z'; i++) codes[i] = (byte) (26 + i - 'a'); for (int i = '0'; i <= '9'; i++) codes[i] = (byte) (52 + i - '0'); codes['+'] = 62; codes['/'] = 63; } /** * 将原始数据编码为base64编码 */ static private String encode(byte[] data) { char[] out = new char[((data.length + 2) / 3) * 4]; for (int i = 0, index = 0; i < data.length; i += 3, index += 4) { boolean quad = false; boolean trip = false; int val = (0xFF & (int) data[i]); val <<= 8; if ((i + 1) < data.length) { val |= (0xFF & (int) data[i + 1]); trip = true; } val <<= 8; if ((i + 2) < data.length) { val |= (0xFF & (int) data[i + 2]); quad = true; } out[index + 3] = alphabet[(quad ? (val & 0x3F) : 64)]; val >>= 6; out[index + 2] = alphabet[(trip ? (val & 0x3F) : 64)]; val >>= 6; out[index + 1] = alphabet[val & 0x3F]; val >>= 6; out[index + 0] = alphabet[val & 0x3F]; } return new String(out); } /** * 将base64编码的数据解码成原始数据 */ static private byte[] decode(char[] data) { int len = ((data.length + 3) / 4) * 3; if (data.length > 0 && data[data.length - 1] == '=') --len; if (data.length > 1 && data[data.length - 2] == '=') --len; byte[] out = new byte[len]; int shift = 0; int accum = 0; int index = 0; for (int ix = 0; ix < data.length; ix++) { int value = codes[data[ix] & 0xFF]; if (value >= 0) { accum <<= 6; shift += 6; accum |= value; if (shift >= 8) { shift -= 8; out[index++] = (byte) ((accum >> shift) & 0xff); } } } if (index != out.length) throw new Error("miscalculated data length!"); return out; } } }
代码就不贴了,就是用random生成,而后用model写回去数组
当用户在文本框输入帐号密码的时候,须要向隐藏域中实时的写入当前用户输入数据的加密值。代码以下: 浏览器
function synchronize(){ var NewUser = $("#um").val(); var NewPass = $("#pw").val(); var ranDom = $("#random").val(); //NewPass是用户输入值,ranDom是加密密匙 document.getElementById('pw1').value =encryptByDES(NewPass, ranDom); document.getElementById('um1').value =encryptByDES(NewUser, ranDom); } //执行同步 setInterval(synchronize,300);//同步的时间间隔,每0.3秒同步一次
而后提交表单的时候,把隐藏域中加密好的用户名密码及加密密匙传回后台进行解密,再去查数据库判断就OK了!dom
下面是加密数据的效果图:能够看到全部数据已经加密工具
而后我再补一张服务端解密的Debug图:首先能够看到传来的用户名密码都是加密的。大数据
接下来是解密成原始数据,数据已经成功解密!!