工作奇谈——使用对称密匙加密数据
1、對稱密匙及對稱加密算法DES簡介
???????? 對稱密鑰加密,又稱私鑰加密,即信息的發(fā)送方和接收方用一個密鑰去加密和解密數(shù)據(jù)。它的最大優(yōu)勢是加/解密速度快,適合于對大數(shù)據(jù)量進(jìn)行加密。
???????? DES算法全稱為Data Encryption Standard,即數(shù)據(jù)加密算法,它是IBM公司于1975年研究成功并公開發(fā)表的。DES算法的入口參數(shù)有三個:Key、Data、Mode。其中Key為8個字節(jié)共64位,是DES算法的工作密鑰;Data也為8個字節(jié)64位,是要被加密或被解密的數(shù)據(jù);Mode為DES的工作方式,有兩種:加密或解密。
2、實(shí)現(xiàn)思路(防君子不防小人)
??????? 項(xiàng)目里有個活,要求登錄的時候賬號密碼加密傳輸,又不能使用SSL(真的坑),沒辦法,自己想了想,決定使用對稱密匙來加密解密數(shù)據(jù)。
??????? 但是密匙總不能是固定的吧,萬一別人拿到了我的密匙就可以隨意破解數(shù)據(jù)了(因?yàn)榧用芩惴ㄊ枪潭ǖ?#xff09;,所以我的實(shí)現(xiàn)思路是在用戶訪問login頁面的時候,服務(wù)端生成一個40位(此算法的密匙必須是八的倍數(shù))的隨機(jī)密匙給瀏覽器,然后寫一個JQ在瀏覽器同步加密用戶輸入的用戶名及密碼,當(dāng)用戶提交表單的時候再將加密好的用戶名密碼及密匙傳到服務(wù)端解密出原始數(shù)據(jù)不就OK了?想到這里說干就干!!!
3、代碼實(shí)現(xiàn)
??? 3.1、 加密及解密算法實(shí)現(xiàn)
??????????? 加密及解密算法的代碼我已經(jīng)寫成一個工具類,不太懂的同學(xué)可以去百度,百度上一大堆 ?щ(゚Д゚щ) ,代碼如下:我也已經(jīng)傳到碼云上: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異常,// 不能把加密后的字節(jié)數(shù)組直接轉(zhuǎn)換成字符串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;}/*** 將原始數(shù)據(jù)編碼為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編碼的數(shù)據(jù)解碼成原始數(shù)據(jù)*/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;}} }??? 3.2 當(dāng)用戶訪問登錄頁,向?yàn)g覽器寫入一個40位的密匙
??????? 代碼就不貼了,就是用random生成,然后用model寫回去
? ?? 3.3 使用JQ同步加密數(shù)據(jù)
??????? 當(dāng)用戶在文本框輸入賬號密碼的時候,需要向隱藏域中實(shí)時的寫入當(dāng)前用戶輸入數(shù)據(jù)的加密值。代碼如下:???????
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); } //執(zhí)行同步 setInterval(synchronize,300);//同步的時間間隔,每0.3秒同步一次??? 然后提交表單的時候,把隱藏域中加密好的用戶名密碼及加密密匙傳回后臺進(jìn)行解密,再去查數(shù)據(jù)庫判斷就OK了!
??? 下面是加密數(shù)據(jù)的效果圖:可以看到所有數(shù)據(jù)已經(jīng)加密
????? 然后我再補(bǔ)一張服務(wù)端解密的Debug圖:首先可以看到傳來的用戶名密碼都是加密的。
??? 接下來是解密成原始數(shù)據(jù),數(shù)據(jù)已經(jīng)成功解密!!
轉(zhuǎn)載于:https://my.oschina.net/u/3637243/blog/1510861
總結(jié)
以上是生活随笔為你收集整理的工作奇谈——使用对称密匙加密数据的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么用迅捷PDF转换器在线为PDF文件添
- 下一篇: 一篇文章搞定Shiro权限管理框架