DES单元

来源:互联网 发布:赛门铁克数据备份软件 编辑:程序博客网 时间:2024/05/02 15:29

//Delphi version
//ZswangY37, October 2006
//
//THIS SOFTWARE IS PROVIDED "AS IS" AND
//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
//FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
//DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
//OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
//HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
//OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
//SUCH DAMAGE.

unit DESUtils;

interface

type
  TDesKey = array of Longword;
 
function des_createKeys(key: string): TDesKey;
function des(key: string; message: string;
  encrypt: Boolean; mode: Boolean; iv: string): string;

implementation

//设计 Zswang 2006-10-26 wjhu111#21cn.com 尊重作者,转贴请注明出处

//des_createKeys
//this takes as input a 64 bit key (even though only 56 bits are used)
//as an array of 2 integers, and returns 16 48 bit keys
function des_createKeys(key: string): TDesKey;
const
  //declaring this locally speeds things up a bit
  pc2bytes0: array[0..15] of Integer = (0, $4, $20000000, $20000004, $10000,
    $10004, $20010000, $20010004, $200, $204, $20000200, $20000204, $10200,
    $10204, $20010200, $20010204);
  pc2bytes1: array[0..15] of Integer = (0, $1, $100000, $100001, $4000000,
    $4000001, $4100000, $4100001, $100, $101, $100100, $100101, $4000100,
    $4000101, $4100100, $4100101);
  pc2bytes2: array[0..15] of Integer = (0, $8, $800, $808, $1000000, $1000008,
    $1000800, $1000808, 0, $8, $800, $808, $1000000, $1000008, $1000800,
    $1000808);
  pc2bytes3: array[0..15] of Integer = (0, $200000, $8000000, $8200000, $2000,
    $202000, $8002000, $8202000, $20000, $220000, $8020000, $8220000, $22000,
    $222000, $8022000, $8222000);
  pc2bytes4: array[0..15] of Integer = (0, $40000, $10, $40010, 0, $40000, $10,
    $40010, $1000, $41000, $1010, $41010, $1000, $41000, $1010, $41010);
  pc2bytes5: array[0..15] of Integer = (0, $400, $20, $420, 0, $400, $20, $420,
    $2000000, $2000400, $2000020, $2000420, $2000000, $2000400, $2000020,
    $2000420);
  pc2bytes6: array[0..15] of Integer = (0, $10000000, $80000, $10080000, $2,
    $10000002, $80002, $10080002, 0, $10000000, $80000, $10080000, $2,
    $10000002, $80002, $10080002);
  pc2bytes7: array[0..15] of Integer = (0, $10000, $800, $10800, $20000000,
    $20010000, $20000800, $20010800, $20000, $30000, $20800, $30800, $20020000,
    $20030000, $20020800, $20030800);
  pc2bytes8: array[0..15] of Integer = (0, $40000, 0, $40000, $2, $40002, $2,
    $40002, $2000000, $2040000, $2000000, $2040000, $2000002, $2040002,
    $2000002, $2040002);
  pc2bytes9: array[0..15] of Integer = (0, $10000000, $8, $10000008, 0,
    $10000000, $8, $10000008, $400, $10000400, $408, $10000408, $400, $10000400,
    $408, $10000408);
  pc2bytes10: array[0..15] of Integer = (0, $20, 0, $20, $100000, $100020,
    $100000, $100020, $2000, $2020, $2000, $2020, $102000, $102020, $102000,
    $102020);
  pc2bytes11: array[0..15] of Integer = (0, $1000000, $200, $1000200, $200000,
    $1200000, $200200, $1200200, $4000000, $5000000, $4000200, $5000200,
    $4200000, $5200000, $4200200, $5200200);
  pc2bytes12: array[0..15] of Integer = (0, $1000, $8000000, $8001000, $80000,
    $81000, $8080000, $8081000, $10, $1010, $8000010, $8001010, $80010, $81010,
    $8080010, $8081010);
  pc2bytes13: array[0..15] of Integer = (0, $4, $100, $104, 0, $4, $100, $104,
  $1, $5, $101, $105, $1, $5, $101, $105);
  shifts: array[0..15] of Boolean = (False, False, True, True, True, True, True,
    True, False, True, True, True, True, True, True, False);
