flutter 加密安全

前言:数据安全

        数据的加密解密操作在 日常网络交互中经常会用到,现在密码的安全主要在于 秘钥的安全,如论 DES 3DES  AES 还是 RSA, 秘钥的算法(计算秘钥不固定) 和 保存,都决定了你的数据安全;但是常见的逆向操作 比如 hook 加密算法 都很容易拿到 秘钥; 这个时候我们可以 回溯到 之前的 古典密码学依赖算法本身),基本思路  置换 移位 编码 等等手段 来配合 加密算法一起使用,提高我们应用的安全

密码学概论_在传统的密码学中,加解密基础操作包括移位置换替换编码-CSDN博客文章浏览阅读201次。密码学基础_在传统的密码学中,加解密基础操作包括移位置换替换编码https://blog.csdn.net/nicepainkiller/article/details/132978492?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170902384916777224453245%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=170902384916777224453245&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-132978492-null-null.nonecase&utm_term=%E5%AF%86%E7%A0%81&spm=1018.2226.3001.4450

android frida 逆向 自吐加密算法_frida 自吐算法 教程-CSDN博客文章浏览阅读1.8k次。frida hook android Android 逆向神器_frida 自吐算法 教程https://blog.csdn.net/nicepainkiller/article/details/132554698?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170902437216800182198144%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=170902437216800182198144&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-132554698-null-null.nonecase&utm_term=hook&spm=1018.2226.3001.4450

 flutter 数据加密

如果是 android 原生应用,可以 hook 系统加密代码,来获取加密秘钥,而在 flutter 中,dart 是被直接编译为 .so 文件,也就是汇编,对于低级汇编语言 可读性大大降低。当然也是可以下断点动态调试的;但是相对于难度 大大增加,我们可以结合 古典密码学 主要特点 数据安全基于算法的保密,算法不公开, 设计繁琐的算法过程,增加汇编可读性难度;

