【electron7】调试对话图片的加密处理

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/902898.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

3DS MAX三维建模平面基础与修改工具(图形编辑与二维建模修改工具)

又是一年1024祝大家程序员节日快乐 3DS MAX三维建模平面基础与修改工具&#xff08;图形编辑与二维建模修改工具&#xff09; 欢迎大家来学习3DS MAX教程&#xff0c;在这里先说一下研究好3ds Max一定要一边看教程一边要自己学的操作才能更快的进步&#xff0c;预祝大家学习顺利…

医疗保健知识中台:引领医疗行业智能化转型的新篇章

前言 随着科技的迅猛进步&#xff0c;医疗保健领域正迎来一场深刻的智能化变革。在这场变革中&#xff0c;知识中台作为医疗行业智能化升级的重要基石&#xff0c;正逐步成为提升医疗服务质量和效率的关键驱动力。本文将深入剖析医疗保健知识中台的内容构成、应用场景以及更新…

控制回撤哪家强?魔改DMA指标,比MACD更强大!

一、DMA的基本原理 前边我们讲过MACD&#xff0c;它利用了短期EMA和长期EMA的偏离来做文章&#xff0c;今天要讲的DMA也是类似的思路。DMA和MACD的本质区别在于&#xff0c;它在计算均线时将EMA替换为了SMA&#xff0c;其他的两者基本一致。 其完整的计算公式如下。很明显&am…

C++设计模式创建型模式———简单工厂模式、工厂方法模式、抽象工厂模式

文章目录 一、引言二、简单工厂模式三、工厂方法模式三、抽象工厂模式四、总结 一、引言 创建一个类对象的传统方式是使用关键字new &#xff0c; 因为用 new 创建的类对象是一个堆对象&#xff0c;可以实现多态。工厂模式通过把创建对象的代码包装起来&#xff0c;实现创建对…

生成式 AI 与向量搜索如何扩大零售运营:巨大潜力尚待挖掘

在竞争日益激烈的零售领域&#xff0c;行业领导者始终在探索革新客户体验和优化运营的新途径&#xff0c;而生成式 AI 和向量搜索在这方面将大有可为。从个性化营销到高效库存管理&#xff0c;二者在零售领域的诸多应用场景中都展现出变革性潜力&#xff0c;已成为保持行业领先…

leetcode438. 找到字符串中所有字母异位词

题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 示例 1: 输入: s "cbaebabacd", p "abc" 输出: [0,6] 解释: 起始索引等于 0 的子串是 &quo…

【IC每日一题】

IC每日一题 1 组合逻辑VS时序逻辑1.1 组合逻辑1.1.1 竞争冒险1.1.2 解决方法 1.2 时序逻辑1.3 比较1.4 场景 2 计数器2.1 代码片段法2.2 实现计数器--异步复位&#xff0c;带clear端&#xff0c;计10则归0&#xff1b; 1 组合逻辑VS时序逻辑 1.1 组合逻辑 组合逻辑&#xff1…

MySQL练习题-求连续、累计、环比和同比问题

目录 准备数据 1&#xff09;求不同产品每个月截止当月最近3个月的平均销售额 2&#xff09;求不同产品截止当月的累计销售额 3&#xff09;求环比增长率和同比增长率 准备数据 -- product 表示产品名称&#xff0c;ym 表示年月&#xff0c;amount 表示销售金额&#xff…

【K8S系列】Kubernetes Service 基础知识 详细介绍

在 Kubernetes 中&#xff0c;Service 是一种抽象的资源&#xff0c;用于定义一组 Pod 的访问策略。它为这些 Pod 提供了一个稳定的访问入口&#xff0c;解决了 Pod 可能频繁变化的问题。本文将详细介绍 Kubernetes Service 的类型、功能、使用场景、DNS 和负载均衡等方面。 1.…

react 总结+复习+应用加深

文章目录 一、React生命周期1. 挂载阶段&#xff08;Mounting&#xff09;补充2. 更新阶段&#xff08;Updating&#xff09;补充 static getDerivedStateFromProps 更新阶段应用补充 getSnapshotBeforeUpdate3. 卸载阶段&#xff08;Unmounting&#xff09; 二、React组件间的…

