欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android使用RSA加密实现接口调用时的校验功能

程序员文章站 2022-03-10 22:02:45
rsa算法是一种非对称加密算法,那么何为非对称加密算法呢?一般我们理解上的加密是这样子进行的:原文经过了一把钥匙(密钥)加密后变成了密文,然后将密文传递给接收方,接收方再用这把钥匙(密钥)解开密文。在...

rsa算法是一种非对称加密算法,那么何为非对称加密算法呢?

一般我们理解上的加密是这样子进行的:原文经过了一把钥匙(密钥)加密后变成了密文,然后将密文传递给接收方,接收方再用这把钥匙(密钥)解开密文。在这个过程中,其实加密和解密使用的是同一把钥匙,这种加密方式称为对称加密。

而非对称加密就是和对称加密相对,加密用的钥匙和解密所用的钥匙,并不是同一把钥匙。非对称加密首先会创建两把钥匙,而这两把钥匙是成对的分别称为公钥和私钥。在进行加密时我们使用公钥进行加密,而在解密的时候就必须要使用私钥才能进行解密,这就是非对称加密算法。

假如使用非对称加密,甲发送消息给乙,这时候乙会预先创建好两把钥匙,私钥乙自己保存好,然后把公钥发送给甲,甲使用公钥对信息进行加密,然后传给乙。最后乙使用自己的私钥对数据进行解密。这个过程中,公钥还是有可能被第三者所截获,但是不同的是,这个第三者纵然得到了公钥,也无法解开密文,因为解密密文所需要的私钥从始至终一直在乙的手里。因此这个过程是安全的。

在一个android应用中录音完成后将录音文件上传到springboot搭建的后台接口中。

由于android应用中没有登录功能,所以需要对一串自定义字符串进行加密并传输,然后在springboot后台进行解密验证。防止上传接口暴露。

实现

首先在springboot端新建一个rsautils工具类

import com.sun.org.apache.xerces.internal.impl.dv.util.base64;
import java.io.bytearrayoutputstream;
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.spec.pkcs8encodedkeyspec;
import java.security.spec.x509encodedkeyspec;
import java.util.base64;

import javax.crypto.cipher;

//java 后端
public class rsautils {
 //私钥
 public static string privatekey = "自己生成的私钥";
 //公钥
 private static string publickey = "自己生成的公钥";
 /**
  * rsa最大加密明文大小
  */
 private static final int max_encrypt_block = 117;

 /**
  * rsa最大解密密文大小
  */
 private static final int max_decrypt_block = 128;

 /**
  * 获取密钥对
  *
  * @return 密钥对
  */
 public static keypair getkeypair() throws exception {
  keypairgenerator generator = keypairgenerator.getinstance("rsa");
  generator.initialize(1024);
  return generator.generatekeypair();
 }

 /**
  * 获取私钥
  *
  * @param privatekey 私钥字符串
  * @return
  */
 public static privatekey getprivatekey(string privatekey) throws exception {
  keyfactory keyfactory = keyfactory.getinstance("rsa");

  byte[] decodedkey = com.sun.org.apache.xerces.internal.impl.dv.util.base64.decode(new string(privatekey.getbytes()));
  pkcs8encodedkeyspec keyspec = new pkcs8encodedkeyspec(decodedkey);
  return keyfactory.generateprivate(keyspec);
 }

 /**
  * 获取公钥
  *
  * @param publickey 公钥字符串
  * @return
  */
 public static publickey getpublickey(string publickey) throws exception {
  keyfactory keyfactory = keyfactory.getinstance("rsa");
  byte[] decodedkey = base64.decode(publickey);
  x509encodedkeyspec keyspec = new x509encodedkeyspec(decodedkey);
  return keyfactory.generatepublic(keyspec);
 }

