微信小程序RSA非对称加密。

因公司做的产品为金融项目,所以对数据安全性有很高要求,因为项目中的数据都会通过3DES 对称加密,和RSA非对称加密进行数据传输。

在这里先简单介绍一下什么是对称加密非对称加密

对称加密:对称加密采用了对称密码编码技术,它的特点是文件加密和解密使用相同的密钥加密

非对称加密:对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)(ps:公钥放在客户端,用于加密;私钥放在服务器端,用于解密)

 

本文先实现RSA非对称加解密,3DES对称加密的文章在

https://blog.csdn.net/qq_34024275/article/details/82421075

RSA一般用于重要数据加密,例如用户密码,金额,优惠卷等,并且解密速度比3DES解密慢许多,所以慎用。

提供一个生成RSA秘钥的网站

http://web.chacuo.net/netrsakeypair

需要注意的是:区分RSA私钥的类型,有pkcs1和pkcs8。pkcs8格式的私钥主要用于java中。   

// pkcs1格式:
-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY------

// pkcs8格式:
-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----

本文生成的key为pkcs1格式的。

第一步:构建前端加解密工具

 另一篇微信小程序3DES加密文章中用到加密的库为google的Cryptojs,里面有很多种加密方式,但唯独没有RSA的,这就比较坑爹,不得不寻找新的加解密工具。

由于并非专业前端工程师,所以只有请求度娘的帮助,查到了现在前端工程师一般都是用JSEncrypt,下面附上官网地址:

http://travistidwell.com/jsencrypt/

由于JSEncrypt主要是用于前端H5开发加解密,工具内部本身会调用浏览器Window对象和navigator对象,而微信小程序本身不属于浏览器环境,没有Window对象和navigator对象。所以我们需要去修改原文件jsencrypt.min.js(这是压缩版)或jsencrypt.js,去构建Window对象和navigator对象,不然会提示undefined。

主要将以下代码插入到jsencrypt.js文件中:

var navigator = {
    appName: 'Netscape',
    userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46     (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1'
};
var window={
    ASN1:null,
    Base64:null,
    Hex:null,
    crypto:null,
    href:null
};

插入位置,

插入到  'use strict'; 后面。

第二步:在项目加密工具类用引入JSEncrypt

import { JSEncrypt } from '../js/jsencrypt.min.js'

/**rsa加密
**@param text 需要加密的文本
**@param publicKey 加密需要的公钥  pkcs1 类型的公钥
**/
export const encryptByRsa = (text,publicKey) => {
  var encrypt = new JSEncrypt();
  encrypt.setPublicKey(publicKey);
  var encrypted = encrypt.encrypt(text);
  return encrypted
}

ps:由于项目中RSA前端只加密,所以这里只写了加密方法,解密方法类似,具体可以看文档

第三步:创建java后端加解密工具类RSAUtil.java

package com.uaf.wxAppWeb.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

import org.apache.commons.codec.binary.Base64;

/**
 * RSA算法
 * 
 */
public class RSAUtil {



	/**
	 * 公钥加密
	 * 
	 * @param content
	 * @param public_key
	 * @return
	 * @throws Exception
	 */
	public static String signWithPublicKey(String content, String public_key) throws Exception {
		byte[] buffer = Base64.decodeBase64(public_key);
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
		RSAPublicKey publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);
		Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
		cipher.init(1, publicKey);
		byte[] data = content.getBytes("utf-8");
		int inputLen = data.length;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		int offSet = 0;
		int key_len = publicKey.getModulus().bitLength() / 8 - 11;
		for (int i = 0; inputLen - offSet > 0; offSet = i * key_len) {
			byte[] cache;
			if (inputLen - offSet > key_len) {
				cache = cipher.doFinal(data, offSet, key_len);
			} else {
				cache = cipher.doFinal(data, offSet, inputLen - offSet);
			}

			out.write(cache, 0, cache.length);
			++i;
		}

		byte[] encryptedData = out.toByteArray();
		out.close();
		return new String(Base64.encodeBase64(encryptedData));
	}

	/**
	 * 私钥解密
	 * 
	 * @param content 密文
	 * @param private_key 私钥
	 * @param input_charset  编码UTF-8
	 * @return
	 * @throws Exception
	 */
	public static String decryptByPrivateKey(String content, String private_key) throws Exception {

		String input_charset = "UTF-8";
		PrivateKey prikey = getPrivateKey(private_key);

		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.DECRYPT_MODE, prikey);

		InputStream ins = new ByteArrayInputStream(Base64.decodeBase64(content));
		ByteArrayOutputStream writer = new ByteArrayOutputStream();
		// rsa解密的字节大小最多是128,将需要解密的内容,按128位拆开解密
		byte[] buf = new byte[128];
		int bufl;

		while ((bufl = ins.read(buf)) != -1) {
			byte[] block = null;

			if (buf.length == bufl) {
				block = buf;
			} else {
				block = new byte[bufl];
				for (int i = 0; i < bufl; i++) {
					block[i] = buf[i];
				}
			}

			writer.write(cipher.doFinal(block));
		}

		return new String(writer.toByteArray(), input_charset);
	}

}

到这里小程序所需要的RSA加密工具类都已经构建完毕。

需要注意的地方是:这里的代码适用于生成PKCS1秘钥,一定要在JSencrypt里面构建Window对象和navigator对象。

由于小程序主包大小限制,所以选择的是min压缩的js文件,修改的时候需要注意一点。

小白程序员一枚,如有问题欢迎留言一起探讨~~

 

 

 

 

 

 

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值