国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

詳解Android端與JavaWeb傳輸加密(DES+RSA)

2019-10-22 18:24:15
字體:
來源:轉載
供稿:網友

一、加密介紹

本文采用對稱式加密算法DES和非對稱式加密算法RSA結合做數據傳輸加密的方式。

先說一下對稱式加密 DES:對稱式加密即使用單鑰密碼加密的方法,信息的加密和解密使用同一個秘鑰,這種方式也稱為單秘鑰加密。所謂對稱就是指加密和解密使用的是同一個秘鑰!

常用的對稱加密有:DES、IDEA、RC2、RC4、SKIPJACK、RC5、AES算法等。

與對稱加密算法不同,非對稱加密算法需要兩個密鑰:公開密鑰(publickey)和私有密鑰 (privatekey)。公開密鑰與私有密鑰是一對,如果用公開密鑰對數據進行加密,只有用對應的私有密鑰才能解密;如果用私有密鑰對數據進行加密,那么只有用對應的公開密鑰才能解密。因為加密和解密使用的是兩個不同的密鑰,所以這種算法叫作非對稱加密算法。

RSA 公鑰加密算法是1977年由Ron Rivest、Adi Shamirh和LenAdleman在(美國麻省理工學院)開發的。RSA取名來自開發他們三者的名字。RSA是目前最有影響力的公鑰加密算法,它能夠抵抗到目前為止已知的所有密碼攻擊,已被ISO推薦為公鑰數據加密標準。 RSA算法基于一個十分簡單的數論事實:將兩個大素數相乘十分容易,但那時想要對其乘積進行因式分解卻極其困難,因此可以將乘積公開作為加密密鑰。

二、RSA密鑰生成

RSA密鑰采用OpenSSL協議進行生成,本文僅簡單生成公鑰和私鑰,如有其它需要可以通過CA證書進行密鑰的生成

1、OpenSSL安裝

http://slproweb.com/products/Win32OpenSSL.html

請自行選擇32位64位進行下載安裝

2、打開工作空間

打開OpenSSL安裝目錄下的bin,運行OpenSSL.exe進入OpenSSL工作空間

3、密鑰生成

①、私鑰生成(生成位置位于bin目錄下)

genrsa -out rsa_private_key.pem 1024

openssl隨機生成了一份私鑰,加密長度是1024位。加密長度是指理論上最大允許”被加密的信息“長度的限制,也就是明文的長度限制。隨著這個參數的增大(比方說2048),允許的明文長度也會增加,但同時也會造成計算復雜度的極速增長。一般推薦的長度就是1024位(128字節)

JAVA需要使用的私鑰需要經過PKCS#8編碼,PHP程序不需要

當前私鑰格式需要轉換為pkcs#8的格式,命令為:

pkcs8 -topk8 -inform PEM -in pkcs8_rsa_private_key.pem -outform PEM -nocrypt

②、公鑰生成

rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout

至此,RSA+DES相關前期準備工作完成

三、Android端配置

本文主要針對數據傳輸過程進行加密,采取加密Json字符串完成整個加密過程,由此,需要統一傳輸參數為"data=********&sign="*******************"的格式,如有其它需求請自行更改。

由于本項目網絡框架采用Retrofit+OkHttp的實現方式,所以對參數進行加密的過程由OkHttp攔截器來實現

