前言 按加密結(jié)果是否可以被解密分為可逆和不可逆: 1,不可逆: MD5(Message-Digest消息摘要):不可逆,長度固定(32位),容易計算,僅一字節(jié)只差加密結(jié)果都會有很大區(qū)別 通常情況下為了讓加密過程變得不可預(yù)測,我們會進(jìn)行加鹽操作。 SHA:安全散列算法,數(shù)字簽名工具 , 長度比MD5要長,所以更安全,但是加密的效率要比MD5慢一些. 2,可逆: 按秘鑰數(shù)量和加密規(guī)則分為:對稱加密和非對稱加密 1,對稱加密:即通過key加密,也可以通過key來解密 優(yōu)點:算法公開、計算量小、加密速度快、加密效率高 缺點:雙方都使用同樣的密鑰,密鑰可以自己指定,并且只有一把,如果密鑰泄漏數(shù)據(jù)就會被解密 DES,AES 高級加密標(biāo)準(zhǔn)(英語:Advanced Encryption Standard,縮寫:AES),在密碼學(xué)中又稱Rijndael加密法,是美國聯(lián)邦政府采用的一種區(qū)塊加密標(biāo)準(zhǔn)。 這個標(biāo)準(zhǔn)用來替代原先的DES,已經(jīng)被多方分析且廣為全世界所使用,Android 中的AES 加密 秘鑰 key 必須為16/24/32位字節(jié),否則拋異常。 2,非對稱加密:如RSA加密算法公鑰加密只能私鑰解密,私鑰加密也只能公鑰解密 RSA :他有兩把密鑰,且是由程序生成的,不能自己指定; 特點是加密速度比較慢,但是安全性比較高; 加密和解密的規(guī)則是:公鑰加密只能私鑰解密,私鑰加密只能公鑰解密; RSA對加密數(shù)據(jù)的長度有限制,一般為密鑰的長度值-11,要加密較長的數(shù)據(jù),可以采用數(shù)據(jù)截取的方法,分段加密。 RSA算法是最流行的公鑰密碼算法,使用長度可以變化的密鑰。RSA是第一個既能用于數(shù)據(jù)加密也能用于數(shù)字簽名的算法。 MD5加密 使用場景: 1.驗證密碼:只要算法不變,就能和服務(wù)器上的MD5匹配; 2.文件完整性的校驗:當(dāng)下載一個文件時,服務(wù)器返回的信息包括這個文件的md5,在本地下載完畢時進(jìn)行md5加密,將兩個md5值進(jìn)行比較,如果一致則說明文件完整沒有丟包現(xiàn)象。 /** * 使用md5方式進(jìn)行加密 * @return */ public static String digest(String content){ StringBuilder builder = new StringBuilder(); try { MessageDigest msgDitest = MessageDigest.getInstance("MD5"); msgDitest.update(content.getBytes()); byte[] digests = msgDitest.digest(); //將每個字節(jié)轉(zhuǎn)為16進(jìn)制 for (int i=0;i<digests.length;i++){ builder.append(Integer.toHexString(digests[i] & 0xff +8));//+8為加鹽操作 } } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return builder.toString(); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 SHA: 著名的圖片加載框架Glide在緩存key時就采用的此加密 文件的秒傳功能,以及相同的v4包沖突都是可以根據(jù)sha1值進(jìn)行比對的 /** * 使用sha-1方式進(jìn)行加密 * @return */ public static String digest(String content){ StringBuilder builder = new StringBuilder(); try { MessageDigest msgDitest = MessageDigest.getInstance("SHA-1"); msgDitest.update(content.getBytes()); byte[] digests = msgDitest.digest(); //將每個字節(jié)轉(zhuǎn)為16進(jìn)制 for (int i=0;i<digests.length;i++){ builder.append(Integer.toHexString(digests[i] & 0xff +8));//+8為加鹽操作 } } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return builder.toString(); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 DES String data = "我是俊哥"; String desKey = "青龍偃月刀";// 密鑰,口號 boolean isDesEncrypt = false; private void useDes() { try { if(isDesEncrypt){ //解密 text.setText(Des.decrypt(text.getText().toString(), desKey)); }else { //加密 text.setText(Des.encrypt(data, desKey)); } isDesEncrypt = !isDesEncrypt; } catch (Exception e) { e.printStackTrace(); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 AES AES加密是一種高級加密標(biāo)準(zhǔn),是一種區(qū)塊加密標(biāo)準(zhǔn)。它是一個對稱密碼,就是說加密和解密用相同的密鑰。WPA/WPA2經(jīng)常用的加密方式就是AES加密算法。 public class AESUtils3 { /* 算法/模式/填充 */ private static final String CipherMode = "AES/ECB/PKCS5Padding"; /* 創(chuàng)建密鑰 */ private static SecretKeySpec createKey(String password) { byte[] data = null; if (password == null) { password = ""; } StringBuffer sb = new StringBuffer(32); sb.append(password); while (sb.length() < 32) { sb.append("0"); } if (sb.length() > 32) { sb.setLength(32); } try { data = sb.toString().getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return new SecretKeySpec(data, "AES"); } /* 加密字節(jié)數(shù)據(jù) */ public static byte[] encrypt(byte[] content, String password) { try { SecretKeySpec key = createKey(password); System.out.println(key); Cipher cipher = Cipher.getInstance(CipherMode); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] result = cipher.doFinal(content); return result; } catch (Exception e) { e.printStackTrace(); } return null; } /*加密(結(jié)果為16進(jìn)制字符串) */ public static String encrypt(String content, String password) { byte[] data = null; try { data = content.getBytes("UTF-8"); } catch (Exception e) { e.printStackTrace(); } data = encrypt(data, password); String result = byte2hex(data); return result; } /*解密字節(jié)數(shù)組*/ public static byte[] decrypt(byte[] content, String password) { try { SecretKeySpec key = createKey(password); Cipher cipher = Cipher.getInstance(CipherMode); cipher.init(Cipher.DECRYPT_MODE, key); byte[] result = cipher.doFinal(content); return result; } catch (Exception e) { e.printStackTrace(); } return null; } /*解密16進(jìn)制的字符串為字符串 */ public static String decrypt(String content, String password) { byte[] data = null; try { data = hex2byte(content); } catch (Exception e) { e.printStackTrace(); } data = decrypt(data, password); if (data == null) return null; String result = null; try { result = new String(data, "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return result; } /*字節(jié)數(shù)組轉(zhuǎn)成16進(jìn)制字符串 */ public static String byte2hex(byte[] b) { // 一個字節(jié)的數(shù), StringBuffer sb = new StringBuffer(b.length * 2); String tmp = ""; for (int n = 0; n < b.length; n++) { // 整數(shù)轉(zhuǎn)成十六進(jìn)制表示 tmp = (java.lang.Integer.toHexString(b[n] & 0XFF)); if (tmp.length() == 1) { sb.append("0"); } sb.append(tmp); } return sb.toString().toUpperCase(); // 轉(zhuǎn)成大寫 } /*將hex字符串轉(zhuǎn)換成字節(jié)數(shù)組 */ private static byte[] hex2byte(String inputString) { if (inputString == null || inputString.length() < 2) { return new byte[0]; } inputString = inputString.toLowerCase(); int l = inputString.length() / 2; byte[] result = new byte[l]; for (int i = 0; i < l; ++i) { String tmp = inputString.substring(2 * i, 2 * i + 2); result[i] = (byte) (Integer.parseInt(tmp, 16) & 0xFF); } return result; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 RSA 文件或數(shù)據(jù)在本地使用公鑰或私鑰加密,加密后的數(shù)據(jù)傳送到服務(wù)器,服務(wù)器使用同一套密鑰中的私鑰或者公鑰進(jìn)行解密。 public class RSAUtils { //構(gòu)建Cipher實例時所傳入的的字符串,默認(rèn)為"RSA/NONE/PKCS1Padding" private static String sTransform = "RSA/NONE/PKCS1Padding"; //進(jìn)行Base64轉(zhuǎn)碼時的flag設(shè)置,默認(rèn)為Base64.DEFAULT private static int sBase64Mode = Base64.DEFAULT; //初始化方法,設(shè)置參數(shù) public static void init(String transform, int base64Mode) { sTransform = transform; sBase64Mode = base64Mode; } //產(chǎn)生密鑰對 public static KeyPair generateRSAKeyPair(int keyLength) { KeyPair keyPair = null; try { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); //設(shè)置密鑰長度 keyPairGenerator.initialize(keyLength); //產(chǎn)生密鑰對 keyPair = keyPairGenerator.generateKeyPair(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return keyPair; } /** * 加密或解密數(shù)據(jù)的通用的方法,srcData:待處理的數(shù)據(jù);key:公鑰或者私鑰,mode指 * 加密還是解密,值為Cipher.ENCRYPT_MODE或者Cipher.DECRYPT_MODE */ public static byte[] processDAta(byte[] srcData, Key key, int mode) { //用來保存處理的結(jié)果 byte[] resultBytes = null; //構(gòu)建Cipher對象,需要傳入一個字符串,格式必須為"algorithm/mode/padding"或者"algorithm/",意為"算法/加密模式/填充方式" try { Cipher cipher = Cipher.getInstance("RSA/NONE/PKCS1Padding"); //初始化Cipher,mode指定是加密還是解密,key為公鑰或密鑰 cipher.init(mode, key); //處理數(shù)據(jù) resultBytes = cipher.doFinal(srcData); } catch (Exception e) { e.printStackTrace(); } return resultBytes; } //使用公鑰加密數(shù)據(jù),結(jié)果用Base64轉(zhuǎn)碼 public static String encryptDataByPublicKey(byte[] srcData, PublicKey publicKey) { byte[] resultBytes = processDAta(srcData, publicKey, Cipher.ENCRYPT_MODE); return Base64.encodeToString(resultBytes, sBase64Mode); } //使用私鑰解密,結(jié)果用Base64轉(zhuǎn)碼 public static byte[] decryptDataByPrivate(String encryptedData, PrivateKey privateKey) { byte[] bytes = Base64.decode(encryptedData, sBase64Mode); return processDAta(bytes, privateKey, Cipher.DECRYPT_MODE); } //使用私鑰解密,返回解碼數(shù)據(jù) public static String decryptToStrByPrivate(String encryptedData, PrivateKey privateKey) { return new String(decryptDataByPrivate(encryptedData, privateKey)); } } ———————————————— 版權(quán)聲明:本文為CSDN博主「智玲君」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。 原文鏈接:https://blog.csdn.net/gpf1320253667/article/details/86218393 |
|