 /**
  * rsa加密
  *
  * @param data  待加密数据
  * @param publickey 公钥
  * @return
  */
 public static string encrypt(string data, publickey publickey) throws exception {
  cipher cipher = cipher.getinstance("rsa");
  cipher.init(cipher.encrypt_mode, publickey);
  int inputlen = data.getbytes().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.getbytes(), offset, max_encrypt_block);
   } else {
    cache = cipher.dofinal(data.getbytes(), offset, inputlen - offset);
   }
   out.write(cache, 0, cache.length);
   i++;
   offset = i * max_encrypt_block;
  }
  byte[] encrypteddata = out.tobytearray();
  out.close();
  // 获取加密内容使用base64进行编码,并以utf-8为标准转化成字符串
  // 加密后的字符串
  return new string(base64.encode((encrypteddata)));
 }

 /**
  * rsa解密
  *
  * @param data  待解密数据
  * @param privatekey 私钥
  * @return
  */
 public static string decrypt(string data, privatekey privatekey) throws exception {

  cipher cipher = cipher.getinstance("rsa");
  cipher.init(cipher.decrypt_mode, privatekey);
  byte[] databytes = base64.decode(data);
  int inputlen = databytes.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(databytes, offset, max_decrypt_block);
   } else {
    cache = cipher.dofinal(databytes, offset, inputlen - offset);
   }
   out.write(cache, 0, cache.length);
   i++;
   offset = i * max_decrypt_block;
  }
  byte[] decrypteddata = out.tobytearray();
  out.close();
  // 解密后的内容
  return new string(decrypteddata, "utf-8");
 }

 /**
  * 签名
  *
  * @param data  待签名数据
  * @param privatekey 私钥
  * @return 签名
  */
 public static string sign(string data, privatekey privatekey) throws exception {
  byte[] keybytes = privatekey.getencoded();
  pkcs8encodedkeyspec keyspec = new pkcs8encodedkeyspec(keybytes);
  keyfactory keyfactory = keyfactory.getinstance("rsa");
  privatekey key = keyfactory.generateprivate(keyspec);
  signature signature = signature.getinstance("md5withrsa");
  signature.initsign(key);
  signature.update(data.getbytes());
  return base64.encode(signature.sign());
 }

 /**
  * 验签
  *
  * @param srcdata 原始字符串
  * @param publickey 公钥
  * @param sign  签名
  * @return 是否验签通过
  */
 public static boolean verify(string srcdata, publickey publickey, string sign) throws exception {
  byte[] keybytes = publickey.getencoded();
  x509encodedkeyspec keyspec = new x509encodedkeyspec(keybytes);
  keyfactory keyfactory = keyfactory.getinstance("rsa");
  publickey key = keyfactory.generatepublic(keyspec);
  signature signature = signature.getinstance("md5withrsa");
  signature.initverify(key);
  signature.update(srcdata.getbytes());
  return signature.verify(base64.decode(sign));
 }


/* public static void main(string[] args) {
  try {
   // 生成密钥对
   keypair keypair = getkeypair();
   string privatekey = new string(base64.getencoder().encode(keypair.getprivate().getencoded()));
   string publickey = new string(base64.getencoder().encode(keypair.getpublic().getencoded()));
   system.out.println("私钥:" + privatekey);
   system.out.println("公钥:" + publickey);


   // rsa加密
*//*   string data = "待加密的文字内容";
   string encryptdata = encrypt(data, getpublickey(publickey));
   system.out.println("加密后内容:" + encryptdata);
   // rsa解密
   string decryptdata = decrypt("encryptdata ", getprivatekey(privatekey));
   system.out.println("解密后内容:" + decryptdata);

   // rsa签名
   string sign = sign(data, getprivatekey(privatekey));
   // rsa验签
   boolean result = verify(data, getpublickey(publickey), sign);
   system.out.print("验签结果:" + result);*//*
  } catch (exception e) {
   e.printstacktrace();
   system.out.print("加解密异常");
  }
 }*/

}

