一个性能还不错的DES加密库(转换自同事改写的一份C++代码)_c++ des库-程序员宅基地

技术标签: input  c++  byte  integer  加密  Delphi  permutation  

由于项目需要将日志进行加密,并且合同附件写明是使用DES,不得已而做了下来,经过测试,性能仅为原来没有加密前的九至十分之一,而现成的东西不确定是否为线程安全的,即便是使用DLL库,进行线程分离加载也算大废周章。难耐之下,取来一C++的DES加密单元进行了代码转换,直接将其中公共变量(存在线程安全问题)声明改为threadval,调入程序当中,发现性能还不错,是原来加密库的四至五倍,接近不加密时的45%~50%,多少也算了过得去。下面列出源代码和用例(时间关系,注释都是原来C++单元当中搬过来的):

unit UnitDES;
{$ifndef LITTLE_ENDIAN}
    
{$define LITTLE_ENDIAN 1}
{$endif}
interface
const
(
*   32 - bit permutation function P used on the output of the S - boxes  * )
p32i: array[
0 .. 31 ] of Byte  =  (
    
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
);

(
*  The ( in )famous S - boxes  * )
     si: array[
0 .. 7 , 0 .. 63 ] of Byte  =
(
    (
*  S1  * )
    (
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 ),

    (
*  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 )
);

(
*  bit  0   is  left - most  in   byte   * )
bytebit: array [
0 .. 7 ] of Integer  =
(
    
0200 0100 040 020 010 04 02 01
);

nibblebit : array [
0 .. 3 ] of Integer  =
(
    
010 04 02 01
);

(
*  initial permutation IP  * )
ip :array[
0 .. 63 ] of Byte  =
(
    
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
);

(
*  final permutation IP ^- 1   * )
fp: array[
0 .. 63 ] of Byte  =
(
    
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
);

(
*  permuted choice table (key)  * )
pc1: array[
0 .. 55 ]of Byte  =
(
    
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
);

(
*  number left rotations of pc1  * )
totrot: array [
0 .. 15 ] of Byte  =
(
    
1 2 4 6 8 10 12 14 15 17 19 21 23 25 27 28
);


(
*  permuted choice key (table)  * )
 pc2:array[
0 .. 47 ] of Byte  =
(
    
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
);
// var
threadvar
(
*  Lookup tables initialized once only at startup by desinit()  * )
  sp: array [
0 .. 7 , 0 .. 63 ]  of LongWord; ( *  Combined S and P boxes  * )
  iperm: array [
0 .. 15 , 0 .. 15 , 0 .. 7 ]  of Byte;( *  Initial and final permutations  * )
  fperm: array[
0 .. 15 , 0 .. 15 , 0 .. 7 ]  of Byte;
  (
*   8   6 - bit subkeys  for  each of  16  rounds, initialized by dessetkey()  * )
  kn: array [
0 .. 15 , 0 .. 7 ]  of Byte;
  desmode: Integer;
function desinit(mode: Integer):Integer;
function dessetkey(
const  key:PByte): Integer;
procedure endes(block:PByte);
procedure dedes(block:PByte);
function spinit: Integer;(
* static * )
procedure DES_round(num:Integer; block:PLongWord);(
* static * )

implementation
{$ifdef    LITTLE_ENDIAN}
(
*  Byte swap a  long   * )
// function byteswap(x:LongWord):LongWord;
// var
//     cp,CP1:PChar;
//   tmp:Char;(*register*)
// begin
//     cp := PChar( @x);
//   Inc(cp,3);
//     tmp := cp^;
//   cp1 := cp;
//   Dec(cp,3);
//     cp1^ := cp^;
//     cp^ := tmp;
//
//   Dec(cp1);
//   Inc(cp);
//     tmp := cp1^;
//     cp1^ := cp^;
//     cp^ := tmp;
//
//     Result := x;
// end;
// {$else}
function byteswap(x:LongWord):LongWord;assembler;
asm
  bswap eax
end;
{$endif}                 ( *  LITTLE_ENDIAN  * )

(
*  Initialize the lookup table  for  the combined S and P boxes  * )
function spinit: Integer;
var
    pbox: array [
0 .. 31 ] of Byte;
    p, i, s, j, rowcol: Integer;
    val: longInt;
