crypto.js 4.3 KB
Newer Older
VK1688's avatar
VK1688 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
/**
 * 加密模块
 */

/*
加密解密示例
const payCrypto = require('../libs/crypto.js'); // 获取加密服务(注意文件所在相对路径)
let ciphertext = { a:1,b:2 };
let encrypted = payCrypto.aes.encrypt({
	data: ciphertext, // 待加密的原文
});

let decrypted = payCrypto.aes.decrypt({
	data: encrypted, // 待解密的原文
});
// 最终解密得出 decrypted = { a:1,b:2 } 
*/

const configCenter = require("uni-config-center");
const config = configCenter({ pluginId: 'uni-pay' }).requireFile('config.js');
const crypto = require("crypto");

var util = {};
util.aes = {};
/**
 * aes加密
 * @param {Object} data 待加密的原文
 * @param {Object} key 密钥,如不传,自动取config
 * @param {String} mode 默认为aes192支持64位或64以上密钥 其他可选(aes-256-ecb 兼容java等其他后端语言)
 * 调用示例
let encrypted = crypto.aes.encrypt({
	mode: "aes192",
	data: "", // 待加密的原文
});
 */
util.aes.encrypt = function(obj) {
	let {
		data, // 待加密的原文
		key, // 密钥,如不传,自动取config
		mode = "aes192",
	} = obj;
	if (!key) key = config.notifyKey;
	if (typeof data === "object") data = JSON.stringify(data);
	if (mode === "aes-256-ecb") {
		// aes-256-ecb算法
		return encryptUseAes256Ecb(data, key);
	} else {
		return encryptUseAes192(data, key);
	}
};

/**
 * aes解密
 * @param {Object} data 待解密的原文
 * @param {Object} key 密钥,如不传,自动取config
 * @param {String} mode 默认为aes192支持64位或64以上密钥 其他可选(aes-256-ecb 兼容java等其他后端语言)
 * 调用示例
let decrypted = crypto.aes.decrypt({
	mode: "aes192",
	data: "", // 待解密的原文
});
 */
util.aes.decrypt = function(obj) {
	let {
		data, // 待解密的原文
		key, // 密钥,如不传,自动取config
		mode = "aes192",
	} = obj;
	if (typeof data === "undefined") {
		throw "待解密原文不能为空";
	}
	if (!key) key = config.notifyKey;
	// 解密
	let decrypted;
	if (mode === "aes-256-ecb") {
		// aes-256-ecb算法
		return decryptUseAes256Ecb(data, key);
	} else {
		return decryptUseAes192(data, key);
	}
	// decrypted 为解密后的内容,即最开始需要加密的原始数据文本data
	return decrypted;
};

module.exports = util;

// aes192算法 - 加密
function encryptUseAes192(data, key) {
	const cipher = crypto.createCipher('aes192', key);
	let encrypted = cipher.update(data, 'utf8', 'hex');
	encrypted += cipher.final('hex');
	// encrypted 为加密后的内容
	return encrypted;
}

// aes192算法 - 解密
function decryptUseAes192(data, key) {
	// aes192 算法
	let decrypted;
	try {
		const decipher = crypto.createDecipher('aes192', key);
		decrypted = decipher.update(data, 'hex', 'utf8');
		decrypted += decipher.final('utf8');
		try {
			decrypted = JSON.parse(decrypted);
		} catch (err) {}
	} catch (err) {
		throw "解密失败";
	}
	// decrypted 为解密后的内容,即最开始需要加密的原始数据文本data
	return decrypted;
}

// aes-256-ecb算法 - 加密
function encryptUseAes256Ecb(data, key) {
	let paddedData = Buffer.from(data);
	let paddedkey = key;
	if (paddedkey.length > 32) {
		paddedkey = paddedkey.substring(0, 32);
	}
	paddedkey = Buffer.from(paddedkey);
	const cipher = crypto.createCipheriv('aes-256-ecb', paddedkey, '');
	cipher.setAutoPadding(false);
	const blockSize = 16; // AES块大小为16字节
	const paddingSize = blockSize - (paddedData.length % blockSize);
	const paddingBuffer = Buffer.alloc(paddingSize, paddingSize);
	paddedData = Buffer.concat([paddedData, paddingBuffer]);
	let encrypted = cipher.update(paddedData, null, 'base64');
	encrypted += cipher.final('base64');
	return encrypted;
}

// aes-256-ecb算法 - 解密
function decryptUseAes256Ecb(data, key) {
	let paddedkey = key;
	if (paddedkey.length > 32) {
		paddedkey = paddedkey.substring(0, 32);
	}
	paddedkey = Buffer.from(paddedkey);
	let decrypted;
	try {
		const decipher = crypto.createDecipheriv('aes-256-ecb', paddedkey, '');
		decipher.setAutoPadding(false);

		let decrypted = decipher.update(data, 'base64');
		decrypted += decipher.final();

		const lastByte = decrypted.charCodeAt(decrypted.length - 1);
		const paddingSize = lastByte;
		decrypted = decrypted.slice(0, decrypted.length - paddingSize);
		try {
			decrypted = JSON.parse(decrypted);
		} catch (err) {}
		return decrypted;
	} catch (err) {
		throw "解密失败";
	}
	return decrypted;
}