黑客攻防从入门到精通(加密与解密篇)
上QQ阅读APP看书,第一时间看更新

2.4 伪随机数加密技术概述

伪随机数加密技术其实质就是通过伪随机数序列使文件的字节值发生变化而产生密文。由于相同的初值能得到相同的随机数序列,因此,可以采用同样的伪随机数序列来对密文进行解密并将其恢复为明文。

而其加密算法则为:当取定一个初值时,在加密过程中将产生伪随机数序列r1, r2, …, rn。对应密文Ci有(其中所得的a1, a2, …, an即为原明文)。

ai= Ci- ri,当Ciri

ai=(Ci+256)-ri,当Ciri

下面是伪随机数加密法的加密和解密程序。

加密程序的C语言源代码如下。

define KEY 10
        #define SIZE 160
        #define NULL 0
        #include <stdio.h>
        #include <math.h>
    main()
    {
      FILE *fp
      int k, j, i, count, rj, t;
      char fbuf[SIZE], sbuf[SIZE], filename[10], ch;
      j=KEY;
      printf("input locked filename :\n");
      scanf("%s, fi lename);
      if((fp=fopen(fi lename, "r"))==NULL)
      {
        printf("Cannot open file! \n");
        exit(0);
      }
      for (k=0; (ch=fgetc(fp))! =EOF; k++)
      {
        fbuk[k]=ch;
        putchar(fbuf[k]);
      }
      putchar('\n');
      fclose(fp);
      count=k;
      for(i=0; i<count; i++)
      {
        rj=rand(j);
        sbuf[i]=fbuf[i]+rj)%256;
        j++;
      }
      if((fp=fopen(filename, "w"))= =NULL)
      {
        printf("Cannot open 1.ss! \n");
        exit(0);
      }
      for(i=0; i<count; i++)
      {
        fputc(sbuf[i], fp);
        putchar(subf[i]);
      }
      putchar('\n');
      fclose(fp);
    }

解密程序的C语言源代码如下。

#define KEY 10
    #define SIZE 160
    #define NULL 0
    #include <stdio.h>
    #include <math.h>
    main()
    {
      FILE *fp;
      int  k, j, i, count, rj;
      char fbuf[SIZE], sbuf[SIZE], ch, filename[10];
      j=KEY;
      printf("input unlocked filename:\n");
      scanf("%s", fi lename);
      if((fp=fopen(fi lename, "r"))==NULL)
      {
        printf("Cannot open file! \n");
        exit(0);
      }
      for(k=0; (ch=fgetc(fp))! =EOF; k++)
      {
        fbuf[k]=ch;
        putchar(fbuf[k];
      }
      putchar('\n');
      fclose(fp);
      count=k;
      for(i=0; i<count; i++)
      {
        rj=rand(j);
        if (fbuf[i]<rj)
          sbuf[i]=fbuf[i]+256-rj;
        else
          sbuf[i]=fbuf[i]-rj;
        j++;
      }
      if((fp=fopen(fi lename, "w"))==NULL)
      {
        printf("Cannot open u.ss! \n");
        exit(0);
      }
      for(i=0; i<count; i++)
      {
      fputc(sbuf[i], fp);
          putchar(subf[i]);
          }
          putchar('\n');
          fclose(fp);
        }

设其可执行文件名为TEST.EXE,说明文件的内容为:

garden plants need different amounts of sunlight cucumbers, for
      example, are very hard to please

加密/解密均覆盖操作如下。

加密操作:

C:\>TEST
        输入说明文件名
            显示原文件内容(garden…please)
            显示加密后的内容(乱码)

解密操作:

C:\>TEST
        显示input unlocked filename:
        说明文件名
        显示加密后的内容(乱码)
        显示解密后的文件内容(garden…please)

通常伪随机数用随机函数来产生,这样就产生一个问题,破解者可以通过阅读程序知道你的随机函数并得到全部的随机数组成员。如果你的加密过于简单,他可以用随机数组逐字节地与你的密文进行运算,实现破解,那你的密文就危险了。这里给出3个方法,可以有效地解决这个问题。

① 多次加密法。一个明文字节用两个以上的密钥字节进行加密,如果使用多个随机函数来生成密钥最好,随机函数种子要和密码相关。如果用同一函数要使用不同的区段,各区段的起点(对应不同的种子)一定是密码相关的,也就是动态的、随加密者的密码动态变化的。这样处理的结果是破解几乎无计可施。

② 序列重排法。通过运算得到了密钥的随机数组,不直接使用它,对随机数组的序列进行重新排列,实际作用是建立新的数组,这个重排最好用其他随机数组来完成,随机函数种子要和密码相关。如果使用相同的函数要使用不同的区段,各区段的起点(对应不同的种子)最好是密码相关的,也就是动态的、随加密者的密码动态变化的。这样生成的随机数组,对破解者来说就是真随机数组了,你就可以实现一次一密的安全加密了。

③ 随机函数内部参数动态化。让它内部参数和用户密码相关,这样破解者将无法复现伪随机数组进行破解,实际是对随机函数簇中的一个进行调用,如果是多个参数就更好了,但要确保随机函数的发散性不被破坏或影响。

如果加密程序编排得当,破解无从下手。只能用暴力破解。这里是这样对付他们的。无论密码正确与否都将进行解密操作,如果密码正确可以解密,如果错误将毁坏密文。所以破解者必须判断结果,从而给他造成很大的麻烦。

其实防止暴力破解、穷举法的最有效措施就是对文件进行二次加密。破解者无法判断中间结果是否成功,而且一次加密后也不会有空白为分析提供方便。但如果采用单一密码进行二次加密,窃密者知晓后可设计专门的程序进行二次解密。保险的做法是二次加密采用不同的密码,使其彻底绝望。当然这是要牺牲加密速度的做法,用户要根据具体情况选择加密方案。

防止暴力破解、穷举法的另一方法是加长密码的位数。这个方法有效但是给使用者也造成了使用上的麻烦。你可以这样做,让程序自动对密码加首尾字符串,而首尾串表写在文本文件里供使用者复制,然后修改中间部分即可,需要通信双方约定好其内容,并可经常更改。因为是自动添加的你就可以做长一些,可以用一些冷僻的汉字和符号做密码。密码增加许多位对窃密者是个大麻烦,破解时间将是天文数字。这里密码的位数增加对运算速度几乎没有什么影响。