⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 idea.pas

📁 串口调试助手的源代码
💻 PAS
字号:
{
***************************************************
* A binary compatible IDEA implementation         *
* written by Dave Barton (davebarton@bigfoot.com) *
***************************************************
* 64bit block encryption                          *
* 128bit key size                                 *
***************************************************
}
unit IDEA;

interface
uses
  Sysutils, Tools;

type
  PWord = ^word;
  TIDEAData = record
    InitBlock: array[0..7] of byte; { initial IV }
    LastBlock: array[0..7] of byte; { current IV }
    EK: array[0..51] of word;
    DK: array[0..51] of word;
  end;

function IDEASelfTest: boolean;
  { performs a self test on this implementation }
procedure IDEAInit(var Data: TIDEAData; Key: pointer; Len: integer; IV:
  pointer); stdcall; export;
  { initializes the TIDEAData structure with the key information and IV if applicable }
procedure IDEABurn(var Data: TIDEAData); stdcall; export;
  { erases all information about the key }

procedure IDEAEncryptECB(var Data: TIDEAData; InData, OutData: pointer);
stdcall; export;
  { encrypts the data in a 64bit block using the ECB mode }
procedure IDEAEncryptCBC(var Data: TIDEAData; InData, OutData: pointer);
stdcall; export;
  { encrypts the data in a 64bit block using the CBC chaining mode }
procedure IDEAEncryptOFB(var Data: TIDEAData; InData, OutData: pointer);
stdcall; export;
  { encrypts the data in a 64bit block using the OFB chaining mode }
procedure IDEAEncryptCFB(var Data: TIDEAData; InData, OutData: pointer; Len:
  integer); stdcall; export;
  { encrypts Len bytes of data using the CFB chaining mode }
procedure IDEAEncryptOFBC(var Data: TIDEAData; InData, OutData: pointer; Len:
  integer); stdcall; export;
  { encrypts Len bytes of data using the OFB counter chaining mode }

procedure IDEADecryptECB(var Data: TIDEAData; InData, OutData: pointer);
stdcall; export;
  { decrypts the data in a 64bit block using the ECB mode }
procedure IDEADecryptCBC(var Data: TIDEAData; InData, OutData: pointer);
stdcall; export;
  { decrypts the data in a 64bit block using the CBC chaining mode }
procedure IDEADecryptOFB(var Data: TIDEAData; InData, OutData: pointer);
stdcall; export;
  { decrypts the data in a 64bit block using the OFB chaining mode }
procedure IDEADecryptCFB(var Data: TIDEAData; InData, OutData: pointer; Len:
  integer); stdcall; export;
  { decrypts Len bytes of data using the CFB chaining mode }
procedure IDEADecryptOFBC(var Data: TIDEAData; InData, OutData: pointer; Len:
  integer); stdcall; export;
  { decrypts Len bytes of data using the OFB counter chaining mode }

procedure IDEAReset(var Data: TIDEAData); stdcall; export;
  { resets the chaining mode information }

{******************************************************************************}
implementation

function IDEASelfTest: boolean;
const
  Key: array[0..15] of byte =
  ($00, $01, $00, $02, $00, $03, $00, $04, $00, $05, $00, $06, $00, $07, $00,
    $08);
  InBlock: array[0..7] of byte =
  ($00, $00, $00, $01, $00, $02, $00, $03);
  OutBlock: array[0..7] of byte =
  ($11, $FB, $ED, $2B, $01, $98, $6D, $E5);
var
  Block: array[0..7] of byte;
  Data: TIDEAData;
begin
  IDEAInit(Data, @Key, Sizeof(Key), nil);
  IDEAEncryptECB(Data, @InBlock, @Block);
  Result := CompareMem(@Block, @OutBlock, Sizeof(Block));
  IDEADecryptECB(Data, @Block, @Block);
  Result := Result and CompareMem(@Block, @InBlock, Sizeof(Block));
  IDEABurn(Data);
end;

procedure Mul(var x: word; y: word);
var
  p: DWord;
  t16: word;
begin
  p := DWord(x) * y;
  if p = 0 then
    x := 1 - x - y
  else
  begin
    x := p shr 16;
    t16 := p and $FFFF;
    x := t16 - x;
    if (t16 < x) then
      Inc(x);
  end;
end;

function MulInv(x: word): word;
var
  t0, t1, q, y: word;
