跳转到主要内容

概述

RSAUtils 是实现RSA公钥加密和解密的工具类,采用非对称加密算法保障数据传输安全。在API通信中,用于对敏感业务数据进行加密传输,以及解密服务器返回的加密数据。

代码实例

import java.io.ByteArrayOutputStream;
import java.util.Base64;
import javax.crypto.Cipher;
import java.security.Key;
import java.security.KeyFactory;
import java.security.spec.X509EncodedKeySpec;

/**
* RSA公钥加解密工具类
* <p>
* 提供基于公钥的非对称加密解密功能,
* 适用于API通信中的数据加密传输。
*/
public class RSAUtils {
  // RSA加密最大块大小(单位:字节)
  private static final int MAX_ENCRYPT_BLOCK = 117;

  /**
   * 使用公钥加密数据
   *
   * @param data 原始二进制数据
   * @param publicKey Base64编码的公钥字符串
   * @return 加密后的二进制数据
   *
   * 使用场景:在发送API请求前,加密业务数据。
   * 自动处理大数据的分段加密(117字节/块)。
   *
   * 示例:
   * byte[] encrypted = RSAUtils.encryptByPublicKey(
   *     jsonData.getBytes(),
   *     "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQ..."
   * );
   */
  public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {
      // 1. Base64解码公钥
      byte[] keyBytes = Base64Util.decodeString(publicKey);

      // 2. 生成公钥对象
      KeyFactory keyFactory = KeyFactory.getInstance("RSA");
      Key publicK = keyFactory.generatePublic(
              new X509EncodedKeySpec(keyBytes)
      );

      // 3. 创建并初始化加密器
      Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
      cipher.init(Cipher.ENCRYPT_MODE, publicK);

      // 4. 分段加密处理大数据
      int inputLen = data.length;
      int offset = 0;
      java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();

      while (inputLen - offset > 0) {
          int blockSize = Math.min(inputLen - offset, MAX_ENCRYPT_BLOCK);
          byte[] encryptedBlock = cipher.doFinal(data, offset, blockSize);
          out.write(encryptedBlock, 0, encryptedBlock.length);
          offset += blockSize;
      }

      return out.toByteArray();
  }

  /**
   * 使用公钥解密数据
   *
   * @param encryptedData 加密后的二进制数据
   * @param publicKey Base64编码的公钥字符串
   * @return 解密后的原始二进制数据
   *
   * 使用场景:解密API返回的加密数据。
   * 适用于小数据块的一次性解密操作。
   *
   * 示例:
   * byte[] decrypted = RSAUtils.decryptByPublicKey(
   *     encryptedBytes,
   *     "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQ..."
   * );
   */
  public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey) throws Exception {

      final int MAX_DECRYPT_BLOCK = 128;
      // 1. Base64解码公钥
      byte[] keyBytes = Base64Util.decodeString(publicKey);

      // 2. 生成公钥对象
      KeyFactory keyFactory = KeyFactory.getInstance("RSA");
      Key publicK = keyFactory.generatePublic(
              new X509EncodedKeySpec(keyBytes)
      );

      // 3. 创建并初始化解密器
      Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
      cipher.init(Cipher.DECRYPT_MODE, publicK);
     // 4. 一次性解密(适合小数据)
     //return cipher.doFinal(encryptedData);
      int inputLen = encryptedData.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(encryptedData, offSet, MAX_DECRYPT_BLOCK);
          } else {
              cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
          }
          out.write(cache, 0, cache.length);
          i++;
          offSet = i * MAX_DECRYPT_BLOCK;
      }
      byte[] decryptedData = out.toByteArray();
      out.close();
      return decryptedData;
  }
}
const crypto = require('crypto');
const Base64Util = require('./Base64Util');

/**
* RSA 公钥加解密工具类
*
* 提供基于公钥的非对称加密解密功能,
* 适用于 API 通信中的数据加密传输。
*/
class RSAUtils {
  // RSA 加密最大块大小(单位:字节)
  static MAX_ENCRYPT_BLOCK = 117;

  /**
   * 使用公钥加密数据
   * @param {Buffer} data - 原始二进制数据
   * @param {string} publicKey - Base64 编码的公钥字符串
   * @returns {Buffer} 加密后的二进制数据
   *
   * 使用场景:在发送 API 请求前,加密业务数据。
   * 自动处理大数据的分段加密(117 字节/块)。
   */
  static encryptByPublicKey(data, publicKey) {
      try {
          // 1. 将 Base64 公钥转换为 PEM 格式
          const pemKey = `-----BEGIN PUBLIC KEY-----\n${publicKey}\n-----END PUBLIC KEY-----`;

          // 2. 生成公钥对象
          const key = crypto.createPublicKey(pemKey);

          // 3. 创建并初始化加密器
          const encryptedParts = [];
          const buffer = Buffer.from(data);
          let offset = 0;
          const inputLen = buffer.length;

          // 4. 分段加密处理大数据
          while (offset < inputLen) {
              const blockSize = Math.min(inputLen - offset, RSAUtils.MAX_ENCRYPT_BLOCK);
              const chunk = buffer.slice(offset, offset + blockSize);
              const encryptedChunk = crypto.publicEncrypt({
                  key: key,
                  padding: crypto.constants.RSA_PKCS1_PADDING
              }, chunk);
              encryptedParts.push(encryptedChunk);
              offset += blockSize;
          }

          return Buffer.concat(encryptedParts);
      } catch (error) {
          throw new Error(`RSA 加密失败: ${error.message}`);
      }
  }

