实现PROXY穿越(3):DES算法之一

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

 

   在NTLM中使用DES算法生成LM-HASH和NTLM-HASH(以后在介绍)。我们现讨论DES算法的实现。 DES是Data Encryption Standard(数据加密标准)的缩写。它是由IBM公司研制的一种加密算法,美国国家标准局于1977年公布把它作为非机要部门使用的数据加密标准,二十年来,它一直活跃在国际保密通信的舞台上,扮演了十分重要的角色。而DES算法本身称自己为DEA(Data Encryption Althorithm),因此DES和DEA实际是同一个东东。
  DES输入64bit的数据源,通过56bits的key(由8bytes去掉CRC校验位获得,输入也可以看作是64bits,至少在程序代码中是这样体现),生成一个64bits的结果,DES属于对称加密方式。一共分为三个步骤。
  在实现的过程中,最为郁闷的是网上有很多代码和例子,也有一些检测工具,例如Crytotool1.2,但是很奇怪,他们给出的结果不一样,因此有必要认真了解一下整个DES的过程。

步骤一:源和key的初始化序列改动(Initail permutation)
通过对比特的序列移动,生成新的源'和key’,用于后续的算法计算。

A:对源的处理
  8字节,共64bits,从1到64按下面左阵列的摆列方式,经过序列移动,成规下面右阵列的排列方式,实际上新的第一个8bit就是左阵列的第2 列,从下到上的顺序,后面的7组8比特分别为第4、6、8、1、3、5、7列从下到上的排序。这种方式,我想对于芯片实现是很便利的,可惜C编程语言不等 直接按列处理,只好写段代码来实现。
| 1  2  3  4  5  6  7  8|    |58 50 42 34 26 18 10 2|
| 9 10 11 12 13 14 15 16|    |60 52 44 36 28 20 12 4|
|17 18 19 20 21 22 23 24|    |62 54 46 38 30 22 14 6|
|25 26 27 28 29 30 31 32|    |64 56 48 40 32 24 16 8|
|33 34 35 36 37 38 39 40| -> |57 49 41 33 25 17  9 1|
|41 42 43 44 45 46 47 48|    |59 51 43 35 27 19 11 3|
|49 50 51 52 53 54 55 56|    |61 53 45 37 29 21 13 5|
|57 58 59 60 61 62 63 64|    |63 55 47 39 31 23 15 7|
 实现代码:
//变换序列
static int ip_data_seq[] = {
    58,50,42,34,26,18,10,2,
    60,52,44,36,28,20,12,4,
    62,54,46,38,30,22,14,6,
    64,56,48,40,32,24,16,8,
    57,49,41,33,25,17,9,1 ,
    59,51,43,35,27,19,11,3,
    61,53,45,37,29,21,13,5,
    63,55,47,39,31,23,15,7};

//由于后面存在大量的比特操作,而C程序中一般以字节为单位,因此我们将字节中的比特分别
//存贮在8个字节中,以方便后面的大量运算
static void storebit(IN unsigned char * data, IN int data_len, OUT unsigned char * dst){
    int i = 0;
    for(i = 0 ; i < data_len;i ++){
        dst[i*8] = getbit(data[i],7);
        dst[i*8 + 1] = getbit(data[i],6);
        dst[i*8 + 2] = getbit(data[i],5);
        dst[i*8 + 3] = getbit(data[i],4);
        dst[i*8 + 4] = getbit(data[i],3);
        dst[i*8 + 5] = getbit(data[i],2);
        dst[i*8 + 6] = getbit(data[i],1);
        dst[i*8 + 7] = getbit(data[i],0);
    }
}
//这是storebit得反操作。
static void parsebit(IN unsigned char * data,OUT unsigned char * dst,IN int dst_len){
    int i = 0;
    for(i = 0 ; i < dst_len ; i ++){
        dst[i] = data[8*i] * 0x80 +
            data[8*i + 1] * 0x40 +
            data[8*i + 2] * 0x20 +
            data[8*i + 3] * 0x10 +
            data[8*i + 4] * 0x8 +
            data[8*i + 5] * 0x4 +
            data[8*i + 6] * 0x2 +
            data[8*i + 7];
    }
}

//移位操作函数
static void initail_permutation(IN unsigned char * data,IN int * schedule, IN int num,
                                OUT unsigned char * dst){
    int i = 0;
    unsigned char * temp;
    temp = (unsigned char *)malloc(num);

    for(i = 0 ; i < num; i ++){
        temp[i] = data[schedule[i] - 1];
    }
    memcpy(dst,temp,num);
    free(temp);
}

//算法主函数
void algorithm_des(IN unsigned char * src, IN unsigned char * secrect,
                   OUT unsigned char * dst){
    unsigned char s[64],key[64],L[32],R[32],K[48],E[48];
    int i = 0;

    //步骤1
    storebit(src,8,s);
    initail_permutation(s,ip_data_seq,64,s);
}

B:对key的处理
  对于输入的8字节的key,每个字节去除其CRC校验位(第8位),然后经过类似的序列移位生成了56bit的新的key。从这个处理,我们也可以看出DES算法的古老,采用流的概念,而CRC校验位用于初期比较古老的误码率高的通信中。
  这种以通信以流的方式传递,需要注意和我们程序中的顺序问题。如果我们使用byte(unsinged char)来放置一8bit的信息,那么第一位是我们byte的高位。这与我们网络编程中碰到的little_endian和big_endian的情况有点类似。闲话少谈,移动位的方式如下:
| 1 2  3  4  5  6  7  8 |    |57 49 41 33 25 17  9|    |57 49 41 33 25 17  9  1|
| 9 10 11 12 13 14 15 16|    | 1 58 50 42 34 26 18|    |58 50 42 34 26 18 10  2|
|17 18 19 20 21 22 23 24|    |10  2 59 51 43 35 27|    |59 51 43 35 27 19 11  3|
|25 26 27 28 29 30 31 32|    |19 11  3 60 52 44 36|    |60 52 44 36            |
|33 34 35 36 37 38 39 40| -> |63 55 47 39 31 23 15| -> |63 55 47 39 31 23 15  7|
|41 42 43 44 45 46 47 48|    | 7 62 54 46 38 30 22|    |62 54 46 38 30 22 14  6|
|49 50 51 52 53 54 55 56|    |14  6 61 53 45 37 29|    |61 53 45 37 29 21 13  5|
|57 58 58 60 61 62 63 64|    |21 13  5 28 20 12  4|    |28 20 12  4            |

  中间和右图是一样的,只是我们采用7bit一组还是按照8bit一组的方式存放,我们希望通过右图给出一个有规律的处理。
static int ip_key_seq[] ={
    57,49,41,33,25,17,9,
    1,58,50,42,34,26,18,
    10,2,59,51,43,35,27,
    19,11,3,60,52,44,36,
    63,55,47,39,31,23,15,
    7,62,54,46,38,30,22,
    14,6,61,53,45,37,29,
    21,13,5,28,20,12,4};

//算法主函数
void algorithm_des(IN unsigned char * src, IN unsigned char * secrect,
                   OUT unsigned char * dst){
    unsigned char s[64],key[64],L[32],R[32],K[48],E[48];
    int i = 0;

    //步骤1
    storebit(src,8,s);
    storebit(secrect,8,key);
    initail_permutation(s,ip_data_seq,64,s);
    initail_permutation(key,ip_key_seq,56,key);
}

OK,终于完成了第一步,得到了s[64]和key[56]为第二步算法的输入。

相关链接:我的网络通信相关文章

NTLM的实现:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值