有个业务需求是相当于是一个签到功能,每天可以领取,这里防止脚本调用使用两层 基于算法加密 和 AES加密 相结合的方式;(当然还用到了第三方的的安全软件

以下是我上个版本加密算法设计:整体思路就是:

  • 按照规则 移动字符 替换字符
  • 阶段一主要是 按规则打乱字符(密文)位置
  • 阶段二主要是 指定位置(密文)插入无关字符

match_request_data.dart

import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:encrypt/encrypt.dart' as encrypt;///匹配接口加密工具类
///整体加密思路:按照规则 移动字符 替换字符
///阶段一主要是 按规则打乱字符位置
///阶段二主要是 指定位置插入无关字符
class MatchRequestData {final String gameId;final String chatSign;final String nickName;late List<int> _gameIdSort;MatchRequestData({required this.gameId, required this.chatSign, required this.nickName});String generateCode(String datum) {String idStr = '${int.parse(gameId)}';List<int> searchKeywords =List<int>.generate(idStr.length, (index) => int.parse(idStr[index]));searchKeywords.sort();_gameIdSort = searchKeywords;String base64 = _encodeBase64(datum);String base64Step0 =base64.substring(0, _gameIdSort[_gameIdSort.length - 1]) +_stepOne((base64.substring(_gameIdSort[_gameIdSort.length - 1],base64.length -_gameIdSort[3] -_gameIdSort[_gameIdSort.length - 1]))) +base64.substring(base64.length -_gameIdSort[3] -_gameIdSort[_gameIdSort.length - 1]);String _strHex = _strToHex(base64Step0);final key = encrypt.Key.fromUtf8(_generateMd5(chatSign + nickName));final iv = encrypt.IV.fromUtf8(_ivStepOne().substring(4, 20).toUpperCase());final encrypter =encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc));final encrypted = encrypter.encrypt(_strHex, iv: iv);final encryptCode = _stepTwo(encrypted.base64);idStr = _strHex = base64 = base64Step0 = '';return encryptCode;}String _stepOne(String str) {String res = '';str = _inverse(str);int lastPosition = _gameIdSort[_gameIdSort.length - 1];int count = 0;if (lastPosition % 2 == 0) {count = _gameIdSort[_gameIdSort.length - 2];} else {count = _gameIdSort[_gameIdSort.length - 3];}if (count == 0) {count = lastPosition;}int step = str.length ~/ count;List<String> base64Parts = [];for (int i = 0; i < count; i++) {if (i % 2 == 1) {base64Parts.add(_inverse(str.substring(step * i, step * (i + 1))));} else {base64Parts.add(str.substring(step * i, step * (i + 1)));}}if (step * count < str.length) {if (lastPosition % 2 == 0) {base64Parts.insert(0, str.substring(step * count));} else {base64Parts.insert(base64Parts.length, str.substring(step * count));}}if (lastPosition % 2 == 1) {for (int i = 0; i < base64Parts.length; i++) {res = res + base64Parts[i];}} else {for (int i = base64Parts.length - 1; i >= 0; i--) {res = res + base64Parts[i];}}str = '';lastPosition = count = step = -1;return res;}String _stepTwo(String data) {String res = "";String _strHex = _strToHex(data);String _code = _inverse(_strHex);final key = encrypt.Key.fromUtf8(_generateMd5(gameId + chatSign));final iv = encrypt.IV.fromUtf8(_ivStepTwo().substring(14, 30));final encrypter =encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc));final encrypted = encrypter.encrypt(_code, iv: iv);res = encrypted.base64;int maxLength = res.length;int indexSub = 0;int insertPos = 0;String insertStr = '';for (int i = 1; i < _gameIdSort.length; i++) {indexSub = _gameIdSort[i] + 1;insertPos = _magic(indexSub + i) + i * 11 + i - 1;// insertStr = chatSign.substring(1,indexSub);insertStr = chatSign[indexSub];//前面插入if (insertPos > res.length) {insertPos = maxLength;}res ='${res.substring(0, insertPos)}$insertStr${res.substring(insertPos)}';}_strHex = _code = '';return res;}String _stepThree(String str) {return str;}String _inverse(String tag) {String res = '';List<String> searchKeywords =List<String>.generate(tag.length, (index) => tag[index]);Iterable<String> array = searchKeywords.reversed;for (var e in array) {res = '$res$e';}return res;}String _ivStepOne() {String res = '';String map = _generateMd5(chatSign) + _generateMd5(nickName);int index = _gameIdSort[_gameIdSort.length - 2];while (res.length < 50) {res += map[index];index++;}index = 0;return res;}String _ivStepTwo() {String res = '';String map = _generateMd5(_inverse(chatSign)) + _generateMd5(chatSign);int index = _gameIdSort[_gameIdSort.length - 1];while (res.length < 50) {res += map[index];index++;}index = 0;return _inverse(res);}/// 字符串转 十六进制String _strToHex(String str) {List<int> charCodes = str.runes.toList();return charCodes.map((code) => code.toRadixString(16)).join('');}/// 字符串转 base64String _encodeBase64(String data) {return base64Encode(utf8.encode(data));}/// base64转 普通字符String _decodeBase64(String data) {return String.fromCharCodes(base64Decode(data));}String _generateMd5(String str) {return md5.convert(utf8.encode(str)).toString();}int _magic(int num) {if (num < 3) {return 1;} else {return _magic(num - 1) + _magic(num - 2);}}
}

调用的地方:

MatchRequestData data = MatchRequestData (gameId: userArray[i]['gameID'],chatSign: userArray[i]['chatSign'],nickName: userArray[i]['nickName'],
);//需要传递给后台的 内容
Map datum = {'inTrust': 'TRUE','time': DateTime.now().millisecondsSinceEpoch,'GameID': userArray[i]['gameID'],'nickName': userArray[i]['nickName'],'MachineCode':md5.convert(utf8.encode(userArray[i]['gameID'])).toString(),'sign': md5.convert(utf8.encode(userArray[i]['gameID'] + userArray[i]['chatSign'])).toString(),
};String res = data.generateCode(jsonEncode(datum));

