朋友之前遇到一个问题 ,找到我。 他在对接一个服务,api文档给的示例是php的,如下:
function decrypt($crypt, $key, $type, $iv = "0123456789abcdef") {
$crypt = base64_decode($crypt);
$padtext = openssl_decrypt($crypt, "AES-256-CBC", base64_decode($key), OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
$pad = ord($padtext [strlen($padtext) - 1]);
if ($pad > strlen($padtext)) { return false;}
if (strspn($padtext, $padtext[strlen($padtext) - 1], strlen($padtext) - $pad) != $pad) {
$text = "Error";
}
}
Default key: 9v6ZyFBzNYoP2Un8H5cZq5FeBwxL6itqNZsm7lisGBQ=
正常来说 我们使用node 实现如下
const crypto = require('crypto');
const algorithm = 'aes-256-cbc';
const keyStr = '9v6ZyFBzNYoP2Un8H5cZq5FeBwxL6itqNZsm7lisGBQ='
const ivStr = keyStr.substr(0, 16)
const keyByte = Buffer.from(keyStr)
const ivByte = Buffer.from(ivStr)
function encrypt(text) {
let cipher = crypto.createCipheriv(algorithm, Buffer.from(keyStr), ivByte);
let encrypted = cipher.update(text);
encrypted = Buffer.concat([encrypted, cipher.final()]);
return {
keyStr: keyStr,
ivStr: ivByte.toString('hex'),
encryptedData: encrypted.toString('hex'),
rawBuffer: encrypted,
base64Str: encrypted.toString("base64")
};
}
但运行后发现报错 Invalid key length 查了一些资料 发现 aes-256-cbc 的key长度应该是32位的,他们给的默认key 是44位的,当然,如果你看的多了,自然会发现这个应该是base64加密后的。尝试先解密,发现是乱码。 然后考虑会不会是编码导致的乱码,于是尝试把node 所有的编码都试了下
const base64 = keyStr;
// create a buffer
const buff = Buffer.from(base64, 'base64');
let banma="'ascii'| 'utf8' | 'utf-8' | 'utf16le' | 'ucs2' | 'ucs-2' | 'base64' | 'base64url' | 'latin1' | 'binary' | 'hex'"
const arr=banma.replace(/'/g,'').replace(/ /g,'').split('|')
console.log(arr)
arr.forEach(item=>{
const str = buff.toString(item);
console.log(str,item,str.length)
console.log('-----------------------')
})
输出的还全是乱码
v~HPs5
YI|+^
Kj+j5X, ascii 32
-----------------------
����Ps5��I����^
K�+j5�&�X� utf8 32
-----------------------
����Ps5��I����^
K�+j5�&�X� utf-8 32
-----------------------
ﻶ좙獐訵�ﱉ霟庑ఇ樫鬵걘ᐘ utf16le 16
-----------------------
ﻶ좙獐訵�ﱉ霟庑ఇ樫鬵걘ᐘ ucs2 16
-----------------------
ﻶ좙獐訵�ﱉ霟庑ఇ樫鬵걘ᐘ ucs-2 16
-----------------------
9v6ZyFBzNYoP2Un8H5cZq5FeBwxL6itqNZsm7lisGBQ= base64 44
-----------------------
9v6ZyFBzNYoP2Un8H5cZq5FeBwxL6itqNZsm7lisGBQ base64url 43
-----------------------
öþÈPs5ÙIü«^
Kê+j5X¬ latin1 32
-----------------------
öþÈPs5ÙIü«^
Kê+j5X¬ binary 32
-----------------------
f6fe99c85073358a0fd949fc1f9719ab915e070c4bea2b6a359b26ee58ac1814 hex 64
后来灵机一动,反正都是buffer了 ,为什么还要去考虑解密key 于是使用 Buffer.from(keyStr,'base64') 试了一下 成功了。
let cipher = crypto.createCipheriv(algorithm, Buffer.from(keyStr,'base64'), ivByte);
完整代码如下
// Nodejs encryption with CTR
const { atob } = require('buffer');
const crypto = require('crypto');
const algorithm = 'aes-256-cbc';
const keyStr = '9v6ZyFBzNYoP2Un8H5cZq5FeBwxL6itqNZsm7lisGBQ='
const ivStr = keyStr.substr(0, 16)
const keyByte = Buffer.from(keyStr)
const ivByte = Buffer.from(ivStr)
function encrypt(text) {
let cipher = crypto.createCipheriv(algorithm, Buffer.from(keyStr,'base64'), ivByte);
let encrypted = cipher.update(text);
encrypted = Buffer.concat([encrypted, cipher.final()]);
return {
keyStr: keyStr,
ivStr: ivByte.toString('hex'),
encryptedData: encrypted.toString('hex'),
rawBuffer: encrypted,
base64Str: encrypted.toString("base64")
};
}
function decrypt(text) {
let encryptedData = text.encryptedData
let iv = Buffer.from(text.ivStr, 'hex');
let encryptedText = Buffer.from(encryptedData, 'hex');
let decipher = crypto.createDecipheriv(algorithm, Buffer.from(keyStr,'base64'), iv);
let decrypted = decipher.update(encryptedText);
decrypted = Buffer.concat([decrypted, decipher.final()]);
return decrypted.toString();
}
function decryptBase64(base64Str, ivStr) {
let buff = Buffer.from(base64Str, 'base64')
let encryptedData = buff.toString('hex')
let iv = Buffer.from(ivStr, 'hex');
let encryptedText = Buffer.from(encryptedData, 'hex');
let decipher = crypto.createDecipheriv(algorithm, Buffer.from(keyStr), iv);
let decrypted = decipher.update(encryptedText);
decrypted = Buffer.concat([decrypted, decipher.final()]);
return decrypted.toString();
}
var hw = encrypt("001002003004005006007+()")
console.log('encrypted = ', hw)
console.log('decode = ', decrypt(hw))
console.log('decode2 = ', decryptBase64(keyStr,ivStr))