Android中的加密解密安全

0x01不安全的加密hash函数


常见的hash函数,像md5,sha1,sha256,它们都是不可逆加密函数。
由于计算机运算能力的提高,md5和sha1函数现在都有比较成熟的破解方法,像彩虹表,字典库等,故建议使用安全的sha256函数对message字符串做哈希。sha256函数在java中的使用方法,参考代码如下。

package com.pc.test;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Encrypt {

	public static String SHA256(final String strText) {
		return SHA(strText, "SHA-256");
	}
	private static String SHA(final String strText, final String strType) {
		String strResult = null;
		if (strText != null && strText.length() > 0) {
			try {
				MessageDigest messageDigest = MessageDigest
						.getInstance(strType);
				messageDigest.update(strText.getBytes());
				byte byteBuffer[] = messageDigest.digest();

				StringBuffer strHexString = new StringBuffer();
				for (int i = 0; i < byteBuffer.length; i++) {
					String hex = Integer.toHexString(0xff & byteBuffer[i]);
					if (hex.length() == 1) {
						strHexString.append('0');
					}
					strHexString.append(hex);
				}
				strResult = strHexString.toString();
			} catch (NoSuchAlgorithmException e) {
				e.printStackTrace();
			}
		}
		return strResult;
	}
	public static void main(String[] args) throws Exception{
		String str = "admin";
		System.out.println(SHA256(str));
		//result: 8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918
	}
}

0x02安全随机数的生成

在Android加密算法中需要随机数时要使用SecureRandom来获取随机数。注意不要使用Random类来获取随机数,且使用SecureRandom获取随机数时不要设置种子。代码示例如下。

SecureRandom random = new SecureRandom();
		byte bytes[] = new byte[20];
		random.nextBytes(bytes);

0x03对称加密算法DES/AES安全

在使用对称加密算法的过程中,使用DES/AES和AES的AES/EBC/PKCS5Padding模式都是不安全的,(AES默认模式是ECB模式),所以我们要使用安全的对称加密函数AES/CBC/PKCS5Padding模式。使用这些加密函数的过程中,当密钥硬编码程序中时,密钥很容易通过反编译被还原,不建议密钥硬编码在代码中,可以通过白盒加密的方式进行加密,可以调用阿里云开发的安全组件进行相应的安全防护是一个比较好的防御方式。

下面重点说一下加密函数的用法代码

DES对称加密算法的使用

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.pc.destest;  
  2.   
  3. import java.security.Key;  
  4. import java.security.SecureRandom;  
  5. import javax.crypto.Cipher;  
  6. import javax.crypto.SecretKey;  
  7. import javax.crypto.SecretKeyFactory;  
  8. import javax.crypto.spec.DESKeySpec;  
  9.   
  10.   
  11. public class DesTest{  
  12.       
  13.     //DES加密  
  14.     public static byte[] encrypt(byte[] datasource, String password) throws Exception {   
  15.           
  16.   
  17.         SecureRandom random = new SecureRandom();  
  18.         Key key = toKey(password.getBytes());  
  19.         Cipher cipher = Cipher.getInstance("DES");  
  20.         cipher.init(Cipher.ENCRYPT_MODE, key,random);  
  21.         return cipher.doFinal(datasource);  
  22.         }  
  23.       
  24.     //DES解密  
  25.     public static byte[] decrypt(byte[] src, String password) throws Exception {  
  26.           
  27.     SecureRandom random = new SecureRandom();  
  28.     Key key = toKey(password.getBytes());  
  29.     Cipher cipher = Cipher.getInstance("DES");  
  30.     cipher.init(Cipher.DECRYPT_MODE, key,random);  
  31.     return cipher.doFinal(src);  
  32.     }  
  33.       
  34.     private static Key toKey(byte[] key) throws Exception {  
  35.   
  36.         DESKeySpec dks = new DESKeySpec(key);    
  37.         SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");    
  38.         SecretKey secretKey = keyFactory.generateSecret(dks);    
  39.   
  40.         return secretKey;  
  41.     }  
  42.     //二进制转换为字符串  
  43.     private static String byte2String(byte[] b) {  
  44.         StringBuilder hs = new StringBuilder();  
  45.         String stmp;  
  46.         for (int n = 0; b != null && n < b.length; n++) {  
  47.             stmp = Integer.toHexString(b[n] & 0XFF);  
  48.             if (stmp.length() == 1)  
  49.                 hs.append('0');  
  50.             hs.append(stmp);  
  51.         }  
  52.         return hs.toString();  
  53.     }  
  54.     //字符串转换为二进制  
  55.     private static byte[] str2Byte(String strIn) throws NumberFormatException {  
  56.             byte[] arrB = strIn.getBytes();  
  57.             int iLen = arrB.length;  
  58.             byte[] arrOut = new byte[iLen / 2];  
  59.             for (int i = 0; i < iLen; i = i + 2) {  
  60.                 String strTmp = new String(arrB, i, 2);  
  61.                 arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16);  
  62.             }  
  63.             return arrOut;  
  64.         }  
  65.       
  66.   
  67.     public static void main(String[] args) throws Exception {  
  68.         String str = "abddddc123tesaabbc";  
  69.      
  70.         String password = "1234567890ABCDEF";  
  71.           
  72.         System.out.println("加密前:" + str);  
  73.         byte[] result = DesTest.encrypt(str.getBytes(),password);  
  74.         String res = byte2String(result);  
  75.         System.out.println("加密后:"+res);  
  76.   
  77.         byte[] decryResult = DesTest.decrypt(str2Byte(res), password);  
  78.         System.out.println("解密后:"+new String(decryResult));  
  79.   
  80.         }  
  81.   
  82. }  

