任何一个数组,对数组中的每个数据进行处理,让每一个值和它的前一个值进行异或计算(第一个除外),那么只需要重复这个计算过程,执行2的n次方次计算后,一定可以得到原本的结果。
n的值是数组长度除以2,并向上取整。例如长度为1、2、3、4、5、6的数组,n的值分别是:1、1、2、2、3、3,也就是重复执行这个计算过程2次,4次,8次。
例如js中可以这么实现代码
P.S. js中一个数字异或undefined相当于异或0
function fun(arr){
var len = Math.pow(2, Math.ceil((arr.length/2)) );
for (var x = 0 ; x < len; x ++){
arr=arr.map((item,index,sourceArr)=>item^sourceArr[index-1]);
}
return arr;
}
尝试一下就可以发现,在这个计算中,传入任何数组,返回的都是数组本身。不过由于计算次数指数级上升,数组越大,计算时间越长。
这个算法有什么用呢?
- 加密混淆:由于执行重复的计算次数一定可以拿到原始值。那么可以先对某个数据进行一定次数的计算,保存起来。其他人即使拿到了这个数据,他也不知道你已经做了几次计算了,所以要还原原始数据还是有难度的。而且一个数组也可以拆分成不同的子数组,一段一段分开计算,这样更难破解。
- 防反汇编:反汇编通常需要一步一步调试程序执行。有些重要步骤为了可以读懂需要一点点看,但是如果程序里多出很多无意义的循环处理,那就十分消耗分析人员的精力。例如长度为20的数组,还原计算次数就高达100w次,但是程序执行却不到1秒,在重要的操作中加入这个无意义的计算,就可以增加破解难度。
- 内存加密:有些时候需要做内存加密。内存加密本质就是内存中不会直接出现某个数据,所有数据在使用的时候都需要通过特定计算得到结果。这个计算就可以针对较小的内存数据进行加密处理。只需要重复计算几次就拿到原始结果了。
P.S. 补充知识
异或计算满足交换律,结合律。连续的异或计算中任何两个相同的数字可以相互抵消。
例如:a^b^c^d^c^b^a=d