现在的文件一般都是以字节为单位,这里的讨论也是这样。我用的是流密码加密,现设明文长度为N字节,它们是A1、A2、...AN,密钥数组也是N字节,它们是B1、B2、...BN,相应的密文是M1、M2、...MN。密文是这样得到的:
加密算法 (i是小于或等于N的整数)
Ai + Bi = Mi
解密算法
Mi - Bi = Ai
密文是公开的,也就是已知数,Ai和Bi都是未知数,这样的方程共有N个,而未知数是2N个,所以方程式些不定方程是无解的。但如果你掌握了密钥数组就可以解密了。
密钥数组的建立
(1)组分的均匀;为了达到隐藏信息的目的你需要制作密钥数组,理想的密钥数组应是分布均匀的、数值是随机的、相互之间没有任何关联。根据这些要求我们建造它。定义最小单元概念,最小单元——所有元素的最小集合,也就是所有元素,每元素只出现一次的集合。首先要达到元素的分布均匀,现实中只能是相对的均匀,例如现在用字节为单位,共有0至255个元素,从中随便拿出几个数谈不上均匀,而最小单元的组合则是绝对均匀的,这时其中所有元素都是相同数量的,我是这样处理的,数组长度N除256=M+余数,以M+1个最小单元的元素组成绝对均匀数组,对数组进行数值分布均匀处理,最后从中任取N个作为密钥数组。
(2)分布的均匀;上面建立了元素成员绝对均匀的原始数组,设数组长度为n,现在我们设法将其变为分布均匀的数组,并且数组成员之间是没有关系的,我们采用随机排序的方法,来打乱数组的原有秩序,随机排序就是让数组内的元素位置随机的交换,一般可以用循环来完成,例如n 长度的数组,用一个循环变量i,从头到尾的循环,另外随机的在n 中选择一个位置,用这个位置的元素和第i 个元素进行交换,这样循环一次每个元素都被交换了,交换完成后新的顺序建立了,生成了新的数组。从n 中随机的选择位置的操作可以用随机函数来完成,也可以拼凑一些变数来完成,让随机函数值和一些变量经代数运算生成一个大数据,用此数据模n(就是除n的余数),就可以得到随机位置了。一遍随机排序不理想可以进行多遍,一般借助于优秀的随机函数一遍就足够混乱了。
我这样控制随机排序,由用户密码的计算值做成随机函数的种子和参数。,这些完成后你将得到一个长度为n 的乱码数组,从中取任取 N个密钥数组的建立就完成了。
安全性问题
现在如果使用用户密码生成器,产生一些随机的字节数组作为用户密码,来完成加密等是足够安全了。但一般用户密码是用户由键盘输入而产生的,键盘输入的字符只是字节数域内的一小部分,可能产生的问题是,输入过于简单、重复使用相同的用户密码,算计你秘密的人就可能积累一些数据来破译你的密文。为了避免上述问题的发生,另外设置了自动密码(俗称加盐salt),就是让程序自动生成一些随机数字节,这些数据作为用户密码的补充其用法和其它用户密码是一样的,它需要保存在密文中解密时要用,它的隐藏位置、加密等是由其它用户密码控制的。自动密码的加入带来的好处是,使密码分析更加困难,现在对同一文件进行同样用户密码的加密,每次得到的密文是完全不一样的,另外其可能打乱密文的排列秩序。
程序不对解密成功或密码是否正确作出判断,那样做的结果是被破解者利用,使用暴力破解来攻击你。这样就需要破解者自己来判断解密是否成功,但也是徒劳的,因为用户密码足够随机、密钥数组足够随机,所以所有状态是等概率的,例如“今日进攻”和“今日撤退”是等概率的你将陷于无法判断的僵局。这是严格意义上的对策,实际应用中为用户使用方便,你可以只判断例如密码的一小部分是否正确,比如10个用户密码只判断其中两个,这样密码错误能被挡住,但检测通过也未必是正解,但正确的密码会得到正解的。
Ai + Bi = Mi
假设和值为10,那么可以枚举Ai、Bi的所有可能性,比如1+9=10,2+8=10,3+7=10......排除0+10的两种可能性和,而5+5只有一种可能性,也就是最终会有9中可能性,但是如果像楼主说的随机数和明文没有任何关联的话,对于爆破来说确实增加了很大的难度,毕竟是2个未知数,不过既然有一个已知数,那么爆破的可能性也是有,只是投入的会比较大,排除爆破的话,个人觉得可能真的不好破解出来。并且我上面举的例子仅仅是有理数相加,如果从Ai和Bi经过某种运算得到Mi的方法又算法作者自定义的,那么难度更大了。对于爆破者来说,无疑是一种徒劳,表示支持楼主的思想。