算法运行结果

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. 加密前:abddddc123tesaabbc  
  2. 加密后:57990b25549a0ff8ab57b2ba08175546210a01e2dee06bee  
  3. 解密后:abddddc123tesaabbc  

AES对称加密算法使用及代码

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.pc.aestest;  
  2.   
  3. import java.security.Key;  
  4. import java.security.SecureRandom;  
  5.   
  6. import javax.crypto.Cipher;  
  7. import javax.crypto.SecretKey;  
  8. import javax.crypto.spec.SecretKeySpec;  
  9.   
  10.   
  11. public class AesTest{  
  12.       
  13.     //AES加密  
  14.     public static byte[] encrypt(byte[] datasource, String password) throws Exception {   
  15.           
  16.   
  17.         SecureRandom random = new SecureRandom();  
  18.         Key key = toKey(password.getBytes());  
  19.         Cipher cipher = Cipher.getInstance("AES");  
  20.         cipher.init(Cipher.ENCRYPT_MODE, key,random);  
  21.         return cipher.doFinal(datasource);  
  22.         }  
  23.       
  24.     //AES解密  
  25.     public static byte[] decrypt(byte[] src, String password) throws Exception {  
  26.           
  27.     SecureRandom random = new SecureRandom();  
  28.     Key key = toKey(password.getBytes());  
  29.     Cipher cipher = Cipher.getInstance("AES");  
  30.     cipher.init(Cipher.DECRYPT_MODE, key,random);  
  31.     return cipher.doFinal(src);  
  32.     }  
  33.       
  34.     private static Key toKey(byte[] key) throws Exception {  
  35.   
  36.         SecretKey secretKey = new SecretKeySpec(key, "AES");   
  37.         return secretKey;  
  38.     }  
  39.     //二进制转换为字符串  
  40.     private static String byte2String(byte[] b) {  
  41.         StringBuilder hs = new StringBuilder();  
  42.         String stmp;  
  43.         for (int n = 0; b != null && n < b.length; n++) {  
  44.             stmp = Integer.toHexString(b[n] & 0XFF);  
  45.             if (stmp.length() == 1)  
  46.                 hs.append('0');  
  47.             hs.append(stmp);  
  48.         }  
  49.         return hs.toString();  
  50.     }  
  51.     //字符串转换为二进制  
  52.     private static byte[] str2Byte(String strIn) throws NumberFormatException {  
  53.             byte[] arrB = strIn.getBytes();  
  54.             int iLen = arrB.length;  
  55.             byte[] arrOut = new byte[iLen / 2];  
  56.             for (int i = 0; i < iLen; i = i + 2) {  
  57.                 String strTmp = new String(arrB, i, 2);  
  58.                 arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16);  
  59.             }  
  60.             return arrOut;  
  61.         }  
  62.       
  63.   
  64.     public static void main(String[] args) throws Exception {  
  65.         String str = "abddddc123tesaabbc";  
  66.      
  67.         String password = "1234567890ABCDEF";  
  68.           
  69.         System.out.println("加密前:" + str);  
  70.         byte[] result = AesTest.encrypt(str.getBytes(),password);  
  71.         String res = byte2String(result);  
  72.         System.out.println("加密后:"+res);  
  73.   
  74.         byte[] decryResult = AesTest.decrypt(str2Byte(res), password);  
  75.         System.out.println("解密后:"+new String(decryResult));  
  76.   
  77.         }  
  78.   
  79. }  