begin
    (
*
    
*  Compute pbox, the inverse of p32i. This  is  easier to work with
    
* )
    
for  p : =   0  to   32 - 1   do
    begin
        
for  i : =   0  to  32 - 1   do
        begin
            
if  (p32i[i]  -   1   =  p) then
            begin
                pbox[p] :
=  i;
                
break ;
            end;
        end;
    end;
    
for  s : =   0  to  8   -   1   do
    begin    (
*  For each S - box  * )
        
for  i : =   0  to  64   -   1   do
        begin    (
*  For each possible input  * )
            val :
=   0 ;
            (
*
            
*  The row number  is  formed from the first and last bits; the
            
*  column number  is  from the middle  4
            
* )

            
// rowcol := (i and 32) or ((i and 1) ? 16 : 0) or ((i shr 1) and $f);
       if  (i and  1 <>   0  then
        rowcol :
=  (i and  32 ) or (  16  ) or ((i shr  1 ) and $f)
      
else
        rowcol :
=  (i and  32 ) or (  0 ) or ((i shr  1 ) and $f);

            
for  j : =   0  to  4 - 1   do
            begin    (
*  For each output bit  * )
                
if  (si[s][rowcol] and ( 8  shr j))  <>   0  then
                begin
                    val :
=  val or ( 1  shl ( 31   -  pbox[ 4   *  s  +  j]));
                end;
            end;
            sp[s][i] :
=  val;
        end;
    end;
    Result :
=   0 ;
end;

(
*  The nonlinear function f(r,k), the heart of DES  * )
//     unsigned long    r;        /* 32 bits */
//     unsigned char    subkey[8];    /* 48-bit key for this round */
function f( r:LongWord; subkey:PByte):LongWord;( * static * )
var
     rval, rt:LongWord;(
* register  * )
begin
    (
*
    
*  Run E(R)  ^  K through the combined S  &  P boxes This code takes
    
*  advantage of a convenient regularity  in  E, namely that each group of  6
    
*  bits  in  E(R) feeding a single S - box  is  a contiguous segment of R.
    
* )
    
// rt := (r shr 1) or ((r and 1) ? $80000000 : 0);
   if  (r and  1 <>   0  then
    rt :
=  (r shr  1 ) or $ 80000000
  
else
    rt :
=  (r shr  1 ) or  0 ;

    rval :
=   0 ;
    rval :
= rval or ( sp[ 0 ][((rt shr  26 ) xor subkey ^ ) and $3f]);
  Inc(subkey);
    rval :
= rval or ( sp[ 1 ][((rt shr  22 ) xor subkey ^ ) and $3f]);
  Inc(subkey);
    rval :
= rval or ( sp[ 2 ][((rt shr  18 ) xor subkey ^ ) and $3f]);
  Inc(subkey);
    rval :
= rval or ( sp[ 3 ][((rt shr  14 ) xor subkey ^ ) and $3f]);
  Inc(subkey);
    rval :
= rval or ( sp[ 4 ][((rt shr  10 ) xor subkey ^ ) and $3f]);
  Inc(subkey);
    rval :
= rval or ( sp[ 5 ][((rt shr  6 ) xor subkey ^ ) and $3f]);
  Inc(subkey);
    rval :
= rval or ( sp[ 6 ][((rt shr  2 ) xor subkey ^ ) and $3f]);
  Inc(subkey);
    
// rt := (r shl 1) or ((r and $80000000) ? 1 : 0);
   if  (r and $ 80000000 ) <> 0  then
    rt :
=  (r shl  1 ) or (  1  )
  
else
    rt :
=  (r shl  1 ) or ( 0 );
  
    rval :
= rval or sp[ 7 ][(rt xor subkey ^ ) and $3f];
    
    result :
=  rval;
end;

(
*  Do one DES cipher round  * )
//     int             num;    /* i.e. the num-th one     */
//     unsigned long  *block;
procedure DES_round(num:Integer; block:PLongWord);( * static * )
var
  block1:PLongWord;
begin
    
//     long            f();

    (
*
    
*  The rounds are numbered from  0  to  15 . On even rounds the right half  is
    
*  fed to f() and the result exclusive - ORs the left half; on odd rounds
    
*  the reverse  is  done.
    
* )
  block1 :
=  block;
  Inc(block1);
    
if  (num and  1 ) <>   0  then
    begin
        block1
^  : = block1 ^  xor f(block ^ , @kn[num]);
    end
    
else
    begin
        block
^  : = block ^  xor f(block1 ^ , @kn[num]);
    end;
end;

(
*  Allocate space and initialize DES lookup arrays
*  mode  ==   0 : standard Data Encryption Algorithm
*  mode  ==   1 : DEA without initial and final permutations  for  speed
*  mode  ==   2 : DEA without permutations and with  128 - byte  key (completely
*               independent subkeys  for  each round)
* )
function desinit(mode: Integer):Integer;
procedure iperminit;

var
  l, j, k: Integer;(
* register * )
    i, m: Integer;
begin
    (
*  Clear the permutation array  * )
    
for  i : =   0  to  16   -   1   do
    begin
        
for  j : =   0  to  16 - 1   do
        begin
            
for  k : =   0  to  8 - 1   do
            begin
                iperm[i][j][k] :
=   0 ;
            end;
        end;
    end;
    
    
for  i : =   0  to  16 - 1   do     ( *  each input nibble position  * )
    begin
        
for  j : =   0  to  16 - 1   do ( *  each possible input nibble  * )
        begin
            
for  k : =   0  to  64 - 1   do
            begin    (
*  each output bit position  * )
                l :
=  ip[k]  -   1 ;    ( *   where  does  this  bit come from  * )
                
if  ((l shr  2 <>  i)    then ( *  does it come from input posn ?   * )
                    
continue ;    ( *   if  not, bit k  is   0       * )
                
if  ( 0   =  (j and nibblebit[l and  3 ])) then
                    
continue ;    ( *  any such bit  in  input ?   * )
                m :
=  k and  07 ; ( *  which bit  is   this   in  the  byte   * )
                iperm[i][j][k shr 
3 ] : =  iperm[i][j][k shr  3 ] or bytebit[m];
            end;
    end;
    end;
end;

procedure fperminit;

var
  l, j, k: Integer;(
* register * )
    i, m: Integer;
begin
    (
*  Clear the permutation array  * )
    
for  i : =   0  to  16   -   1   do
    begin
        
for  j : =   0  to  16 - 1   do
        begin
            
for  k : =   0  to  8 - 1   do
            begin
                fperm[i][j][k] :
=   0 ;
            end;
        end;
    end;
    
    
for  i : =   0  to  16 - 1   do     ( *  each input nibble position  * )
    begin
        
for  j : =   0  to  16 - 1   do ( *  each possible input nibble  * )
        begin
            
for  k : =   0  to  64 - 1   do
            begin    (
*  each output bit position  * )
                l :
=  fp[k]  -   1 ;    ( *   where  does  this  bit come from  * )
                
if  ((l shr  2 <>  i)    then ( *  does it come from input posn ?   * )
                    
continue ;    ( *   if  not, bit k  is   0       * )
                
if  ( 0   =  (j and nibblebit[l and  3 ])) then
                    
continue ;    ( *  any such bit  in  input ?   * )
                m :
=  k and  07 ; ( *  which bit  is   this   in  the  byte   * )
                fperm[i][j][k shr 
3 ] : =  fperm[i][j][k shr  3 ] or bytebit[m];
            end;
    end;
    end;
end;
begin
  Result :
=   0 ;
    desmode :
=  mode;
    spinit();
    
if  (mode  =   1 ) or (mode  =   2 ) then( *  No permutations  * )
    Exit;
  iperminit;
  fperminit;
end;


(
*  Set key (initialize key schedule array)  * )
//     char           *key;    /* 64 bits (will use only 56) */
function dessetkey( const  key:PByte): Integer;
var
    pc1m:array [
0 .. 55 ] of Byte;    ( *  place to modify pc1 into  * )
    pcr: array [
0 .. 55 ] of Byte;    ( *  place to rotate pc1 into  * )
    i, j, l:Integer;(
* register * )
    M:integer;
  Key1:PByte;
begin
    (
*
    
*  In mode  2 , the  128  bytes of subkey are  set  directly from the user ' s
     *  key, allowing him to use completely independent subkeys  for  each
    
*  round. Note that the user MUST specify a full  128  bytes.
    
*
    
*  I would like to think that  this  technique gives the NSA a real headache,
    
*  but I ' m not THAT naive.
     * )
  Result :
=   - 1 ;
    
if  (desmode  =   2 ) then
    begin
    Key1 :
=  Key;
        
for  i : =   0  to  16 - 1   do
        begin
            
for  j : =   0  to  8 - 1   do
            begin
                kn[i][j] :
=  key1 ^ ;
        Inc(Key1);
            end;
        end;
        Exit;
    end;
    (
*  Clear key schedule  * )
    
for  i : =   0  to  16 - 1   do
    begin
        
for  j : =   0  to  8 - 1   do
        begin
            kn[i][j] :
=   0 ;
        end;
    end;
    
for  j : =   0  to  56 - 1   do
    begin    (
*  convert pc1 to bits of key  * )
        l :
=  pc1[j]  -   1 ;     ( *  integer bit location   * )
        m :
=  l and  07 ;     ( *  find bit       * )
        
// pc1m[j] := (key[l shr 3]  and (* find which key byte l is in *)
        
//     bytebit[m])    (* and which bit of that byte *)
        
//     ? 1 : 0;        (* and store 1-bit result *)
     if  (PByte(Integer(key) + (l shr  3 )) ^   and bytebit[m])  <>   0  then
      pc1m[j] :
=   1
    
else
      pc1m[j] :
=   0 ;
    end;
    
for  i : =   0  to  16 - 1   do
    begin    (
*  key chunk  for  each iteration  * )
        
for  j : =   0  to  56 - 1   do ( *  rotate pc1 the right amount  * )
    begin
            
// pcr[j] := pc1m[(l = j + totrot[i]) < (j < 28 ? 28 : 56) ? l : l - 28];
      l : =  j  +  totrot[I];
      
if  J  <   28  then
        begin
          
if  l  <   28  then
            begin
              pcr[j] :
=  pc1m[l];
            end
          
else
            begin
              pcr[j] :
=  pc1m[l - 28 ];
            end;
        end
      
else
        begin
          
if  l  <   56  then
            begin
              pcr[j] :
=  pc1m[l];
            end
          
else
            begin
              pcr[j] :
=  pc1m[l - 28 ];
            end;
        end;
    end;
        (
*  rotate left and right halves independently  * )
        
for  j : =   0  to  48 - 1   do
        begin    (
*  select bits individually  * )
            (
*  check bit that goes to kn[j]  * )
            
if  (pcr[pc2[j]  -   1 <>   0 ) then
            begin
                (
*  mask it  in   if  it ' s there *)
                l : =  j mod  6 ;
                kn[i][j div 
6 ] : = kn[i][j div  6 ] or (bytebit[l] shr  2 );
            end;
        end;
    end;
    Result :
=   0 ;
end;

(
*  In - place encryption of  64 - bit block  * )
procedure endes(block:PByte);
var
    i:Integer;(
* register * )
    work:array [
0 .. 1 ] of LongWord;    ( *  Working data storage  * )
    tmp:LongInt;
function Ipermute:Integer;(
* static * )
var
    i, j:Integer;(
* register * )
    ib,ob:PByte;(
* register * )    ( *  ptr to input or output block  * )
  p, q:PByte;(
* register * )
begin
  Result :
=   0 ;
    
if  (iperm[ 0 ][ 0 ][ 0 =   0 ) then
    begin
        (
*  No permutation, just copy  * )
    ib :
=  block;
    ob :
=  PByte(@work[ 0 ]);
        
for  i : =   8  downto  1   do
      begin
              ob
^ : =  ib ^ ;
        Inc(ib);
        Inc(ob);
      end;
        Exit;
    end;

    (
*  Clear output block      * )
  ob :
=  PByte(@work[ 0 ]);
    
for  i : =   8  downto  1   do
    begin
          ob
^  : =   0 ;
      Inc(ob);
    end;

    ib :
=  block;
  J :
=   0 ;
    
while  j  <   16   do
    begin (
*   for  each input nibble  * )
        ob :
=  PByte(@work[ 0 ]);
        p :
=  @iperm[j][(ib ^  shr  4 ) and  017 ];
        q :
=  @iperm[j  +   1 ][ib ^  and  017 ];
        
for  i : =   8  downto  1   do
        begin    (
*  and each output  byte   * )
            ob
^  : = ob ^  or (p ^  or q ^ );    ( *  OR the masks together  * )
      inc(q);
      inc(p);
      Inc(ob);
        end;
    Inc(ib);
    Inc(J,
2 );
  end;
end;
function fpermute:Integer;(
* static * )
var
    i, j:Integer;(
* register * )
    ib,ob:PByte;(
* register * )    ( *  ptr to input or output block  * )
  p, q:PByte;(
* register * )
begin
  Result :
=   0 ;
    
if  (fperm[ 0 ][ 0 ][ 0 =   0 ) then
    begin
        (
*  No permutation, just copy  * )
    ib :
=  PByte(@work[ 0 ]);
    ob :
=  block;
        
for  i : =   8  downto  1   do
      begin
              ob
^ : =  ib ^ ;
        Inc(ib);
        Inc(ob);
      end;
        Exit;
    end;

    (
*  Clear output block      * )
  ob :
=  block;
    
for  i : =   8  downto  1   do
    begin
          ob
^  : =   0 ;
      Inc(ob);
    end;

    ib :
=  PByte(@work[ 0 ]);
  j :
=   0 ;
    
while  j  <   16   do
    begin (
*   for  each input nibble  * )
        ob :
=  block;
        p :
=  @fperm[j][(ib ^  shr  4 ) and  017 ];
        q :
=  @fperm[j  +   1 ][ib ^  and  017 ];
        
for  i : =   8  downto  1   do
        begin    (
*  and each output  byte   * )
            ob
^  : = ob ^  or (p ^  or q ^ );    ( *  OR the masks together  * )
      inc(q);
      inc(p);
      Inc(ob);
        end;
    Inc(ib);
    Inc(J,
2 );
  end;
end;
begin
  Ipermute; (
*  Initial Permutation  * )

{$ifdef LITTLE_ENDIAN}
    work[
0 ] : =  byteswap(work[ 0 ]);
    work[
1 ] : =  byteswap(work[ 1 ]);
{$endif}                 ( *  LITTLE_ENDIAN  * )

    (
*  Do the  16  rounds  * )
    
for  i : =   0  to  16 - 1   do
        DES_round(i, @work[
0 ]);

    (
*  Left / right half swap  * )
    tmp :
=  work[ 0 ];
    work[
0 ] : =  work[ 1 ];
    work[
1 ] : =  tmp;

{$ifdef LITTLE_ENDIAN}
    work[
0 ] : =  byteswap(work[ 0 ]);
    work[
1 ] : =  byteswap(work[ 1 ]);
{$endif}                 ( *  LITTLE_ENDIAN  * )

  fpermute;  (
*  Inverse initial  *  permutation  * )
end;

(
*  In - place decryption of  64 - bit block  * )
procedure dedes(block:PByte);
var
    I: Integer;(
* register * )
    work: array [
0 .. 1 ] of LongWord;    ( *  Working data storage  * )
    tmp:LongInt;
function Ipermute:Integer;(
* static * )
var
    i, j:Integer;(
* register * )
    ib,ob:PByte;(
* register * )    ( *  ptr to input or output block  * )
  p, q:PByte;(
* register * )
begin
  Result :
=   0 ;
    
if  (iperm[ 0 ][ 0 ][ 0 =   0 ) then
    begin
        (
*  No permutation, just copy  * )
    ib :
=  block;
    ob :
=  PByte(@work[ 0 ]);
        
for  i : =   8  downto  1   do
      begin
              ob
^ : =  ib ^ ;
        Inc(ib);
        Inc(ob);
      end;
        Exit;
    end;

    (
*  Clear output block      * )
  ob :
=  PByte(@work[ 0 ]);
    
for  i : =   8  downto  1   do
    begin
          ob
^  : =   0 ;
      Inc(ob);
    end;

    ib :
=  block;
  J :
=   0 ;
    
while  j  <   16   do
    begin (
*   for  each input nibble  * )
        ob :
=  PByte(@work[ 0 ]);
        p :
=  @iperm[j][(ib ^  shr  4 ) and  017 ];
        q :
=  @iperm[j  +   1 ][ib ^  and  017 ];
        
for  i : =   8  downto  1   do
        begin    (
*  and each output  byte   * )
            ob
^  : = ob ^  or (p ^  or q ^ );    ( *  OR the masks together  * )
      inc(q);
      inc(p);
      Inc(ob);
        end;
    Inc(ib);
    Inc(J,
2 );
  end;
end;
function Fpermute:Integer;(
* static * )
var
    i, j:Integer;(
* register * )
    ib,ob:PByte;(
* register * )    ( *  ptr to input or output block  * )
  p, q:PByte;(
* register * )
begin
  Result :
=   0 ;
    
if  (fperm[ 0 ][ 0 ][ 0 =   0 ) then
    begin
        (
*  No permutation, just copy  * )
    ib :
=  PByte(@work[ 0 ]);
    ob :
=  block;
        
for  i : =   8  downto  1   do
      begin
              ob
^ : =  ib ^ ;
        Inc(ib);
        Inc(ob);
      end;
        Exit;
    end;

    (
*  Clear output block      * )
  ob :
=  block;
    
for  i : =   8  downto  1   do
    begin
          ob
^  : =   0 ;
      Inc(ob);
    end;

    ib :
=  PByte(@work[ 0 ]);
  J :
=   0 ;
    
while  j  <   16   do
    begin (
*   for  each input nibble  * )
        ob :
=  block;
        p :
=  @fperm[j][(ib ^  shr  4 ) and  017 ];
        q :
=  @fperm[j  +   1 ][ib ^  and  017 ];
        
for  i : =   8  downto  1   do
        begin    (
*  and each output  byte   * )
            ob
^  : = ob ^  or (p ^  or q ^ );    ( *  OR the masks together  * )
      inc(q);
      inc(p);
      Inc(ob);
        end;
    Inc(ib);
    Inc(J,
2 );
  end;
end;
begin
  Ipermute;  (
*  Initial permutation  * )

{$ifdef LITTLE_ENDIAN}
    work[
0 ] : =  byteswap(work[ 0 ]);
    work[
1 ] : =  byteswap(work[ 1 ]);
{$endif}                 ( *  LITTLE_ENDIAN  * )

    (
*  Left / right half swap  * )
    tmp :
=  work[ 0 ];
    work[
0 ] : =  work[ 1 ];
    work[
1 ] : =  tmp;

    (
*  Do the  16  rounds  in  reverse order  * )
    
for  i : =   15  downto  0   do
        DES_round(i, @work[
0 ]);

{$ifdef LITTLE_ENDIAN}
    work[
0 ] : =  byteswap(work[ 0 ]);
    work[
1 ] : =  byteswap(work[ 1 ]);
{$endif}                 ( *  LITTLE_ENDIAN  * )

  Fpermute;  (
*  Inverse initial  *  permutation  * )
end;

end.
uses
  UnitDES;
procedure TForm1.btnTestClick(Sender: TObject);
var
  sIn,sOutHex,sKey:String;
  NewLen,I: Integer;
  block :PByte;
  P,P1:PChar;
  B,B1:Byte;
begin
  sIn :
=   ' 测试字符串 ' ;
  sKey :
=   ' 这是密钥 ' ;

  desinit(
0 );

  I :
=  Length(sKey);
  SetLength(sKey,
8 );  // 调整密钥为8位
   if  I  <   8  then
    
// 填充密钥
    FillChar(PChar(Integer(PChar(sKey)) + I) ^ , 8 - I, 100 );

  I :
=  Length(sIn);
  
if  (I mod  8  ) <> 0  then
    begin
      
// 调整串长为8的倍数
      NewLen : =  ((I div  8 +   1 *   8 ;
      SetLength(sIn,NewLen);
      
// 置串结束符(这里是串加密
      PChar(Integer(PChar(sIn)) + I) ^  : =  # 0 ;
    end;

  
// 初始化密钥
  dessetkey(PByte(PChar(sKey)));

  block :
=  Pointer(sIn);
  NewLen :
=  Length(sIn);
  
while ( NewLen  >   0  )  do
    begin
      
// 加密
      endes( PByte(block));
      Dec(NewLen,
8 );
      Inc(block,
8 );
    end;

  
// 十六进制转换
  SetString(sOutHex,Nil,Length(sIn)  *   2 );
  P :
=  PChar(sIn);
  P1 :
=  PChar(sOutHex);
  
for  I : =   0  to Length(sIn)  -   1   do
    begin
      B :
=  Byte(P ^ );
      B1 :
=  ((B shr  4 ) and $f);
      
case  B1 of
        
0 .. 9 :
          P1
^  : =  Chr(B1  +   48 )
        
else
          P1
^  : =  Chr(B1  +   65   -   10 );
      end;

      Inc(P1);
      B1 :
=  (B  and $f);

      
case  B1 of
        
0 .. 9 :
          P1
^  : =  Chr(B1  +   48 )
        
else
          P1
^  : =  Chr(B1  +   65   -   10 );
      end;

      Inc(P1);
      Inc(P);
    end;

  ShowMessage(sOutHex);

  
// 初始化密钥
  dessetkey(PByte(PChar(sKey)));

  NewLen :
=  Length(sIn);
  block :
=  Pointer(sIn);
  
while ( NewLen  >   0  )  do
    begin
      
// 解密
      dedes(PByte(block));
      Dec(NewLen, 
8 );
      Inc(block, 
8 );
    end;
  SetLength(sIn,strlen(PChar(sIn)));

  ShowMessage(sIn);
end;
 
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/unsigned/article/details/2196616

智能推荐

Seata介绍、原理、配置_seata配置-程序员宅基地

文章浏览阅读4.5k次,点赞4次,收藏29次。Seata是一款开源的分布式事务解决方案,可以用于解决分布式系统中的数据一致性问题。它是由阿里巴巴集团发起的开源项目,目前得到了广泛的应用和支持。在 Seata 开源之前,其内部版本在阿里系内部一直扮演着应用架构层数据一致性的中间件角色,帮助经济体平稳的度过历年的双11在分布式系统中,由于数据存储在不同的节点上,因此需要保证分布式事务的原子性(即要么全部成功,要么全部失败),否则将会出现数据不一致的情况。Seata提供了一种可靠的分布式事务解决方案,可以对全局事务进行管理和协调,从而实现分布式事务的原子_seata配置

Golang | Leetcode Golang题解之第36题有效的数独-程序员宅基地

文章浏览阅读520次。Golang | Leetcode Golang题解之第36题有效的数独

稍微深入分析Ubuntu环境下安装NVIDIA驱动导致黑屏的原因_prime-select nvidia 黑屏-程序员宅基地

文章浏览阅读8.2k次,点赞5次,收藏48次。本文承接之前写的有关如何用正确姿势安装NVIDIA驱动的博文 (https://blog.csdn.net/Edward_ed_liu/article/details/109552761)。首先之所以要更新Linux内核,是因为不更新内核就无法使用笔记本自带的无线网卡。其次,目前NVIDIA官方不建议把Linux内核更新到最新版(5.9),而且这条消息只在英文的官网才有,中文的则是广告。TWICE如果强行更新到5.9版本,之后的Cuda安装表面上会显示成功,但在实际使用Cuda的过程中._prime-select nvidia 黑屏

java中间件有哪些_金九银十期间成功斩获58万架构师Offer!六面字节跳动面经和面试题分享 - 小梦爱Java...-程序员宅基地

文章浏览阅读167次。金九银十期间成功斩获58万Offer!六面字节跳动面经(成功关键:吃透九大核心知识+狂刷大厂面试真题)第一轮:团队面试第一轮基本上是你的团队成员面试你,是和你同级或者高你一个P的师兄来面你,我的话基本没问什么特别的,主要还是讲自己简历上的做的项目,这里需要你很熟悉自己的项目才行,我个人觉得这里你要把项目里你的角色做了什么没做什么讲清楚,然后最好能把自己做的那部分重点展开来讲,然后面试官会从你讲的内..._java架构师 中间件简历

【规则引擎】一、规则引擎简介_规则引擎 风险 功能-程序员宅基地

文章浏览阅读1.9k次。(第一章规则引擎学习入门之规则引擎简介)# 系列文章目录规则引擎简介前言一、为什么要使用规则引擎?1.不使用规则引擎的规则执行现状2. 规则引擎优点二、规则引擎的功能三、规则引擎的分类实现1.事中规则实现2.事后规则实现四、规则引擎调研1.开源规则引擎2.商业规则引擎五、Drools六、Aviator前言规则引擎由推理引擎发展而来,是一种嵌入在应用程序中的组件,实现了将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策。接受数据输入,解释业务规则,并根据业务规则做出业务决策。–来自百_规则引擎 风险 功能

oracle设置生成归档日志大小,Oracle 改变归档日志大小-程序员宅基地

文章浏览阅读1k次。该变归档日志大小只有改变日志组的大小!方法:加入新的大的日志文件,然后删掉旧的小的日志文件假设现有三个日志组,每个组内有一个成员,每个成员的大小为1MB,现在想把此三个日志组的成员大小都改为10MB1、创建2个新的日志组alter database add logfile group 4 ('D:\ORACLE\ORADATA\ORADB\REDO04_1.LOG') size 1024k;alt..._oracle归档日志空间大小

随便推点

初识中央处理器CPU_cpu总线架构-程序员宅基地

文章浏览阅读2k次,点赞2次,收藏5次。CPU_cpu总线架构

美团2024届秋招笔试第一场编程真题——小美的好矩阵-程序员宅基地

文章浏览阅读1.3k次。现在给定一个n∗m的矩阵,小美想知道有多少个3*3的子矩阵是好矩阵,你能帮帮她吗?接下来的n行,每行输入一个仅包含大写字母的长度为m的字符串。第一行输入两个整数n,m,代表矩阵的行数和列数。左下角的存在两个相邻的字母相同,因此不合法。左上角的子矩阵出现了’D’,因此不合法。右下角的子矩阵里没有’C’,因此不合法。解法:纯模拟,被恶心到了。输出一个整数表示答案。有4个3*3的子矩阵。_小美的好矩阵

Vector - CANoe - LIN一致性测试_vector canoe-程序员宅基地

文章浏览阅读2.5k次,点赞6次,收藏40次。CANoe一键生成LIN一致性测试_vector canoe

当下 React 项目该放弃的以及更好用的技术推荐-程序员宅基地

文章浏览阅读210次。React 版本推荐当前 React 都已经发布 18 了,虽然是个 alpha 版本,但是 17 确实也已经有大厂在用了。目前如果你的版本还停留在 v16.8 之前的话还是尽早升了吧。毕..._react 放弃

C++基础-资源管理:堆、栈与 RAII_c++heap内存堆管理-程序员宅基地

文章浏览阅读161次。堆,英文是 heap,在内存管理的语境下,指的是动态内存分配的区域,和数据结构中的“大根堆和小根堆”不是一个概念。同时,这里堆分配的内存需要手工释放,否则会造成内存泄漏。 C++ 标准里有一个和堆相关的概念是自由存储区,英文是 free store,特指使用 new 和 delete 来分配和释放内存的区域。一般而言,这是堆的一个子集。_c++heap内存堆管理

CentOS7中安装MySQL8.0.21爬坑记录:1045-Access denied、Job for firewalld.service failed等异常_error: failed to read file "/proc/sys/net/netfilte-程序员宅基地

文章浏览阅读1.3k次。在CentOS7.3中安装了MySQL8.0.21之后,就开启了一段漫长的爬坑历程,简要回顾如下:一、从Win10中用Navicat连接安装好的MySQL服务器出现如下异常:1045 - Access denied for user ‘root’@‘192.168.101.151’(using password: YES) 于是,在网上查阅了多篇博客,结论可能是3306端口没有加入到防火墙的允许列表。之后,开始研究了CentOS7中的防火墙,发现RHEL6之前版本用的防火墙管理工具都是iptab_error: failed to read file "/proc/sys/net/netfilter/nf_conntrack_helper": [e