1.不可逆的算法
主要為MD5和SHA-1算法。(二者都不屬於加密只能算作一種算法)
相同點:都是使用目前比較廣泛的散列(Hash)函數,就是把任意長度的輸入,變換成固定長度的輸出,該輸出就是散列值。計算的時候所有的數據都參與了運算,其中任何一個數據變化了都會導致計算出來的Hash值完全不同。(理論上來講產生的密文都有可能產生碰撞)
不同點:MD5輸出是128位的,SHA-1輸出是160位的,MD5比SHA1運行速度快,SHA1比MD5強度高。MD5一般用於文件的校驗,SHA-1主要使用於數字簽名標准。
MD5使用:
1 public static String digest(String content){ 2 StringBuilder builder = new StringBuilder(); 3 try { 4 MessageDigest msgDitest = MessageDigest.getInstance("MD5"); 5 msgDitest.update(content.getBytes()); 6 byte[] digests = msgDitest.digest(); 7 //將每個字節轉為16進制 8 for (int i=0;i<digests.length;i++){ 9 // TODO: 2019/11/10 需要再了解一下 10 builder.append(Integer.toHexString(digests[i] & 0xff +8));//+8為加鹽操作 11 } 12 } catch (NoSuchAlgorithmException e) { 13 e.printStackTrace(); 14 } 15 return builder.toString(); 16 }
SHA-1使用:
1 public static String sha1Digest(String content){ 2 StringBuilder builder = new StringBuilder(); 3 try { 4 MessageDigest msgDitest = MessageDigest.getInstance("SHA-1"); 5 msgDitest.update(content.getBytes()); 6 byte[] digests = msgDitest.digest(); 7 //將每個字節轉為16進制 8 for (int i=0;i<digests.length;i++){ 9 // TODO: 2019/11/10 再了解一下 10 builder.append(Integer.toHexString(digests[i] & 0xff +8));//+8為加鹽操作 11 } 12 } catch (NoSuchAlgorithmException e) { 13 e.printStackTrace(); 14 } 15 return builder.toString(); 16 }
2.可逆算法
其中可逆算法按照密鑰的數量和加密規則又分為對稱加密和非對稱加密。
(1)對稱加密
密鑰可以自己指定,只有一把密鑰。常用的對稱加密算法有DES和AES兩種。對稱加密的速度快,但是缺點是安全性低,因為只要密鑰暴漏,數據就可以被解密。
AES加密解密使用:

1 package com.cn; 2 3 import sun.misc.BASE64Decoder; 4 import sun.misc.BASE64Encoder; 5 6 import javax.crypto.*; 7 import javax.crypto.spec.SecretKeySpec; 8 import java.io.IOException; 9 import java.io.UnsupportedEncodingException; 10 import java.security.InvalidKeyException; 11 import java.security.NoSuchAlgorithmException; 12 import java.security.SecureRandom; 13 import java.util.Scanner; 14 15 public class SymmetricEncoder { 16 /* 17 * 加密 18 * 1.構造密鑰生成器 19 * 2.根據ecnodeRules規則初始化密鑰生成器 20 * 3.產生密鑰 21 * 4.創建和初始化密碼器 22 * 5.內容加密 23 * 6.返回字符串 24 */ 25 public static String AESEncode(String encodeRules,String content){ 26 try { 27 //1.構造密鑰生成器,指定為AES算法,不區分大小寫 28 KeyGenerator keygen=KeyGenerator.getInstance("AES"); 29 //2.根據ecnodeRules規則初始化密鑰生成器 30 //生成一個128位的隨機源,根據傳入的字節數組 31 keygen.init(128, new SecureRandom(encodeRules.getBytes())); 32 //3.產生原始對稱密鑰 33 SecretKey original_key=keygen.generateKey(); 34 //4.獲得原始對稱密鑰的字節數組 35 byte [] raw=original_key.getEncoded(); 36 //5.根據字節數組生成AES密鑰 37 SecretKey key=new SecretKeySpec(raw, "AES"); 38 //6.根據指定算法AES自成密碼器 39 Cipher cipher=Cipher.getInstance("AES"); 40 //7.初始化密碼器,第一個參數為加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二個參數為使用的KEY 41 cipher.init(Cipher.ENCRYPT_MODE, key); 42 //8.獲取加密內容的字節數組(這里要設置為utf-8)不然內容中如果有中文和英文混合中文就會解密為亂碼 43 byte [] byte_encode=content.getBytes("utf-8"); 44 //9.根據密碼器的初始化方式--加密:將數據加密 45 byte [] byte_AES=cipher.doFinal(byte_encode); 46 //10.將加密后的數據轉換為字符串 47 //這里用Base64Encoder中會找不到包 48 //解決辦法: 49 //在項目的Build path中先移除JRE System Library,再添加庫JRE System Library,重新編譯后就一切正常了。 50 String AES_encode=new String(new BASE64Encoder().encode(byte_AES)); 51 //11.將字符串返回 52 return AES_encode; 53 } catch (NoSuchAlgorithmException e) { 54 e.printStackTrace(); 55 } catch (NoSuchPaddingException e) { 56 e.printStackTrace(); 57 } catch (InvalidKeyException e) { 58 e.printStackTrace(); 59 } catch (IllegalBlockSizeException e) { 60 e.printStackTrace(); 61 } catch (BadPaddingException e) { 62 e.printStackTrace(); 63 } catch (UnsupportedEncodingException e) { 64 e.printStackTrace(); 65 } 66 67 //如果有錯就返加null 68 return null; 69 } 70 /* 71 * 解密 72 * 解密過程: 73 * 1.同加密1-4步 74 * 2.將加密后的字符串反紡成byte[]數組 75 * 3.將加密內容解密 76 */ 77 public static String AESDncode(String encodeRules,String content){ 78 try { 79 //1.構造密鑰生成器,指定為AES算法,不區分大小寫 80 KeyGenerator keygen=KeyGenerator.getInstance("AES"); 81 //2.根據ecnodeRules規則初始化密鑰生成器 82 //生成一個128位的隨機源,根據傳入的字節數組 83 keygen.init(128, new SecureRandom(encodeRules.getBytes())); 84 //3.產生原始對稱密鑰 85 SecretKey original_key=keygen.generateKey(); 86 //4.獲得原始對稱密鑰的字節數組 87 byte [] raw=original_key.getEncoded(); 88 //5.根據字節數組生成AES密鑰 89 SecretKey key=new SecretKeySpec(raw, "AES"); 90 //6.根據指定算法AES自成密碼器 91 Cipher cipher=Cipher.getInstance("AES"); 92 //7.初始化密碼器,第一個參數為加密(Encrypt_mode)或者解密(Decrypt_mode)操作,第二個參數為使用的KEY 93 cipher.init(Cipher.DECRYPT_MODE, key); 94 //8.將加密並編碼后的內容解碼成字節數組 95 byte [] byte_content= new BASE64Decoder().decodeBuffer(content); 96 /* 97 * 解密 98 */ 99 byte [] byte_decode=cipher.doFinal(byte_content); 100 String AES_decode=new String(byte_decode,"utf-8"); 101 return AES_decode; 102 } catch (NoSuchAlgorithmException e) { 103 e.printStackTrace(); 104 } catch (NoSuchPaddingException e) { 105 e.printStackTrace(); 106 } catch (InvalidKeyException e) { 107 e.printStackTrace(); 108 } catch (IOException e) { 109 e.printStackTrace(); 110 } catch (IllegalBlockSizeException e) { 111 e.printStackTrace(); 112 } catch (BadPaddingException e) { 113 e.printStackTrace(); 114 } 115 116 //如果有錯就返加null 117 return null; 118 } 119 120 public static void main(String[] args) { 121 SymmetricEncoder se=new SymmetricEncoder(); 122 Scanner scanner=new Scanner(System.in); 123 /* 124 * 加密 125 */ 126 System.out.println("使用AES對稱加密,請輸入加密的規則"); 127 String encodeRules=scanner.next(); 128 System.out.println("請輸入要加密的內容:"); 129 String content = scanner.next(); 130 System.out.println("根據輸入的規則"+encodeRules+"加密后的密文是:"+se.AESEncode(encodeRules, content)); 131 132 /* 133 * 解密 134 */ 135 System.out.println("使用AES對稱解密,請輸入加密的規則:(須與加密相同)"); 136 encodeRules=scanner.next(); 137 System.out.println("請輸入要解密的內容(密文):"); 138 content = scanner.next(); 139 System.out.println("根據輸入的規則"+encodeRules+"解密后的明文是:"+se.AESDncode(encodeRules, content)); 140 } 141 }
DES加密解密使用:

1 package com.cn; 2 3 import javax.crypto.*; 4 import javax.crypto.spec.DESKeySpec; 5 import java.security.InvalidAlgorithmParameterException; 6 import java.security.InvalidKeyException; 7 import java.security.NoSuchAlgorithmException; 8 import java.security.SecureRandom; 9 import java.security.spec.InvalidKeySpecException; 10 11 public class DESUtil { 12 public static byte[] encode(String mes) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidKeySpecException, InvalidAlgorithmParameterException { 13 SecureRandom random = new SecureRandom(); 14 // TODO: 2019/11/10 密鑰長度應該是要大於8 15 DESKeySpec desKey = new DESKeySpec("123abc123".getBytes()); 16 //創建一個密匙工廠,然后用它把DESKeySpec轉換成 17 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); 18 SecretKey securekey = keyFactory.generateSecret(desKey); 19 //Cipher對象實際完成加密操作 20 Cipher cipher = Cipher.getInstance("DES"); 21 //用密匙初始化Cipher對象 22 cipher.init(Cipher.ENCRYPT_MODE, securekey, random); 23 return cipher.doFinal(mes.getBytes()); 24 } 25 26 public static byte[] decode(byte[] encodeBytes) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException { 27 // DES算法要求有一個可信任的隨機數源 28 SecureRandom random = new SecureRandom(); 29 // 創建一個DESKeySpec對象 30 DESKeySpec desKey = new DESKeySpec("123abc123".getBytes()); 31 // 創建一個密匙工廠 32 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); 33 // 將DESKeySpec對象轉換成SecretKey對象 34 SecretKey securekey = keyFactory.generateSecret(desKey); 35 // Cipher對象實際完成解密操作 36 Cipher cipher = Cipher.getInstance("DES"); 37 // 用密匙初始化Cipher對象 38 cipher.init(Cipher.DECRYPT_MODE, securekey, random); 39 // 真正開始解密操作 40 return cipher.doFinal(encodeBytes); 41 } 42 }
(2)非對稱加密
常見的非對稱加密算法是RSA;他有兩把密鑰,且是由程序生成的,不能自己指定;特點是加密速度比較慢,但是安全性比較高;加密和解密的規則是:公鑰加密只能私鑰解密,私鑰加密只能公鑰解密。

1 package com.cn; 2 3 import android.util.Base64; 4 5 import javax.crypto.Cipher; 6 import java.security.*; 7 import java.security.interfaces.RSAPrivateKey; 8 import java.security.interfaces.RSAPublicKey; 9 import java.security.spec.PKCS8EncodedKeySpec; 10 import java.security.spec.X509EncodedKeySpec; 11 import java.util.HashMap; 12 import java.util.Map; 13 14 public class RSAUtil { 15 private static Map<Integer, String> keyMap = new HashMap<Integer, String>(); //用於封裝隨機產生的公鑰與私鑰 16 public static void main(String[] args) throws Exception { 17 //生成公鑰和私鑰 18 genKeyPair(); 19 //加密字符串 20 String message = "abc12301230"; 21 System.out.println("隨機生成的公鑰為:" + keyMap.get(0)); 22 System.out.println("隨機生成的私鑰為:" + keyMap.get(1)); 23 String messageEn = encrypt(message,keyMap.get(0)); 24 System.out.println(message + "\t加密后的字符串為:" + messageEn); 25 String messageDe = decrypt(messageEn,keyMap.get(1)); 26 System.out.println("還原后的字符串為:" + messageDe); 27 } 28 29 /** 30 * 隨機生成密鑰對 31 * @throws NoSuchAlgorithmException 32 */ 33 public static void genKeyPair() throws NoSuchAlgorithmException { 34 // KeyPairGenerator類用於生成公鑰和私鑰對,基於RSA算法生成對象 35 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); 36 // 初始化密鑰對生成器,密鑰大小為96-1024位 37 keyPairGen.initialize(1024,new SecureRandom()); 38 // 生成一個密鑰對,保存在keyPair中 39 KeyPair keyPair = keyPairGen.generateKeyPair(); 40 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到私鑰 41 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 得到公鑰 42 String publicKeyString = new String(Base64.encode(publicKey.getEncoded(), 0)); 43 // 得到私鑰字符串 44 String privateKeyString = new String(Base64.encode(privateKey.getEncoded(), 0)); 45 // 將公鑰和私鑰保存到Map 46 keyMap.put(0,publicKeyString); //0表示公鑰 47 keyMap.put(1,privateKeyString); //1表示私鑰 48 } 49 /** 50 * RSA公鑰加密 51 * 52 * @param str 53 * 加密字符串 54 * @param publicKey 55 * 公鑰 56 * @return 密文 57 * @throws Exception 58 * 加密過程中的異常信息 59 */ 60 public static String encrypt(String str, String publicKey) throws Exception{ 61 //base64編碼的公鑰 62 byte[] decoded = Base64.decode(publicKey, 0); 63 RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded)); 64 //RSA加密 65 Cipher cipher = Cipher.getInstance("RSA"); 66 cipher.init(Cipher.ENCRYPT_MODE, pubKey); 67 String outStr = new String(Base64.encode(cipher.doFinal(str.getBytes("UTF-8")), 0)); 68 return outStr; 69 } 70 71 /** 72 * RSA私鑰解密 73 * 74 * @param str 75 * 加密字符串 76 * @param privateKey 77 * 私鑰 78 * @return 銘文 79 * @throws Exception 80 * 解密過程中的異常信息 81 */ 82 public static String decrypt(String str, String privateKey) throws Exception{ 83 //64位解碼加密后的字符串 84 byte[] inputByte = Base64.decode(str.getBytes(), 0); 85 //base64編碼的私鑰 86 byte[] decoded = Base64.decode(privateKey, 0); 87 RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded)); 88 //RSA解密 89 Cipher cipher = Cipher.getInstance("RSA"); 90 cipher.init(Cipher.DECRYPT_MODE, priKey); 91 String outStr = new String(cipher.doFinal(inputByte)); 92 return outStr; 93 } 94 }
// TODO AES加密模式, padding填充模式??
參考資料:https://www.cnblogs.com/yegong0214/p/6498409.html
https://blog.csdn.net/u011897782/article/details/81163387
https://blog.csdn.net/joshho/article/details/88716314
https://www.cnblogs.com/jying/p/9511247.html
https://blog.csdn.net/qy20115549/article/details/83105736
// TODO
https://www.cnblogs.com/think-in-java/p/5527389.html