运算结果

[plain]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. 加密前:abddddc123tesaabbc  
  2. 加密后:6ce0add18dbcdc4a8394db087ea7da6a46afc04fc4a2728c8a9ea7b0bb5a38d2  
  3. 解密后:abddddc123tesaabbc  

AES的ECB加密算法使用代码

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.pc.aestest;  
  2.   
  3.   
  4. import java.security.Key;  
  5. import java.security.SecureRandom;  
  6. import javax.crypto.Cipher;  
  7. import javax.crypto.SecretKey;  
  8. import javax.crypto.spec.SecretKeySpec;  
  9.   
  10.   
  11. public class AesTestECB{  
  12.       
  13.     //AES的ECB模式加密  
  14.     public static byte[] encrypt(byte[] datasource, String password) throws Exception {   
  15.           
  16.         SecureRandom random = new SecureRandom();  
  17.         Key key = toKey(password.getBytes());  
  18.         Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");  
  19.         cipher.init(Cipher.ENCRYPT_MODE, key,random);  
  20.         return cipher.doFinal(datasource);  
  21.         }  
  22.       
  23.     //AES的ECB模式解密  
  24.     public static byte[] decrypt(byte[] src, String password) throws Exception {  
  25.           
  26.     SecureRandom random = new SecureRandom();  
  27.     Key key = toKey(password.getBytes());  
  28.     Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");  
  29.     cipher.init(Cipher.DECRYPT_MODE, key,random);  
  30.     return cipher.doFinal(src);  
  31.     }  
  32.       
  33.     private static Key toKey(byte[] key) throws Exception {  
  34.   
  35.        SecretKey secretKey = new SecretKeySpec(key, "AES");   
  36.   
  37.         return secretKey;  
  38.     }  
  39.     //二进制转换为字符串  
  40.     private static String byte2String(byte[] b) {  
  41.         StringBuilder hs = new StringBuilder();  
  42.         String stmp;  
  43.         for (int n = 0; b != null && n < b.length; n++) {  
  44.             stmp = Integer.toHexString(b[n] & 0XFF);  
  45.             if (stmp.length() == 1)  
  46.                 hs.append('0');  
  47.             hs.append(stmp);  
  48.         }  
  49.         return hs.toString();  
  50.     }  
  51.     //字符串转换为二进制  
  52.     private static byte[] str2Byte(String strIn) throws NumberFormatException {  
  53.             byte[] arrB = strIn.getBytes();  
  54.             int iLen = arrB.length;  
  55.             byte[] arrOut = new byte[iLen / 2];  
  56.             for (int i = 0; i < iLen; i = i + 2) {  
  57.                 String strTmp = new String(arrB, i, 2);  
  58.                 arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16);  
  59.             }  
  60.             return arrOut;  
  61.         }  
  62.       
  63.   
  64.     public static void main(String[] args) throws Exception {  
  65.         String str = "abddddc123tesaabbc";  
  66.      
  67.         String password = "1234567890ABCDEF";  
  68.           
  69.         System.out.println("加密前:" + str);  
  70.         byte[] result = AesTestECB.encrypt(str.getBytes(),password);  
  71.         String res = byte2String(result);  
  72.         System.out.println("加密后:"+res);  
  73.   
  74.         byte[] decryResult = AesTestECB.decrypt(str2Byte(res), password);  
  75.   
  76.         System.out.println("解密后:"+new String(decryResult));  
  77.     }  
  78. }  

运算结果,根据运算结果可知AES算法默认使用的是ECB模式

[plain]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. 加密前:abddddc123tesaabbc  
  2. 加密后:6ce0add18dbcdc4a8394db087ea7da6a46afc04fc4a2728c8a9ea7b0bb5a38d2  
  3. 解密后:abddddc123tesaabbc  

AES的CBC模式加密算法代码,建议使用这一种模式的对称加密算法,这种模式的使用是安全。


