文档章节

delphi 银联POS终端MAC算法(单倍DES算法)

雨田ZER0
 雨田ZER0
发布于 2015/08/10 17:36
字数 3884
阅读 756
收藏 2
//主窗体界面代码
procedure TForm1.Button1Click(Sender: TObject);
 var
   lv_context : string;
   lv_acontext : TMyByteArray;
   lv_key : string;
begin
  lv_context := HexToString(Trim(Edit1.Text));
  lv_key := Trim(Edit3.Text);
  strToByteArray(lv_context, lv_acontext);
  Edit2.Text := bytesToHex(clacMac(lv_key, lv_acontext));
end;
//unit unt_MacEcb;

interface

uses
  Windows, Classes, SysUtils, unt_des;
type
  TMyByteArray = array of Byte;

  function clacMac(pvkey : string; pvInput : TMyByteArray) :TMyByteArray;

  procedure strToByteArray(str: string; var dest: TMyByteArray);

  function bytesToHex(const pvsrc: TMyByteArray): string;

  function HexToString(str:string):string;
  
  function HexToInt(hex: string): integer;

implementation
  function  byteXOR(pvsrc : Byte; pvsrc1 : Byte) : Byte;
  begin
    Result := (pvsrc and $FF) xor (pvsrc1 and $FF);
  end;

  function bytesXOR(pvsrc : TMyByteArray; pvsrc1 : TMyByteArray) :TMyByteArray;
  var
    lv_len,lv_len1 : Integer;
    lv_ret : TMyByteArray;
    lv_i  : Integer;
  begin
    Result := nil;
    lv_len := length(pvsrc);
    lv_len1 := length(pvsrc1);
    if (lv_len = lv_len1) then
    begin
      SetLength(lv_ret, lv_len);
      for lv_i := 0 to lv_len -1 do
      begin
        lv_ret[lv_i] := byteXOR(pvsrc[lv_i], pvsrc1[lv_i]);
      end;
      Result := lv_ret;
    end;
  end;

  function byteToHex(const pvsrc: Byte): string;
  begin
    Result := SysUtils.IntToHex(pvsrc, 2 * SizeOf(pvsrc));
  end;

  function bytesToHex(const pvsrc: TMyByteArray): string;
  var
    lv_len : Integer;
    lv_i : Integer;
  begin
    Result := '';
    lv_len := Length(pvsrc);
    for lv_i := 0 to lv_len -1 do
    begin
      Result := Result + byteToHex(pvsrc[lv_i]);
    end;
  end;

  procedure strToByteArray(str: string; var dest: TMyByteArray);
  var
    c : char;
  begin
    SetLength(dest, 0);
    while str <>'' do
    begin
      c := str[1];
      SetLength(dest, Length(dest) + 1);
      dest[High(dest)] := Byte(c);
      delete(str, 1, 1);
    end;
  end;

  function clacMac(pvkey : string; pvInput : TMyByteArray) :TMyByteArray;
  var
    lv_lenin, lv_lendata,
    lv_datacount : Integer;
    lv_x, lv_i : Integer;
    lv_addlen : Integer;
    lv_pos : Integer;
    lv_data,lv_oper1,
    lv_oper2,
    lv_aret, lv_front8, lv_behind8,
    lv_desfront8,lv_resultXOR,
    lv_buff, lv_retbuff,
    lv_retbuff2, lv_temp : TMyByteArray;
    lv_sret : string;
  begin
    //******************************************************************************************************//
    //银联POS终端报文规则
    {
    POS终端采用ECB的加密方式,简述如下:
    a) 将欲发送给POS中心的消息中,从消息类型(MTI)到63域之间的部分构成MAC ELEMEMENT BLOCK (MAB)。
    b) 对MAB,按每8个字节做异或(不管信息中的字符格式),如果最后不满8个字节,则添加“0X00”。
    示例	:
    MAB = M1 M2 M3 M4
    其中:	
    M1 = MS11 MS12 MS13 MS14 MS15 MS16 MS17 MS18
    M2 = MS21 MS22 MS23 MS24 MS25 MS26 MS27 MS28
    M3 = MS31 MS32 MS33 MS34 MS35 MS36 MS37 MS38
    M4 = MS41 MS42 MS43 MS44 MS45 MS46 MS47 MS48

    按如下规则进行异或运算:
      MS11 MS12 MS13 MS14 MS15 MS16 MS17 MS18
    XOR)	MS21 MS22 MS23 MS24 MS25 MS26 MS27 MS28
    ---------------------------------------------------
    TEMP BLOCK1 =	TM11 TM12 TM13 TM14 TM15 TM16 TM17 TM18

    然后,进行下一步的运算:
    TM11 TM12 TM13 TM14 TM15 TM16 TM17 TM18
    XOR)	MS31 MS32 MS33 MS34 MS35 MS36 MS37 MS38
    ---------------------------------------------------
    TEMP BLOCK2 =	TM21 TM22 TM23 TM24 TM25 TM26 TM27 TM28

    再进行下一步的运算:
    TM21 TM22 TM23 TM24 TM25 TM26 TM27 TM28
    XOR)	MS41 MS42 MS43 MS44 MS45 MS46 MS47 MS48
    ---------------------------------------------------
    RESULT BLOCK =	TM31 TM32 TM33 TM34 TM35 TM36 TM37 TM38

    c) 将异或运算后的最后8个字节(RESULT BLOCK)转换成16 个HEXDECIMAL:
    RESULT BLOCK = TM31 TM32 TM33 TM34 TM35 TM36 TM37 TM38
    = TM311 TM312 TM321 TM322 TM331 TM332 TM341 TM342 ||
    TM351 TM352 TM361 TM362 TM371 TM372 TM381 TM382

    d) 取前8 个字节用MAK加密:
    ENC BLOCK1 = eMAK(TM311 TM312 TM321 TM322 TM331 TM332 TM341 TM342)
    = EN11 EN12 EN13 EN14 EN15 EN16 EN17 EN18

    e) 将加密后的结果与后8 个字节异或:
    EN11 EN12 EN13 EN14 EN15 EN16 EN17 EN18
    XOR) TM351 TM352 TM361 TM362 TM371 TM372 TM381 TM382
    ------------------------------------------------------------
    TEMP BLOCK=	TE11 TE12 TE13 TE14 TE15 TE16 TE17 TE18

    f) 用异或的结果TEMP BLOCK 再进行一次单倍长密钥算法运算。
    ENC BLOCK2 = eMAK(TE11 TE12 TE13 TE14 TE15 TE16 TE17 TE18)
    = EN21 EN22 EN23 EN24 EN25 EN26 EN27 EN28

    g) 将运算后的结果(ENC BLOCK2)转换成16 个HEXDECIMAL:
    ENC BLOCK2 = EN21 EN22 EN23 EN24 EN25 EN26 EN27 EN28
    = EM211 EM212 EM221 EM222 EM231 EM232 EM241 EM242 ||
      EM251 EM252 EM261 EM262 EM271 EM272 EM281 EM282
    示例	:
    ENC RESULT= %H84, %H56, %HB1, %HCD, %H5A, %H3F, %H84, %H84
    转换成16 个HEXDECIMAL:
    “8456B1CD5A3F8484”
    h) 取前8个字节作为MAC值。
    取”8456B1CD”为MAC值。}
    //******************************************************************************************************//
        
    Result := nil;
    //1、长度不足8位进行补0x00操作
    lv_lenin := Length(pvInput);
    lv_x := lv_lenin mod 8;
    lv_addlen := 0;

    //不足8位,补长大小
    if (lv_x <> 0) then
      lv_addlen := 8 - lv_x;
    lv_pos := 0;

    //补长后数据大小
    lv_lendata := lv_lenin + lv_addlen;
    //按8位算数据块大小
    lv_datacount := lv_lendata div 8;

    //数据块进行赋值
    SetLength(lv_data, lv_lendata);
    for lv_i := 0 to lv_lenin -1 do
    begin
      lv_data[lv_i] := pvInput[lv_i];
    end;

    //不足8位竞价补0x00操作
    for lv_i := lv_lenin to lv_lendata -1 do
    begin
      lv_data[lv_i] := $00;
    end;

    //2、异或运算
    SetLength(lv_oper1,8);
    lv_oper1 := Copy(lv_data, lv_pos , 8);

    lv_pos := lv_pos + 8;

    SetLength(lv_oper2,8);
    for lv_x := 1 to lv_datacount -1 do
    begin
      lv_oper2 := Copy(lv_data, lv_pos, 8);
      //异或运算
      lv_temp := bytesXOR(lv_oper1, lv_oper2);
       //lv_oper1 异或后运算得的值,再与下一组原数据进行异或运算
      lv_oper1 := Copy(lv_temp, 0 , 8);
      lv_pos := lv_pos + 8;
    end;

    //3、将异或运算后的最后8个字节(RESULT BLOCK)转换成16 个HEXDECIMAL:
    lv_sret := bytesToHex(lv_oper1);
    strToByteArray(lv_sret, lv_aret);
    //前8值
    lv_front8 := Copy(lv_aret, 0 ,8);
    //后8值
    lv_behind8 := Copy(lv_aret, 8, 8);

    //4、取前8 个字节用MAK加密     
    //用mak对这8个字节做des加密       【memcmp】
    //des加密
    strToByteArray(DES3_Encry(bytesToHex(lv_front8), pvkey),lv_desfront8);

    //5、将加密后的结果与后8 个字节异或:
    lv_resultXOR := bytesXOR(lv_desfront8, lv_behind8);

    //6、用异或的结果TEMP BLOCK 再进行一次单倍长密钥算法运算。
    //用mak对这8个字节做des加密
    strToByteArray(DES3_Encry(bytesToHex(lv_resultXOR), pvkey),lv_buff);

    //7、将运算后的结果(ENC BLOCK2)转换成16 个HEXDECIMAL:
    strToByteArray(bytesToHex(lv_buff), lv_retbuff);
    
    //前8位取为MAC值
    lv_retbuff2 := Copy(lv_retbuff, 0, 8);
    Result := lv_retbuff2;
  end;

