Android使用RSA加密實現(xiàn)接口調用時的校驗功能
RSA算法是一種非對稱加密算法,那么何為非對稱加密算法呢?
一般我們理解上的加密是這樣子進行的:原文經過了一把鑰匙(密鑰)加密后變成了密文,然后將密文傳遞給接收方,接收方再用這把鑰匙(密鑰)解開密文。在這個過程中,其實加密和解密使用的是同一把鑰匙,這種加密方式稱為對稱加密。
而非對稱加密就是和對稱加密相對,加密用的鑰匙和解密所用的鑰匙,并不是同一把鑰匙。非對稱加密首先會創(chuàng)建兩把鑰匙,而這兩把鑰匙是成對的分別稱為公鑰和私鑰。在進行加密時我們使用公鑰進行加密,而在解密的時候就必須要使用私鑰才能進行解密,這就是非對稱加密算法。
假如使用非對稱加密,甲發(fā)送消息給乙,這時候乙會預先創(chuàng)建好兩把鑰匙,私鑰乙自己保存好,然后把公鑰發(fā)送給甲,甲使用公鑰對信息進行加密,然后傳給乙。最后乙使用自己的私鑰對數(shù)據(jù)進行解密。這個過程中,公鑰還是有可能被第三者所截獲,但是不同的是,這個第三者縱然得到了公鑰,也無法解開密文,因為解密密文所需要的私鑰從始至終一直在乙的手里。因此這個過程是安全的。
在一個Android應用中錄音完成后將錄音文件上傳到SpringBoot搭建的后臺接口中。
由于Android應用中沒有登錄功能,所以需要對一串自定義字符串進行加密并傳輸,然后在SpringBoot后臺進行解密驗證。防止上傳接口暴露。
實現(xiàn)
首先在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 待加密數(shù)據(jù)
* @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;
// 對數(shù)據(jù)分段加密
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 待解密數(shù)據(jù)
* @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;
// 對數(shù)據(jù)分段解密
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 待簽名數(shù)據(jù)
* @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 待加密數(shù)據(jù)
* @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;
// 對數(shù)據(jù)分段加密
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));
}
}
這里的公鑰與上面生成的公鑰一致。
注意著兩個工具類的區(qū)別
在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();
}
將其作為接口調用的參數(shù)傳遞到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加密實現(xiàn)接口調用時的校驗功能的詳細內容,更多關于Android rsa加密接口調用的資料請關注腳本之家其它相關文章!
相關文章
android 限制某個操作每天只能操作指定的次數(shù)(示例代碼詳解)
這篇文章主要介紹了android 限制某個操作每天只能操作指定的次數(shù),本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-06-06
Android最新版本開發(fā)環(huán)境搭建圖文教程
這篇文章主要為大家詳細介紹了Android最新版本開發(fā)環(huán)境搭建圖文教程,重點在于配置JDK,以及adt-bundle,感興趣的小伙伴們可以參考一下2016-07-07
Android nativePollOnce函數(shù)解析
這篇文章主要介紹了Android nativePollOnce函數(shù)解析的相關資料,幫助大家更好的理解和學習使用Android,感興趣的朋友可以了解下2021-03-03
Android開發(fā)教程之Fragment定義、創(chuàng)建與使用方法詳解【包含Activity通訊,事務執(zhí)行等】
這篇文章主要介紹了Android開發(fā)教程之Fragment定義、創(chuàng)建與使用方法,詳細介紹了Fragment的概念、功能、定義、創(chuàng)建及使用方法,包括Fragment與Activity通訊,Fragment事務執(zhí)行及Fragment應用示例等,需要的朋友可以參考下2017-11-11

