AES-CBC在ActionScript中加密,在Javascript中解密
我们有一个用ActionScript编写的遗留工具,它使用AES-CBC和硬编码共享密钥加密输入。我正在尝试用Typescript编写相应的解密函数,但没有成功。AS3端使用Hurlant as3crypto库,该库带有NullPad和一个空(例如长度为0)IV。同样值得注意的是,共享机密只有15字节,而不是16字节。as3crypto似乎并不介意,我也尝试过使用16字节的密钥,但没有成功。我的目标是修复Javascript中的AESDeccrypt()函数,以便成功解密AS3 AESNecypt()函数的输出 下面是AS3中的encypt(以及工作解密对应项),然后是Typescript中的尝试解密(和相应的加密)函数。在本例中,输入“test”在AS3中被加密为“ryhkw3BmJ85+qBr0E9bYqw==”,但Javascript解密不会产生“test” AS3AES-CBC在ActionScript中加密,在Javascript中解密,javascript,node.js,actionscript-3,node-crypto,as3crypto,Javascript,Node.js,Actionscript 3,Node Crypto,As3crypto,我们有一个用ActionScript编写的遗留工具,它使用AES-CBC和硬编码共享密钥加密输入。我正在尝试用Typescript编写相应的解密函数,但没有成功。AS3端使用Hurlant as3crypto库,该库带有NullPad和一个空(例如长度为0)IV。同样值得注意的是,共享机密只有15字节,而不是16字节。as3crypto似乎并不介意,我也尝试过使用16字节的密钥,但没有成功。我的目标是修复Javascript中的AESDeccrypt()函数,以便成功解密AS3 AESNecyp
<?xml version="1.0"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" visible="false">
<fx:Script><![CDATA[
import com.hurlant.crypto.Crypto;
import com.hurlant.crypto.symmetric.ICipher;
import com.hurlant.crypto.symmetric.IPad;
import com.hurlant.crypto.symmetric.IVMode;
import com.hurlant.crypto.symmetric.NullPad;
import com.hurlant.util.Hex;
import mx.utils.Base64Decoder;
import mx.utils.Base64Encoder;
static var KEY:String = "vI^diTubIwH]Gag";
internal static function aesEncrypt(decoded:String):String
{
var pad:IPad = new NullPad();
var mode:ICipher = Crypto.getCipher("aes-cbc", Hex.toArray(Hex.fromString(KEY)), pad);
pad.setBlockSize(mode.getBlockSize());
var iv:ByteArray = new ByteArray();
if (mode is IVMode) {
(mode as IVMode).IV = iv;
}
var encoder:Base64Encoder = new Base64Encoder();
var ba:ByteArray = Hex.toArray(Hex.fromString(decoded));
mode.encrypt(ba);
encoder.reset();
encoder.encodeBytes(ba);
return encoder.toString();
}
internal static function aesDecrypt(encoded:String):String
{
var pad:IPad = new NullPad();
var mode:ICipher = Crypto.getCipher("aes-cbc", Hex.toArray(Hex.fromString(KEY)), pad);
pad.setBlockSize(mode.getBlockSize());
var iv:ByteArray = new ByteArray();
if (mode is IVMode) {
(mode as IVMode).IV = iv;
}
var decoder:Base64Decoder = new Base64Decoder();
decoder.reset();
decoder.decode(encoded);
var ba:ByteArray = decoder.toByteArray();
mode.decrypt(ba);
return Hex.toString(Hex.fromArray(ba));
}
trace(aesEncrypt('test'));
trace(aesDecrypt('ryhkw3BmJ85+qBr0E9bYqw=='));
]]></fx:Script>
</s:Application>
不幸的是,我们不能像我们希望的那样更新ActionScript工具的遗留代码(特别是因为空IV和空填充都不好,更不用说非标准密钥长度了)。如果有人能帮我演示如何修复Javascript端以进行解密,我将不胜感激。我更喜欢纯节点加密解决方案,但如果CryptoJS或Forge可以使用的话,我很乐意使用它们(我在这项任务中使用它们也不成功)
let crypto = require('crypto');
function aesEncrypt(cleartext:string, cipherType:string = 'AES', keyBitLength:number = 128, mode:string = 'CBC', cryptkey:string = 'vI^diTubIwH]Gag') {
const algorithm = `${cipherType.toLowerCase()}-${keyBitLength}-${mode.toLowerCase()}`;
const blockSize = keyBitLength / 8;
const key = Buffer.from(cryptkey);
const paddedKey = nullPad(key, blockSize);
const iv = Buffer.alloc(blockSize, 0);
const cipher = crypto.createCipheriv(algorithm, paddedKey, iv);
cipher.setAutoPadding(false);
const encodedInputBuffer = Buffer.from(cleartext, 'utf8');
const encodedInput = encodedInputBuffer.toString('hex');
const paddedInputBuffer = nullPad(Buffer.from(encodedInput), blockSize);
const encrypted = Buffer.concat([cipher.update(paddedInputBuffer), cipher.final()])
return encrypted.toString('base64');
}
function aesDecrypt(encoded:string, cipherType:string = 'AES', keyBitLength:number = 128, mode:string = 'CBC', cryptkey:string = 'vI^diTubIwH]Gag') {
const algorithm = `${cipherType.toLowerCase()}-${keyBitLength}-${mode.toLowerCase()}`;
const blockSize = keyBitLength / 8;
const key = Buffer.from(cryptkey);
const paddedKey = nullPad(key, blockSize);
let iv = Buffer.alloc(blockSize, 0);
const decipher = crypto.createDecipheriv(algorithm, paddedKey, iv);
decipher.setAutoPadding(false);
const decodedInput = Buffer.from(encoded, 'base64').toString( 'binary');
let decrypted = Buffer.concat([decipher.update(decodedInput, 'binary'), decipher.final()]);
return decrypted.toString().trim();
}
function nullPad(input:Buffer, length:number) {
const nullPad = Buffer.alloc(length);
let padLength = length - (input.length % length);
if (padLength == length) {
padLength = 0;
}
if(padLength > 0) {
input = Buffer.concat([input, nullPad.slice(0, padLength)]);
}
return input;
}
// should output "ryhkw3BmJ85+qBr0E9bYqw=="
console.log("Encrypt 'test'\t\t\t\t>>>\t" + aesEncrypt("test"));
// should output "test"
console.log("Decrypt 'ryhkw3BmJ85+qBr0E9bYqw=='\t>>>\t" + aesDecrypt("ryhkw3BmJ85+qBr0E9bYqw=="));
// working roundtrips
console.log("Decrypt '+3C9rjmO7W7hIQqcJMPgXQ=='\t>>>\t" + Buffer.from(aesDecrypt("+3C9rjmO7W7hIQqcJMPgXQ=="), 'hex').toString());
console.log("Decrypt 'elaKkhcvG75EBFvZwB1KiA=='\t>>>\t" + aesDecrypt("elaKkhcvG75EBFvZwB1KiA=="));