public class EncryptionInterceptor implements Interceptor {private Context mContext;public EncryptionInterceptor(Context context) { this.mContext = context;}@Overridepublic Response intercept(@NonNull Chain chain) throws IOException { Request request = chain.request(); RequestBody oldBody = request.body(); Buffer buffer = new Buffer(); if (oldBody != null) {  oldBody.writeTo(buffer); } String strOldBody = buffer.readUtf8(); Map<String, String> map = new HashMap<>(); String dataByte = URLDecoder.decode(strOldBody.substring(5), "utf-8"); try {  //獲取DES的key  byte[] desKey = DESCoder.initKey();  //DES加密數據  byte[] encrypt = DESCoder.encrypt(dataByte.getBytes(), desKey);  map.put("data", parseByte2HexStr(encrypt));  //RSA加密  RSAEncrypt rsaEncrypt = new RSAEncrypt();  InputStream inputStream =  mContext.getResources().getAssets().open("rsa_public_key.pem");  //rsa設置公鑰  rsaEncrypt.loadPublicKey(inputStream);  //rsa加密DES的key  byte[] rsaData = rsaEncrypt.encrypt(rsaEncrypt.getPublicKey(), desKey);  map.put("sign", parseByte2HexStr(rsaData)); } catch (Exception e) {  e.printStackTrace(); } FormBody body = new FormBody.Builder().add("data", map.get("data")).add("sign", map.get("sign")).build(); request = request.newBuilder().header("Content-Type", body.contentType().type()).header("Content-Length", String.valueOf(body.contentLength())).method(request.method(), body).build(); return chain.proceed(request);}/** * 將二進制轉換成16進制 * * @since v1.0 */private static String parseByte2HexStr(byte buf[]) { StringBuilder sb = new StringBuilder(); for (byte aBuf : buf) {  String hex = Integer.toHexString(aBuf & 0xFF);  if (hex.length() == 1) {   hex = '0' + hex;  }  sb.append(hex.toUpperCase()); } return sb.toString();}/** * 按照key排序得到參數列表字符串 * * @param paramValues 參數map對象 * @return 參數列表字符串 */public static String getParamsOrderByKey(Map<String, String> paramValues) { String params = ""; List<String> paramNames = new ArrayList<>(paramValues.size()); paramNames.addAll(paramValues.keySet()); Collections.sort(paramNames); for (String paramName : paramNames) {  if (params.equals("")) {   params += paramName + "=" + paramValues.get(paramName);  } else {   params += "&" + paramName + "=" + paramValues.get(paramName);  } } return params;}/** * 將16進制轉換為二進制 * * @since v1.0 */public byte[] parseHexStr2Byte(String hexStr) { if (hexStr.length() < 1)  return null; byte[] result = new byte[hexStr.length() / 2]; for (int i = 0; i < hexStr.length() / 2; i++) {  int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);  int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);  result[i] = (byte) (high * 16 + low); } return result;}}

添加OkHttp攔截器

new OkHttpClient.Builder()    .addInterceptor(new EncryptionInterceptor(this))    .build();

RSA工具類實現

public class RSAEncrypt {public static final String DEFAULT_PUBLIC_KEY =  "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC1Qcf1zVOuhseFxvo6+FnVvEPs" + "/r" + "Uvczg6oX+HjMNksiiDWcNkbPHfznaPDtgoBY2xF0R8HGHbrT53LNvkj7UMcI48tq" + "/r" + "K+B4YdJHe9SgJVDCCiceLLGtf/ev206qJ/XgKgrLFD+vMmjIB8gQCkZvy/dxhEf1" + "/r" + "aAmoz5tdJhOVdxT7QwIDAQAB" + "/r";public static final String DEFAULT_PRIVATE_KEY =  "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALVBx/XNU66Gx4XG" + "/r" +    "+jr4WdW8Q+xS9zODqhf4eMw2SyKINZw2Rs8d/Odo8O2CgFjbEXRHwcYdutPncs2+" + "/r" +    "SPtQxwjjy2or4Hhh0kd71KAlUMIKJx4ssa1/96/bTqon9eAqCssUP68yaMgHyBAK" + "/r" +    "Rm/L93GER/VoCajPm10mE5V3FPtDAgMBAAECgYAf1hEAHHNhSS0MUzmqV+q3ftzT" + "/r" +    "SnM+6hZbJXpaLAMgapo3+NSRFmxQXP9MSEqw0LGNIfloCdrB03o3pv98nOCIZCh7" + "/r" +    "PHsU2GhxJ04Qro+wKhK358326KNXCjjqVIBG0xMbJxVhjM2/jjfocxFpe5iD7h53" + "/r" +    "c+GvDgUVduAYO4I1GQJBAO21n2aIzQV3mScS1O8BRV+9CmHaDbVHqBetRoB3kJ2U" + "/r" +    "piflKTNofwWmTA5A8sKt8WcOz7LsB2SWcp9jNvatxA8CQQDDNCmfo6eix9e5f11K" + "/r" +    "Rf8sRiN7XGDzlKkZlmQAN0UtXdTP4AN9cuZrwnntWKysXr/zLntYLGYn9rdrohbD" + "/r" +    "9RGNAkBOEsog7iuQcSCfQcMoIN29PSSs0OaRtNBTvniadyrLZuhP0CeBGAAoRd9T" + "/r" +    "CyfwoxrXg3jaRkWDVxqcmQSTbq0nAkB8flcRhilSqsuNdYpE5VFxpiXY9jirAKO8" + "/r" +    "Our6LEXFQjOIhCEVr+L+1OA4HDa8FA2thXaK7H4WfMXMMmr8fN69AkEAuR0YU9My" + "/r" +    "snzWLDWYR5sNp90PhyDSL/HTZHBnebD+JlAYwoYRFYt+tXw0/PEmV2B3thYGPeiZ" + "/r" +    "kHKd/TeLIVbxGg==" + "/r";/** * 私鑰 */private RSAPrivateKey privateKey;/** * 公鑰 */private RSAPublicKey publicKey;/** * 字節數據轉字符串專用集合 */private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};/** * 獲取私鑰 * * @return 當前的私鑰對象 */public RSAPrivateKey getPrivateKey() { return privateKey;}/** * 獲取公鑰 * * @return 當前的公鑰對象 */public RSAPublicKey getPublicKey() { return publicKey;}/** * 隨機生成密鑰對 */public void genKeyPair() { KeyPairGenerator keyPairGen = null; try {  keyPairGen = KeyPairGenerator.getInstance("RSA"); } catch (NoSuchAlgorithmException e) {  e.printStackTrace(); } keyPairGen.initialize(1024, new SecureRandom()); KeyPair keyPair = keyPairGen.generateKeyPair(); this.privateKey = (RSAPrivateKey) keyPair.getPrivate(); this.publicKey = (RSAPublicKey) keyPair.getPublic();}/** * 從文件中輸入流中加載公鑰 * * @param in 公鑰輸入流 * @throws Exception 加載公鑰時產生的異常 */public void 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('/r');   }  }  loadPublicKey(sb.toString()); } catch (IOException e) {  throw new Exception("公鑰數據流讀取錯誤"); } catch (NullPointerException e) {  throw new Exception("公鑰輸入流為空"); }}/** * 從字符串中加載公鑰 * * @param publicKeyStr 公鑰數據字符串 * @throws Exception 加載公鑰時產生的異常 */public void loadPublicKey(String publicKeyStr) throws Exception { try { // byte[] buffer = Base64.decode(publicKeyStr.getBytes(), Base64.DEFAULT);  BASE64Decoder base64Decoder= new BASE64Decoder();  byte[] buffer= base64Decoder.decodeBuffer(publicKeyStr);  KeyFactory keyFactory = KeyFactory.getInstance("RSA");  X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);  this.publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec); } catch (NoSuchAlgorithmException e) {  throw new Exception("無此算法"); } catch (InvalidKeySpecException e) {  throw new Exception("公鑰非法"); } catch (NullPointerException e) {  throw new Exception("公鑰數據為空"); }}/** * 從文件中加載私鑰 * * @return 是否成功 * @throws Exception */public void 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('/r');   }  }  loadPrivateKey(sb.toString()); } catch (IOException e) {  throw new Exception("私鑰數據讀取錯誤"); } catch (NullPointerException e) {  throw new Exception("私鑰輸入流為空"); }}public void loadPrivateKey(String privateKeyStr) throws Exception { try {  //byte[] buffer = Base64.encode(privateKeyStr.getBytes(), Base64.DEFAULT);  BASE64Decoder base64Decoder= new BASE64Decoder();  byte[] buffer= base64Decoder.decodeBuffer(privateKeyStr);  PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);  KeyFactory keyFactory = KeyFactory.getInstance("RSA");  this.privateKey = (RSAPrivateKey) keyFactory.generatePrivate(keySpec); } catch (NoSuchAlgorithmException e) {  throw new Exception("無此算法"); } catch (InvalidKeySpecException e) {  throw new Exception("私鑰非法"); } catch (NullPointerException e) {  throw new Exception("私鑰數據為空"); }}/** * 加密過程 * * @param publicKey  公鑰 * @param plainTextData 明文數據 * @return * @throws Exception 加密過程中的異常信息 */public byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData) throws Exception { if (publicKey == null) {  throw new Exception("加密公鑰為空, 請設置"); } Cipher cipher = null; try {    cipher = Cipher.getInstance("RSA");  //Android端無需添加此加密提供者,已默認實現  //cipher = Cipher.getInstance("RSA", new BouncyCastleProvider());  cipher.init(Cipher.ENCRYPT_MODE, publicKey);  return cipher.doFinal(plainTextData); } catch (NoSuchAlgorithmException e) {  throw new Exception("無此加密算法"); } catch (NoSuchPaddingException e) {  e.printStackTrace();  return null; } catch (InvalidKeyException e) {  throw new Exception("加密公鑰非法,請檢查"); } catch (IllegalBlockSizeException e) {  throw new Exception("明文長度非法"); } catch (BadPaddingException e) {  throw new Exception("明文數據已損壞"); }}/** * 解密過程 * * @param privateKey 私鑰 * @param cipherData 密文數據 * @return 明文 * @throws Exception 解密過程中的異常信息 */public byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherData) throws Exception { if (privateKey == null) {  throw new Exception("解密私鑰為空, 請設置"); } Cipher cipher = null; try {  cipher = Cipher.getInstance("RSA");  //Android端無需添加此加密提供者,已默認實現  //cipher = Cipher.getInstance("RSA", new BouncyCastleProvider());  cipher.init(Cipher.DECRYPT_MODE, privateKey);  byte[] output = cipher.doFinal(cipherData);  return output; } catch (NoSuchAlgorithmException e) {  throw new Exception("無此解密算法"); } catch (NoSuchPaddingException e) {  e.printStackTrace();  return null; } catch (InvalidKeyException e) {  throw new Exception("解密私鑰非法,請檢查"); } catch (IllegalBlockSizeException e) {  throw new Exception("密文長度非法"); } catch (BadPaddingException e) {  throw new Exception("密文數據已損壞"); }}/** * 字節數據轉十六進制字符串 * * @param data 輸入數據 * @return 十六進制內容 */public static String byteArrayToString(byte[] data) { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < data.length; i++) {  //取出字節的高四位 作為索引得到相應的十六進制標識符 注意無符號右移   stringBuilder.append(HEX_CHAR[(data[i] & 0xf0) >>> 4]);  //取出字節的低四位 作為索引得到相應的十六進制標識符   stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]);  if (i < data.length - 1) {   stringBuilder.append(' ');  } } return stringBuilder.toString();}public static void main(String[] args) { RSAEncrypt rsaEncrypt = new RSAEncrypt(); //加載公鑰 try {  rsaEncrypt.loadPublicKey(RSAEncrypt.DEFAULT_PUBLIC_KEY);  System.out.println("加載公鑰成功"); } catch (Exception e) {  System.err.println(e.getMessage());  System.err.println("加載公鑰失敗"); } /*try {  rsaEncrypt.loadPublicKey(RSAEncrypt.DEFAULT_PUBLIC_KEY);  System.out.println("加載公鑰成功"); } catch (Exception e) {  System.err.println(e.getMessage());  System.err.println("加載公鑰失敗"); } //加載私鑰 try {  rsaEncrypt.loadPrivateKey(RSAEncrypt.DEFAULT_PRIVATE_KEY);  System.out.println("加載私鑰成功"); } catch (Exception e) {  System.err.println(e.getMessage());  System.err.println("加載私鑰失敗"); } try {  SecureRandom sr = new SecureRandom();  KeyGenerator kg = KeyGenerator.getInstance("DES");  kg.init(56, sr);  SecretKey generateKey = kg.generateKey();  String encodeHexString = Hex.toHexString(generateKey.getEncoded());  System.out.println(encodeHexString); } catch (NoSuchAlgorithmException e) {  e.printStackTrace(); } //測試字符串 String encryptStr= "Test String chaijunkun"; try {  //加密  long encryptStart = System.currentTimeMillis();  byte[] cipher = rsaEncrypt.encrypt(rsaEncrypt.getPublicKey(), encryptStr.getBytes());  long encryptEnd = System.currentTimeMillis();  System.out.println("密文長度:"+ cipher.length);  System.out.println(RSAEncrypt.byteArrayToString(cipher));  System.out.println("加密時間"+ (encryptEnd-encryptStart));  //解密  long decryptStart = System.currentTimeMillis();  byte[] plainText = rsaEncrypt.decrypt(rsaEncrypt.getPrivateKey(), cipher);  long decryptEnd = System.currentTimeMillis();  System.out.println("明文長度:"+ plainText.length);  System.out.println(RSAEncrypt.byteArrayToString(plainText));  System.out.println("解密時間"+ (decryptEnd-decryptStart));  System.out.println(new String(plainText)); } catch (Exception e) {  System.err.println(e.getMessage()); }*/   }} 

DES工具類實現

public class DESCoder {/** * 密鑰算法 * java 7只支持56位密鑰 * Bouncy Castle 支持64位密鑰 */public static final String KEY_ALGORITHM = "DES";/** * 加密/解密算法 /工作模式/填充方式 */public static final String CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding";/** * 轉換密鑰 * @param key 二進制密鑰 * @return key 密鑰 * @throws Exception */private static Key toKey(byte[] key) throws Exception{ //實例化DES密鑰材料 DESKeySpec dks = new DESKeySpec(key); //實例化密鑰工廠 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM); //生產密鑰 SecretKey secretKey = keyFactory.generateSecret(dks); return secretKey;}/** * 解密 * @param data 待解密數據 * @param key 密鑰 * @return byte[] 解密數據 * @throws Exception */public static byte[] decrypt(byte[] data,byte[] key) throws Exception{ //還原密鑰 Key k = toKey(key); //實例化  Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); //初始化,設置為解密模式 cipher.init(Cipher.DECRYPT_MODE, k); //執行操作 return cipher.doFinal(data);}/** * 加密 * @param data 待加密數據 * @param key 密鑰 * @return byte[] 加密數據 * @throws Exception */public static byte[] encrypt(byte[] data,byte[] key) throws Exception{ //還原密鑰 Key k = toKey(key); //實例化 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM,new BouncyCastleProvider()); //初始化,設置為加密模式 cipher.init(Cipher.ENCRYPT_MODE,k); //執行操作 return cipher.doFinal(data);}/** * 生產密鑰 * java 7只支持56位 密鑰 * Bouncy Castle 支持64位密鑰 * @return byte[] 二進制密鑰 * @throws Exception */public static byte[] initKey() throws Exception{ /*  * 實例化密鑰生成器  * 若要使用64位密鑰注意替換  * 講下述代碼中的  * KeyGenerator.getInstance(KEY_ALGORITHM);  * 替換為  * KeyGenerator.getInstance(KEY_ALGORITHM,"BC");  */ KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM,new BouncyCastleProvider()); kg.init(64); //生成密鑰 SecretKey secretKey = kg.generateKey(); //獲得密鑰的二進制編碼形式 return secretKey.getEncoded();}}

四、JavaWeb端配置

Web后端只需要在Controller中添加以下代碼,接受服務端傳遞的data和sign,并完成接收的Json字符串轉換為實體類即可

/** * 解密所需數據 * * @param data 接受客戶端上傳的Json格式的數據 * @param sign 接受客戶端上傳的解密數據的key值 */public <T> T convertJson(String data, String sign,Class<T> clazz) { System.out.println(data); System.out.println(sign); T tClass = null; try {  //rsa加密  RSAEncrypt rsaEncrypt = new RSAEncrypt();  //加載rsa私鑰  InputStream in = new FileInputStream(new File("C://OpenSSL-Win64//bin//pkcs8_rsa_private_key.pem"));  rsaEncrypt.loadPrivateKey(in);  //獲取RSA加密的key的數據,并把該16進制的sign轉成byte[],(客戶端采用將byte[]轉成16進制進行數據上傳)  byte[] keyBytes = parseHexStr2Byte(sign);  //通過RSA解密DES的key值  byte[] rsaKey = rsaEncrypt.decrypt(rsaEncrypt.getPrivateKey(), keyBytes);  //通過DES的key值解密需要的json數據  byte[] desData = DESCoder.decrypt(parseHexStr2Byte(data), rsaKey);  System.out.println(Arrays.toString(desData));  System.out.println(new String(desData));  tClass = JSON.parseObject(new String(desData), clazz); } catch (Exception e) {  e.printStackTrace(); } return tClass;}

五、備注

后續會上傳相關Demo到Github

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 蛟河市| 长岛县| 义乌市| 洮南市| 佳木斯市| 林州市| 山东省| 任丘市| 乌兰县| 舞阳县| 沙河市| 叶城县| 洛隆县| 仪陇县| 滨海县| 徐水县| 黄冈市| 五大连池市| 无棣县| 奉节县| 措勤县| 明星| 武强县| 新建县| 宜章县| 永仁县| 房产| 罗城| 都兰县| 剑河县| 隆子县| 济南市| 内乡县| 哈密市| 济阳县| 吴川市| 岳阳县| 西平县| 磐石市| 哈密市| 大悟县|