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 }

     

  • 相关阅读:
    ZOJ 1002 Fire Net (火力网)
    UVa OJ 117 The Postal Worker Rings Once (让邮差只走一圈)
    UVa OJ 118 Mutant Flatworld Explorers (变体扁平世界探索器)
    UVa OJ 103 Stacking Boxes (嵌套盒子)
    UVa OJ 110 MetaLoopless Sorts (无循环元排序)
    第一次遇到使用NSNull的场景
    NSURL使用浅析
    从CNTV下载《小小智慧树》
    NSDictionary and NSMutableDictionary
    Category in static library
  • 原文地址:https://www.cnblogs.com/kuoaidebb/p/4031914.html
Copyright © 2011-2022 走看看