function HexToString(str:string):string;
var
  s,t:string;
  i,j:Integer;
  p:PChar;
begin
  s:='';
  i := 1 ;
  while i < Length(str) do
  begin
    t:=str[i]+str[i+1];
    s:=s+chr(HexToInt(t));
    i:=i+2;
  end;    
  Result := s ;
end;

function HexToInt(hex: string): integer;
var
  i: integer;
  function Ncf(num, f: integer): integer;
  var
    i: integer;
  begin
    Result := 1;
    if f = 0 then exit;
    for i := 1 to f do
      result := result * num;
  end;
  function HexCharToInt(HexToken: char): integer;
  begin
    if HexToken > #97 then
      HexToken := Chr(Ord(HexToken) - 32);
      Result := 0;
    if (HexToken > #47) and (HexToken < #58) then { chars 0....9 }
      Result := Ord(HexToken) - 48
    else if (HexToken > #64) and (HexToken < #71) then { chars A....F }
      Result := Ord(HexToken) - 65 + 10;
  end;
begin
  result := 0;
    hex := ansiuppercase(trim(hex));
  if hex = '' then
    exit;
  for i := 1 to length(hex) do
  result := result + HexCharToInt(hex[i]) * ncf(16, length(hex) - i);
end;

end.
//单倍DES算法
unit unt_des;

interface

uses
  Windows, Classes, SysUtils;

type
  fdArray   = array of dword;

  function DES3_Encry_Hex(Context, Key: string): string;
  function DES3_Encry(Context, Key: string): string;
  function DES3_Decry(Context, Key: string): string;

  function StrToHex(Str:string):string;
implementation


function IsInt(Str:String):Boolean;
begin
   result := True;
   try
     StrToInt(Str);
   except
     result := False
   end;
end;

function HexToStr(Hex:string):string;
var
   i:Integer;
begin
   Result := '';
   for i := 1 to length(Hex) div 2 do
     if IsInt('$' + Hex[i * 2 - 1] + Hex[i * 2]) then
       Result := Result + Chr(StrToInt('$' + Hex[i * 2 - 1] + Hex[i * 2]));
end;

function StrToHex(Str:string):string;
var
   i:integer;
begin
   result := '';
   for i := 1 to length(Str) do
     result := result + IntToHex(Ord(Str[i]), 2);
end;

//des_createKeys
//this takes as input a 64 bit key (even though only 56 bits are used)
//as an array of 2 dwords, and returns 16 48 bit keys
function des_createKeys(key:string):fdArray;
const
   //declaring this locally speeds things up a bit
   pc2bytes0   :array[0..15] of dword= (0,$4,$20000000,$20000004,$10000,$10004,$20010000,$20010004,$200,$204,$20000200,$20000204,$10200,$10204,$20010200,$20010204);
   pc2bytes1   :array[0..15] of dword= (0,$1,$100000,$100001,$4000000,$4000001,$4100000,$4100001,$100,$101,$100100,$100101,$4000100,$4000101,$4100100,$4100101);
   pc2bytes2   :array[0..15] of dword= (0,$8,$800,$808,$1000000,$1000008,$1000800,$1000808,0,$8,$800,$808,$1000000,$1000008,$1000800,$1000808);
   pc2bytes3   :array[0..15] of dword= (0,$200000,$8000000,$8200000,$2000,$202000,$8002000,$8202000,$20000,$220000,$8020000,$8220000,$22000,$222000,$8022000,$8222000);
   pc2bytes4   :array[0..15] of dword= (0,$40000,$10,$40010,0,$40000,$10,$40010,$1000,$41000,$1010,$41010,$1000,$41000,$1010,$41010);
   pc2bytes5   :array[0..15] of dword= (0,$400,$20,$420,0,$400,$20,$420,$2000000,$2000400,$2000020,$2000420,$2000000,$2000400,$2000020,$2000420);
   pc2bytes6   :array[0..15] of dword= (0,$10000000,$80000,$10080000,$2,$10000002,$80002,$10080002,0,$10000000,$80000,$10080000,$2,$10000002,$80002,$10080002);
   pc2bytes7   :array[0..15] of dword= (0,$10000,$800,$10800,$20000000,$20010000,$20000800,$20010800,$20000,$30000,$20800,$30800,$20020000,$20030000,$20020800,$20030800);
   pc2bytes8   :array[0..15] of dword= (0,$40000,0,$40000,$2,$40002,$2,$40002,$2000000,$2040000,$2000000,$2040000,$2000002,$2040002,$2000002,$2040002);
   pc2bytes9   :array[0..15] of dword= (0,$10000000,$8,$10000008,0,$10000000,$8,$10000008,$400,$10000400,$408,$10000408,$400,$10000400,$408,$10000408);
   pc2bytes10 :array[0..15] of dword= (0,$20,0,$20,$100000,$100020,$100000,$100020,$2000,$2020,$2000,$2020,$102000,$102020,$102000,$102020);
   pc2bytes11 :array[0..15] of dword= (0,$1000000,$200,$1000200,$200000,$1200000,$200200,$1200200,$4000000,$5000000,$4000200,$5000200,$4200000,$5200000,$4200200,$5200200);
   pc2bytes12 :array[0..15] of dword= (0,$1000,$8000000,$8001000,$80000,$81000,$8080000,$8081000,$10,$1010,$8000010,$8001010,$80010,$81010,$8080010,$8081010);
   pc2bytes13 :array[0..15] of dword= (0,$4,$100,$104,0,$4,$100,$104,$1,$5,$101,$105,$1,$5,$101,$105);

   //now define the left shifts which need to be done
   shifts :array[0..15] of dword = (0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0);
var
   iterations:integer;
   keys:fdArray;
   lefttemp, righttemp, temp:dword;
   m, n, j,i:integer;
   left,right:dword;
begin
   //how many iterations (1 for des, 3 for triple des)
   key := HexToStr(key);
   if length(key) = 24 then
     iterations := 3
   else
     iterations := 1;

   //stores the return keys
   setlength(keys,32 * iterations);

   //other variables
   m:=0;n:=0;

   for j:=0 to iterations-1 do //either 1 or 3 iterations
     begin
       left := (ord(key[m+1]) shl 24) or (ord(key[m+2]) shl 16) or (ord(key[m+3]) shl 8) or ord(key[m+4]);
       right := (ord(key[m+5]) shl 24) or (ord(key[m+6]) shl 16) or (ord(key[m+7]) shl 8) or ord(key[m+8]);
       m:=m+8;

       temp := ((left shr 4) xor right) and $0f0f0f0f; right :=right xor temp; left :=left xor (temp shl 4);
       temp := ((right shr 16) xor left) and $0000ffff; left := left xor temp; right :=right xor (temp shl 16);
       temp := ((left shr 2) xor right) and $33333333; right :=right xor temp; left := left xor (temp shl 2);
       temp := ((right shr 16) xor left) and $0000ffff; left :=left xor temp; right := right xor (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 keys
       for i:=low(shifts) to   high(shifts) do
         begin
           //shift the keys either one or two bits to the left
           if shifts[i] > 0 then
             begin
               left := (left shl 2) or (left shr 26);
               right := (right shl 2) or (right shr 26);
               //left := left shl 0;
               //right:= right shl 0;
             end
           else
             begin
               left := (left shl 1) or (left shr 27);
               right := (right shl 1) or (right shr 27);
               //left := left shl 0;
               //right:= right shl 0;
             end;

           left := left and $fffffff0;
           right:= right and $fffffff0;

           //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;
           keys[n+0] := lefttemp xor temp;
           keys[n+1] := righttemp xor (temp shl 16);
           n:=n+2;
         end;
     end; //for each iterations

   //return the keys we've created
   Result := keys;

end;//end of des_createKeys

function des(key:string;smessage:string;encrypt:dword):string;
const
   spfunction1 : array[0..63] of dword = ($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 dword = ($80108020,$80008000,$8000,$108020,$100000,$20,$80100020,$80008020,$80000020,$80108020,$80108000,$80000000,$80008000,$100000,$20,$80100020,$108000,$100020,$80008020,0,$80000000,$8000,$108020,$80100000,$100020,$80000020,0,$108000,$8020,$80108000,$80100000,$8020,0,$108020,$80100020,$100000,$80008020,$80100000,$80108000,$8000,$80100000,$80008000,$20,$80108020,$108020,$20,$8000,$80000000,$8020,$80108000,$100000,$80000020,$100020,$80008020,$80000020,$100020,$108000,0,$80008000,$8020,$80000000,$80100020,$80108020,$108000);
   spfunction3 : array[0..63] of dword = ($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 dword = ($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 dword = ($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 dword = ($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 dword = ($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 dword = ($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:fdArray;
   m, i, j:integer;
   temp, right1, right2, left, right:dword;
   looping:array of integer;
   endloop, loopinc:integer;
   len, iterations:integer;
   chunk:integer;
   tempresult:string;
begin
   //create the 16 or 48 subkeys we will need
   keys := des_createKeys(key);
   m:=0;chunk:=0;
   len := length(smessage);
   //set up the loops for single and triple des
   if length(keys) = 32 then
     iterations := 3
   else
     iterations := 9;

   if iterations = 3 then
     begin
       if encrypt = 1 then
         begin
           setlength(looping,3);
           looping[0] := 0;
           looping[1] := 32;
           looping[2] := 2;
         end
       else
         begin
           setlength(looping,3);
           looping[0] := 30;
           looping[1] := -2;
           looping[2] := -2;
         end;
     end
   else
     begin
       if encrypt = 1 then
         begin
           setlength(looping,9);
           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
           setlength(looping,9);
           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;

   smessage := smessage + #0#0#0#0#0#0#0#0; //pad the message out with null bytes

   //store the result here
   result := '';
   tempresult := '';

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

       //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 (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;
             end;
           temp := left; left := right; right := temp; //unreverse left and right
           j:=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);

       tempresult := tempresult + chr(left shr 24) + chr((left shr 16) and $ff) + chr((left shr 8) and $ff) + chr(left and $ff) + chr(right shr 24) + chr((right shr 16) and $ff) + chr((right shr 8) and $ff) + chr(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

function EncryStr(Str, Key: String): String; overload;
begin
   Result := des(Key, Str, 1);
end;

function EncryStr(Str:TStream; Key: String): String; overload;
var
   AStr:String;
begin
   Str.Seek(0,soFromBeginning);
   setlength(AStr, Str.Size);
   Str.Read(AStr[1], Str.Size);
   Result := des(Key, AStr, 1);
end;

function DecryStr(Str, Key: String): String; overload;
begin
   Result := trim(des(Key, Str, 0));
end;

function DecryStr(Str:TStream; Key: String): String; overload;
var
   AStr:String;
begin
   Str.Seek(0,soFromBeginning);
   setlength(AStr, Str.Size);
   Str.Read(AStr[1], Str.Size);
   Result := trim(des(Key, AStr, 0));
end;

function EncryStrHex(Str, Key: String): String;
begin
   Result := trim(StrToHex(des(Key, HexToStr(Str), 1)));
end;

function DecryStrHex(Str, Key: String): String; overload;
begin
   Result := trim(StrToHex(des(Key, HexToStr(Str), 0)));
end;

function DecryStrHex(Str:TStream; Key: String): String; overload;
var
   AStr:String;
begin
  Str.Seek(0,soFromBeginning);
  setlength(AStr, Str.Size);
  Str.Read(AStr[1], Str.Size);
  Result := trim(des(Key, HexToStr(AStr), 0));
end;

function DES3_Encry_Hex(Context, Key: string): string;
begin
  Result := trim(StrToHex(des(Key, HexToStr(Context), 1)));
end;

function DES3_Encry(Context, Key: string): string;
begin
  Result := trim(des(Key, HexToStr(Context), 1));
end;

function DES3_Decry(Context, Key: string): string;
begin
  Result := DecryStrHex(Context, Key);
end;  

end.


© 著作权归作者所有

雨田ZER0
粉丝 0
博文 7
码字总数 4584
作品 0
衢州
程序员
私信 提问
交易平台基本密钥处理流程(SJL05加密机)

在平时的工作中,很少接触安全这块内容,最近需要自己独立完成安全这块内容,在开发中遇到的问题会在下面的理解中得到相应的解决。 在交易平台中,基于安全考虑会对传输中的报文进行加密处理...

01010101010101010101
2014/02/17
2.1K
1
DES加密、RC4加密、AES加密等加密算法的优势及应用

1篇文章,1部小说被盗取,全靠维(si)权(bi)捍卫自己的原创权利。程序员捍卫自己珍贵的代码,全靠花式的加密算法。代码加密有多重要?程序员半年做出的产品,盗版者可能半天就能完全破解。...

达斯雷马
2017/03/23
674
1
DES加密、RC4加密、AES加密等加密算法的优势及应用

1篇文章,1部小说被盗取,全靠维(si)权(bi)捍卫自己的原创权利。程序员捍卫自己珍贵的代码,全靠花式的加密算法。代码加密有多重要?程序员半年做出的产品,盗版者可能半天就能完全破解。...

我还是那个我
2017/03/22
8
0
通用 POS 收单系统

本产品用于具有第三方支付牌照的机构,主要针对收单机构在收单过程中的各种个性化的业务需求进行设计和开发。 [产品功能] 支持银联 POS 规范、包括标准 POS(Q/CUP 009.1)、脚本 POS(Q/CUP...

luckybyte
2016/08/05
30
0
3·15曝光闪付风险,银联回应:可全额赔付

3·15晚会曝光“闪付”功能存在被“隔空盗刷”的风险,以此对广大消费者进行消费预警。3月16日晚,银联就该事做出回应。 银联回应称:“接受3·15晚会的监督意见,并称“隔空盗刷”一事是极少...

灵火K
03/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Java 8 Optional:优雅地避免 NPE

本篇文章将详细介绍 Optional 类,以及如何用它消除代码中的 null 检查。在开始之前首先来看下什么是 NPE,以及在 Java 8 之前是如何处理 NPE 问题的。 空指针异常(NullPointException,简称...

武培轩
31分钟前
7
0
CountDownLatch实现的并发框架

目录结构 package com.**.**.base.support.executor;import lombok.NoArgsConstructor;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;imp......

MR_TE
32分钟前
11
0
学习记录(day06-事件、按键修饰符、计算属性)

[TOC] 1.1 事件修饰符/按键修饰符 vue 通过事件修饰符对dom事件细节进行控制 <标签 @事件.修饰符="函数"></标签>.prevent ---阻止浏览器默认行为.stop ---阻止浏览器事件冒泡.e...

庭前云落
52分钟前
9
0
006-Sigle-基于blockstack去中心化博客

本篇文章主要讲解有关基于Blockstack的Sigle是一个去中心化的博客项目; 官网地址:https://www.sigle.io/ Github地址:https://github.com/pradel/sigle 页面展示: 介绍: A beautiful de...

Riverzhou
59分钟前
22
0
驰骋工作流引擎开发平台属性功能的隐藏显示介绍

关键字: 工作流程管理系统 工作流引擎 asp.net工作流引擎 java工作流引擎. 表单引擎 工作流功能说明 工作流设计 工作流快速开发平台 业务流程管理 bpm工作流系统 java工作流主流框架 自定义...

孟娟
今天
19
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部