zoukankan      html  css  js  c++  java
  • DES原理与实现

    一 DES综述

    DES是对称密码的一种,它使用56位秘钥对64位长分组进行加密。DES对每个分组的内容都会进行16轮迭代,每轮的操作相同但是对应不同的子秘钥。所有的子秘钥都是由主密钥推导而来。

    64位明文加密过程如下:

    1. 按位置换(IP)

    2. 明文被分成L0和R0两部分。

    3. L1=R0  R1=L0⊕f(R0,k1)

    4. 重复步骤3 16次

    5. 按位置换(IP^-1)

     

    二 细节分析

    其中的重点在于:1. 如何实现函数f  2. 如何生成子秘钥k

    1. 函数f 输入与输出的数据为32位。

      E:    将输入的数据分成8个4位的分组。这个过程在E盒中进行。E盒是一种特殊的置换。32位输入中有16位输入位在输出中出现了两次。分别为第1 4 5 8 9 12 ... 32位。E盒的输入数据为32位,输出为48位,仅有置换操作。

      S:   将拓展得到的48位结果与密钥ki进行XOR操作,将8个6位长的分组送入8个不同的替换盒S中,将6位输出裁剪成4位。S盒的输入数据为48位,输出为32位,有和密钥的XOR操作,也有置换。

      P:   按位置换,以实现扩散。P盒的输入和输出均为32位,仅有置换操作。

    2. 密钥生成函数GetKey的输入为64位密钥,输出为16个48位子密钥。

      密钥的实际有效位数为56位,其余8位为奇校验位。PC-1处理得到的56位密钥分为C和D两部分。首先将C和D按照轮数移动一位或者两位。然后将C和D合起来,用PC-2将56位密钥置换成48位密钥。

      PC-1:置换的意义是去掉校验位。

      PC-2:意义是将56位置换成48位。

     

    三 几个小问题

    1. 从总体上来说,DES是什么?

      前面杂七杂八的扯了那么多细节问题,不免让人头昏脑涨。用最简单的话讲,DES是什么?一种加密方法。将8位密钥处理得到16组子密钥。它还将待加密数据分成许多个分组,每个分组有8个字符组成。然后每组待加密数据,做16轮加密处理,每轮加密处理都用不同的密钥,即最初得到的16组子密钥。

      举例说明:

    密钥:12345678

    待加密数据:i am a good student

    子密钥:

    Array ( 
    [1] => 010100000010110010101100010101110010101011000010
    [2] => 010100001010110010100100010100001010001101000111
    [3] => 110100001010110000100110111101101000010010001100
    [4] => 111000001010011000100110010010000011011111001011
    [5] => 111000001001011000100110001111101111000000101001
    [6] => 111000001001001001110010011000100101110101100010
    [7] => 101001001101001001110010100011001010100100111010
    [8] => 101001100101001101010010111001010101111001010000
    [9] => 001001100101001101010011110010111001101001000000
    [10] => 001011110101000101010001110100001100011100111100
    [11] => 000011110100000111011001000110010001111010001100
    [12] => 000111110100000110011001110110000111000010110001
    [13] => 000111110000100110001001001000110110101000101101
    [14] => 000110110010100010001101101100100011100110010010
    [15] => 000110010010110010001100101001010000001100110111
    [16] => 010100010010110010001100101001110100001111000000 )

       

    待加密数据:
    i am a g => 281EBCF251148911 (16进制) ood stud =>ECFB5BFD44D714EF (16进制) ent00004 =>BFBE729B56B9B540(16进制)#最后一组待加密数据位数不足8位,用0补齐,最后一位表示补0的个数

    2. 怎么实现置换?

      置换在代码中的实现尤为简单,具体见最下方的代码 function move()。

    3. 函数过程中数据应该是以二进制流动的,二进制如何与字母数字转化?

      被加密字符采用了ASCII码到二进制的转换。密钥每一位都被当做10进制数字处理。

      被加密的字符首先被转化成两位16进制表示的ASCII码,然后每个字符转换成8位2进制,即为二进制原始待加密数据。

    4. 密钥的格式是什么:字母或者是数字?多少位?

      在整个加密过程中,共生成16组子密钥,分别用于16轮加密。每个生成的子密钥的实际均为48位的二进制数组。具体格式如上所示。具体转换的方法是:用户提供的密钥中的每一位数字,都由1位十进制转化成8位二进制,不足8位的在最前方补0。即得出64位二进制原始密钥。

     

    四 贴代码(php)

    $S = array(
        1 => array(
            array(14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7),
            array(0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8),
            array(4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0),
            array(15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13),
        ),
        2 => array(
            array(15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10),
            array(3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5),
            array(0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15),
            array(13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9),
        ),
        3 =>array(
            array(10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8),
            array(13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1),
            array(13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7),
            array(1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12),
        ),
        4 => array(
            array(7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15),
            array(13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9),
            array(10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4),
            array(3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14),
        ),
        5 => array(
            array(2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9),
            array(14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6),
            array(4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14),
            array(11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3),
        ),
        6 => array(
            array(12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11),
            array(10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8),
            array(9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6),
            array(4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13),
        ),
        7 => array(
            array(4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1),
            array(13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6),
            array(1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2),
            array(6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12),
        ),
        8 => array(
            array(13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7),
            array(1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2),
            array(7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8),
            array(2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11),
        ),
    );
    
    $E = array(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);
    
    $P = array(
    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,
    );
    
    
    $PC1 = array(
    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);
    
    $PC2 = array(
    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,
    );
    
    $IP = array(
    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,
    );
    
    $IP1 = array(
    40,    8,    48,    16,    56,    24,    64,    32,    39,    7,    47,    15,    55,    23,    63,    31,
    38,    6,    46,    14,    54,    22,    62,    30,    37,    5,    45,    13,    53,    21,    61,    29,
    36,    4,    44,    12,    52,    20,    60,    28,    35,    3,    43,    11,    51,    19,    59,    27,
    34,    2,    42,    10,    50,    18,    58,    26,    33,    1,    41,    9,    49,    17,    57,    25,
    );
    
    $r = array(1=>1,2=>1,3=>2,4=>2,5=>2,6=>2,7=>2,8=>2,9=>1,10=>2,11=>2,12=>2,13=>2,14=>2,15=>2,16=>1,);

     

     

      1 $k = array();
      2 
      3 function index($data,$key,$type=1){
      4     global $k;
      5     $k=GetKey($key);
      6     if($type==1){
      7         $str=BitByte($data);
      8         return DES($str);
      9     }
     10     else{
     11         $str=DecodeTrans($data);
     12         return ToASCII(DES($str,2));
     13     }
     14 }
     15 
     16 function shiftleft($data,$num) {    //循环左移一位
     17     return substr($data, $num, (strlen($data) - $num)) . substr($data, 0, $num);
     18 }
     19 
     20 function move($array, $data) {        //置换
     21     $rs = '';
     22     foreach($array as $index) {
     23         $rs .= $data[$index-1];
     24     }
     25 
     26     return $rs;
     27 }
     28 
     29 function dataXOR($data1, $data2) {
     30     if(strlen($data1) != strlen($data2)) {
     31         exit('xor err');
     32     }
     33 
     34     $rs = '';
     35     for($i=0; $i<strlen($data1); $i++){
     36         $rs .= ($data1[$i] == $data2[$i])?0:1;
     37     }
     38 
     39     return $rs;
     40 }
     41 
     42 function S($EL) {
     43     global $S;
     44 
     45     $B = array();
     46     for($i=1;$i<=8;$i++){
     47         $B[$i] = substr($EL, 6*($i-1),6);
     48     }
     49 
     50     $BI = array();
     51     foreach($B as $id => $row) {
     52         $a = base_convert($row[0] . $row[5], 2, 10);
     53         $b = base_convert(substr($row, 1, 4), 2, 10);
     54         $BICurrent = base_convert($S[$id][$a][$b], 10, 2);
     55 
     56         while(strlen($BICurrent) < 4) {
     57             $BICurrent = 0 . $BICurrent;
     58         }
     59 
     60         $BI[$id] = $BICurrent;
     61     }
     62 
     63     return implode('', $BI);
     64 }
     65 
     66 function BitByte($data){
     67     $str='';
     68     for($i=0;$i<strlen($data); $i++){
     69         $temp=base_convert(ord($data[$i]), 10, 2);
     70         while(strlen($temp) < 8) {
     71             $temp = 0 . $temp;
     72         }    
     73 
     74         $str .= $temp;    
     75     }
     76 
     77     return $str;
     78 }
     79 
     80 function DecodeTrans($data){    //16进制转换为二进制
     81     $result = '';
     82     for($start = 0; $start < strlen($data); $start += 2) {
     83         $bin = substr($data, $start, 2);
     84         $temp= strtoupper(base_convert($bin, 16, 2));
     85         while(strlen($temp) < 8) {
     86             $temp = 0 . $temp;
     87         }
     88 
     89         $result .=$temp;
     90     }
     91 
     92     return $result;
     93 }
     94 
     95 function GetKey($key){
     96     global $PC1,$PC2;
     97 
     98     if(strlen($key)!=8){
     99         exit('密钥长度错误!');
    100     } 
    101 
    102     $binKey=BitByte($key);    //key转成二进制
    103     $keyPC1 = move($PC1,$binKey);    //对key(binkey)进行pc-1处理
    104     $C[0] = substr($keyPC1, 0, 28);
    105     $D[0] = substr($keyPC1, 28, 28);
    106     $C=GetMove($C);
    107     $D=GetMove($D);    
    108 
    109     for($i=1; $i<=16; $i++) {
    110         $concat = $C[$i] . $D[$i];
    111         $k[$i]=move($PC2,$concat);
    112     }
    113 
    114     return $k;
    115 }
    116 
    117 function GetMove($data)    //获取左移之后的密钥
    118 {
    119     global $r;
    120 
    121     for($i=1; $i<=16; $i++) {
    122         $shift = $data[$i-1];
    123         $data[$i] = shiftleft($shift,$r[$i]);
    124     }
    125 
    126     return $data;
    127 }
    128 
    129 
    130 function DES($data,$type=1){
    131     global $IP,$IP1,$E,$k,$P;
    132     $temp=move($IP,$data);
    133 
    134     $L = $R = array();
    135     $L[0] = substr($temp, 0, 32);
    136     $R[0] = substr($temp, 32, 32);
    137 
    138     
    139     for($i=1; $i<=16; $i++) {
    140         $L[$i] = $R[$i-1];
    141         $EL = move($E, $L[$i]);
    142 
    143         $EL = ($type==1)?dataXOR($EL, $k[$i]): dataXOR($EL, $k[17-$i]);
    144         $s = S($EL);
    145         $f = move($P, $s);
    146         $R[$i] = dataXOR($L[$i-1], $f);
    147     }    
    148         
    149     $concat = $R[16] . $L[16];
    150 
    151     $encoded = move($IP1, $concat);
    152     $result = '';
    153     for($start = 0; $start < strlen($encoded); $start += 4) {
    154         $bin = substr($encoded, $start, 4);
    155         $result .= strtoupper(base_convert($bin, 2, 16));
    156     }
    157 
    158     return $result;
    159 }
    160 
    161 function ToASCII($data){
    162     $str='';
    163     for($start = 0; $start < strlen($data); $start += 2) {
    164         $bin = substr($data, $start, 2);
    165         $str .= chr(base_convert($bin, 16, 10));
    166     }
    167 
    168     return $str;
    169 }

     

  • 相关阅读:
    IO
    mouseover,mouseout和mouseenter,mouseleave
    【译】addEventListener 第二个参数
    Git 常用命令
    我对Backbone中url属性的理解
    小失误引起大失败
    收集各大网站的登录页面
    随笔2
    随笔1
    创建数据库
  • 原文地址:https://www.cnblogs.com/kuoaidebb/p/4031914.html
Copyright © 2011-2022 走看看