最近項目在維護過程當中,估計這一週都會沒有什麼事情作了。因而開始打量本身作完的這個項目,項目在展現方面乏善可陳,而後仔細的想了想,這個項目的亮點無非就在數據加密和解密這一塊了。由於是銀行的項目,因此對數據的安全要求比較高,其次在這個項目裏面學到的就是銀行項目開發的嚴謹,好比說數據類型和先後臺數據統一和維護,以及接口的規範。java
好了如今就進入到這篇博客的正文,那就是數據的加密解密問題。git
一般咱們在進行數據的傳遞的時候都會對請求的數據以及獲得的數據進行加解密,這樣別人在截取咱們應用的數據的時候就不會對咱們形成太多的破壞。通常的應用只要進行一些簡單的數據加解密就好了,咱們通常進行的操做就是用BASE64 或者MD5對數據進行加解密。可是,在王小云教授宣佈已經破解了MD5以及利用hash數組進行加解密的算法後,MD5再也不是那麼安全了,特別是關於銀行的和一些對數據比較敏感的開發就只能用更安全或者更復雜的算法進行加解密了。好比DES/AES/等算法。算法
首先咱們來看一下在開發中接觸到的密碼學。數組
咱們在開發的時候會接觸到雙向解密和單向加密,其中雙向加密又分爲對稱機密和非對稱加密。對稱加密就是指的咱們用同一祕鑰進行加密解密,因此對稱加密又稱爲單密鑰加密,它主要運用在一些加密的數據量比較大的場合。對稱加密主要的加密算法有DES/3DES/AES.等。其次就是非對稱加密,這種加密算法須要有公開祕鑰和私有祕鑰,也就是說數據通信的兩端必須擁有公開祕鑰和私有祕鑰的其中一個才能進行數據的加密和解密。非對稱加密主要包括了RSA/DSA等算法。第2、就是單向加密,數據只能進行加密不能解密(不少的文章說數據不能解密,我當時就納悶了,不能解密了那人家怎麼對你的數據進行校驗啊?在看了算法之後才明白,就是在甲方進行加密而後對乙方公佈加密的算法,而後乙方對得到的數據按照乙方給的算法進行數據的校對,經過這樣的機制進行數據的傳遞)。安全
在本項目中咱們主要應用的是AES算法+MD5+SHA算法對數據進行加解密。app
下面是主要用到的幾個類:dom
AES加密算法部分代碼ide
import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec;/** * 加密解密 */ public class AESUtil { public static String algorithm ="AES"; public static String enctrypt(String content,String password){ SecretKey key = getKey(algorithm,password); byte [] enCodeFormat = key.getEncoded(); SecretKeySpec ss = new SecretKeySpec(password.getBytes(), algorithm); try { IvParameterSpec iv = new IvParameterSpec(password.getBytes("UTF-8")); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, ss,iv); // cipher.init(Cipher.ENCRYPT_MODE, ss); byte b [] = cipher.doFinal(content.getBytes()); return byteToHex(b); } catch (Exception e) { LogCatLog.e("AES 加密失敗",e); } return null; } public static String decrypt(byte [] content,String password){ // SecretKey key = getKey(algorithm,password); // byte [] enCodeFormat = key.getEncoded(); SecretKeySpec ss = new SecretKeySpec(password.getBytes(), algorithm); try { IvParameterSpec iv = new IvParameterSpec(password.getBytes("UTF-8")); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, ss,iv); // cipher.init(Cipher.DECRYPT_MODE, ss); byte b [] = cipher.doFinal(content); return new String(b); } catch (Exception e) { LogCatLog.e("AES 解密失敗",e); } return null; } /** * 使用keygenerator 依賴平臺,致使Android和java加密出來的密文不一致 * * @param algorithm * @param password * @return */ public static SecretKey getKey(String algorithm,String password){ try { KeyGenerator gen = KeyGenerator.getInstance(algorithm); SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); secureRandom.setSeed(password.getBytes()); gen.init(128, secureRandom); // gen.init(128); return gen.generateKey(); } catch (NoSuchAlgorithmException e) { LogCatLog.e("getKey 獲取加密密鑰失敗 ",e); e.printStackTrace(); } return null; } private static String byteToHex(byte [] b){ StringBuilder sb = new StringBuilder(); for (int i = 0; i < b.length; i++) { String s = Integer.toHexString(b[i] & 0xFF); if(s.length()==1){ s = '0'+s; } sb.append(s.toUpperCase()); } return sb.toString(); } public static byte[] hexStrToByte(String hexStr) { if (hexStr == null || hexStr.equals("")) { return null; } hexStr = hexStr.toUpperCase(); int length = hexStr.length() / 2; char[] hexChars = hexStr.toCharArray(); byte[] d = new byte[length]; for (int i = 0; i < length; i++) { int pos = i * 2; d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1])); } return d; } private static byte charToByte(char c) { int index = "0123456789ABCDEF".indexOf(c); if(index==-1){ index = "0123456789abcdef".indexOf(c); } return (byte)index; } }
MD5算法部分代碼ui
import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.security.MessageDigest; /** * @Description 不解釋 */ public final class MD5Util { private static final char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'B', 'C', 'D', 'B', 'O', 'T', 'H', 'O', 'F', 'Y', 'O', 'U' }; /** 對文件加密 */ public static String encode(File file) { FileInputStream in = null; MessageDigest md5 = null; try { in = new FileInputStream(file); FileChannel ch = in.getChannel(); MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length()); md5 = MessageDigest.getInstance("MD5"); md5.update(byteBuffer); } catch (Exception e) { e.printStackTrace(); } finally { try { if(in != null) in.close(); } catch (IOException e) { e.printStackTrace(); } } return toHex(md5.digest()); } /** 對字符串加密 */ public static String encode(String arg) { if (arg == null) { arg = ""; } MessageDigest md5 = null; try { md5 = MessageDigest.getInstance("MD5"); md5.update(arg.getBytes("utf-8")); } catch (Exception e) { e.printStackTrace(); } return toHex(md5.digest()); } private static String toHex(byte[] bytes) { StringBuffer str = new StringBuffer(32); for (byte b : bytes) { str.append(hexDigits[(b & 0xf0) >> 4]); str.append(hexDigits[(b & 0x0f)]); } return str.toString(); } public static String md5_3(String arg) { if (arg == null) { arg = ""; } MessageDigest md5 = null; try { md5 = MessageDigest.getInstance("MD5"); byte[] a = md5.digest(arg.getBytes("utf-8")); a = md5.digest(a); md5.update(a); } catch (Exception e) { e.printStackTrace(); } return toHex(md5.digest()); } /** * MD5加密 以byte數組表示的字符串 * 結果與encode(String arg)返回的同樣 * * @param bytes 目標byte數組 * @return MD5加密後的字符串 */ public static String getMD5String(String str) { return getMD5String(str.getBytes()); } public static String getMD5String(byte[] bytes) { MessageDigest md5 = null; try { md5 = MessageDigest.getInstance("MD5"); md5.update(bytes); } catch (Exception e) { e.printStackTrace(); } return toHex(md5.digest()); } public static String toHex2(byte[] bytes){ StringBuffer sb = new StringBuffer(); for (int i = 0; i < bytes.length; i++) { String shex = Integer.toHexString(bytes[i] & 0xff); if(shex.length()==1){ shex='0'+shex; } sb.append(shex); } return sb.toString().toUpperCase(); } public static String getMD5StringQGen(String str) { MessageDigest md5 = null; try { md5 = MessageDigest.getInstance("MD5"); md5.update(str.getBytes()); } catch (Exception e) { e.printStackTrace(); } return toHex2(md5.digest()); } }