var
  //other variables
  iterations: Longword;
  lefttemp, righttemp: Longword;
  m, n, temp: Longword;
  i, j: Longword;
  left, right: Longword;
begin
  //how many iterations (1 for des, 3 for triple des)
  if Length(key) >= 24 then
    iterations := 3
  else iterations := 1;
  //stores the return keys
  SetLength(Result, 32 * iterations);
  //now define the left shifts which need to be done
  m := 1;
  n := 0;
  for j := 1 to iterations do //either 1 or 3 iterations
  begin
    left := (Ord(Key[m]) shl 24) or (Ord(Key[m + 1]) shl 16) or
      (Ord(Key[m + 2]) shl 8) or Ord(Key[m + 3]);
    Inc(m, 4);
    right := (Ord(Key[m]) shl 24) or (Ord(Key[m + 1]) shl 16) or
      (Ord(Key[m + 2]) shl 8) or Ord(Key[m + 3]);
    Inc(m, 4);

    temp := ((left shr 4) xor right) and $0f0f0f0f;
    right := right xor temp;
    left := left xor (temp shl 4);
    temp := ((Int64(right) shr -16) xor left) and $0000ffff;
    left := left xor temp;
    right := right xor Longword(Int64(temp) shl -16);
    temp := ((left shr 2) xor right) and $33333333;
    right := right xor temp;
    left := left xor (temp shl 2);
    temp := ((Int64(right) shr -16) xor left) and $0000ffff;
    left := left xor temp;
    right := right xor Longword(Int64(temp) shl -16);
    temp := ((left shr 1) xor right) and $55555555;
    right := right xor temp;
    left := left xor (temp shl 1);
    temp := ((right shr 8) xor left) and $00ff00ff;
    left := left xor temp;
    right := right xor (temp shl 8);
    temp := ((left shr 1) xor right) and $55555555;
    right := right xor temp;
    left := left xor (temp shl 1);

    //the right side needs to be shifted and to get the last four bits of the left side
    temp := (left shl 8) or ((right shr 20) and $000000f0);
    //left needs to be put upside down
    left := (right shl 24) or ((right shl 8) and $ff0000) or ((right shr 8) and $ff00) or ((right shr 24) and $f0);


    right := temp;

    //now go through and perform these shifts on the left and right Result
    for i := Low(shifts) to High(shifts) do
    begin
      //shift the Result either one or two bits to the left
      if shifts[i] then
      begin
        left := (left shl 2) or (left shr 26);
        right := (right shl 2) or (right shr 26);
      end else
      begin
        left := (left shl 1) or (left shr 27);
        right := (right shl 1) or (right shr 27);
      end;
      left := left and -$f;
      right := right and -$f;

      //now apply PC-2, in such a way that E is easier when encrypting or decrypting
      //this conversion will look like PC-2 except only the last 6 bits of each byte are used
      //rather than 48 consecutive bits and the order of lines will be according to
      //how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7
      lefttemp := pc2bytes0[left shr 28] or pc2bytes1[(left shr 24) and $f] or
        pc2bytes2[(left shr 20) and $f] or pc2bytes3[(left shr 16) and $f] or
        pc2bytes4[(left shr 12) and $f] or pc2bytes5[(left shr 8) and $f] or
        pc2bytes6[(left shr 4) and $f];
      righttemp := pc2bytes7[right shr 28] or pc2bytes8[(right shr 24) and $f]
        or pc2bytes9[(right shr 20) and $f] or pc2bytes10[(right shr 16) and $f]
        or pc2bytes11[(right shr 12) and $f] or pc2bytes12[(right shr 8) and $f]
        or pc2bytes13[(right shr 4) and $f];
      temp := ((righttemp shr 16) xor lefttemp) and $0000ffff;
      Result[n] := lefttemp xor temp;
      Inc(n);
      Result[n] := Integer(righttemp xor (temp shl 16));
      Inc(n);
    end;
  end; //for each iterations
