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.rhkb.cn/news/267374.html

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

相关文章

【重温设计模式】享元模式及其Java示例

享元模式的介绍 在编程世界中&#xff0c;我们常常面临着如何有效管理系统资源的挑战。这就好比我们在生活中&#xff0c;面对有限的物质资源&#xff0c;如何做到既满足需求又节约使用&#xff0c;是一门艺术。在设计模式中&#xff0c;有一种模式&#xff0c;恰如其分地解决…

Android之UI Automator框架源码分析(第九篇:UiDevice获取UiAutomation对象的过程分析)

前言 学习UiDevice对象&#xff0c;就需要看它的构造方法&#xff0c;构造方法中有UiDevice对象持有一些对象&#xff0c;每个对象都是我们分析程序的重点&#xff0c;毕竟UiDevice对象的功能&#xff0c;依赖这些组合的对象 备注&#xff1a;当前对象持有的对象&#xff0c;初…

leedcode刷题--day7(字符串)

23 文章讲解 力扣地址 C class Solution { public:void reverseString(vector<char>& s) {int left 0;int right s.size() - 1; // right 应该初始化为 s.size() - 1while (left < right) {swap(s[left], s[right]); // 直接交换 s[left] 和 s[right] 的值lef…

蓝桥杯-单片机组基础5——外部中断与LED的控制(附小蜜蜂课程代码)

蓝桥杯单片机组备赛指南请查看这篇文章&#xff1a;戳此跳转蓝桥杯备赛指南文章 本文章针对蓝桥杯-单片机组比赛开发板所写&#xff0c;代码可直接在比赛开发板上使用。 型号&#xff1a;国信天长4T开发板&#xff08;绿板&#xff09;&#xff0c;芯片&#xff1a;IAP15F2K6…

Excel常用公式总结非常实用

16个最实用的Excel万能公式 1、多条件判断 IF(And(条件1,条件2..条件N),条件成立返回值) IF(or(条件1,条件2..条件N),条件成立返回值) 2、多条件查找 Lookup(1,0/((条件1*条件2*...条件N)),返回值区域&#xff09; 3、多条件求和 Sumifs(值区域,判断区域1,条件1,判断区域2,条…

1_SQL

文章目录 前端复习SQL数据库的分类关系型数据库非关系型数据库&#xff08;NoSQL&#xff09; 数据库的构成软件架构MySQL内部数据组织方式 SQL语言登录数据库数据库操作查看库创建库删除库修改库 数据库中表的操作选择数据库创建表删除表查看表修改表 数据库中数据的操作添加数…

GO—函数

Go 语言支持普通函数、匿名函数和闭包&#xff0c;从设计上对函数进行了优化和改进&#xff0c;让函数使用起来更加方便。 Go 语言的函数属于“一等公民”&#xff08;first-class&#xff09;&#xff0c;也就是说&#xff1a; 函数本身可以作为值进行传递。支持匿名函数和闭…

Android 混淆是啥玩意儿?

什么是混淆 Android混淆&#xff0c;是伴随着Android系统的流行而产生的一种Android APP保护技术&#xff0c;用于保护APP不被破解和逆向分析。简单的说&#xff0c;就是将原本正常的项目文件&#xff0c;对其类、方法、字段&#xff0c;重新命名a,b,c…之类的字母&#xff0c…

假如有n个台阶,一次只能上1个台阶或2个台阶,请问走到第n个台阶有几种走法?

说明如下:假如有 3个台阶&#xff0c;那么总计就有3种走法:第一种为每次上1个台阶&#xff0c;上3次;第二种为先上2个台阶&#xff0c;再上1个台阶;第三种为先上1个台阶&#xff0c;再上2个台阶。 解决方法&#xff1a;递归 代码展示&#xff1a; #include <stdio.h> …

SD NAND:为车载显示器注入智能与安全的心脏

SD NAND 在车载显示器的应用 在车载显示器上&#xff0c;SD NAND&#xff08;Secure Digital NAND&#xff09;可以有多种应用&#xff0c;其中一些可能包括&#xff1a; 导航数据存储&#xff1a; SD NAND 可以用于存储地图数据、导航软件以及车载系统的相关信息。这有助于提…

【Vue3】插槽使用和animate使用

插槽使用 插槽slot匿名插槽具名插槽插槽作用域简写 动态插槽transition动画组件自定义过渡class类名如何使用animate动画库组件动画生命周期appear transition- group过渡列表transition- group平面过渡代码展示 gsap动画库 状态过渡 插槽slot 插槽就是子组件中提供给父组件使…

备战蓝桥杯---状态压缩DP进阶题1

我们来看一看一道比较难的问题&#xff08;十分十分的巧妙&#xff09;&#xff1a; 显然我们应该一行一行放&#xff0c;又竖的会对下一行产生影响&#xff0c;我们令横着放为0&#xff0c;竖着放的上方为1. 对于下一行&#xff0c;前一行放1的下面为0&#xff0c;但是会出现…

Python 实现Excel自动化办公(中)

在上一篇文章的基础上进行一些特殊的处理&#xff0c;这里的特殊处理主要是涉及到了日期格式数据的处理&#xff08;上一篇文章大家估计也看到了日期数据的处理是不对的&#xff09;以及常用的聚合数据统计处理&#xff0c;可以有效的实现你的常用统计要求。代码如下&#xff1…

Python爬虫——Urllib库-2

编解码 问题引入 例如&#xff1a; https://www.baidu.com/s?wd章若楠 https://www.baidu.com/s?wd%E7%AB%A0%E8%8B%A5%E6%A5%A0 第二部分的一串乱码就是章若楠 如果这里是写的章若楠就会 产生这样的错误 所以我们就可以使用get请求方式的quote方法了 get请求方式的q…

YOLOv9:使用可编程梯度信息学习您想学习的内容

摘要 arxiv.org/pdf/2402.13616.pdf 当今的深度学习方法侧重于如何设计最合适的目标函数,以便模型的预测结果能最接近于实际结果。同时,还必须设计一个适当的架构,以便于获取足够的预测信息。现有的方法忽略了一个事实,即当输入数据经历层层特征提取和空间变换时,会损失…

(学习日记)2024.02.29:UCOSIII第二节

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

BUGKU 本地管理员

打开环境&#xff0c;先F12查看看到一串代码。Base64解码一下&#xff0c;得到的应该是密码&#xff0c;然后输入admin | test123试一下 使用BP抓包&#xff0c;修改XFF&#xff0c;得到flag

社区分享|中华保险基于MeterSphere开展接口自动化测试

中华联合保险集团股份有限公司&#xff08;以下简称为“中华保险”&#xff09;始创于1986年&#xff0c;是全国唯一一家以“中华”冠名的国有控股保险公司。截至2022年12月底&#xff0c;中华保险总资产为1006.06亿元&#xff0c;在全国拥有超过2900个营业网点&#xff0c;员工…

破解SQL Server迷局,彻底解决“管道的另一端无任何进程错误233”

问题描述&#xff1a;在使用 SQL Server 2014的时候&#xff0c;想用 SQL Server 身份方式登录 SQL Servcer Manager&#xff0c;结果报错&#xff1a; 此错误消息&#xff1a;表示SQL Server未侦听共享内存或命名管道协议。 问题原因&#xff1a;此问题的原因有多种可能 管道…

SpringBoot整合JdbcTemplate

✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏: 循序渐进学SpringBoot ✨特色专栏: MySQL学习 🥭本文内容:SpringBoot整合JdbcTemplate 📚个人知识库: Leo知识库,欢迎大家访问 目录 …