用随机乱序建造理想的密钥数组

  这里的目的是通过随机乱序方法来建立作为密钥的随机数组。要建立的随机数组要求具有真随机数的某些性质,例如数组元素之间没有任何关系,每个元素都是独立的存在,你无法由前面的数据推算后面的数据,没有周期等,但它们又是可以控制的可以重复产生,目的是用来做加密文件的密钥,所以它的产生要和用户密码密切关联,用户密码是独立于加密软件和密文或明文的,要充分利用这一点,控制密钥数组的产生。
  随机乱序是将一个数组,经随机排序生成新数组的操作。现在我们以字节为单位组成的数组为例。(这是因为现在的文件多以字节为单位,如果需要其它形式的数组可用字节来组合或分解)下面以例说明:
  这里用 C语言表达方式叙述,设一个长度为n的字节数组s[0],s[1],....,s[n-1]。
对数组的随机排序就是:
int i;
int k;
char ch;
char s[n]; //省略数组赋值过程

  for(i=0;i<n;i++)
  {
  k=rand()%n;
  ch = s[i];
  s[i] = s[k];
  s[k] = ch;
  }
  rand()表式任何一个随机函数,用它或其代数式随机地产生一个序号k,k的取值从0到n-1。 然后让s[i]和s[k]做数值交换,循环i从0到n-1。循环结束s[]已经是新的数组了。
  随机乱序操作简单,但它有许多重要应用。这里重点说一下用它来生成随机数。
  上面的程序使用随机函数控制重新排序的,新数组与原始的s[]及rand()函数有关,s[]中的成员还是原来的,只是顺序发生了变化,rand()及其算式只起到帮助排序的作用。但不是说没有随机函数就不能完成随机排序,实际上用任何字符串的值放到上面rand()位置都可以进行排序,只是如果字符串的随机性不好使得排序的效率不高。当数组比较混乱时用数组自身加上些其它变量也可以对自身进行排序。
  上面的程序是在数组长度 n的范围内随机排序,如果 n较大速度不会高的,效率也就不高了。想办法提高效率吧。
  以字节为单位的数组有256个不同元素它们是0 - 255。我们使用密钥都希望使用随机性好的,各元素等概率出现的乱码,如果密钥数组里重复元素频繁出现,尤其是连续两个零等就是一种漏洞或缺陷,当然这不一定影响使用,既然建造就要造得更理想些,所以这里避免重复元素出现。以256个不同元素做成一个小数组,这里称之为最小单元数组,这种单元数组共有256!个,这是个庞大的数字,在众多此类数组中除去极少量有规律的以外大部分都是乱码,我们就用这些小数组来建立密钥数组。这里建立随机数组的思路是对最小单元数组进行随机乱序,并将得到的小数组连接起来组成大数组,并且避免重复元素的出现,这只要上一个小数组最后一个元素和下一个小数组第一个元素不一样即可,这样就使得整个数组没有任何两个相邻的元素是相同的。
  假设dy[]是一个单元数组,这是256!中的一个。
  for(i=0;i<256;i++)
  {
  k=rand()%n;      
  ch = dy[i];
  dy[i] = dy[k];
  dy[k] = ch;
  }
  运行一遍将产生新的单元数组,下面是由小数组组成大数组。这里假设 n是256的倍数,这样处理简单些。为了程序表面清晰没有加上避免重复字符产生的程序段,那是轻而易举的。
  for(i=0;i<n;i=i+256)
  {
    for(j=0;j<256;j++)
    {
    k=rand()%n;
    ch = dy[j];
    dy[j] = dy[k];
    dy[k] = ch;
    }
    for(j=0;j<256;j++)
    {
    ss[i+j]=dy[j];
    }
  }
  上式中k=rand()%n 如果改成k=(dy[j]+k+j)%n速度要更快些(需要给k赋初值,k参与到这里将使变换成为不可逆的),这是让最小单元数组自我发展不断衍生出新的小数组,而且这样自然就没有重复元素了。
  下面说一下初始化问题。假如我们用某一个周期为 T1的随机函数对原始的最小单元数组进行了一遍排序,因为只有256次的循环这是个很快的过程,假如破解者想要通过实验找到变换后的结果,他们需要做 T1次试验,如果是多个随机函数参与初始化则要做T1×T2×...次试验,如果用周期10的20次以上的随机函数,困难可想而知,如果只用一个随机函数,使用多个用户密码相关的种子(初始值),分别对原始小数组初始化效果是一样的,这样需要做T1×T1×...次试验。找一些长周期随机函数对原始单元数组进行初始化排序将使破解难度增加许多倍(增加了时间复杂度),而且处理也不浪费时间,但注意这些随机函数的初值(种子)要和用户密码相关。
  再者上面第二式中k=rand()%n换成k=(rand()+N)%n或k=(dy[j]+k+j+N)%n其中N是个与户密码相关的数值,这样要复现结果数组就更加困难,至少增加了N倍的试验量。
  上面讨论了如何高效建立随机数组,分小段处理将大大提高速度。并且考虑了增加破解难度的方式,用长周期随机函数初始化最小单元数组。下面考虑让数组不可复现的其它方法,且看下式
  for(j=0;j<kn;j)
  {
    for(i=0;i<256;i++)
    {
    k=rand()%n;      
    ch = dy[i];
    dy[i] = dy[k];
    dy[k] = ch;
    }
  }
  这段程序放到建造随机数组之前,它也是单元数组初始化的一部分,dy[]是单元数组,rand()表示随机函数,现在让它循环kn遍,kn是个与用户密码相关的数值,我们知道用户密码对加密程序和密文都是未知数,也就是kn是未知数,采用此种设计可以有效的防止破解者跟踪再造密钥数组,但kn太大了将耽误时间,kn换成 kn1%kn2,这是kn1对kn2取模,这样就好了既节省时间又难以琢磨 ,这样即使程序的源码公开也无法有效跟踪复现密钥数组。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值