  /**
   * 使用公钥解密数据
   * @param {Buffer} encryptedData - 加密后的二进制数据
   * @param {string} publicKey - Base64 编码的公钥字符串
   * @returns {Buffer} 解密后的原始二进制数据
   *
   * 使用场景:解密 API 返回的加密数据。
   * 自动处理大数据的分段解密(128 字节/块)。
   */
  static decryptByPublicKey(encryptedData, publicKey) {
      try {
          // 1. 将 Base64 公钥转换为 PEM 格式
          const pemKey = `-----BEGIN PUBLIC KEY-----\n${publicKey}\n-----END PUBLIC KEY-----`;

          // 2. 生成公钥对象
          const key = crypto.createPublicKey(pemKey);

          // 3. 创建并初始化解密器
          const decryptedParts = [];
          const buffer = Buffer.from(encryptedData);
          let offset = 0;
          const inputLen = buffer.length;
          const MAX_DECRYPT_BLOCK = 128;

          // 4. 分段解密
          while (offset < inputLen) {
              const blockSize = Math.min(inputLen - offset, MAX_DECRYPT_BLOCK);
              const chunk = buffer.slice(offset, offset + blockSize);
              const decryptedChunk = crypto.publicDecrypt({
                  key: key,
                  padding: crypto.constants.RSA_PKCS1_PADDING
              }, chunk);
              decryptedParts.push(decryptedChunk);
              offset += blockSize;
          }

          return Buffer.concat(decryptedParts);
      } catch (error) {
          throw new Error(`RSA 解密失败: ${error.message}`);
      }
  }
}

module.exports = RSAUtils;
import base64
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.backends import default_backend

class RSAUtils:
  # RSA加密最大块大小(单位:字节)
  MAX_ENCRYPT_BLOCK = 117

  @staticmethod
  def encrypt_by_public_key(data: bytes, public_key_str: str) -> bytes:
      """
      使用公钥加密数据
      @param data: 原始二进制数据
      @param public_key_str: Base64编码的公钥字符串
      @return: 加密后的二进制数据

      使用场景:在发送API请求前,加密业务数据
      自动处理大数据的分段加密(117字节/块)
      """
      # 1. Base64解码公钥
      public_key_der = base64.b64decode(public_key_str)

      # 2. 加载公钥对象
      public_key = serialization.load_der_public_key(
          public_key_der,
          backend=default_backend()
      )

      # 3. 分段加密
      offset = 0
      encrypted_chunks = []
      while offset < len(data):
          block = data[offset:offset + RSAUtils.MAX_ENCRYPT_BLOCK]
          encrypted_chunk = public_key.encrypt(
              block,
              padding.OAEP(
                  mgf=padding.MGF1(algorithm=hashes.SHA256()),
                  algorithm=hashes.SHA256(),
                  label=None
              )
          )
          encrypted_chunks.append(encrypted_chunk)
          offset += len(block)

      return b''.join(encrypted_chunks)

  @staticmethod
  def decrypt_by_public_key(encrypted_data: bytes, public_key_str: str) -> bytes:
      """
      使用公钥解密数据
      @param encrypted_data: 加密后的二进制数据
      @param public_key_str: Base64编码的公钥字符串
      @return: 解密后的原始二进制数据

      使用场景:解密API返回的加密数据
      适用于小数据块的一次性解密操作
      """
      # 1. Base64解码公钥
      public_key_der = base64.b64decode(public_key_str)

      # 2. 加载公钥对象
      public_key = serialization.load_der_public_key(
          public_key_der,
          backend=default_backend()
      )

      # 3. 一次性解密
      return public_key.decrypt(
          encrypted_data,
          padding.OAEP(
              mgf=padding.MGF1(algorithm=hashes.SHA256()),
              algorithm=hashes.SHA256(),
              label=None
          )
      )

# 使用示例
if __name__ == "__main__":
  # 模拟公钥字符串
  public_key = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQ..."

  # 待加密数据
  data = b"敏感数据12345"

  try:
      # 加密
      encrypted = RSAUtils.encrypt_by_public_key(data, public_key)
      print("加密结果:", base64.b64encode(encrypted).decode())

      # 解密
      decrypted = RSAUtils.decrypt_by_public_key(encrypted, public_key)
      print("解密结果:", decrypted.decode())
  except Exception as e:
      print("RSA操作失败:", e)