[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.pc.aestest;  
  2.   
  3. import java.security.Key;  
  4. import java.security.Security;  
  5. import javax.crypto.Cipher;  
  6. import javax.crypto.SecretKey;  
  7. import javax.crypto.spec.IvParameterSpec;  
  8. import javax.crypto.spec.SecretKeySpec;  
  9.   
  10. import org.bouncycastle.jce.provider.BouncyCastleProvider;  
  11.   
  12.   
  13. public class AesTestCBC{  
  14.       
  15.     public static boolean initialized = false;  
  16.     //AES加密CBC模式  
  17.     public static byte[] encrypt(byte[] datasource, String password) throws Exception {   
  18.           
  19.         initialize();    
  20.         Key key = toKey(password.getBytes());  
  21.         Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding","BC");  
  22.         IvParameterSpec iv = new IvParameterSpec("1234567890123456".getBytes());  
  23.   
  24.         cipher.init(Cipher.ENCRYPT_MODE, key,iv);  
  25.         return cipher.doFinal(datasource);  
  26.         }  
  27.       
  28.     //AES解密CBC模式  
  29.     public static byte[] decrypt(byte[] src, String password) throws Exception {  
  30.           
  31.     initialize();    
  32.     Key key = toKey(password.getBytes());  
  33.   
  34.     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");  
  35.     IvParameterSpec iv = new IvParameterSpec("1234567890123456".getBytes());  
  36.     cipher.init(Cipher.DECRYPT_MODE, key,iv);  
  37.     return cipher.doFinal(src);  
  38.     }  
  39.       
  40.     private static Key toKey(byte[] key) throws Exception {  
  41.   
  42.         SecretKey secretKey = new SecretKeySpec(key, "AES");   
  43.         return secretKey;  
  44.     }  
  45.     //二进制转换为字符串  
  46.     private static String byte2String(byte[] b) {  
  47.         StringBuilder hs = new StringBuilder();  
  48.         String stmp;  
  49.         for (int n = 0; b != null && n < b.length; n++) {  
  50.             stmp = Integer.toHexString(b[n] & 0XFF);  
  51.             if (stmp.length() == 1)  
  52.                 hs.append('0');  
  53.             hs.append(stmp);  
  54.         }  
  55.         return hs.toString();  
  56.     }  
  57.     //字符串转换为二进制  
  58.     private static byte[] str2Byte(String strIn) throws NumberFormatException {  
  59.             byte[] arrB = strIn.getBytes();  
  60.             int iLen = arrB.length;  
  61.             byte[] arrOut = new byte[iLen / 2];  
  62.             for (int i = 0; i < iLen; i = i + 2) {  
  63.                 String strTmp = new String(arrB, i, 2);  
  64.                 arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16);  
  65.             }  
  66.             return arrOut;  
  67.         }  
  68.       
  69.   
  70.     public static void main(String[] args) throws Exception {  
  71.         String str = "abddddc123tesaa";  
  72.      
  73.         String password = "1234567890ABCDEF";  
  74.           
  75.         System.out.println("加密前:" + str);  
  76.         byte[] result = AesTest.encrypt(str.getBytes(),password);  
  77.         String res = byte2String(result);  
  78.         System.out.println("加密后:"+res);  
  79.   
  80.         byte[] decryResult = AesTest.decrypt(str2Byte(res), password);  
  81.         System.out.println("解密后:"+new String(decryResult));  
  82.   
  83.         }  
  84.   
  85.     public static void initialize(){  
  86.         if (initialized) return;  
  87.         Security.addProvider(new BouncyCastleProvider());  
  88.         initialized = true;  
  89.     }  
  90.   
  91. }  

运算结果

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. 加密前:abddddc123tesaa  
  2. 加密后:647c5546059c44d2d35b9b38e52fc6e9  
  3. 解密后:abddddc123tesaa  


0x04 RSA非对称加密算法

RSA非对称加密算法既可以用于非对称加密,又可以用户签名算法。由于在相应的时间方面远远大于对称加密算法,故用户加密少量的数据或用与签名,下面的链接中展示了既可以进行非对称加密,又可以用于签名的java代码,在这里就不再重复贴出。详情见下面的链接RSA非对称加密和签名算法。




参考链接:

RSA非对称加密算法及签名

http://blog.csdn.net/wangqiuyun/article/details/42143957/

http://snowolf.iteye.com/blog/381767


java加密解密的艺术

http://snowolf.iteye.com/blog/379860

猜你喜欢

转载自blog.csdn.net/nextdoor6/article/details/52816490
今日推荐