当前位置:   article > 正文

crypto-js的使用_crypto-js使用

crypto-js使用

如果不是跟c++对接,很多加密算法搞成java的人是很不容易接触到的,因为只需要调用jar就可以了。但是node侧就需要自己实现一些了
1 ECB算法
下面的算法正常貌似没有什么问题,但实际在解密的时候,经常出现有些c++加密的数据,在js侧却解不出来。

const CryptoJS = require('crypto-js');
const mode = CryptoJS.mode.ECB
const padding = CryptoJS.pad.NoPadding
/**
 * 解密方法
 * @param: str 需要解密的字符
 * @param: key 密钥
 * @param: iv 密钥偏移量
 */
function decrypt(str, key, iv) {
  const keyStr = key ? encParse(key) : encParse(defaultKey);
  const ivStr = iv ? encParse(iv) : encParse(defaultIv);

  // 判断str是否为base64,如果不是就要转base64,是了就不能再转
  const flag = isBase64(str);
  if (!flag) {
    // 转为base64之前要先转16进制
    str = CryptoJS.enc.Hex.parse(str);
    // 只有base64格式的字符才能被解密
    str = CryptoJS.enc.Base64.stringify(str);
  }

  const encryptedStr = CryptoJS.AES.decrypt(str, keyStr, {
    // iv: ivStr,
    mode: mode,
    padding: padding
  });
  return encryptedStr.toString(CryptoJS.enc.Utf8);
}
/**
 * 处理密钥字符格式
 * @param: key 需要转格式的字符
 */
function encParse(key) {
  return CryptoJS.enc.Utf8.parse(key);
  // return CryptoJS.enc.Latin1.parse(key);
}
  • 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

但在C++后台对接的时候,9条数据,有两条解密不了提示,这是什么原因呢?