end; //end of des_createKeys

//des
//this takes the key, the message, and whether to encrypt or decrypt
function des(key: string; message: string; encrypt: Boolean;
  mode: Boolean; iv: string): string;
const
  //declaring this locally speeds things up a bit
  spfunction1: array[0..63] of Integer = ($1010400, 0, $10000, $1010404,
    $1010004, $10404, $4, $10000, $400, $1010400, $1010404, $400, $1000404,
    $1010004, $1000000, $4, $404, $1000400, $1000400, $10400, $10400, $1010000,
    $1010000, $1000404, $10004, $1000004, $1000004, $10004, 0, $404, $10404,
    $1000000, $10000, $1010404, $4, $1010000, $1010400, $1000000, $1000000,
    $400, $1010004, $10000, $10400, $1000004, $400, $4, $1000404, $10404,
    $1010404, $10004, $1010000, $1000404, $1000004, $404, $10404, $1010400,
    $404, $1000400, $1000400, 0, $10004, $10400, 0, $1010004);
  spfunction2: array[0..63] of Integer = (-$7fef7fe0, -$7fff8000, $8000,
    $108020, $100000, $20, -$7fefffe0, -$7fff7fe0, -$7fffffe0, -$7fef7fe0,
    -$7fef8000, -$80000000, -$7fff8000, $100000, $20, -$7fefffe0, $108000,
    $100020, -$7fff7fe0, 0, -$80000000, $8000, $108020, -$7ff00000, $100020,
    -$7fffffe0, 0, $108000, $8020, -$7fef8000, -$7ff00000, $8020, 0, $108020,
    -$7fefffe0, $100000, -$7fff7fe0, -$7ff00000, -$7fef8000, $8000, -$7ff00000,
    -$7fff8000, $20, -$7fef7fe0, $108020, $20, $8000, -$80000000, $8020,
    -$7fef8000, $100000, -$7fffffe0, $100020, -$7fff7fe0, -$7fffffe0, $100020,
    $108000, 0, -$7fff8000, $8020, -$80000000, -$7fefffe0, -$7fef7fe0, $108000);
  spfunction3: array[0..63] of Integer = ($208, $8020200, 0, $8020008, $8000200,
    0, $20208, $8000200, $20008, $8000008, $8000008, $20000, $8020208, $20008,
    $8020000, $208, $8000000, $8, $8020200, $200, $20200, $8020000, $8020008,
    $20208, $8000208, $20200, $20000, $8000208, $8, $8020208, $200, $8000000,
    $8020200, $8000000, $20008, $208, $20000, $8020200, $8000200, 0, $200,
    $20008, $8020208, $8000200, $8000008, $200, 0, $8020008, $8000208, $20000,
    $8000000, $8020208, $8, $20208, $20200, $8000008, $8020000, $8000208, $208,
    $8020000, $20208, $8, $8020008, $20200);
  spfunction4: array[0..63] of Integer = ($802001, $2081, $2081, $80, $802080,
    $800081, $800001, $2001, 0, $802000, $802000, $802081, $81, 0, $800080,
    $800001, $1, $2000, $800000, $802001, $80, $800000, $2001, $2080, $800081,
    $1, $2080, $800080, $2000, $802080, $802081, $81, $800080, $800001, $802000,
    $802081, $81, 0, 0, $802000, $2080, $800080, $800081, $1, $802001, $2081,
    $2081, $80, $802081, $81, $1, $2000, $800001, $2001, $802080, $800081,
    $2001, $2080, $800000, $802001, $80, $800000, $2000, $802080);
  spfunction5: array[0..63] of Integer = ($100, $2080100, $2080000, $42000100,
    $80000, $100, $40000000, $2080000, $40080100, $80000, $2000100, $40080100,
    $42000100, $42080000, $80100, $40000000, $2000000, $40080000, $40080000, 0,
    $40000100, $42080100, $42080100, $2000100, $42080000, $40000100, 0,
    $42000000, $2080100, $2000000, $42000000, $80100, $80000, $42000100, $100,
    $2000000, $40000000, $2080000, $42000100, $40080100, $2000100, $40000000,
    $42080000, $2080100, $40080100, $100, $2000000, $42080000, $42080100,
    $80100, $42000000, $42080100, $2080000, 0, $40080000, $42000000, $80100,
    $2000100, $40000100, $80000, 0, $40080000, $2080100, $40000100);
  spfunction6: array[0..63] of Integer = ($20000010, $20400000, $4000,
    $20404010, $20400000, $10, $20404010, $400000, $20004000, $404010, $400000,
    $20000010, $400010, $20004000, $20000000, $4010, 0, $400010, $20004010,
    $4000, $404000, $20004010, $10, $20400010, $20400010, 0, $404010, $20404000,
    $4010, $404000, $20404000, $20000000, $20004000, $10, $20400010, $404000,
    $20404010, $400000, $4010, $20000010, $400000, $20004000, $20000000, $4010,
    $20000010, $20404010, $404000, $20400000, $404010, $20404000, 0, $20400010,
    $10, $4000, $20400000, $404010, $4000, $400010, $20004010, 0, $20404000,
    $20000000, $400010, $20004010);
  spfunction7: array[0..63] of Integer = ($200000, $4200002, $4000802, 0, $800,
    $4000802, $200802, $4200800, $4200802, $200000, 0, $4000002, $2, $4000000,
    $4200002, $802, $4000800, $200802, $200002, $4000800, $4000002, $4200000,
    $4200800, $200002, $4200000, $800, $802, $4200802, $200800, $2, $4000000,
    $200800, $4000000, $200800, $200000, $4000802, $4000802, $4200002, $4200002,
    $2, $200002, $4000000, $4000800, $200000, $4200800, $802, $200802, $4200800,
    $802, $4000002, $4200802, $4200000, $200800, 0, $2, $4200802, 0, $200802,
    $4200000, $800, $4000002, $4000800, $800, $200002);
  spfunction8: array[0..63] of Integer = ($10001040, $1000, $40000, $10041040,
    $10000000, $10001040, $40, $10000000, $40040, $10040000, $10041040, $41000,
    $10041000, $41040, $1000, $40, $10040000, $10000040, $10001000, $1040,
    $41000, $40040, $10040040, $10041000, $1040, 0, 0, $10040040, $10000040,
    $10001000, $41040, $40000, $41040, $40000, $10041000, $1000, $40, $10040040,
    $1000, $41040, $10001000, $40, $10000040, $10040000, $10040040, $10000000,
    $40000, $10001040, 0, $10041040, $40040, $10000040, $10040000, $10001000,
    $10001040, 0, $10041040, $41000, $41000, $1040, $1040, $40040, $10000000,
    $10041000);
