js对AES加密的图片文件进行解密
由于:加密是在客户端加密的,如android 和 IOS app里面,对图片加密后上传到服务器, 服务器接收并存储这个加密后的图片, 假设这个图片访问的url是http://xxx.png, 现在要在H5页面中显示这个加密图片,就要用js解密,用的是CryptoJS解密的(https://github.com/brix/crypto-js/releases)
首先安装:npm install crypto-js --save
新建一个工具类js:utils.js,并引入以下组件
import CryptoJS from 'crypto-js'
import CryptoU8array from './enc-u8array'
由于发现crypto-js官方文档缺失CryptoJS.enc.u8array 这个js文件,所以找了一下这个js文件,源码如下:
新建一个enc-u8array.js文件,引入cryptoJs,并将缺失的源码放进去:
import CryptoJS from 'crypto-js'
CryptoJS.enc.u8array = {/*** Converts a word array to a Uint8Array.** @param {WordArray} wordArray The word array.** @return {Uint8Array} The Uint8Array.** @static** @example** var u8arr = CryptoJS.enc.u8array.stringify(wordArray);*/stringify: function (wordArray) {// Shortcutsvar words = wordArray.wordsvar sigBytes = wordArray.sigBytes// Convertvar u8 = new Uint8Array(sigBytes)for (var i = 0; i < sigBytes; i++) {var byte = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xffu8[i] = byte}return u8},/*** Converts a Uint8Array to a word array.** @param {string} u8Str The Uint8Array.** @return {WordArray} The word array.** @static** @example** var wordArray = CryptoJS.enc.u8array.parse(u8arr);*/parse: function (u8arr) {// Shortcutvar len = u8arr.length// Convertvar words = []for (var i = 0; i < len; i++) {words[i >>> 2] |= (u8arr[i] & 0xff) << (24 - (i % 4) * 8)}return CryptoJS.lib.WordArray.create(words, len)}
}
export default {u8array: CryptoJS.enc.u8array
}
在解密之前,要获取AES解密的key, iv,自行后端协商key和iv的值类型,我们约定key和iv为字符串格式,并采用CBC模式解密。
以下方法放入工具类js-utils.js中,方便全局调用
// ajax获取图片为arraybuffer格式
export const urlToBuffer = (url, key, iv) => {return new Promise(function (resolve, reject) {let xhr = new XMLHttpRequest()xhr.open('GET', url, true)xhr.responseType = 'arraybuffer'xhr.onload = function () {if (xhr.readyState === 4) {if (xhr.status === 200) {let url = process(xhr.response, key, iv)resolve(url)} else {retry(url, key, iv)}}}xhr.send()})
}
// 字符串转字节数组的方法
export const stringToBytes = (str) => {let ch = []let st = []let re = []for (let i = 0; i < str.length; i++) {ch = str.charCodeAt(i) // get charst = [] // set up "stack"do {st.push(ch & 0xFF) // push byte to stackch = ch >> 8 // shift value down by 1 byte}while (ch)// add stack contents to result// done because chars have "wrong" endiannessre = re.concat(st.reverse())}// return an array of bytesreturn re
}
// 将上面下载的图片转为base64编码,并处理key和iv的格式
// 解密方式和后端商定为为CBC模式
export const process = (buffer, key, iv) => {// 密钥转字节数组(16位) let keyBy = stringToBytes(key)let ivBy = stringToBytes(iv)// 字节数组转Uint8Arraylet keyBv = new Uint8Array(keyBy)let ivBv = new Uint8Array(ivBy)// Uint8Array转WordArraylet keyWA = CryptoU8array.u8array.parse(keyBv) let ivWA = CryptoU8array.u8array.parse(ivBv)let view = new Uint8Array(buffer)// 将Uint8Array 转成 WordArraylet contentWA = CryptoU8array.u8array.parse(view)// base64字符串let dcBase64String = contentWA.toString(CryptoJS.enc.Base64)// 解密let decryptedData = CryptoJS.AES.decrypt(dcBase64String, keyWA, {iv: ivWA,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7})// 把解密后的对象再转为base64编码,这步是关键,跟解密文字不同let d64 = decryptedData.toString(CryptoJS.enc.Base64)let url = 'data:image/png;base64,' + d64return url
}
// 如果获取图片失败,尝试再获取一次 ,图片较少且尺寸较小的话不需要重新获取
export const retry = (url, key, iv) => {let xhr = new XMLHttpRequest()xhr.open('GET', url, true)xhr.responseType = 'arraybuffer'xhr.onload = function () {if (xhr.status === 200) {process(xhr.response, key, iv)}}xhr.send()
}
// 其他页面引入及调用
import { urlToBuffer } from '@/libs/utils'let key = "1234567812345678"let iv = "1234567812345678"let url = "http://xxx.png"if (url && key && iv) {urlToBuffer(url, key, iv).then(res => {this.editInfo.url = res}).catch(error => {this.editInfo.url = ''})
}
以上就是AES对图片文件解密的全过程了
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