windows 训练yolov8官方数据集

第一步&#xff1a;安装Anaconda3-2024.06-1-Windows-x86_64.exe 下载地址&#xff1a;https://repo.anaconda.com/archive/ 第二步&#xff1a;创建环境 打开Anaconda Prompt 输入 conda info -e 打印&#xff1a; 已经安装了一些环境&#xff0c;然后我们创建新的环境&a…

大模型面试挺水的,面试官听到这些直接过

AI大模型600道面试总结(LLM) 1、目前主流的开源模型体系有哪些? 目前 主流的开源模型体系 分三种: 第一种:prefixDecoder系 介绍:输入双向注意力&#xff0c;输出单向注意力 代表模型:ChatGLM、ChaGLM2、U-PaLM 第二种:causal Decader系 介绍:从左到右的单向注意力 代表…

【状态机DP】力扣1186. 删除一次得到子数组最大和

给你一个整数数组&#xff0c;返回它的某个 非空 子数组&#xff08;连续元素&#xff09;在执行一次可选的删除操作后&#xff0c;所能得到的最大元素总和。换句话说&#xff0c;你可以从原数组中选出一个子数组&#xff0c;并可以决定要不要从中删除一个元素&#xff08;只能…

驱动-----LED

前面我们学习了demo1的驱动的编写,在写LED的时候,我们可以在demo1的基础上修改。 1.首先就是修改名字,把所有的demo改成led,使用一个字符串替换指令。 2.设备号要变 3.想操作硬件,LED的初始化,亮灭 LED的初始化,在open的时候实现。 亮灭在write的时候实现。 现在就是…

技术成神之路:设计模式(二十三)解释器模式

相关文章&#xff1a;技术成神之路&#xff1a;二十三种设计模式(导航页) 介绍 解释器模式&#xff08;Interpreter Pattern&#xff09;是一种行为设计模式&#xff0c;用于定义一种语言的文法表示&#xff0c;并提供一个解释器来处理这种文法。它用于处理具有特定语法或表达…

移远通信斩获两项车载大奖,引领全球智能网联汽车产业发展

10月24日&#xff0c;由盖世汽车主办的2024第六届金辑奖中国汽车新供应链百强颁奖盛典在上海隆重举行。 作为全球领先的物联网和车联网整体解决方案供应商&#xff0c;移远通信凭借智能座舱模组AG855G、车载5G模组AG59x系列&#xff0c;以及公司在海外市场的优异表现&#xff0…

Mac 上无法烧录 ESP32C3 的问题记录:A fatal error occurred:Failed to write to target RAM

文章目录 问题描述驱动下载地址问题解决&#xff1a;安装 CH343 驱动踩的坑日志是乱码 问题描述 我代码编译可以&#xff0c;但是就是烧录不上去 A fatal error occurred:Failed to write to target RAM(result was 01070000:Operation timed out) Uploaderror:上传失败&…

selenium脚本编写及八大元素定位方法

selenium脚本编写 上篇文章介绍了selenium环境搭建&#xff0c;搭建好之后就可以开始写代码了 基础脚本,打开一个网址 from selenium import webdriver driver webdriver.Chrome()#打开chrome浏览器 driver.get(https://www.baidu.com) #打开百度 打开本地HTML文件 上篇…

ctfshow(265->266)--反序列化漏洞--指针引用与php://input读取请求体

Web265 源代码&#xff1a; error_reporting(0); include(flag.php); highlight_file(__FILE__); class ctfshowAdmin{public $token;public $password;public function __construct($t,$p){$this->token$t;$this->password $p;}public function login(){return $this…

企业贷款大揭秘:税贷VS票贷,哪个更适合你?

在金融界&#xff0c;资金就像是现代经济的血液&#xff0c;特别是对于企业的发展来说&#xff0c;银行的资金支持简直是不可或缺的。最近&#xff0c;多家银行可是动作频频&#xff0c;加快了资金投放的步伐&#xff0c;尤其是制造业、小微企业、专精特新以及“三农”这些领域…