VM2109 WAService.js:2 Error: Malformed UTF-8 data
    at Object.stringify (tripledes.js:450)
    at WordArray.init.toString (tripledes.js:205)
    at Object.decrypt (aes_util.js? [sm]:100)
    at Ze.jiemi (index.js? [sm]:53)
    at Object.o.safeCallback (VM2109 WAService.js:2)
    at VM2109 WAService.js:2
    at s (VM2109 WAService.js:2)
    at VM2109 WAService.js:2
    at v (VM2109 WAService.js:2)
    at VM2109 WAService.js:2(env: Windows,mp,1.06.2206090; lib: 2.17.0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

使用AES在线,是可以解密的
1
使用crypto-js不行,这个js库还是有关系,这个js端无法处理,只能从源头开始处理,将·回车键(换行符)去掉后,再加密后,传到前端,问题就可以解决了
今天想到一种更好的解决办法,灵感来自微信小程序解密手机号的cbc算法。

function decrypt(str, key, iv) {
	iv = iv || "";
	var clearEncoding = 'utf8';
	var cipherEncoding = 'base64';
	var cipherChunks = [];
	var decipher = crypto.createDecipheriv('aes-256-ecb', key, iv);
	decipher.setAutoPadding(false);
	cipherChunks.push(decipher.update(str, cipherEncoding, clearEncoding));
	cipherChunks.push(decipher.final(clearEncoding));
	let decoded = cipherChunks.join('');
	
	return decoded.toString(CryptoJS.enc.Utf8)

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

使用crypto是有权限的,应该是node的内置模块,如果跨平台,则不行,于是调整如下

function decrypt(str, key, iv) {
  key = CryptoJS.enc.Utf8.parse(key || defaultKey); // defaultKey应该是一个UTF-8编码的字符串  
  iv = iv || ""; // ECB模式不需要IV,但这里为了保持一致还是保留  
  // const str = yourEncryptedString; // base64编码的密文  
    
  // CryptoJS默认使用PKCS7填充,所以不需要显式设置setAutoPadding(false)  
  // 但如果你确实需要禁用自动填充(这通常不推荐),你将需要手动处理填充  
    
  // 解密  
  const bytes = CryptoJS.AES.decrypt({  
      ciphertext: CryptoJS.enc.Base64.parse(str) // 解析base64编码的密文  
  }, key, {  
      mode: CryptoJS.mode.ECB, // 注意:ECB模式通常被认为是不安全的  
      padding: CryptoJS.pad.Pkcs7 // CryptoJS默认使用PKCS7填充  
  });  
    
  // 获取解密后的字符串  
  const decoded = bytes.toString(CryptoJS.enc.Utf8); // 转换为UTF-8编码的字符串  
    
  // 返回解密后的字符串  
  return decoded;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

2 CBC算法
这个是微信小程序官方解密手机号的写法,依然是要安装crypto-js,看来crypto-js以来crypto

var crypto = require('crypto')

function WXBizDataCrypt(appId, sessionKey) {
  this.appId = appId
  this.sessionKey = sessionKey
}

WXBizDataCrypt.prototype.decryptData = function (encryptedData, iv) {
  // base64 decode
  var sessionKey = new Buffer(this.sessionKey, 'base64')
  encryptedData = new Buffer(encryptedData, 'base64')
  iv = new Buffer(iv, 'base64')

  try {
     // 解密
    var decipher = crypto.createDecipheriv('aes-128-cbc', sessionKey, iv)
    // 设置自动 padding 为 true,删除填充补位
    decipher.setAutoPadding(true)
    var decoded = decipher.update(encryptedData, 'binary', 'utf8')
    decoded += decipher.final('utf8')
    
    decoded = JSON.parse(decoded)

  } catch (err) {
    throw new Error('Illegal Buffer')
  }

  if (decoded.watermark.appid !== this.appId) {
    throw new Error('Illegal Buffer')
  }

  return decoded
}

module.exports = WXBizDataCrypt

  • 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

3 3DES 2倍长
nodejs实现3des(2倍长)加密方式,与DES加密工具一致
这里稍作了改动,它的程序实际应用有点小问题

const crypto = require('crypto');
const tools = require('./cgw');

const algorithm = { ecb: 'des-ecb' }

function encrypt(plaintext, keytext) {
	let key = new Uint8Array(keytext);
	let iv = new Uint8Array("");
	let txt = new Uint8Array(plaintext)
	let cipher = crypto.createCipheriv(algorithm.ecb, key, iv);
	cipher.setAutoPadding(true);
	let ciph = cipher.update(txt);
	return ciph;
}

function decrypt(encrypttext, keytext) {
	let key = new Uint8Array(keytext);
	let iv = new Uint8Array("");
	let txt = new Uint8Array(encrypttext);
	let decipher = crypto.createDecipheriv(algorithm.ecb, key, iv);
	decipher.setAutoPadding(true);
	decipher.update(txt);
	let ciph = decipher.update(txt);
	return ciph;
}

/**
 * 补00
 * @param {*} p 
 */
function fillZero(p){
	let nAddCount = (16-p.length%16)/2;
	for (let i=0; i<nAddCount; i++){
		p += '00';
	}
	return p;
}

/**
 * 规则是先加80,后面凑齐16的整数倍补00
 * 3DES双倍长
 * @param {*} src 
 * @param {*} key 
 */
function encrypt3Des(src, key) {
	src = tools.StringToAscii(src)+'80'
	src = fillZero(src)
	let temp = null;
	let temp1 = null;
	temp1 = encrypt(tools.HexStringToBytes(src), tools.HexStringToBytes(key.substring(0, 16)));
	temp = decrypt(temp1, tools.HexStringToBytes(key.substring(16, 32)));
	temp1 = encrypt(temp, tools.HexStringToBytes(key.substring(0, 16)));
	return tools.BytesToHexString(temp1);
}

function decrypt3Des(src, key) {
	let temp = null;
	let temp1 = null;
	temp1 = decrypt(tools.HexStringToBytes(src), tools.HexStringToBytes(key.substring(0, 16)));
	temp = encrypt(temp1, tools.HexStringToBytes(key.substring(16, 32)));
	temp1 = decrypt(temp, tools.HexStringToBytes(key.substring(0, 16)));
	return tools.BytesToHexString(temp1);
}



export default {
  encrypt3Des,
  decrypt3Des
}

  • 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
var bytesToHexString = function (src) {
    if (src == null || src.length <= 0) {
        return null;
    }
	
	let d = "";
    for (let i = 0; i < src.length; i++) {
        let v = src[i] & 0xFF;
        let hv = intTo16value(v);
        d += hv;
    }
	let strs = []
	// 字符串每8位进行分隔
	for (let j=0; j<d.length/16; j++){
		strs.push(d.slice(j*16,(j+1)*16))
	}
	// 
	return strs.reverse().join('')
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/一键难忘520/article/detail/873077
推荐阅读
相关标签
  

闽ICP备14008679号