zoukankan      html  css  js  c++  java
  • Android接口安全

    转载请注明出处:

    http://blog.csdn.net/aa464971/article/details/51034462


    本文以Androidclient加密提交数据到Java服务端后进行解密为样例。


    生成RSA公钥和密钥的方法请參考:

    http://blog.csdn.net/aa464971/article/details/51035200


    Android端的加密思路须要4步:

    1.生成AES密钥;

    2.使用RSA公钥加密刚刚生成的AES密钥;

    3.再使用第1步生成的AES密钥,通过AES加密须要提交给服务端的数据;

    4.将第2与第3生成的内容传给服务端。


    JAVA服务端的解密思路仅仅需3步:

    1.获取到client传过来的AES密钥密文和内容密文;

    2.使用RSA私钥解密从client拿到的AES密钥密文。

    3.再使用第2步解密出来的明文密钥。通过AES解密内容的密文。


    AES的代码能够在JAVA和Android上通用

    package com.dyhdyh.encrypt;
    
    import java.io.UnsupportedEncodingException;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    
    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    
    /**
     * AES
     * @author dengyuhan
     * @create 2016/3/31 15:43
     */
    public class AES {
        // /** 算法/模式/填充 **/
        private static final String CipherMode = "AES/ECB/PKCS5Padding";
        // private static final String CipherMode = "AES";
    
        /**
         * 生成一个AES密钥对象
         * @return
         */
        public static SecretKeySpec generateKey(){
    		try {
    			KeyGenerator kgen = KeyGenerator.getInstance("AES");
    	        kgen.init(128, new SecureRandom());  
    	        SecretKey secretKey = kgen.generateKey();  
    	        byte[] enCodeFormat = secretKey.getEncoded();  
    	        SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
    			return key;
    		} catch (NoSuchAlgorithmException e) {
    			e.printStackTrace();
    		}
    		return null;
        }
    
        /**
         * 生成一个AES密钥字符串
         * @return
         */
        public static String generateKeyString(){
        	return byte2hex(generateKey().getEncoded());
        }
    
        /**
         * 加密字节数据
         * @param content
         * @param key
         * @return
         */
        public static byte[] encrypt(byte[] content,byte[] key) {
            try {
                Cipher cipher = Cipher.getInstance(CipherMode);
                cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"));
                byte[] result = cipher.doFinal(content);
                return result;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * 通过byte[]类型的密钥加密String
         * @param content
         * @param key
         * @return 16进制密文字符串
         */
        public static String encrypt(String content,byte[] key) {
            try {
                Cipher cipher = Cipher.getInstance(CipherMode);
                cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"));
                byte[] data = cipher.doFinal(content.getBytes("UTF-8"));
                String result = byte2hex(data);
                return result;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * 通过String类型的密钥加密String
         * @param content
         * @param key
         * @return 16进制密文字符串
         */
        public static String encrypt(String content,String key) {
            byte[] data = null;
            try {
                data = content.getBytes("UTF-8");
            } catch (Exception e) {
                e.printStackTrace();
            }
            data = encrypt(data,new SecretKeySpec(hex2byte(key), "AES").getEncoded());
            String result = byte2hex(data);
            return result;
        }
    
        /**
         * 通过byte[]类型的密钥解密byte[]
         * @param content
         * @param key
         * @return
         */
        public static byte[] decrypt(byte[] content,byte[] key) {
            try {
                Cipher cipher = Cipher.getInstance(CipherMode);
                cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"));
                byte[] result = cipher.doFinal(content);
                return result;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * 通过String类型的密钥 解密String类型的密文
         * @param content
         * @param key
         * @return
         */
        public static String decrypt(String content, String key) {
            byte[] data = null;
            try {
                data = hex2byte(content);
            } catch (Exception e) {
                e.printStackTrace();
            }
            data = decrypt(data, hex2byte(key));
            if (data == null)
                return null;
            String result = null;
            try {
                result = new String(data, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            return result;
        }
    
        /**
         * 通过byte[]类型的密钥 解密String类型的密文
         * @param content
         * @param key
         * @return
         */
        public static String decrypt(String content,byte[] key) {
        	try {
                Cipher cipher = Cipher.getInstance(CipherMode);
                cipher.init(Cipher.DECRYPT_MODE,new SecretKeySpec(key, "AES"));
                byte[] data = cipher.doFinal(hex2byte(content));
                return new String(data, "UTF-8");
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * 字节数组转成16进制字符串
         * @param b
         * @return
         */
        public static String byte2hex(byte[] b) { // 一个字节的数。
            StringBuffer sb = new StringBuffer(b.length * 2);
            String tmp = "";
            for (int n = 0; n < b.length; n++) {
                // 整数转成十六进制表示
                tmp = (Integer.toHexString(b[n] & 0XFF));
                if (tmp.length() == 1) {
                    sb.append("0");
                }
                sb.append(tmp);
            }
            return sb.toString().toUpperCase(); // 转成大写
        }
    
        /**
         * 将hex字符串转换成字节数组
         * @param inputString
         * @return
         */
        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;
        }
    }


    Android - RSA实现

    package com.dyhdyh.encrypt;
    
    import android.util.Base64;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.security.KeyFactory;
    import java.security.NoSuchAlgorithmException;
    import java.security.interfaces.RSAPrivateKey;
    import java.security.interfaces.RSAPublicKey;
    import java.security.spec.InvalidKeySpecException;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    
    import javax.crypto.Cipher;
    
    /**
     * 用于Android平台的RSA加密解密
     * 
     * @desc
     * @author dengyuhan
     * @create 2016-3-31 下午2:36:18
     */
    public class RSA {
    	private static final String ALGORITHM = "RSA";
    	private static final String TRANSFORMATION = "RSA";
    
    	/**
    	 * 从文件里输入流中载入公钥
    	 * 
    	 * @param in
    	 *            公钥输入流
    	 * @throws Exception
    	 *             载入公钥时产生的异常
    	 */
    	public static RSAPublicKey loadPublicKey(InputStream in) throws Exception {
    		try {
    			BufferedReader br = new BufferedReader(new InputStreamReader(in));
    			String readLine = null;
    			StringBuilder sb = new StringBuilder();
    			while ((readLine = br.readLine()) != null) {
    				if (readLine.charAt(0) == '-') {
    					continue;
    				} else {
    					sb.append(readLine);
    					sb.append('
    ');
    				}
    			}
    			return loadPublicKey(sb.toString());
    		} catch (IOException e) {
    			throw new Exception("公钥数据流读取错误");
    		} catch (NullPointerException e) {
    			throw new Exception("公钥输入流为空");
    		}
    	}
    
    	/**
    	 * 从字符串中载入公钥
    	 * 
    	 * @param publicKeyStr
    	 *            公钥数据字符串
    	 * @return
    	 * @throws Exception
    	 *             载入公钥时产生的异常
    	 */
    	public static RSAPublicKey loadPublicKey(String publicKeyStr)
    			throws Exception {
    		try {
    			byte[] buffer = Base64.decode(publicKeyStr, Base64.DEFAULT);
    			KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
    			X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
    			return (RSAPublicKey) keyFactory.generatePublic(keySpec);
    		} catch (NoSuchAlgorithmException e) {
    			throw new Exception("无此算法");
    		} catch (InvalidKeySpecException e) {
    			throw new Exception("公钥非法");
    		}catch (NullPointerException e) {
    			throw new Exception("公钥数据为空");
    		}
    	}
    
    	/**
    	 * 从文件里载入私钥
    	 * 
    	 * @param in
    	 *            私钥输入流
    	 * @return
    	 * @throws Exception
    	 */
    	public static RSAPrivateKey loadPrivateKey(InputStream in) throws Exception {
    		try {
    			BufferedReader br = new BufferedReader(new InputStreamReader(in));
    			String readLine = null;
    			StringBuilder sb = new StringBuilder();
    			while ((readLine = br.readLine()) != null) {
    				if (readLine.charAt(0) == '-') {
    					continue;
    				} else {
    					sb.append(readLine);
    					sb.append('
    ');
    				}
    			}
    			return loadPrivateKey(sb.toString());
    		} catch (IOException e) {
    			throw new Exception("私钥数据读取错误");
    		} catch (NullPointerException e) {
    			throw new Exception("私钥输入流为空");
    		}
    	}
    
    	/**
    	 * 从字符串中载入私钥
    	 * 
    	 * @desc
    	 * @param privateKeyStr
    	 *            私钥字符串
    	 * @return
    	 * @throws Exception
    	 */
    	public static RSAPrivateKey loadPrivateKey(String privateKeyStr)
    			throws Exception {
    		try {
    			byte[] buffer = Base64.decode(privateKeyStr, Base64.DEFAULT);
    			PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
    			KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
    			return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
    		} catch (NoSuchAlgorithmException e) {
    			throw new Exception("无此算法");
    		} catch (InvalidKeySpecException e) {
    			throw new Exception("私钥非法");
    		}catch (NullPointerException e) {
    			throw new Exception("私钥数据为空");
    		}
    	}
    
    	/**
    	 * 公钥加密
    	 * 
    	 * @param data
    	 * @param publicKey
    	 * @return
    	 * @throws Exception
    	 */
    	public static String encryptByPublicKey(String data, RSAPublicKey publicKey)
    			throws Exception {
    		// 模长
    		int key_len = publicKey.getModulus().bitLength() / 8;
    		// 加密数据长度 <= 模长-11
    		String[] datas = splitString(data, key_len - 11);
    		String mi = "";
    		// 假设明文长度大于模长-11则要分组加密
    		for (String s : datas) {
    			mi += bcd2Str(encryptByPublicKey(s.getBytes(), publicKey));
    		}
    		return mi;
    	}
    
    	/**
    	 * 公钥加密
    	 * @desc 
    	 * @param data
    	 * @param publicKey
    	 * @return
    	 * @throws Exception
    	 */
    	public static byte[] encryptByPublicKey(byte[] data, RSAPublicKey publicKey)
    			throws Exception {
    		Cipher cipher = Cipher.getInstance(TRANSFORMATION);
    		cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    		return cipher.doFinal(data);
    	}
    
    	/**
    	 * 私钥加密
    	 * @desc 
    	 * @param data
    	 * @param privateKey
    	 * @return
    	 * @throws Exception
    	 */
    	public static byte[] encryptByPrivateKey(byte[] data,
    			RSAPrivateKey privateKey) throws Exception {
    		Cipher cipher = Cipher.getInstance(TRANSFORMATION);
    		cipher.init(Cipher.ENCRYPT_MODE, privateKey);
    		return cipher.doFinal(data);
    	}
    
    
    	/**
    	 * 私钥加密
    	 * @desc 
    	 * @param data
    	 * @param privateKey
    	 * @return
    	 * @throws Exception
    	 */
    	public static String encryptByPrivateKey(String data,
    			RSAPrivateKey privateKey) throws Exception {
    		// 模长
    		int key_len = privateKey.getModulus().bitLength() / 8;
    		// 加密数据长度 <= 模长-11
    		String[] datas = splitString(data, key_len - 11);
    		String mi = "";
    		// 假设明文长度大于模长-11则要分组加密
    		for (String s : datas) {
    			mi += bcd2Str(encryptByPrivateKey(s.getBytes(), privateKey));
    		}
    		return mi;
    	}
    
    	/**
    	 * 私钥解密
    	 * 
    	 * @param data
    	 * @param privateKey
    	 * @return
    	 * @throws Exception
    	 */
    	public static String decryptByPrivateKey(String data,
    			RSAPrivateKey privateKey) throws Exception {
    		// 模长
    		int key_len = privateKey.getModulus().bitLength() / 8;
    		byte[] bytes = data.getBytes();
    		byte[] bcd = ASCII_To_BCD(bytes, bytes.length);
    		// 假设密文长度大于模长则要分组解密
    		String ming = "";
    		byte[][] arrays = splitArray(bcd, key_len);
    		for (byte[] arr : arrays) {
    			ming += new String(decryptByPrivateKey(arr, privateKey));
    		}
    		return ming;
    	}
    	
    	/**
    	 * 私钥解密
    	 * @desc 
    	 * @param data
    	 * @param privateKey
    	 * @return
    	 * @throws Exception
    	 */
    	public static byte[] decryptByPrivateKey(byte[] data,
    			RSAPrivateKey privateKey) throws Exception {
    		Cipher cipher = Cipher.getInstance(TRANSFORMATION);
    		cipher.init(Cipher.DECRYPT_MODE, privateKey);
    		return cipher.doFinal(data);
    	}
    	
    	/**
    	 * 公钥解密
    	 * @desc 
    	 * @param data
    	 * @param publicKey
    	 * @return
    	 * @throws Exception
    	 */
    	public static String decryptByPublicKey(String data,
    			RSAPublicKey publicKey) throws Exception {
    		// 模长
    		int key_len = publicKey.getModulus().bitLength() / 8;
    		byte[] bytes = data.getBytes();
    		byte[] bcd = ASCII_To_BCD(bytes, bytes.length);
    		// 假设密文长度大于模长则要分组解密
    		String ming = "";
    		byte[][] arrays = splitArray(bcd, key_len);
    		for (byte[] arr : arrays) {
    			ming += new String(decryptByPublicKey(arr, publicKey));
    		}
    		return ming;
    	}
    	
    	/**
    	 * 公钥解密
    	 * @desc 
    	 * @param data
    	 * @param publicKey
    	 * @return
    	 * @throws Exception
    	 */
    	public static byte[] decryptByPublicKey(byte[] data,
    			RSAPublicKey publicKey) throws Exception {
    		Cipher cipher = Cipher.getInstance(TRANSFORMATION);
    		cipher.init(Cipher.DECRYPT_MODE, publicKey);
    		return cipher.doFinal(data);
    	}
    
    	/**
    	 * ASCII码转BCD码
    	 * 
    	 */
    	private static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {
    		byte[] bcd = new byte[asc_len / 2];
    		int j = 0;
    		for (int i = 0; i < (asc_len + 1) / 2; i++) {
    			bcd[i] = asc_to_bcd(ascii[j++]);
    			bcd[i] = (byte) (((j >= asc_len) ?

    0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4)); } return bcd; } private static byte asc_to_bcd(byte asc) { byte bcd; if ((asc >= '0') && (asc <= '9')) bcd = (byte) (asc - '0'); else if ((asc >= 'A') && (asc <= 'F')) bcd = (byte) (asc - 'A' + 10); else if ((asc >= 'a') && (asc <= 'f')) bcd = (byte) (asc - 'a' + 10); else bcd = (byte) (asc - 48); return bcd; } /** * BCD转字符串 */ private static String bcd2Str(byte[] bytes) { char temp[] = new char[bytes.length * 2], val; for (int i = 0; i < bytes.length; i++) { val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f); temp[i * 2] = (char) (val > 9 ?

    val + 'A' - 10 : val + '0'); val = (char) (bytes[i] & 0x0f); temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0'); } return new String(temp); } /** * 拆分字符串 */ private static String[] splitString(String string, int len) { int x = string.length() / len; int y = string.length() % len; int z = 0; if (y != 0) { z = 1; } String[] strings = new String[x + z]; String str = ""; for (int i = 0; i < x + z; i++) { if (i == x + z - 1 && y != 0) { str = string.substring(i * len, i * len + y); } else { str = string.substring(i * len, i * len + len); } strings[i] = str; } return strings; } /** * 拆分数组 */ private static byte[][] splitArray(byte[] data, int len) { int x = data.length / len; int y = data.length % len; int z = 0; if (y != 0) { z = 1; } byte[][] arrays = new byte[x + z][]; byte[] arr; for (int i = 0; i < x + z; i++) { arr = new byte[len]; if (i == x + z - 1 && y != 0) { System.arraycopy(data, i * len, arr, 0, y); } else { System.arraycopy(data, i * len, arr, 0, len); } arrays[i] = arr; } return arrays; } }


    JAVA - RSA实现

    package com.dyhdyh.encrypt;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.security.KeyFactory;
    import java.security.NoSuchAlgorithmException;
    import java.security.interfaces.RSAPrivateKey;
    import java.security.interfaces.RSAPublicKey;
    import java.security.spec.InvalidKeySpecException;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    
    import javax.crypto.Cipher;
    
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    
    import sun.misc.BASE64Decoder;
    
    /**
     * 用于java平台的RSA加密解密
     * 
     * @desc
     * @author dengyuhan
     * @create 2016-3-31 下午2:36:18
     */
    public class RSA {
    	private static final String ALGORITHM = "RSA";
    	private static final String TRANSFORMATION = "RSA";
    
    	/**
    	 * 从文件里输入流中载入公钥
    	 * 
    	 * @param in
    	 *            公钥输入流
    	 * @throws Exception
    	 *             载入公钥时产生的异常
    	 */
    	public static RSAPublicKey loadPublicKey(InputStream in) throws Exception {
    		try {
    			BufferedReader br = new BufferedReader(new InputStreamReader(in));
    			String readLine = null;
    			StringBuilder sb = new StringBuilder();
    			while ((readLine = br.readLine()) != null) {
    				if (readLine.charAt(0) == '-') {
    					continue;
    				} else {
    					sb.append(readLine);
    					sb.append('
    ');
    				}
    			}
    			return loadPublicKey(sb.toString());
    		} catch (IOException e) {
    			throw new Exception("公钥数据流读取错误");
    		} catch (NullPointerException e) {
    			throw new Exception("公钥输入流为空");
    		}
    	}
    
    	/**
    	 * 从字符串中载入公钥
    	 * 
    	 * @param publicKeyStr
    	 *            公钥数据字符串
    	 * @return
    	 * @throws Exception
    	 *             载入公钥时产生的异常
    	 */
    	public static RSAPublicKey loadPublicKey(String publicKeyStr)
    			throws Exception {
    		try {
    			BASE64Decoder base64Decoder = new BASE64Decoder();
    			byte[] buffer = base64Decoder.decodeBuffer(publicKeyStr);
    			KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
    			X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
    			return (RSAPublicKey) keyFactory.generatePublic(keySpec);
    		} catch (NoSuchAlgorithmException e) {
    			throw new Exception("无此算法");
    		} catch (InvalidKeySpecException e) {
    			throw new Exception("公钥非法");
    		} catch (IOException e) {
    			throw new Exception("公钥数据内容读取错误");
    		} catch (NullPointerException e) {
    			throw new Exception("公钥数据为空");
    		}
    	}
    
    	/**
    	 * 从文件里载入私钥
    	 * 
    	 * @param in
    	 *            私钥输入流
    	 * @return
    	 * @throws Exception
    	 */
    	public static RSAPrivateKey loadPrivateKey(InputStream in) throws Exception {
    		try {
    			BufferedReader br = new BufferedReader(new InputStreamReader(in));
    			String readLine = null;
    			StringBuilder sb = new StringBuilder();
    			while ((readLine = br.readLine()) != null) {
    				if (readLine.charAt(0) == '-') {
    					continue;
    				} else {
    					sb.append(readLine);
    					sb.append('
    ');
    				}
    			}
    			return loadPrivateKey(sb.toString());
    		} catch (IOException e) {
    			throw new Exception("私钥数据读取错误");
    		} catch (NullPointerException e) {
    			throw new Exception("私钥输入流为空");
    		}
    	}
    
    	/**
    	 * 从字符串中载入私钥
    	 * 
    	 * @desc
    	 * @param privateKeyStr
    	 *            私钥字符串
    	 * @return
    	 * @throws Exception
    	 */
    	public static RSAPrivateKey loadPrivateKey(String privateKeyStr)
    			throws Exception {
    		try {
    			BASE64Decoder base64Decoder = new BASE64Decoder();
    			byte[] buffer = base64Decoder.decodeBuffer(privateKeyStr);
    			PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
    			KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
    			return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
    		} catch (NoSuchAlgorithmException e) {
    			throw new Exception("无此算法");
    		} catch (InvalidKeySpecException e) {
    			throw new Exception("私钥非法");
    		} catch (IOException e) {
    			throw new Exception("私钥数据内容读取错误");
    		} catch (NullPointerException e) {
    			throw new Exception("私钥数据为空");
    		}
    	}
    
    	/**
    	 * 公钥加密
    	 * 
    	 * @param data
    	 * @param publicKey
    	 * @return
    	 * @throws Exception
    	 */
    	public static String encryptByPublicKey(String data, RSAPublicKey publicKey)
    			throws Exception {
    		// 模长
    		int key_len = publicKey.getModulus().bitLength() / 8;
    		// 加密数据长度 <= 模长-11
    		String[] datas = splitString(data, key_len - 11);
    		String mi = "";
    		// 假设明文长度大于模长-11则要分组加密
    		for (String s : datas) {
    			mi += bcd2Str(encryptByPublicKey(s.getBytes(), publicKey));
    		}
    		return mi;
    	}
    
    	/**
    	 * 公钥加密
    	 * @desc 
    	 * @param data
    	 * @param publicKey
    	 * @return
    	 * @throws Exception
    	 */
    	public static byte[] encryptByPublicKey(byte[] data, RSAPublicKey publicKey)
    			throws Exception {
    		Cipher cipher = Cipher.getInstance(TRANSFORMATION);
    		cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    		return cipher.doFinal(data);
    	}
    
    	/**
    	 * 私钥加密
    	 * @desc 
    	 * @param data
    	 * @param privateKey
    	 * @return
    	 * @throws Exception
    	 */
    	public static byte[] encryptByPrivateKey(byte[] data,
    			RSAPrivateKey privateKey) throws Exception {
    		Cipher cipher = Cipher.getInstance(TRANSFORMATION);
    		cipher.init(Cipher.ENCRYPT_MODE, privateKey);
    		return cipher.doFinal(data);
    	}
    	
    	/**
    	 * 私钥加密
    	 * @desc 
    	 * @param data
    	 * @param privateKey
    	 * @return
    	 * @throws Exception
    	 */
    	public static String encryptByPrivateKey(String data,
    			RSAPrivateKey privateKey) throws Exception {
    		// 模长
    		int key_len = privateKey.getModulus().bitLength() / 8;
    		// 加密数据长度 <= 模长-11
    		String[] datas = splitString(data, key_len - 11);
    		String mi = "";
    		// 假设明文长度大于模长-11则要分组加密
    		for (String s : datas) {
    			mi += bcd2Str(encryptByPrivateKey(s.getBytes(), privateKey));
    		}
    		return mi;
    	}
    
    	/**
    	 * 私钥解密
    	 * 
    	 * @param data
    	 * @param privateKey
    	 * @return
    	 * @throws Exception
    	 */
    	public static String decryptByPrivateKey(String data,
    			RSAPrivateKey privateKey) throws Exception {
    		// 模长
    		int key_len = privateKey.getModulus().bitLength() / 8;
    		byte[] bytes = data.getBytes();
    		byte[] bcd = ASCII_To_BCD(bytes, bytes.length);
    		// 假设密文长度大于模长则要分组解密
    		String ming = "";
    		byte[][] arrays = splitArray(bcd, key_len);
    		for (byte[] arr : arrays) {
    			ming += new String(decryptByPrivateKey(arr, privateKey));
    		}
    		return ming;
    	}
    	
    	/**
    	 * 私钥解密
    	 * @desc 
    	 * @param data
    	 * @param privateKey
    	 * @return
    	 * @throws Exception
    	 */
    	public static byte[] decryptByPrivateKey(byte[] data,
    			RSAPrivateKey privateKey) throws Exception {
    		Cipher cipher = Cipher.getInstance(TRANSFORMATION,new BouncyCastleProvider());
    		cipher.init(Cipher.DECRYPT_MODE, privateKey);
    		return cipher.doFinal(data);
    	}
    	
    	/**
    	 * 公钥解密
    	 * @desc 
    	 * @param data
    	 * @param publicKey
    	 * @return
    	 * @throws Exception
    	 */
    	public static String decryptByPublicKey(String data,
    			RSAPublicKey publicKey) throws Exception {
    		// 模长
    		int key_len = publicKey.getModulus().bitLength() / 8;
    		byte[] bytes = data.getBytes();
    		byte[] bcd = ASCII_To_BCD(bytes, bytes.length);
    		// 假设密文长度大于模长则要分组解密
    		String ming = "";
    		byte[][] arrays = splitArray(bcd, key_len);
    		for (byte[] arr : arrays) {
    			ming += new String(decryptByPublicKey(arr, publicKey));
    		}
    		return ming;
    	}
    	
    	/**
    	 * 公钥解密
    	 * @desc 
    	 * @param data
    	 * @param publicKey
    	 * @return
    	 * @throws Exception
    	 */
    	public static byte[] decryptByPublicKey(byte[] data,
    			RSAPublicKey publicKey) throws Exception {
    		Cipher cipher = Cipher.getInstance(TRANSFORMATION,new BouncyCastleProvider());
    		cipher.init(Cipher.DECRYPT_MODE, publicKey);
    		return cipher.doFinal(data);
    	}
    
    	/**
    	 * ASCII码转BCD码
    	 * 
    	 */
    	private static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {
    		byte[] bcd = new byte[asc_len / 2];
    		int j = 0;
    		for (int i = 0; i < (asc_len + 1) / 2; i++) {
    			bcd[i] = asc_to_bcd(ascii[j++]);
    			bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4));
    		}
    		return bcd;
    	}
    
    	private static byte asc_to_bcd(byte asc) {
    		byte bcd;
    
    		if ((asc >= '0') && (asc <= '9'))
    			bcd = (byte) (asc - '0');
    		else if ((asc >= 'A') && (asc <= 'F'))
    			bcd = (byte) (asc - 'A' + 10);
    		else if ((asc >= 'a') && (asc <= 'f'))
    			bcd = (byte) (asc - 'a' + 10);
    		else
    			bcd = (byte) (asc - 48);
    		return bcd;
    	}
    
    	/**
    	 * BCD转字符串
    	 */
    	private static String bcd2Str(byte[] bytes) {
    		char temp[] = new char[bytes.length * 2], val;
    
    		for (int i = 0; i < bytes.length; i++) {
    			val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);
    			temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
    
    			val = (char) (bytes[i] & 0x0f);
    			temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
    		}
    		return new String(temp);
    	}
    
    	/**
    	 * 拆分字符串
    	 */
    	private static String[] splitString(String string, int len) {
    		int x = string.length() / len;
    		int y = string.length() % len;
    		int z = 0;
    		if (y != 0) {
    			z = 1;
    		}
    		String[] strings = new String[x + z];
    		String str = "";
    		for (int i = 0; i < x + z; i++) {
    			if (i == x + z - 1 && y != 0) {
    				str = string.substring(i * len, i * len + y);
    			} else {
    				str = string.substring(i * len, i * len + len);
    			}
    			strings[i] = str;
    		}
    		return strings;
    	}
    
    	/**
    	 * 拆分数组
    	 */
    	private static byte[][] splitArray(byte[] data, int len) {
    		int x = data.length / len;
    		int y = data.length % len;
    		int z = 0;
    		if (y != 0) {
    			z = 1;
    		}
    		byte[][] arrays = new byte[x + z][];
    		byte[] arr;
    		for (int i = 0; i < x + z; i++) {
    			arr = new byte[len];
    			if (i == x + z - 1 && y != 0) {
    				System.arraycopy(data, i * len, arr, 0, y);
    			} else {
    				System.arraycopy(data, i * len, arr, 0, len);
    			}
    			arrays[i] = arr;
    		}
    		return arrays;
    	}
    }

    JAVA的RSA跟Android的RSA有所不同:

    1.载入key的时候。JAVA上用的是BASE64Decoder

    BASE64Decoder base64Decoder = new BASE64Decoder();
    byte[] buffer = base64Decoder.decodeBuffer(publicKeyStr);

    而Android上用的Base64这个地方仅仅是API不一样,作用是一样的

    byte[] buffer = Base64.decode(publicKeyStr, Base64.DEFAULT);


    2.在JAVA平台上调用Cipher.getInstance()的时候。须要多传一个參数。也就是BouncyCastleProvider的实例:

    Cipher cipher = Cipher.getInstance("RSA",new BouncyCastleProvider());

    这个类jdk上是没有的。所以须要加入一个jar包bcprov-jdk15-143.jar



    假设不这样做。JAVA上解密的时候就会抛出一个BadPaddingException

    Exception in thread "main" javax.crypto.BadPaddingException: Blocktype mismatch: 0
    	at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:332)
    	at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:272)
    	at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:356)
    	at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:382)
    	at javax.crypto.Cipher.doFinal(Cipher.java:2087)
    	at com.dyhdyh.encrypt.RSA.decryptByPrivateKey(RSA.java:255)
    	at com.dyhdyh.encrypt.RSA.decryptByPrivateKey(RSA.java:238)
    这是由于Android的加密标准与JAVA的加密标准不一致导致,Android上的RSA实现是"RSA/None/NoPadding"。而标准JDK实现是"RSA/None/PKCS1Padding",这造成了在Android上加密后无法在server上解密


    最后来看看如何混合加密(这里仅仅举一种方式,附件里有完整的)


    Android上加密

    1.将openssl生成出来的公钥,放入assets目录内(不一定要放这里,仅仅要能拿到文件内容即可)。



    2.载入放在assets文件中的公钥

    //载入RSA公钥
    RSAPublicKey rsaPublicKey = RSA.loadPublicKey(getAssets().open("rsa_public_key.pem"));

    3.再生成一个AES的密钥,用于AES加密

    //生成一个AES密钥
    String aesKey=AES.generateKeyString();

    4.通过RSA的公钥来加密刚刚生成的AES密钥

    //用RSA公钥加密AES的密钥
    String encryptAesKey = RSA.encryptByPublicKey(aesKey, rsaPublicKey);

    5.最后使用AES来加密须要传输的数据。AES加密须要传入两个參数,第一个是明文数据,第二个是3步生成出来的密钥

    //再使用AES加密内容。传给server
    String encryptContent = AES.encrypt(content, aesKey);

    6.第5步返回的字符串就是加密过后的数据。最后将4和5传给服务端。接下来就是服务端的事情了。


    client传过来密文之后,接下来就须要服务端来解密了


    JAVA解密

    1.载入RSA私钥(这里的私钥是跟client的公钥是成对的)

    //载入私钥
    RSAPrivateKey privateKey = RSA.loadPrivateKey(new FileInputStream("G:/RSA密钥/pkcs8_rsa_private_key.pem"));


    2.通过RSA的私钥解密client传来的AES-KEY(也就是client的第4),由于这个key是加过密的,所以我们须要先将key解密成明文

    //解密AES-KEY
    String decryptAesKey = RSA.decryptByPrivateKey(aesKey, privateKey);

    3.AES-KEY加密成明文之后,如今能够拿这个key来解密client传过来的数据了

    //AES解密数据
    String decrypt = AES.decrypt(content, decryptAesKey);


    RSA-AES混合加密就是这个样子,有什么问题请跟帖回复。我会继续改进


    最后附上完整demo

    http://download.csdn.net/detail/aa464971/9478798


    Android交流群:146262062


  • 相关阅读:
    Ubuntu下Nginx与Apache2修改默认端口号
    Kerbernetes的Pod资源管理进阶
    Kerbernetes的Pod资源管理
    Kerbernetes的Pod资源清单配置基础
    kubernetes快速入门
    K8S镜像下载报错解决方案(使用阿里云镜像去下载kubeadm需要的镜像文件)
    CentOS 7.6使用kubeadm部署k8s 1.17.2测试集群实战篇
    8
    7
    6
  • 原文地址:https://www.cnblogs.com/llguanli/p/7258392.html
Copyright © 2011-2022 走看看