1.图片加解密的公共数据:key、iv等
// 字符串转字节数组的方法
const stringToBytes = (str: string) => {
let ch = 0
let st = []
let re: any[] = []
for (let i = 0; i < str.length; i++) {
ch = str.charCodeAt(i) // get char
st = [] // set up "stack"
do {
st.push(ch & 0xFF) // push byte to stack
ch = ch >> 8 // shift value down by 1 byte
}
while (ch)
// add stack contents to result
// done because chars have "wrong" endianness
re = re.concat(st.reverse())
}
// return an array of bytes
return re
}
/**
* 生成加解密:公共加密key、iv、
*/
export const CryptoGlobal = (Codekey: string) => {
// 将上面下载的图片转为base64编码,并处理key和iv的格式
const key = Codekey || 'xxxxxxxxxx'
const iv = 'xxxxxxxxxxxxxxx'
// 密钥转字节数组(16位)
let keyBy = stringToBytes(key)
let ivBy = stringToBytes(iv)
// 字节数组转Uint8Array
let keyBv = new Uint8Array(keyBy)
let ivBv = new Uint8Array(ivBy)
// Uint8Array转WordArray
let keyWA = CryptoU8array.u8array.parse(keyBv)
let ivWA = CryptoU8array.u8array.parse(ivBv)
return {
key: keyWA,
subtile: {
iv: ivWA,
// 解密方式和后端商定为为CBC模式
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}
}
}
2.图片插件所需的方法u8array方法
注:此代码我用了单独的代码管理,文件名:enc-u8array.ts
const CryptoJS = require(‘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: { words: any; sigBytes: any }) {
// Shortcuts
var words = wordArray.words
var sigBytes = wordArray.sigBytes
// Convert
var u8 = new Uint8Array(sigBytes)
for (var i = 0; i < sigBytes; i++) {
var byte = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff
u8[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: string | any[]) {
// Shortcut
var len = u8arr.length
// Convert
var words: number[] = []
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
}
3.图片加密
const CryptoJS = require('crypto-js');
import CryptoU8array from './enc-u8array'
import { CryptoGlobal } from './cryptoGlobal'
/**
* 图片加密
*/
export function avatarEncrypt(type: string, reorganizationUrl: string, file: any, Codekey?: string, ) {
const recodekey = Codekey?.slice(0, 16)
const { key, subtile } = CryptoGlobal(recodekey)
const messageWordArray = CryptoU8array.u8array.parse(file);
let encrypted = CryptoJS.AES.encrypt(messageWordArray, key, subtile);
const encryptedBytes = encrypted.ciphertext;
const toWordArray = CryptoU8array.u8array.stringify(encryptedBytes)
let blob = new Blob([toWordArray], { type }); // 将加密后串转blob
let blobToFile = new File([blob], reorganizationUrl);
return blobToFile
}
4.图片解密
import axios from 'axios'
const CryptoJS = require('crypto-js');
import CryptoU8array from './enc-u8array'
import { CryptoGlobal } from './cryptoGlobal'
/**
* base64转blob
* @param {*} base64
* @returns
*/
function base64ToBlob(base64: string) {
const binary = atob(base64.split(',')[1]);
const array = [];
for (let i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
return new Blob([new Uint8Array(array)], { type: 'image/jpeg' }); // 这里的type可以根据实际情况进行修改
}
/**
* 头像解密
* @param {*} buffer
* @returns
*/
function avatarDecrypt(buffer: ArrayBuffer, Codekey?: string) {
let view = new Uint8Array(buffer)
// 将Uint8Array 转成 WordArray
let contentWA = CryptoU8array.u8array.parse(view)
// base64字符串
let dcBase64String = contentWA.toString(CryptoJS.enc.Base64)
// 解密
const { key, subtile } = CryptoGlobal(Codekey)
let decryptedData = CryptoJS.AES.decrypt(dcBase64String, key, subtile)
console.log(decryptedData)
// 把解密后的对象再转为base64编码,这步是关键,跟解密文字不同
let d64 = decryptedData.toString(CryptoJS.enc.Base64)
let encodedData = 'data:image/png;base64,' + d64
// 将blob解析URL
const blob = base64ToBlob(encodedData);
var url = URL.createObjectURL(blob);
return url
}
/**
* 获取图片路径并调用头像解密方法
* @param list 路径
* @param key sessionId 对话图片才会需要用
* @returns
*/
export async function decodeAvatarUrl(list: string, key?: string) {
const resetList = list[0]=== '{' && list[list.length - 1] === '}' ? JSON.parse(list) : list
let isListType = null;
if(resetList != null) {
isListType = typeof resetList === 'string' ? resetList : resetList?.url
isListType = isListType.replace(/^http:/gi, '')
// 判断是否需要解密头像, 并判断图片数据是否有损坏,损坏显示默认头像
try {
if(isListType.includes('@#¥%&')) {
const res: {data: ArrayBuffer} = await axios.request({
responseType: 'arraybuffer',
url: isListType,
method: 'get'
})
if(res.data) {
const reKey = key?.slice(0, 16)
const avatarBase64 = avatarDecrypt(res.data, reKey)
isListType = avatarBase64
} else {
isListType = null
}
}
} catch (error) {
isListType = null
}
}
return isListType
}
5.图片加密使用
/** 上传图片方法传参校验 */
type UploadFileType = {
/** 图片数据:Uint8Array */
stream: any;
/** 图片名字 */
key: string,
/** 上传图片的类型: 1:头像 2:消息图片 */
updateType: number;
/** sessionId */
sessionId: string
}
/**
* 上传图片 -> 七牛云
*
* @param stream 图片流:Uint8Array
* @param stream 图片名称
* @param updateType 1:头像 2:消息图片
* @param sessionId 1:头像 2:消息图片
*
*/
export const uploadFile = ({ stream, key, updateType, sessionId }: UploadFileType) => {
return new Promise(async (resolve: (res: { rescode: number, url: string, error: any }) => void, reject) => {
const folderOs = 'Desktop'
const folder = updateType === 1 ? 'avatars' : 'conversations'
const folderEnd = '@#¥%&'
const reorganizationUrl = `${folderOs}/${folder}/${reorganizationName()}${folderEnd}`
const imageType = 'image/' + key.split('.').pop()
const putExtra = { // 上传需要的参数
fname: '',
params: {},
mimeType: [imageType]
};
const config = { // 上传需要的参数
useCdnDomain: true,
};
// token是接口获取
const { data } = await updateImageToken()
const { qiniuLinkUrl, token } = data
const decode: any = await avatarEncrypt(imageType, reorganizationUrl, stream, sessionId)
const observable = qiniu.upload(decode, reorganizationUrl, token, putExtra, config);
observable.subscribe({
next(res: any){
// console.log(res)
},
error(err: any){ // 失败
// console.log(err)
reject({
error: err,
url: '',
rescode: 100
})
},
complete(res: any){ // 成功
// console.log(res)
resolve({
error: null,
url: qiniuLinkUrl+reorganizationUrl,
rescode: 200
})
}
})
})
}
6.图片解密使用
import { decodeAvatarUrl } from '@/utils/decodeAvatar'
// src: 图片路径,sessionId: 唯一key值,每条对话单独的id
decodeAvatarUrl(src, sessionId)
参考:
CSDN(注:仅能参考解密,不够全面):https://blog.csdn.net/ningtt/article/details/118301703
简书(参考的这篇加密,加解密都有,较为全面):https://www.jianshu.com/p/1f75cd571786
本站资源均来自互联网,仅供研究学习,禁止违法使用和商用,产生法律纠纷本站概不负责!如果侵犯了您的权益请与我们联系!
转载请注明出处: 免费源码网-免费的源码资源网站 » 【electron7】调试对话图片的加密处理
发表评论 取消回复