目录
背景
实现
一、node代码
1、引入依赖
2、生成公钥和私钥
3、生成工具类
二、java代码
背景
本来项目的后端是node,里面登录接口用的是后端生成RSA公钥和私钥,公钥给前端网页用来加密,node后端解密,一切很和谐,突然要我上一个Android应用,结果java和node两边就是无法通配。
原因:默认的RSA加解密格式不一样,node默认的 'pkcs1_oaep', 而java中默认的是pkcs8。
解决方法:两边都采用同一种模式就好了,这里我修改node为pkcs8.
实现
一、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' +'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9WbdF8v9qt9u1nEbUnWLlDa/e\n' +'3gc67MhCgzRlwq+s7xVP6usKJbqB7FUIM0k1e7nx1eMgmpkL4y4sLjuWzms6OXo5\n' +'OFdb64RbdTKfo91bBVW9kWov8SiLL3/Y5NlEtG+uG0DWZSbBc73vPQlvUT/6Kuy9\n' +'7qFpCjXmyIDbHLUKQQIDAQAB\n' +'-----END PUBLIC KEY-----'var privateKey = '-----BEGIN PRIVATE KEY-----\n' +'MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAL1Zt0Xy/2q327Wc\n' +'RtSdYuUNr97eBzrsyEKDNGXCr6zvFU/q6woluoHsVQgzSTV7ufHV4yCamQvjLiwu\n' +'O5bOazo5ejk4V1vrhFt1Mp+j3VsFVb2Rai/xKIsvf9jk2US0b64bQNZlJsFzve89\n' +'CW9RP/oq7L3uoWkKNebIgNsctQpBAgMBAAECgYB+KRK15oxL/KjFPpTrANptp0rx\n' +'AZprpmxf9K+qxabrYHkgwHNOVYkJHAAj8JfsrL1d5pbomFk01G9lPICzoGFMSaNA\n' +'kFlC15Td6/ERbDrIXjDjcggL8FfkWm1mb3UEZJsN/dLCclMDCEYnLMgfBKrj651+\n' +'Y9wvlqn0cltrIThbSQJBAO+U10ZHVnzO1A+FFN5NK7yoqGn/mOvwPIObEyASGznK\n' +'X0EpDcamt5giH7GrTaId24vILX1MpI+YamU3xzp3w/8CQQDKU6KUALBuKOLQrYW4\n' +'4wtdBiOSHsYbcMXJoXC+NAhwb6kz1aCnGRfxtzpVZmMtaoIzxuzmqdya09OTazyX\n' +'KjG/AkEAgqdM7wqgY9f3Va9hvgmfvHbNwWCeaKzOk4bSWz8EkfOHFuXomVj57oFN\n' +'f3rID4zw2b4E8LwHUjfwbdqJT51YyQJBAKsP/1tHIeRhqTNqIq9pN0hVUmnOnwzA\n' +'UlnhpyMJd0EpB1QOAKCG9NmnYyilQqE5dhA01kNHxn8ZLb9sYXQldp0CQQC1DOqN\n' +'5N8xx/k65MFgxIM/asyRhe6YCG7SCIAdyAau0S7v+Qf7R6tX4jWHWxhQfRl2dHKx\n' +'a3JZu+LOb8XwDxNQ\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 ="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9WbdF8v9qt9u1nEbUnWLlDa/e" +"3gc67MhCgzRlwq+s7xVP6usKJbqB7FUIM0k1e7nx1eMgmpkL4y4sLjuWzms6OXo5" +"OFdb64RbdTKfo91bBVW9kWov8SiLL3/Y5NlEtG+uG0DWZSbBc73vPQlvUT/6Kuy9" +"7qFpCjXmyIDbHLUKQQIDAQAB";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 ="MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAL1Zt0Xy/2q327Wc" +"RtSdYuUNr97eBzrsyEKDNGXCr6zvFU/q6woluoHsVQgzSTV7ufHV4yCamQvjLiwu" +"O5bOazo5ejk4V1vrhFt1Mp+j3VsFVb2Rai/xKIsvf9jk2US0b64bQNZlJsFzve89" +"CW9RP/oq7L3uoWkKNebIgNsctQpBAgMBAAECgYB+KRK15oxL/KjFPpTrANptp0rx" +"AZprpmxf9K+qxabrYHkgwHNOVYkJHAAj8JfsrL1d5pbomFk01G9lPICzoGFMSaNA" +"kFlC15Td6/ERbDrIXjDjcggL8FfkWm1mb3UEZJsN/dLCclMDCEYnLMgfBKrj651+" +"Y9wvlqn0cltrIThbSQJBAO+U10ZHVnzO1A+FFN5NK7yoqGn/mOvwPIObEyASGznK" +"X0EpDcamt5giH7GrTaId24vILX1MpI+YamU3xzp3w/8CQQDKU6KUALBuKOLQrYW4" +"4wtdBiOSHsYbcMXJoXC+NAhwb6kz1aCnGRfxtzpVZmMtaoIzxuzmqdya09OTazyX" +"KjG/AkEAgqdM7wqgY9f3Va9hvgmfvHbNwWCeaKzOk4bSWz8EkfOHFuXomVj57oFN" +"f3rID4zw2b4E8LwHUjfwbdqJT51YyQJBAKsP/1tHIeRhqTNqIq9pN0hVUmnOnwzA" +"UlnhpyMJd0EpB1QOAKCG9NmnYyilQqE5dhA01kNHxn8ZLb9sYXQldp0CQQC1DOqN" +"5N8xx/k65MFgxIM/asyRhe6YCG7SCIAdyAau0S7v+Qf7R6tX4jWHWxhQfRl2dHKx" +"a3JZu+LOb8XwDxNQ";//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));}
}