前后端AES加解密,java使用CipherOutputStream加密输出时,前端分段解密方案

        如果java输出的数据是使用CipherOutputStream按1024(假设)个字节加密输出的,那么如果前端也必须按照1024个字节分段进行解密,不然将会解密失败,以下是前端的具体解密逻辑:

前端依赖:

<script src="jq.js" />
<script src="crypto-js.js" />

详细逻辑:

convertWordArrayToUint8Array为将CryptoJs解密后的wordArray对象转化为保存文件可用的Uint8Array的字节流对象,下方会使用到

function convertWordArrayToUint8Array(wordArray) {
    let arrayOfwords = wordArray.hasOwnProperty("words") ?  wordArray. words : [];  
    let length = wordArray.hasOwnProperty("sigBytes") ?  wordArray. sigBytes : arrayOfwords. length * 4;  
    let uInt8Array = new Uint8Array(length), index=o, word, i;  
    for (i=0;  i<length;  i++){
        word = arrayOfWords[i];
        uInt8Array[index++] = word >>  24;  
        uInt8Array[index++] = (word >>  16) & 0xff;  
        uInt8Array[index++] = (word >>  8) & 0xff;
        uInt8Array[index++] = word & exff;
    }
    return uInt8Array;
}

 blobToArrayBuffer为将接口返回的密文数据Blob对象转化为ArrayBuffer对象,下方解密是将会使用到

function blobToArrayBuffer(blob) {
    return new Promise((resolve, reject) => { 
        const file = new FileReader();
        file.onload = function(result) { 
            resolve(file.result) ;
        }
        file.readAsArrayBuffer(blob);
    })
}

decryptBlob为解密的具体逻辑,思路为仿照CipherOutputStream的加密逻辑,逆向回去,将流数组也按1024个字节切分,然后通过查阅cryptoJS的源码,模拟调用,先将分割好的流数组,转化为ArrayBuffer对象,再通过ArrayBuffer对象创建出cryptoJS解密可用的WordArray对象,最后不断通过process方法,分段传入解密,结束时调用finalize()方法,需要注意的是,finalize()也会返回解密数据的,记得拼接上去。

几个参数说明一下,blockSize对应的是CipherOutputStream每次加密输入的流长度,blob为接口返回的密文流数据,key是加密的密钥,iv则是偏移量。

let blockSize = 1024;
async function decryptBlob(blob, key, iv) {
    let blobSize = blob.size;
    let max = Math.floor(blobSize / blockSize);
    const aesDecryptor = CryptoJS.algo.AES.createDecryptor(CryptoJS.enc.Utf8.parse(key),{
        iv: CryptoJS.enc.Utf8.parse(iv);
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    });
    let fullWordArray = undefined;
    for( let i = 0; i <= max; i++ ){
        let sliceStart = i*blockSize;
        let sliceLength = i === max ? blobSize : (i+1)*blockSize; 
        let blobSlice = blob.slice(sliceStart, sliceLength);
        const arrayBuffer = await blobToArrayBuffer(blobSlice);
        const wordArray = CryptoJS.lib.WordArray.create(arrayBuffer)
        if(!fullWordArray){
            fullWordArray = aesDecryptor.process(wordArray);
        }else{
            fullWordArray.concat(aesDecryptor.process(wordArray));
        }
    }
    
    if(!fullwordArray){
        fullWordArray = aesDecryptor.finalize();
    }else{
        fullWordArray.concat(aesDecryptor.finalize());
    }
    let fileDec = new Blob([convertWordArrayToUint8Array(fullWordArray)]);
    let url = window.URL.createObjectURL(fileDec);
    let filename = "test.txt";
    let a = document.createElement("a");
    a.href = url;
    a.download = filename;
    a.click();
    window.URL.revokeObjectURL(url);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值