服务端的数据解密:

服务端为 .net 框架:

对应于加密算法写的解密算法:

using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;namespace ToMatch
{public class MatchEncrypt{private string gameID;private string chatSign;private string nickName;private List<int> idSort;/// <summary>/// 匹配构造函数/// </summary>/// <param name="gameId">GameID</param>/// <param name="chatSign">签名</param>/// <param name="nickName">昵称</param>public MatchEncrypt(string gameId, string chatSign, string nickName) {this.gameID = gameId;this.chatSign = chatSign;this.nickName = nickName;this.idSort = new List<int>();string idStr = int.Parse(this.gameID).ToString();for (int i = 0; i < idStr.Length; i++){this.idSort.Add((int)Char.GetNumericValue(idStr[i]));}this.idSort.Sort();}private String IvStepOne {get {String res = "";String map = Md5Hash(chatSign) + Md5Hash(nickName);int index = idSort[idSort.Count - 2];while (res.Length < 50){res += map[index];index++;}return res;}}private String IvStepTwo{get{String res = "";String map = Md5Hash(AESHelper.Inverse(chatSign),false) + Md5Hash(chatSign,false);int index = idSort[idSort.Count - 1];while (res.Length < 50){res += map[index];index++;}return AESHelper.Inverse(res);}}/// <summary>/// 解密客户端内容/// </summary>/// <param name="code">密文</param>/// <returns></returns>public string Resolver(string code) {//第一阶段解密内容string resStepOne = StepOne(code);if (resStepOne.Length > 0){//Console.WriteLine("第一解密 result:" + resStepOne);//第二阶段解密string resSteptwo = Steptwo(resStepOne);//Console.WriteLine("第二解密 result:" + resSteptwo);//Console.WriteLine(AESHelper.FromBase64(resSteptwo));if (resSteptwo.Length > 0){return AESHelper.FromBase64(resSteptwo);}else {return "解密失败——请记录日志.Step-2";}       }else {return "解密失败——请记录日志.Step-1";}            }private string StepOne(string code){// 1.先移除插入的字符// 2.再进行解密操作int maxlength = code.Length - idSort.Count - 1;int indexSub = 0;int insertPos = 0;for (int i = 1; i < idSort.Count; i++){indexSub = idSort[i] + 1;insertPos = magic(indexSub + i) + i * 11;    //前面插入//Console.WriteLine("前面    索引:" + i);//Console.WriteLine("前面插入位置:" + insertPos);//Console.WriteLine("前面插入字符:" + insertStr + "");if (insertPos > code.Length) {//Console.WriteLine("修正Length:" + code.Length);Console.WriteLine("修正insertPos:" + insertPos);//Console.WriteLine("----code.Length:" + (code.Length -maxlength  ));//Console.WriteLine("----code.Length:" + (  idSort.Count-1 - i));//Console.WriteLine("----code.Length:" + ((code.Length - maxlength - (idSort.Count - 1 - i))+1));insertPos = maxlength -4;insertPos = maxlength - ((code.Length - maxlength - (idSort.Count - 1 - i)) + 1);//Console.WriteLine("*******code.Length:" + ((code.Length - maxlength - (idSort.Count - 1 - i)) + 1));//Console.WriteLine("*******code.Length:" + (code.Length - maxlength - (idSort.Count - i)) );//Console.WriteLine("*******code.Length:" + (code.Length - maxlength - idSort.Count  - i ));//Console.WriteLine("code.Length:" + code.Length);//Console.WriteLine("maxlength:" + maxlength);//Console.WriteLine("idSort.Count:" + idSort.Count);//Console.WriteLine("idSort.Count - i:" + (idSort.Count - i));//Console.WriteLine("修正插入位置i:" + i);//Console.WriteLine("修正插入位置:" + insertPos);insertPos = maxlength - ((code.Length - maxlength - (idSort.Count - 1 - i)) + 1);}              code = code.Substring(0, insertPos) + code.Substring(insertPos + 1);}//Console.WriteLine("整理后的:" + code);//Console.WriteLine("整理后的Length:" + code.Length);string key = Md5Hash(this.gameID + this.chatSign, false);string iv = IvStepTwo.Substring(14, 16);//第一次解密是 16进制字符串string result = AESHelper.Decrypt(code, key, iv);return AESHelper.HexStringToString(AESHelper.Inverse(result), Encoding.UTF8);}private string Steptwo(string code) {string key = Md5Hash(this.chatSign + this.nickName, false);string iv = IvStepOne.Substring(4, 16);string base64 = AESHelper.HexStringToString(AESHelper.Decrypt(code, key, iv), Encoding.UTF8);string source = base64.Substring(0, idSort[idSort.Count - 1]) + generateMid(base64.Substring(idSort[idSort.Count - 1], base64.Length - idSort[3] - idSort[idSort.Count - 1] * 2)) + base64.Substring(base64.Length - idSort[3] - idSort[idSort.Count - 1]);//第二次解密是 base64return source ;}private string generateMid(string str) {string res = "";List<String> base64Parts = new List<string>();int lastPosition = this.idSort[this.idSort.Count - 1];string subBefore = "";int count = 0;if (lastPosition % 2 == 0){count = idSort[idSort.Count - 2];}else{count = idSort[idSort.Count - 3];}if (count == 0) {count = lastPosition;}int step = str.Length / count;int subLength = str.Length - step * count;if (lastPosition % 2 == 0){for (int i = 0; i < count; i++){if (i % 2 == 1){base64Parts.Add(AESHelper.Inverse(str.Substring(step * (count - i - 1), step)));}else{//base64Parts.Add(v.Substring(step * i, step));//Console.WriteLine(i + "不需要翻转原始:" + str.Substring(step * (count - i - 1), step));base64Parts.Add(str.Substring(step * (count - i - 1), step));}}for (int i = 0; i < base64Parts.Count; i++){//Console.WriteLine("偶数项目:" + i + " " + base64Parts[i]);res = res + base64Parts[i];}subBefore = str.Substring(step * count);res += subBefore;}else{for (int i = 0; i < count; i++){if (i % 2 == 1){base64Parts.Add(AESHelper.Inverse(str.Substring(step * i, step)));          }else{base64Parts.Add(str.Substring(step * i, step));}}subBefore = str.Substring(step * count);base64Parts.Add(subBefore);for (int i = 0; i < base64Parts.Count; i++){//Console.WriteLine("奇数项目:" + i + " " + base64Parts[i]);res = res + base64Parts[i];}}return AESHelper.Inverse(res);}private static int magic(int num){if (num < 3){return 1;}else{return magic(num - 1) + magic(num - 2);}}private string Md5Hash(string sourceText, bool toUpper = true){StringBuilder result = new StringBuilder();using (MD5 md5 = new MD5CryptoServiceProvider()){byte[] data = md5.ComputeHash(Encoding.UTF8.GetBytes(sourceText));if (toUpper)for (int i = 0; i < data.Length; i++)result.Append(data[i].ToString("X2"));elsefor (int i = 0; i < data.Length; i++)result.Append(data[i].ToString("x2"));}return result.ToString();}}
}

 总结

数据安全不是绝对的,只能说我们多设置些障碍,对于逆向的难度对增大,你挖的坑多远。逆向时候就越困难,当然也可以借助一些第三方安全软件来增加我们数据的安全性。在数据安全的道路上 始终是此消彼长的状态

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue 3, TypeScript 和 Element UI Plus:前端开发的高级技巧与最佳实践

Vue 3、TypeScript 和 Element UI Plus 结合使用时&#xff0c;可以提供一个强大且灵活的前端开发环境。以下是一些高级用法和技巧&#xff0c;帮助你更有效地使用这些技术&#xff1a; 1. Vue 3 高级特性 Composition API 使用 setup 函数: Vue 3 引入了 Composition API&am…

数据结构(C语言)代码实现(十)——链队列循环队列

目录 参考资料 链队列的实现 LinkQueue.h LinkQueue.cpp 测试函数test.cpp 测试结果 循环队列的实现&#xff08;最小操作子集&#xff09; 完整代码 测试结果 参考资料 数据结构严蔚敏版 链队列的实现 LinkQueue.h #pragma once #include <cstdio> #incl…

Vue自定义指令directives

1. 使用<script setup> <template><input v-focus"11111" /><input v-obj"{ id: 1, name: 这里是name }" /> </template> <script setup> //定义一个变量vFocus //命名方法使得DOM元素中可以用v-focus来显示 let vFo…

uniapp:使用DCloud的uni-push推送消息通知(在线模式)java实现

uniapp:使用DCloud的uni-push推送消息通知&#xff08;在线模式&#xff09;java实现 1.背景 今天开发app的时候遇到一个需求&#xff1a; 业务在出发特定条件的时候向对应的客户端推送消息通知。 为什么选择在线模式&#xff0c;因为我们使用的是德邦类似的手持终端&#xf…

干货!教你如何从柏曼/书客/明基中挑选最好用的护眼台灯

又到了一年一度的开学季&#xff0c;家中神兽又回到知识的海洋遨游&#xff0c;家长在得到自由的同时又不禁开始担心孩子的视力健康问题&#xff0c;毕竟繁重的学习生活用眼负担也不小&#xff0c;在听闻市面上有护眼台灯之后也纷纷想入手选购一台给孩子&#xff0c;毕竟这是打…

死区过滤器Deadband和DeadZone区别(应用介绍)

死区过滤器的算法和详细介绍专栏也有介绍,这里我们主要对这两个模块的区别和应用场景进行详细介绍 1、死区过滤器 https://rxxw-control.blog.csdn.net/article/details/128521007https://rxxw-control.blog.csdn.net/article/details/128521007 1、Deadband和DeadZone区别…

【算法 - 动态规划】找零钱问题Ⅲ

在前面的动态规划系列文章中&#xff0c;关于如何对递归进行分析的四种基本模型都介绍完了&#xff0c;再来回顾一下&#xff1a; 从左到右模型 &#xff1a;arr[index ...] 从 index 之前的不用考虑&#xff0c;只考虑后面的该如何选择 。范围尝试模型 &#xff1a;思考 [L ,…

美国硅谷云服务器租用注意事项

随着信息技术的飞速发展&#xff0c;云服务器已成为众多企业和个人用户首选的IT基础设施。美国硅谷作为全球科技创新的摇篮&#xff0c;其云服务器市场也备受关注。然而&#xff0c;在租用硅谷云服务器时&#xff0c;用户需要注意以下几个方面&#xff0c;以确保获得优质、稳定…

4核8G服务器选阿里云还是腾讯云?价格性能对比

4核8G云服务器多少钱一年&#xff1f;阿里云ECS服务器u1价格955.58元一年&#xff0c;腾讯云轻量4核8G12M带宽价格是646元15个月&#xff0c;阿腾云atengyun.com整理4核8G云服务器价格表&#xff0c;包括一年费用和1个月收费明细&#xff1a; 云服务器4核8G配置收费价格 阿里…

新加坡服务器托管:开启全球化发展之门

新加坡作为一个小国家&#xff0c;却在全球范围内享有极高的声誉。新加坡作为亚洲的科技中心&#xff0c;拥有先进的通信基础设施和成熟的机房托管市场。除了其独特的地理位置和发达的经济体系外&#xff0c;新加坡还以其开放的商业环境和便利的托管服务吸引着越来越多的国际公…

在两台CentOS 7服务器上部署MinIO集群---准确

环境说明&#xff1a; 2台Centos7服务器 IP地址分别为172.16.1.9和172.16.1.10 1. 创建minio用户和目录 在两台服务器上执行以下命令&#xff1a; sudo useradd -m -d /app/minio minio sudo mkdir -p /app/minioData sudo mkdir -p /app/minio/logs sudo chown -R mini…

vue项目打包获取git commit信息并输出到打包后的指定文件夹中

需求背景&#xff1a; 前端项目经常打包&#xff0c;发包部署&#xff0c;为了方便测试及运维发现问题时与正确commit信息对比 实现方式&#xff1a; 使用Node.js的child_process模块来执行git命令 实现步骤&#xff1a; 1.在package.json的同级目录下新建一个version.js文件。…

459. 重复的子字符串(力扣LeetCode)

文章目录 459. 重复的子字符串题目描述暴力移动匹配KMP算法 459. 重复的子字符串 题目描述 给定一个非空的字符串 s &#xff0c;检查是否可以通过由它的一个子串重复多次构成。 示例 1: 输入: s “abab” 输出: true 解释: 可由子串 “ab” 重复两次构成。 示例 2: 输入: …

【C++进阶】哈希(万字详解)—— 学习篇(上)

&#x1f387;C学习历程&#xff1a;入门 博客主页&#xff1a;一起去看日落吗持续分享博主的C学习历程博主的能力有限&#xff0c;出现错误希望大家不吝赐教分享给大家一句我很喜欢的话&#xff1a; 也许你现在做的事情&#xff0c;暂时看不到成果&#xff0c;但不要忘记&…

ChatGPT:你真的了解网络安全吗?浅谈攻击防御进行时之传统的网络安全

ChatGPT&#xff08;全名&#xff1a;Chat Generative Pre-trained Transformer&#xff09;&#xff0c;美国OpenAI 研发的聊天机器人程序&#xff0c;是人工智能技术驱动的自然语言处理工具。 基于其语言模型庞大、可控制、具有高度扩展性的特点&#xff0c;本文通过对话Chat…

111期_C++_2024年1月份作业博客_选择题错题总结

一、野指针问题&#xff1a;在定义的时候没有初始化&#xff0c;就不能能用scanf 或 printf 二、一个变量出现在表达式的两边作为两个不同的操作数&#xff0c; 并且其中一个操作数带有&#xff0c;此时表达式出现歧义 三、两端出栈问题&#xff1a; 错因&#xff1a;未理解题…

素皮材质的手机壳,如何才能做到经久耐用?

近几年&#xff0c;素皮材质开始在手机背壳上开始应用&#xff0c;各家手机厂商&#xff0c;基本都给自己的旗舰系列设备推出了带素皮材质版本的手机款式&#xff0c;比如华为的Mate 60系列&#xff0c;不仅Pro版本有素皮材质&#xff0c;Pro版本更是黑白两款全是素皮材质。 那…

Docker的基础知识与应用技巧

文章目录 一.docekr简介二.docekr安装三.docker命令 一.docekr简介 Docker是一个开源的应用容器引擎&#xff0c;它可以让开发者打包他们的应用以及依赖包到一个可移植的镜像中&#xff0c;然后发布到任何流行的Linux或Windows操作系统的机器上。Docker基于轻量级虚拟化技术&a…

交易这条路,没有永远的大神,唯有攀登者

一、摆平心态 很多人一谈及金融&#xff0c;首先想到的就是赚钱&#xff0c;而忽视了亏损和风险的存在。面对亏损时&#xff0c;许多人不是选择止损&#xff0c;而是选择加仓&#xff0c;希望通过大赚一笔来弥补损失。然而&#xff0c;这种做法往往会让他们在市场中受到惨痛的教…

桥接模式(Bridge Pattern) C++

上一节&#xff1a;适配器模式&#xff08;Adapter Pattern&#xff09; C 文章目录 0.理论1.组件2.使用场景 1.实践 0.理论 桥接模式&#xff08;Bridge Pattern&#xff09;是一种结构型设计模式&#xff0c;它的核心思想是将抽象部分与其实现部分分离&#xff0c;使它们可…