目录
背景
实现
一、node代码
1、引入依赖
2、生成公钥和私钥
3、生成工具类
二、java代码
背景
本来项目的后端是node,里面登录接口用的是后端生成RSA公钥和私钥,公钥给前端网页用来加密,node后端解密,一切很和谐,突然要我上一个Android应用,结果java和node两边就是无法通配。
原因:默认的RSA加解密格式不一样,node默认的是DEFAULT_ENCRYPTION_SCHEME = 'pkcs1_oaep', 而java中默认的是pkcs1。
实现
一、node代码
1、引入依赖
npm install node-rsa
2、生成公钥和私钥
const NodeRSA = require('node-rsa')
// 生成密文(和java通用版本)
var key = new NodeRSA({b: 1024})
var privateKey = key.exportKey('pkcs8-private')
var publicKey = key.exportKey('pkcs8-public-pem')
console.log(privateKey)
console.log(publicKey)
3、生成工具类
const NodeRSA = require('node-rsa')
var publicKey = '-----BEGIN PUBLIC KEY-----\n' +
'...公钥...\n' +
'-----END PUBLIC KEY-----'
var privateKey = '-----BEGIN PRIVATE KEY-----\n' +
'...私钥...\n' +
'-----END PRIVATE KEY-----'
var key = new NodeRSA()
key.importKey(privateKey, 'pkcs8-private')
key.importKey(publicKey, 'pkcs8-public-pem')
// 加密
function encryption (data) {
try {
const dataEncry = key.encrypt(data, 'base64')
// 返回结果
return JSON.stringify({
code: 200,
data: dataEncry
})
} catch (e) {
// 返回错误
return JSON.stringify({
code: 500,
data: e
})
}
}
// 解密
function decryption (data) {
try {
const dataDecry = key.decrypt(data, 'utf8')
// 返回结果
return JSON.stringify({
code: 200,
data: dataDecry
})
} catch (e) {
// 返回错误
return JSON.stringify({
code: 500,
data: e
})
}
}
module.exports = {
encryption,
decryption
}
二、java代码
1、直接上工具类
注意:java代码中的公钥不需要开头和结尾的【-----BEGIN PUBLIC KEY-----】这个,只需要保留中间的密钥就好,且不要留有换行符【\n】。
import android.os.Build;
import androidx.annotation.RequiresApi;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
/**
* Rsa加解密工具(node后端通用版本)
*/
public class RsaUtil {
/**
* Rsa加密
* @param data 需要加密的数据
* @return 返回密文
*/
@RequiresApi(api = Build.VERSION_CODES.O)
public static String encrypt(String data) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
byte[] dataBytes = data.getBytes();
if (dataBytes.length > 214) throw new RuntimeException("不能一次性加密超过214字节的数据");
String pubKey =
"......你的公钥......";
Base64.Decoder decoder = Base64.getDecoder();
byte[] keyBytes = decoder.decode(pubKey);
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey pk = kf.generatePublic(spec);
byte[] cipherText;
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pk);
cipherText = cipher.doFinal(dataBytes);
Base64.Encoder encoder = Base64.getEncoder();
return encoder.encodeToString(cipherText);
}
/**
* Rsa解密
* @param data 需要解密的数据
* @return 明文
*/
@RequiresApi(api = Build.VERSION_CODES.O)
public static String decrypt(String data) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException {
String privateKey =
".......你自己的私钥......";
//64位解码加密后的字符串
Base64.Decoder decoder = Base64.getDecoder();
byte[] inputByte = decoder.decode(data.getBytes("UTF-8"));
//base64编码的私钥
byte[] decoded = decoder.decode(privateKey);
RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
//RSA解密
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");
cipher.init(Cipher.DECRYPT_MODE, priKey);
return new String(cipher.doFinal(inputByte));
}
}