详解Android端与JavaWeb传输加密(DES+RSA)

详解Android端与JavaWeb传输加密(DES+RSA),第1张

概述一、加密介绍本文采用对称式加密算法DES和非对称式加密算法RSA结合做数据传输加密的方式。

一、加密介绍

本文采用对称式加密算法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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

总结

以上是内存溢出为你收集整理的详解Android端与JavaWeb传输加密(DES+RSA)全部内容,希望文章能够帮你解决详解Android端与JavaWeb传输加密(DES+RSA)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1143883.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存