因業務須要,須要給android應用安裝證書,經過讀取證書文件內容實現某些功能的控制;html
流程:後臺經過publicKey對指定內容的文件進行加密,生成文件共客戶下載,客戶下載後選擇該證書文件讀取到應用中;前端
package com.zl.unit.printunit; import org.springframework.util.Base64Utils; import java.io.ByteArrayOutputStream; import java.security.Key; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; import javax.crypto.Cipher; /** */ /** * <p> * RSA公鑰/私鑰/簽名工具包 * </p> * <p> * 字符串格式的密鑰在未在特殊說明狀況下都爲BASE64編碼格式<br/> * 因爲非對稱加密速度極其緩慢,通常文件不使用它來加密而是使用對稱加密,<br/> * 非對稱加密算法能夠用來對對稱加密的密鑰加密,這樣保證密鑰的安全也就保證了數據的安全 * </p> * * @author zhagnlei * @date 2019-4-29 * @version 1.0 */ public class RSAUtils { /** */ /** * 加密算法RSA */ public static final String KEY_ALGORITHM = "RSA"; /** */ /** * 簽名算法 */ public static final String SIGNATURE_ALGORITHM = "MD5withRSA"; /** */ /** * 獲取公鑰的key */ private static final String PUBLIC_KEY = "RSAPublicKey"; /** */ /** * 獲取私鑰的key */ private static final String PRIVATE_KEY = "RSAPrivateKey"; /** */ /** * RSA最大加密明文大小 */ private static final int MAX_ENCRYPT_BLOCK = 117; /** */ /** * RSA最大解密密文大小 */ private static final int MAX_DECRYPT_BLOCK = 128; private static final String PRIVATE_KEY_CODE = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAOIw/Piptd33B7yriCdoaDc1p4fVVuP0kDuh2QEMMoJflGgmi1I8tfmf/p1aHeKZRWZzoc0yjygE6GSL9bv7UozI5Soj6H+5ANrfkS+CtRI/DJzRBmzMLJqSTS5e0aot1DP8iCuzLBd8jM0vmxDbrv3GKdyHh5+BqKQCmZdiFIPLAgMBAAECgYEAqTkrWcJmbRzu7emLIKiNJ5j9sLMcockLy4Fnv8/nTgDCIDWOEEWZg5t+uyx7pVc0Q9UI3WMRFUiusOLBQxVhCMhbwzOe+aD+xxXkA5gcQz3lURHkXcCcrSVfOyN9GK2pQg1clmYBwYjNacp4X8UOwQWGhcK1XSAsokGrhHGcwrkCQQD/zImXC1ONUiljf59xjCAbO/G42nbMdaSJIPcGDI9CY4XD135IsNsmPPhWxu4HiJ5/fuh8Z6kapBRJvDldbKeNAkEA4l5+gDpOiAsGO0CVDXgk6kT9yADbTuxOpPM4FEWfsMUf0h8vYO0B+3VPrQ7/mrV5WrrfBufN5hukXCHlDZU2twJAIBVrfIJzLFqNzmkHepp0vHW8T88271YiGQEFesDAhzcsY+/3au6jzhv/mgLBgDhmiN9GEbR+xVSnJshw+YLTUQJBAJQ4i1wq0YECtvHVN8O6B3Hd+s4awX7L/DLFjtK3Q/jbGhrbkIpGpiWgiqsmRvdmHC/sbFx5K7igIN6y0ugx68ECQE7sFCZ+9va95ZMnYdhDvHypZmOfZVZIALT5CfFx1H8y5Qyc0jR6vRKHSv96kVOHlg3XihbIZryD7zqm37jnb6I="; private static final String PUBLIC_KEY_CODE = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDiMPz4qbXd9we8q4gnaGg3NaeH1Vbj9JA7odkBDDKCX5RoJotSPLX5n/6dWh3imUVmc6HNMo8oBOhki/W7+1KMyOUqI+h/uQDa35EvgrUSPwyc0QZszCyakk0uXtGqLdQz/IgrsywXfIzNL5sQ2679xinch4efgaikApmXYhSDywIDAQAB"; /** */ /** * <p> * 生成密鑰對(公鑰和私鑰) * </p> * * @return * @throws Exception */ public static Map<String, Object> genKeyPair() throws Exception { KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM); keyPairGen.initialize(1024); KeyPair keyPair = keyPairGen.generateKeyPair(); RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); Map<String, Object> keyMap = new HashMap<String, Object>(2); keyMap.put(PUBLIC_KEY, publicKey); keyMap.put(PRIVATE_KEY, privateKey); return keyMap; } /** */ /** * <p> * 用私鑰對信息生成數字簽名 * </p> * * @param data 已加密數據 * @param privateKey 私鑰(BASE64編碼) * @return * @throws Exception */ public static String sign(byte[] data, String privateKey) throws Exception { byte[] keyBytes = Base64Utils.decodeFromString(privateKey); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initSign(privateK); signature.update(data); return Base64Utils.encodeToString(signature.sign()); } /** */ /** * <p> * 校驗數字簽名 * </p> * * @param data 已加密數據 * @param publicKey 公鑰(BASE64編碼) * @param sign 數字簽名 * @return * @throws Exception */ public static boolean verify(byte[] data, String publicKey, String sign) throws Exception { byte[] keyBytes = Base64Utils.decodeFromString(publicKey); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PublicKey publicK = keyFactory.generatePublic(keySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initVerify(publicK); signature.update(data); return signature.verify(Base64Utils.decodeFromString(sign)); } /** */ /** * <P> * 私鑰解密 * </p> * * @param encryptedData 已加密數據 * @param privateKey 私鑰(BASE64編碼) * @return * @throws Exception */ public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception { byte[] keyBytes = Base64Utils.decodeFromString(privateKey); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privateK); int inputLen = encryptedData.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 對數據分段解密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_DECRYPT_BLOCK) { cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); } else { cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_DECRYPT_BLOCK; } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; } /** */ /** * <p> * 公鑰解密 * </p> * * @param encryptedData 已加密數據 * @param publicKey 公鑰(BASE64編碼) * @return * @throws Exception */ public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey) throws Exception { byte[] keyBytes = Base64Utils.decodeFromString(publicKey); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicK = keyFactory.generatePublic(x509KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, publicK); int inputLen = encryptedData.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 對數據分段解密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_DECRYPT_BLOCK) { cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); } else { cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_DECRYPT_BLOCK; } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; } /** */ /** * <p> * 公鑰加密 * </p> * * @param data 源數據 * @param publicKey 公鑰(BASE64編碼) * @return * @throws Exception */ public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception { byte[] keyBytes = Base64Utils.decodeFromString(publicKey); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicK = keyFactory.generatePublic(x509KeySpec); // 對數據加密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicK); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 對數據分段加密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); } else { cache = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_ENCRYPT_BLOCK; } byte[] encryptedData = out.toByteArray(); out.close(); return encryptedData; } /** */ /** * <p> * 私鑰加密 * </p> * * @param data 源數據 * @param privateKey 私鑰(BASE64編碼) * @return * @throws Exception */ public static byte[] encryptByPrivateKey(byte[] data, String privateKey) throws Exception { byte[] keyBytes = Base64Utils.decodeFromString(privateKey); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, privateK); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 對數據分段加密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); } else { cache = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_ENCRYPT_BLOCK; } byte[] encryptedData = out.toByteArray(); out.close(); return encryptedData; } /** */ /** * <p> * 獲取私鑰 * </p> * * @param keyMap 密鑰對 * @return * @throws Exception */ public static String getPrivateKey(Map<String, Object> keyMap) throws Exception { Key key = (Key) keyMap.get(PRIVATE_KEY); return Base64Utils.encodeToString(key.getEncoded()); } /** */ /** * <p> * 獲取公鑰 * </p> * * @param keyMap 密鑰對 * @return * @throws Exception */ public static String getPublicKey(Map<String, Object> keyMap) throws Exception { Key key = (Key) keyMap.get(PUBLIC_KEY); return Base64Utils.encodeToString(key.getEncoded()); } /** * java端公鑰加密 */ public static String encryptedDataOnJava(String data, String PUBLICKEY) { try { data = Base64Utils.encodeToString(encryptByPublicKey(data.getBytes("UTF-8"), PUBLICKEY)); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return data; } /** * java端私鑰解密 */ public static String decryptDataOnJava(String data, String PRIVATEKEY) { String temp = ""; try { byte[] rs = Base64Utils.decodeFromString(data); temp = new String(RSAUtils.decryptByPrivateKey(rs, PRIVATEKEY), "UTF-8"); } catch (Exception e) { e.printStackTrace(); } return temp; } public static void main(String[] args) { String data = "hello"; String s = encryptedDataOnJava(data, PUBLIC_KEY_CODE); System.out.println(s); } /** 解密 */ static void doc() { String data = "hAvU3rwHjyl+qf9lx+yo4//hvVWtjxyvQQPmUAa7RbjBJGjdLALiaXwWn3aHqbfajoCJKE7zQDDpAkGtisd9M9hzvboGbZVJ++5vFDxrGMVk5nEd8JR/zZY361gihSLoY3OrBpAOWkWs1f0JD8oe5XADZcH0nM85/K831Iwa6zw="; String s = decryptDataOnJava(data, PRIVATE_KEY_CODE); System.out.println(s); } }
後端代碼就不說了,本身理解下java
下面說下前端代碼:在以下目錄下導入這兩個文件,同時在index的html中引入這兩個文件:android
jsencrypt.main.js連接:https://pan.baidu.com/s/1y0sqTlNrxj2wpKm6_iV7Ow
提取碼:00yt
算法
RSAExport.js文件連接:https://pan.baidu.com/s/11vRmNa0Ior35SXCYpDYutg
提取碼:9rhq spring
在用到解密的地方使用: declare var RSAUtil: any; 聲明後端
須要加密或者解密的地方使用以下:安全
經過文件系統讀取到文件內容,對文件內容進行解密;工具