var
  keys: TDesKey;
  m, i, j: Longword;
  temp, temp2, right1, right2, left, right: Longword;
  looping: array of Integer;
  cbcleft, cbcleft2, cbcright, cbcright2: Longword;
  endloop, loopinc: Longword;
  len: Longword;
  chunk: Longword;
  iterations: Longword;
  tempresult: string;
begin
  keys := des_createKeys(key);
  len := Length(message);
  chunk := 0;
  cbcleft2 := 0;
  cbcright2 := 0;
  cbcleft := 0;
  cbcright := 0;
  //set up the loops for single and triple des
  if Length(Keys) = 32 then
    iterations := 3
  else iterations := 9;
  if (iterations = 3) then
  begin
    SetLength(looping, 3);
    if encrypt then
    begin
      looping[0] := 0;
      looping[1] := 32;
      looping[2] := 2;
    end else
    begin
      looping[0] := 30;
      looping[1] := -2;
      looping[2] := -2;
    end;
  end else
  begin
    SetLength(looping, 9);
    if encrypt then
    begin
      looping[0] := 0;
      looping[1] := 32;
      looping[2] := 2;

      looping[3] := 62;
      looping[4] := 30;
      looping[5] := -2;

      looping[6] := 64;
      looping[7] := 96;
      looping[8] := 2;
    end else
    begin
      looping[0] := 94;
      looping[1] := 62;
      looping[2] := -2;

      looping[3] := 32;
      looping[4] := 64;
      looping[5] := 2;

      looping[6] := 30;
      looping[7] := -2;
      looping[8] := -2;
    end;
  end;
  message := message + #0#0#0#0#0#0#0#0; //pad the message out with null bytes
  //store the result here
  Result := '';
  tempresult := '';
  m := 1;
  if mode then //CBC mode
  begin
    cbcleft := (Ord(iv[m]) shl 24) or (Ord(iv[m + 1]) shl 16) or
      (Ord(iv[m + 2]) shl 8) or Ord(iv[m + 3]);
    cbcright := (Ord(iv[m]) shl 24) or (Ord(iv[m + 1]) shl 16) or
      (Ord(iv[m + 2]) shl 8) or Ord(iv[m + 3]);
    m := 1;
  end;

  //loop through each 64 bit chunk of the message
  while m <= len do
  begin
    left := (Ord(message[m]) shl 24) or (Ord(message[m + 1]) shl 16) or
      (Ord(message[m + 2]) shl 8) or Ord(message[m + 3]);
    Inc(m, 4);
    right := (Ord(message[m]) shl 24) or (Ord(message[m + 1]) shl 16) or
      (Ord(message[m + 2]) shl 8) or Ord(message[m + 3]);
    Inc(m, 4);

    //for Cipher Block Chaining mode, xor the message with the previous result
    if mode then
    begin
      if encrypt then
      begin
        left := left xor cbcleft;
        right := right xor cbcright;
      end else
      begin
        cbcleft2 := cbcleft;
        cbcright2 := cbcright;
        cbcleft := left;
        cbcright := right;
      end;
    end;
    //first each 64 but chunk of the message must be permuted according to IP
    temp := ((left shr 4) xor right) and $0f0f0f0f;
    right := right xor temp;
    left := left xor (temp shl 4);
    temp := ((left shr 16) xor right) and $0000ffff;
    right := right xor temp;
    left := left xor (temp shl 16);
    temp := ((right shr 2) xor left) and $33333333;
    left := left xor temp;
    right := right xor (temp shl 2);
    temp := ((right shr 8) xor left) and $00ff00ff;
    left := left xor temp;
    right := right xor (temp shl 8);
    temp := ((left shr 1) xor right) and $55555555;
    right := right xor temp;
    left := left xor (temp shl 1);

    left := ((left shl 1) or (left shr 31));
    right := ((right shl 1) or (right shr 31));

    //do this either 1 or 3 times for each chunk of the message
    j := 0;
    while j < iterations do
    begin
      endloop := looping[j + 1];
      loopinc := looping[j + 2];
      //now go through and perform the encryption or decryption
      i := looping[j];
      while i <> endloop do
      begin
        right1 := right xor keys[i];
        right2 := ((right shr 4) or (right shl 28)) xor keys[i + 1];
        //the result is attained by passing these bytes through the S selection functions
        temp := left;
        left := right;
        right := temp xor Longword(spfunction2[(right1 shr 24) and $3f] or
          spfunction4[(right1 shr 16) and $3f] or
          spfunction6[(right1 shr 8) and $3f] or spfunction8[right1 and $3f] or
          spfunction1[(right2 shr 24) and $3f] or
          spfunction3[(right2 shr 16) and $3f] or
          spfunction5[(right2 shr 8) and $3f] or spfunction7[right2 and $3f]);
        i := i + loopinc; //for efficiency
      end;
      temp := left;
      left := right;
      right := temp; //unreverse left and right
      Inc(j, 3);
    end; //for either 1 or 3 iterations

    //move then each one bit to the right
    left := ((left shr 1) or (left shl 31));
    right := ((right shr 1) or (right shl 31));

    //now perform IP-1, which is IP in the opposite direction
    temp := ((left shr 1) xor right) and $55555555;
    right := right xor temp;
    left := left xor (temp shl 1);
    temp := ((right shr 8) xor left) and $00ff00ff;
    left := left xor temp;
    right := right xor (temp shl 8);
    temp := ((right shr 2) xor left) and $33333333;
    left := left xor temp;
    right := right xor (temp shl 2);
    temp := ((left shr 16) xor right) and $0000ffff;
    right := right xor temp;
    left := left xor (temp shl 16);
    temp := ((left shr 4) xor right) and $0f0f0f0f;
    right := right xor temp;
    left := left xor (temp shl 4);

    //for Cipher Block Chaining mode, xor the message with the previous result
    if (mode) then
    begin
      if (encrypt) then
      begin
        cbcleft := left;
        cbcright := right;
      end else
      begin
        left := left xor cbcleft2;
        right := right xor cbcright2;
      end;
    end;
    tempresult := tempresult + Char(left shr 24) + Char((left shr 16) and $ff) +
       Char(left shr 8 and $ff) + Char(left and $ff) + Char(right shr 24) +
       Char((right shr 16) and $ff) + Char((right shr 8) and $ff) +
       Char(right and $ff);

    chunk := chunk + 8;
    if chunk = 512 then
    begin
      Result := Result + tempresult;
      tempresult := '';
      chunk := 0;
    end;
  end; //for every 8 characters, or 64 bits in the message

  //return the result as an array
  Result := Result + tempresult;
