Android常見的加密和算法


  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 }
View Code

   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 }
View Code

  (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 }
View Code

  // 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

 

  

 

    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM