实现PROXY穿越(4):DES算法之二

  最近忙,事比较多,活多了,还要降薪,唉。没什么时间看书,将以前的一些技术blog也移到这里。NTLM在去年年底和今年年初研究过一阵子,写了总结和 例子程序。里面涉及很多算法,在网上查了很久。(下面是以前的博客)最近想实现一个通过PROXY穿越的网络编程,将相关的内容进行一下汇总。很多东西来 自网络共产主义,也应该为共产主义有所回馈。介绍DES算法之二的实现。

 

步骤二:16次计算(16 interations)

   在步骤一中,我们获取了64bits的s,以及56bits的key。s分为2个32bit的序列,分布成为L和R,根据第一步计算,我们有了L0、R0,以及K0,进行如下的操作:
L1=R0
R1=L0 XOR F(R0,K1)
   我们得到了新的L1和R1,重复操作,直至得到L16和R16,操作公式为:
Li = R i-1
Ri = L i-1 XOR F(Ri-1,Ki)

A:Ki的获取
  在这个过程中,我们每次运算的操作需要得到新的ki进行参与。下面将介绍如何从K0依次16个获取Ki(K1-K16)。K0是一个56bits的数据,我们将其存贮56个字节的key数组中。这56个比特均分为2组,第一组0-27,第二组28-55。
   左移偏移量:
      1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
   对于Ki,从左移偏移量选择对应的偏移量,例如K1=1,K4=2。将两组28位的比特分别左移指定的便宜量。例如对于K1,经过左移后,第一组为 1-27,0,第二组为29-55,28。得到一个新的56比特的数据,请保留这个新的序列,记做K1',这个数据根据下面进行序列重排:
    |14 17 11 24  1  5|
    | 3 28 15  6 21 10|
    |23 19 12  4 26  8|
    |16  7 27 20 13  2|
    |41 52 31 37 47 55|
    |30 40 51 45 33 48|
    |44 49 39 56 34 53|
    |46 42 50 36 29 32|

   经过重新排序后,我们得到48比特的数据,这个就是K1。由此我们获得了第一个参与运算的K1。
   对于Ki,将Ki-1',例如计算K2,将上次我们得到的K1',分为两组,进行相应的左移操作,得到Ki’,例如计算K2是,我们将K1’分为两组,每组左移1为,得到K2’,将Ki’进行同样排序,得到Ki。
   通过这样的操作,我们依次得到16个Ki,代码如下:
static int key_offset[] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
static int ip_key[] ={
    14,17,11,24,1,5,
    3,28,15,6,21,10,
    23,19,12,4,26,8,
    16,7,27,20,13,2,
    41,52,31,37,47,55,
    30,40,51,45,33,48,
    44,49,39,56,34,53,
    46,42,50,36,29,32};

//左移操作
static void getkey(IN OUT unsigned char * key,int offset){
    unsigned char temp[28];

    memcpy(temp,key + offset,28-offset);
    memcpy(temp + 28 - offset, key , offset);
    memcpy(key,temp,28);

    memcpy(temp,key + 28 + offset,28-offset);
    memcpy(temp + 28 - offset, key + 28 , offset);
    memcpy(key + 28,temp,28);
}

void algorithm_des(IN unsigned char * src, IN unsigned char * secrect,
                   OUT unsigned char * dst){
    ......
    //步骤二:
    //获取原始的L0和R0
    memcpy(L,s,32);
    memcpy(R,s+32,32);
   
    //进行16次计算
    for(i = 0; i < 16 ; i++){
        //获取Ki'仍然放置在key中
        getkey(key,key_offset[i]);
        //获取Ki,放置在K中
        initail_permutation(key,ip_key,48,K);
    }
}


B:F计算

  我们已经有R0,对于每次计算Ri,都将有Ri-1,根据A的步骤,我们已经有了K1,对于每次计算,我们也有Ki。在这个步骤中,我们将实现F(Ri-1,Ki)。

step B.1:
   对于Ri-1进行序列交换,生成一个48比特的数据,排序方式如下:
   | 32  1  2  3  4  5 |
   |  4  5  6  7  8  9 |
   |  8  9 10 11 12 13 |
   | 12 13 14 15 16 17 |
   | 16 17 18 19 20 21 |
   | 20 21 22 23 24 25 |
   | 24 25 26 27 28 29 |
   | 28 29 30 31 32  1 |

   这组48比特的数据和Ki进行异或(XOR),得到一组新的48bite的数据,我们暂时记做E.

step B.2: S box的运算
  48比特的数据均分为8份,每份6比特,我们分别根据S-box的变换,每份产生4比特的数据,生成一个32bite的数据。
1、从6比特的数据中获取一个行号m和一个列号n。
  m=b0b5,n=b1b2b3b4
  例如6比特的数据为100101,则m=11(3),n=0010(2)
2、根据行号和列号,在S-box的序列中,查到相应的数值。48比特分为8组,每组查询的S-box是不一样的,分别为S1, S2, S3, S4, S5, S6, S7,S8具体如下:
S1:   0列 1列 2列 3列 4列 5列 6列 7列 8列 9列 A列 B列 C列 D列 E列 F列
0行    14  4   13  1   2   15  11  8   3   10  6   12  5   9   0   7
1行    0   15  7   4   14  2   13  1   10  6   12  11  9   5   3   8
2行    4   1   14  8   13  6   2   11  15  12  9   7   3   10  5   0
3行    15  12  8   2   4   9   1   7   5   11  3   14  10  0   6   13

S2:
    15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
    3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
    0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
    13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
S3:
    10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
    13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
    13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
    1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
S4
    7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
    13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
    10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
    3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
S5
    2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
    14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
    4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
    11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
S6
    12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
    10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
    9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
    4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
S7
    4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
    13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
    1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
    6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
S8
    13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
    1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
    7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
    2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
  我们仍以100101为例子,假设它的第一组6比特,得到m=3,n=2,我们查询S1,在第3行,第2列中查得8,将其翻译为二进制,则转换为4比特 的数据1000,这样我们得到了新的第一组4比特,如此类推,我们得到了8组4比特的数据,按顺序组合成一个32比特的数据,暂时记为E'。

stepB.3:更换顺序
将32比特的E’根据下面进行序列更换,得到新的32位数据。
   |16 7  20 21|
   |29 12 28 17|
   |1  15 23 26|
   |5  18 31 10|
   |2  8  24 14|
   |32 27 3  9 |
   |19 13 30 6 |
   |22 11 4  25|

至此我们完成了F运算。

C:获得新的Ri和Li
这步骤比较简单,如下
Li = R i-1
Ri = L i-1 XOR F(Ri-1,Ki)

D:重复16次计算,得到L16和R16

static int ip_e[] = {
    32,1,2,3,4,5,
    4,5,6,7,8,9,
    8,9,10,11,12,13,
    12,13,14,15,16,17,
    16,17,18,19,20,21,
    20,21,22,23,24,25,
    24,25,26,27,28,29,
    28,29,30,31,32,1};
static int ip_p[] = {
    16,7,20,21,29,12,28,17,
    1,15,23,26,5,18,31,10,
    2,8,24,14,32,27,3,9,
    19,13,30,6,22,11,4,25};

static unsigned char s1[64] = {
    14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
    0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
    4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
    15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 };

static unsigned char s2[64] = {
    15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
    3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
    0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
    13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 };

static unsigned char s3[64] = {
    10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
    13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
    13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
    1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 };

static unsigned char s4[64] = {
    7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
    13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
    10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
    3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 };

static unsigned char s5[64] = {
    2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
    14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
    4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
    11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 };

static unsigned char s6[64] = {
    12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
    10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
    9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
    4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 };

static unsigned char s7[64] = {
    4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
    13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
    1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
    6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 };

static unsigned char s8[64] = {
    13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
    1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
    7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
    2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 };

static void s_box_function(IN unsigned char * data,IN unsigned char * sbox,
                           OUT unsigned char * dst){
    int m = data[0] * 2 + data[5];
    int n = data[1] * 8 + data[2] * 4 + data[3] * 2 + data[4];
    unsigned char c = sbox[m* 16 + n];
    if(c >= 8){
        dst[0] = 1;
        c = c-8;
    }else{
        dst[0] = 0;
    }
    if(c >= 4){
        dst[1] = 1;
        c = c-4;
    }else{
        dst[1] = 0;
    }
    if(c >= 2){
        dst[2] = 1;
        c = c-2;
    }else{
        dst[2] = 0;
    }
    dst[3] = c;
}

void algorithm_des(IN unsigned char * src, IN unsigned char * secrect,
                   OUT unsigned char * dst){
    ......
    //步骤二:
    //获取原始的L0和R0
    memcpy(L,s,32);
    memcpy(R,s+32,32);
   
    //进行16次计算
    for(i = 0; i < 16 ; i++){
        //获取Ki
        getkey(key,key_offset[i]);
        initail_permutation(key,ip_key,48,K);

        //F计算
        initail_permutation(R,ip_e,48,E);
        xorbit(E,K,48,E);
        s_box_function(E,s1,E);
        s_box_function(E + 6,s2,E + 4);
        s_box_function(E + 12,s3,E + 8);
        s_box_function(E + 18,s4,E + 12);
        s_box_function(E + 24,s5,E + 16);
        s_box_function(E + 30,s6,E + 20);
        s_box_function(E + 36,s7,E + 24);
        s_box_function(E + 42,s8,E + 28);
        initail_permutation(E,ip_p,32,E);

        //更换序列
        xorbit(E,L,32,E);
        memcpy(L,R,32);
        memcpy(R,E,32);
    }
}
相关链接:我的网络通信相关文章

NTLM的实现:

  • 实现PROXY穿越(16):NTLM的PROXY穿越
  • 实现PROXY穿越(15):NTLM Session Security
  • 实现PROXY穿越(14):NTLM type3 Message
  • 实现PROXY穿越(13):NTLM type2 Message
  • 实现PROXY穿越(12):NTLM type1 Message
  • 实现PROXY穿越(11):NTLMv2 session response
  • 实现PROXY穿越(10):NTLMv2 response
  • 实现PROXY穿越(9):NTLMv1 response
  • 实现PROXY穿越(8):NT-Hash的实现
  • 实现PROXY穿越(7):MD4和MD5
  • 实现PROXY穿越(6):LM-Hash的实现
  • 实现PROXY穿越(5):DES算法之三
  • 实现PROXY穿越(4):DES算法之二
  • 实现PROXY穿越(3):DES算法之一
  • 实现PROXY穿越(2):Base64算法
  • 实现PROXY穿越(1):流程和NTLM算法

你可能感兴趣的:(Algorithm,算法,function,session,DST,permutation)