end; //end of des

end. 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 氩弧焊枪管带里进水了怎么办 绝地求生穿头盔的时候连衣帽怎么办 开车不小心把光缆线给挂断了怎么办 脚刺到了生锈钢钉没打针怎么办 一加3t背壳螺丝掉了怎么办 30万美金美金中国被扣怎么办 电脑使用迅雷变的很卡怎么办 优盘拷贝过程中失去优盘路径怎么办 用百度云上传视频文件太慢了怎么办 网易云音乐云盘电脑上传很慢怎么办 路由器的宽带账号密码忘记了怎么办 蚂蚁邦路由器管理密码忘记了怎么办 红米2a刷机失败怎么办 小米手机开机图案锁忘记了怎么办 小米6进水无限闪屏开机重启怎么办 红米手机一直卡在开机画面怎么办 红米4卡在开机画面怎么办 红米手机一直在开机画面怎么办 红米手机一直跳开机画面怎么办 红米note3锁屏密码忘记怎么办 红米手机忘记锁屏密码怎么办 红米4锁屏密码忘了怎么办 红米note忘记锁屏密码怎么办 红米note2锁屏密码忘了怎么办 机打发票抬头名字少写一个字怎么办 卷式发票名字写错了怎么办 发票丢失了销售方不给补手续怎么办 总是把单词归不成句孑怎么办 白色踏板摩托车把漆刮了怎么办 苹果手机用流量缓冲很难怎么办 谷歌浏览器安卓手机版打不开怎么办 怀孕四个月检查高型半氨酸高怎么办 猎豹cs9怎么打不开车门怎么办 孩子在学校被老师冤枉打板子怎么办 么司福利体检暗地查乙肝怎么办 上体育课时被老师罚了腿疼怎么办 义务兵学技术不好班长打他怎么办 耳朵被打了一巴掌听不见了怎么办 耳朵被打了一巴掌后有点闷怎么办 山东省教育云平台密码戳完怎么办 被舍友知道发朋友圈说她们了怎么办