RSA加密---java和node兼容版(可直接复制使用)

目录

背景

实现

一、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、生成公钥和私钥

javascript 复制代码
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、生成工具类

javascript 复制代码
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】。

java 复制代码
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));
    }
}
相关推荐
Liquad Li8 小时前
ABP vNext 标准分层解决方案项目结构完整解析
后端
半夜燃烧的香烟8 小时前
docker 安装minio nginx,配置nginx根据文根路由minio展示图片
java·nginx·docker
MageGojo8 小时前
用 Node.js 把聚合 API 平台封装成零依赖命令行工具:registry 驱动的工程实践
node.js·restful·api接口·命令行工具·cli
吴阿福|一人公司8 小时前
深度解析 Python 类变量修改的命名空间隔离
java·服务器·数据结构
zzz_23688 小时前
【Java基础】链表的七十二变——从LRU缓存到手写浏览器前进后退
java·链表·缓存
番茄去哪了8 小时前
神领物流面试题(一)
java·大数据·中间件
云烟成雨TD8 小时前
Agent Scope Java 2.x 系列【9】接入高德 MCP 服务
java·人工智能·agent
布朗克1688 小时前
39 Spring Boot Web实战
前端·spring boot·后端·实战
gaohe26AIliuzeyu9 小时前
Java内部类
java·开发语言
西安邮电大学9 小时前
有关数组的经典算法题
java·后端·其他·算法·面试