Android使用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方法中的生成密钥对的方法,获取到生成的公钥和密钥对。
然后将它们赋值到最上面的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加密接口调用的资料请关注其它相关文章!
上一篇: 正则表达式教程之元字符的使用详解
下一篇: 正则表达式教程之重复匹配详解