然后运行此工具类的main方法中的生成密钥对的方法,获取到生成的公钥和密钥对。

Android使用RSA加密实现接口调用时的校验功能

然后将它们赋值到最上面的privatekey和publickey。

然后在android端中也新建一个工具类rsautils

package com.badao.badaoimclient.common;

import android.util.base64;
import java.io.bytearrayoutputstream;
import java.security.keyfactory;
import java.security.publickey;
import java.security.spec.x509encodedkeyspec;
import javax.crypto.cipher;

public class rsautils{

 //公钥
 public static string publickey="跟java端同样的公钥";
 /**
  * rsa最大加密明文大小
  */
 private static final int max_encrypt_block = 117;

 /**
  * rsa最大解密密文大小
  */
 private static final int max_decrypt_block = 128;

 

 /**
  * 获取公钥
  *
  * @param publickey 公钥字符串
  * @return
  */
 public static publickey getpublickey(string publickey) throws exception {
  keyfactory keyfactory = keyfactory.getinstance("rsa");
  byte[] decodedkey =base64.decode(publickey.getbytes(), base64.default);
  x509encodedkeyspec keyspec = new x509encodedkeyspec(decodedkey);
  return keyfactory.generatepublic(keyspec);
 }

 /**
  * rsa加密
  *
  * @param data 待加密数据
  * @param publickey 公钥
  * @return
  */
 public static string encrypt(string data, publickey publickey) throws exception {
  cipher cipher ;
  cipher= cipher.getinstance("rsa/ecb/pkcs1padding");
  cipher.init(cipher.encrypt_mode, publickey);
  int inputlen = data.getbytes().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.getbytes(), offset, max_encrypt_block);
   } else {
    cache = cipher.dofinal(data.getbytes(), offset, inputlen - offset);
   }
   out.write(cache, 0, cache.length);
   i++;
   offset = i * max_encrypt_block;
  }
  byte[] encrypteddata = out.tobytearray();
  out.close();
  // 获取加密内容使用base64进行编码,并以utf-8为标准转化成字符串
  // 加密后的字符串
  return new string(base64.encode(encrypteddata, base64.default));
 }

}

这里的公钥与上面生成的公钥一致。

注意着两个工具类的区别

在android工具类中的base64引入的是

import android.util.base64;

而在java中引入的base64是

import com.sun.org.apache.xerces.internal.impl.dv.util.base64;

注意这里为什么不是引用java.util.base64,因为会有换行导致的转移字符的问题。

然后在android中对字符串进行加密

//获取加密字符串
string escode = "";
try {
  escode = rsautils.encrypt(key,rsautils.getpublickey(rsautils.publickey));
 } catch (exception e) {
  e.printstacktrace();
}

将其作为接口调用的参数传递到java中进行解密

if(decode.equals(rsautils.decrypt(key,rsautils.getprivatekey(rsautils.privatekey))))
  {
   try
   {
    // 上传文件路径
    string filepath = ruoyiconfig.getuploadpath();
    // 上传并返回新文件名称
    string filename = fileuploadutils.upload(filepath, file);
    string url = serverconfig.geturl() + filename;
    ajaxresult ajax = ajaxresult.success();
    ajax.put("filename", filename);
    ajax.put("url", url);
    return ajax;
   }
   catch (exception e)
   {
    return ajaxresult.error(e.getmessage());
   }
  }else {
   return ajaxresult.error("非法访问");
  }

这样就限制了只能通过指定的移动端对文件上传接口进行访问。

在移动端调用接口进行测试

Android使用RSA加密实现接口调用时的校验功能

可见调用接口前加密成功

并且能用过后台接口的解密校验

Android使用RSA加密实现接口调用时的校验功能

这样别的第三方请求接口就没法请求

Android使用RSA加密实现接口调用时的校验功能

以上就是android使用rsa加密实现接口调用时的校验功能的详细内容,更多关于android rsa加密接口调用的资料请关注其它相关文章!