begin
  if x <= 1 then
  begin
    Result := x;
    Exit;
  end;
  t1 := DWord($10001) div x;
  y := DWord($10001) mod x;
  if y = 1 then
  begin
    Result := (1 - t1) and $FFFF;
    Exit;
  end;
  t0 := 1;
  repeat
    q := x div y;
    x := x mod y;
    t0 := t0 + (q * t1);
    if x = 1 then
    begin
      Result := t0;
      Exit;
    end;
    q := y div x;
    y := y mod x;
    t1 := t1 + (q * t0);
  until y = 1;
  Result := (1 - t1) and $FFFF;
end;

procedure IDEAInvertKey(EK, DK: PWord);
var
  i: integer;
  t1, t2, t3: word;
  temp: array[0..51] of word;
  p: PWord;
begin
  p := pointer(integer(@temp) + Sizeof(Temp));
  Dec(p);
  t1 := MulInv(EK^);
  Inc(EK);
  t2 := -EK^;
  Inc(EK);
  t3 := -EK^;
  Inc(EK);
  p^ := MulInv(EK^);
  Inc(EK);
  Dec(p);
  p^ := t3;
  Dec(p);
  p^ := t2;
  Dec(p);
  p^ := t1;
  Dec(p);
  for i := 0 to 6 do
  begin
    t1 := EK^;
    Inc(EK);
    p^ := EK^;
    Inc(EK);
    Dec(p);
    p^ := t1;
    Dec(p);
    t1 := MulInv(EK^);
    Inc(EK);
    t2 := -EK^;
    Inc(EK);
    t3 := -EK^;
    Inc(EK);
    p^ := MulInv(EK^);
    Inc(EK);
    Dec(p);
    p^ := t2;
    Dec(p);
    p^ := t3;
    Dec(p);
    p^ := t1;
    Dec(p);
  end;
  t1 := EK^;
  Inc(EK);
  p^ := EK^;
  Dec(p);
  Inc(EK);
  p^ := t1;
  Dec(p);

  t1 := MulInv(EK^);
  Inc(EK);
  t2 := -EK^;
  Inc(EK);
  t3 := -EK^;
  Inc(EK);
  p^ := MulInv(EK^);
  Dec(p);
  p^ := t3;
  Dec(p);
  p^ := t2;
  Dec(p);
  p^ := t1;
  Move(Temp, DK^, Sizeof(Temp));
  FillChar(Temp, Sizeof(Temp), 0);
end;

procedure IDEAInit; stdcall; export;
var
  UserKey: PByteArray;
  PEK: PWordArray;
  j: integer;
begin
  if Len <> 16 then
    raise Exception.Create('IDEA: Invalid key length');
  with Data do
  begin
    if IV = nil then
    begin
      FillChar(InitBlock, 8, 0);
      FillChar(LastBlock, 8, 0);
    end
    else
    begin
      Move(IV^, InitBlock, 8);
      Move(IV^, LastBlock, 8);
    end;
    UserKey := Key;
    PEK := @EK;
    for j := 0 to 7 do
    begin
      PEK[j] := (UserKey[0] shl 8) + UserKey[1];
      UserKey := pointer(integer(UserKey) + 2);
    end;
    for j := 1 to 6 do
    begin
      PEK[8] := (PEK[1] shl 9) or (PEK[2] shr 7);
      PEK[9] := (PEK[2] shl 9) or (PEK[3] shr 7);
      PEK[10] := (PEK[3] shl 9) or (PEK[4] shr 7);
      PEK[11] := (PEK[4] shl 9) or (PEK[5] shr 7);
      PEK[12] := (PEK[5] shl 9) or (PEK[6] shr 7);
      PEK[13] := (PEK[6] shl 9) or (PEK[7] shr 7);
      PEK[14] := (PEK[7] shl 9) or (PEK[0] shr 7);
      PEK[15] := (PEK[0] shl 9) or (PEK[1] shr 7);
      PEK := pointer(integer(PEK) + 16);
    end;
    IDEAInvertKey(@EK, @DK);
  end;
end;

procedure IDEABurn; stdcall; export;
begin
  FillChar(Data, Sizeof(Data), 0);
end;

procedure IDEACipher(Key: PWord; Input, Output: PWordArray);
var
  x1, x2, x3, x4, s2, s3: word;
  i: integer;
