ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

js与java对接RSA加密、解密算法

2022-06-29 17:33:02  阅读:191  来源: 互联网

标签:java String RSA js static forge import security


一、什么是RSA加密

上世纪70年代产生的一种加密算法,其加密方式比较特殊,需要两个密钥:公开密钥简称公钥(publickey)和私有密钥简称私钥(privatekey)。公钥加密,私钥解密;私钥加密,公钥解密。这个算法就是伟大的RSA。

二、加密过程

使用公钥将数据加密,并通过私钥对加密信息进行解密。针对我们遇到的问题,公钥放在前端对用户名密码进行加密,私钥放在服务端对前端提交的加密数据进行解密,然后在做登陆的业务操作。流程如下图所示:

 

 

三、前端加密解密

根据模数和指数生成publicKey

  前端使用 node-forge 插件进行加密,后端并不会返回pem格式的公钥,而是返回模数(modules)和公钥指数(publicExponent),前端根据这两个参数去生成公钥

npm install --save node-forge
import forge from 'node-forge'

/**
 * 
 * @param msg 需要加密的字符
 * @param modules 模数
 * @param publicExponent 公钥指数
 * @returns 加密之后的字符串 16进制
 */
function aesEncrypt(msg, modules, publicExponent) {
  const BigInteger = forge.jsbn.BigInteger
  const n = forge.util.createBuffer(modules).toString('hex')
  const e = forge.util.createBuffer(publicExponent).toString('hex')
  const publicKey = forge.pki.setRsaPublicKey(new BigInteger(n, 16), new BigInteger(e, 16))

  const buffer = forge.util.createBuffer(msg, 'utf8')
  const bytes = buffer.getBytes()

  const res = publicKey.encrypt(bytes, 'RSA-OAEP', {
    md: forge.md.sha256.create(),
    mgf1: {
      md: forge.md.sha256.create()
    }
  })
  return forge.util.bytesToHex(res)
}

/**
 * 
 * @param serect 需要解密的字符串
 * @param modules 模数
 * @param publicExponent 公钥指数
 * @param privateExponent 私钥指数
 * @returns 解密后的字符串
 */
function aesDecrypt(serect, modules, publicExponent, privateExponent) {
  const BigInteger = forge.jsbn.BigInteger
  const n = forge.util.createBuffer(modules).toString('hex')
  const e = forge.util.createBuffer(publicExponent).toString('hex')
  const d = forge.util.createBuffer(privateExponent).toString('hex')
  const privateKey = forge.pki.setRsaPrivateKey(new BigInteger(n, 16), new BigInteger(e, 16), new BigInteger(d, 16))

  const res = privateKey.decrypt(res, 'RSA-OAEP', {
    md: forge.md.sha256.create(),
    mgf1: {
      md: forge.md.sha256.create()
    }
  })
  return res
}

 

四、后端加密代码

package com.example;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import java.security.InvalidParameterException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.Date;

import javax.crypto.Cipher;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.Test;
/**
 * Unit test for simple App.
 */
public class AppTest {
    public static String RSA_KEY = "RSA";
    public static String RSA_ALGORITHM = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
    private static final Provider DEFAULT_PROVIDER = new BouncyCastleProvider();
    private static KeyFactory keyFactory = null;

    public static String PrivateEx="4abbae70395...";
    public static String PrivateMo="c8c156b0806..."; // modules
    public static String PublicEx="10001";
    public static String PublicMo="c8c156b0806..."; // modules
    static {
        try {

          keyFactory = KeyFactory.getInstance("RSA", DEFAULT_PROVIDER);
        } catch (NoSuchAlgorithmException ex) {
        }
    }

    public static String UTF8 = "UTF-8";

    /**
     * 通过私钥byte[]将公钥还原,适用于RSA算法
     * 
     * @param keyBytes
     * @return
     * @throws Exception
     */
    public static RSAPrivateKey getPrivateKey(String modulus, String exponent) throws Exception {
        RSAPrivateKeySpec privateKey = new RSAPrivateKeySpec(new BigInteger(modulus,16), new BigInteger(exponent,16));
        return (RSAPrivateKey) keyFactory.generatePrivate(privateKey);
    }

    public static byte[] decrypt(PrivateKey privateKey, byte[] data) throws Exception {
        RSAPrivateKey rsaKey = (RSAPrivateKey) privateKey;
        Cipher ci = Cipher.getInstance(RSA_ALGORITHM, DEFAULT_PROVIDER);
        ci.init(Cipher.DECRYPT_MODE, rsaKey);

        ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        Integer index = 0;
        Integer blockSize = rsaKey.getModulus().bitLength() / 8;
        byte[] buffer = new byte[blockSize];
        while ((index = inputStream.read(buffer, 0, blockSize)) > 0) {
            byte[] clpherBlock = ci.doFinal(buffer, 0, index);
            outputStream.write(clpherBlock);
        }

        byte[] result= ((ByteArrayOutputStream) outputStream).toByteArray();
        outputStream.flush();
        return result;
    }

    public static String decryptString(PrivateKey privateKey, String encrypttext) {
        try {
            byte[] en_data = Hex.decodeHex(encrypttext.toCharArray());
            byte[] data = decrypt(privateKey, en_data);
            return new String(data);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    /**
     * Rigorous Test :-)
     */
    
    public void shouldAnswerWithTrue() {
        String exponent = PrivateEx;
        String modulus =PrivateMo;
        String encryption = "3532a86906a..."; // 需要解密的串
        try {
            String result = decryptString(getPrivateKey(modulus, exponent),encryption);
            System.out.println("解密结果:" + result);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    public static void main(String[] args) {
      new AppTest().shouldAnswerWithTrue();
    }
}

 

参考:

  node-forge

标签:java,String,RSA,js,static,forge,import,security
来源: https://www.cnblogs.com/shenjp/p/16424267.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有