begin
  x1 := (Input[0] shr 8) or (Input[0] shl 8);
  x2 := (Input[1] shr 8) or (Input[1] shl 8);
  x3 := (Input[2] shr 8) or (Input[2] shl 8);
  x4 := (Input[3] shr 8) or (Input[3] shl 8);
  i := 8;
  repeat
    Mul(x1, Key^);
    Inc(Key);
    x2 := x2 + Key^;
    Inc(Key);
    x3 := x3 + Key^;
    Inc(Key);
    Mul(x4, Key^);
    Inc(Key);

    s3 := x3;
    x3 := x3 xor x1;
    Mul(x3, Key^);
    Inc(Key);
    s2 := x2;
    x2 := x2 xor x4;
    x2 := x2 + x3;
    Mul(x2, Key^);
    Inc(Key);
    x3 := x3 + x2;

    x1 := x1 xor x2;
    x4 := x4 xor x3;
    x2 := x2 xor s3;
    x3 := x3 xor s2;
    Dec(i);
  until (i = 0);
  Mul(x1, Key^);
  Inc(Key);
  x3 := x3 + Key^;
  Inc(Key);
  x2 := x2 + Key^;
  Inc(Key);
  Mul(x4, Key^);
  Output[0] := (x1 shr 8) or (x1 shl 8);
  Output[1] := (x3 shr 8) or (x3 shl 8);
  Output[2] := (x2 shr 8) or (x2 shl 8);
  Output[3] := (x4 shr 8) or (x4 shl 8);
end;

procedure IDEAEncryptECB; stdcall; export;
begin
  IDEACipher(@Data.EK, InData, OutData);
end;

procedure IDEADecryptECB; stdcall; export;
begin
  IDEACipher(@Data.DK, InData, OutData);
end;

procedure IDEAEncryptCBC; stdcall; export;
begin
  XorBlock(InData, @Data.LastBlock, OutData, 8);
  IDEAEncryptECB(Data, OutData, OutData);
  Move(OutData^, Data.LastBlock, 8);
end;

procedure IDEADecryptCBC; stdcall; export;
var
  TempBlock: array[0..7] of byte;
begin
  Move(InData^, TempBlock, 8);
  IDEADecryptECB(Data, InData, OutData);
  XorBlock(OutData, @Data.LastBlock, OutData, 8);
  Move(TempBlock, Data.LastBlock, 8);
end;

procedure IDEAEncryptCFB; stdcall; export;
var
  i: integer;
  TempBlock: array[0..7] of byte;
begin
  for i := 0 to Len - 1 do
  begin
    IDEAEncryptECB(Data, @Data.LastBlock, @TempBlock);
    PByteArray(OutData)[i] := PByteArray(InData)[i] xor TempBlock[0];
    Move(Data.LastBlock[1], Data.LastBlock[0], 7);
    Data.LastBlock[7] := PByteArray(OutData)[i];
  end;
end;

procedure IDEADecryptCFB; stdcall; export;
var
  i: integer;
  TempBlock: array[0..7] of byte;
  b: byte;
begin
  for i := 0 to Len - 1 do
  begin
    b := PByteArray(InData)[i];
    IDEAEncryptECB(Data, @Data.LastBlock, @TempBlock);
    PByteArray(OutData)[i] := PByteArray(InData)[i] xor TempBlock[0];
    Move(Data.LastBlock[1], Data.LastBlock[0], 7);
    Data.LastBlock[7] := b;
  end;
end;

procedure IDEAEncryptOFB; stdcall; export;
begin
  IDEAEncryptECB(Data, @Data.LastBlock, @Data.LastBlock);
  XorBlock(@Data.LastBlock, InData, OutData, 8);
end;

procedure IDEADecryptOFB; stdcall; export;
begin
  IDEAEncryptECB(Data, @Data.LastBlock, @Data.LastBlock);
  XorBlock(@Data.LastBlock, InData, OutData, 8);
end;

procedure IDEAEncryptOFBC; stdcall; export;
var
  i: integer;
  TempBlock: array[0..7] of byte;
begin
  for i := 0 to Len - 1 do
  begin
    IDEAEncryptECB(Data, @Data.LastBlock, @TempBlock);
    PByteArray(OutData)[i] := PByteArray(InData)[i] xor TempBlock[0];
    IncBlock(@Data.LastBlock, 8);
  end;
end;

procedure IDEADecryptOFBC; stdcall; export;
var
  i: integer;
  TempBlock: array[0..7] of byte;
begin
  for i := 0 to Len - 1 do
  begin
    IDEAEncryptECB(Data, @Data.LastBlock, @TempBlock);
    PByteArray(OutData)[i] := PByteArray(InData)[i] xor TempBlock[0];
    IncBlock(@Data.LastBlock, 8);
  end;
end;

procedure IDEAReset; stdcall; export;
begin
  Move(Data.InitBlock, Data.LastBlock, 8);
end;

exports
  IDEAInit, IDEABurn, IDEAReset,
  IDEAEncryptECB, IDEAEncryptCBC, IDEAEncryptOFB, IDEAEncryptCFB,
  IDEAEncryptOFBC,
  IDEADecryptECB, IDEADecryptCBC, IDEADecryptOFB, IDEADecryptCFB,
  IDEADecryptOFBC;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -