0

我正在为 VNC 协议(RFB)做一个客户端。从我连接到服务器的部分到我从服务器接收“挑战”的部分,一切都在工作。挑战是一个 16 字节的随机数,应使用用户提供的密码作为 DES 算法中的密钥进行加密。我尝试在这个项目中使用 2 个单元进行 DES 加密,一个完全失败,另一个是这个......我应该得到一个 16 字节的加密字符串来发送,当我调试时,我看到我的 AnsiString 有16 长度(我相信对于 AnsiStrings 我们有 LENGTH = BYTES)...无论如何,我的代码很简单,我将在此处粘贴涉及此问题的最重要部分。

Challenge: array[0..15] of AnsiChar;
PasswdDES: AnsiString;
Result: array[0..3] of AnsiChar;
  begin
      MySocket:= TClientSocket.Create(Nil);
      ....
      MySocket.Socket.ReceiveBuf(Challenge, SizeOf(Challenge));
      PasswdDES:= EncryStr(AnsiString(Challenge), AnsiString('123'));
      MySocket.Socket.SendText(PasswdDES);
      MySocket.Socket.ReceiveBuf(Result, SizeOf(Result));

我总是在“结果”上收到值 #1,这意味着身份验证失败... EncryStr 是该单元的一个功能。我阅读了此链接并尝试在 Delphi 中实现该解决方案,但仍然无法正常工作。

注意:我已经尝试使用 Challenge 作为字节数组,并做了类似的事情:

PasswdDES:= EncryStr(LPCSTR(Challenge[0]), '123'); 

但没有成功.. 因为我使用的是 Delphi 2010,所以我使用的是 AnsiString... 感谢您的关注!

我试图在delphi上实现的java解决方案是这样的:

Function BitFlip(B: Byte): Byte; //stackoverflow
const
  N: array[0..15] of Byte = (0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15);
begin
  Result := N[B div 16] or N[B mod 16] shl 4;
End;

Function Invert(input: PAnsiChar): AnsiString;
var
  I : int32;
Begin
  Result := '';
  for I := 0 to length(input)-1 do
    Result := Result + AnsiChar(BitFlip(Byte(Input[I])));
End;
4

1 回答 1

1

这是来自 UltraVNC 项目的 des.c 文件的 Free Pascal 转换。

unit pasd3des;

{$mode objfpc}{$H+}

interface

const
  EN0 = 0; (* MODE == encrypt *)
  DE1 = 1; (* MODE == decrypt *)

procedure des(inblock, outblock: PChar);
procedure deskey(key: PChar; edf: ShortInt);

implementation

const
  Df_Key: array[0..23] of byte = (
    $01, $23, $45, $67, $89, $AB, $CD, $EF,
    $FE, $DC, $BA, $98, $76, $54, $32, $10,
    $89, $AB, $CD, $EF, $01, $23, $45, $67);

  bytebit: array[0..7] of word = (1, 2, 4, 8, 16, 32, 64, 128);

  bigbyte: array[0..23] of Longword = (
    $800000, $400000, $200000, $100000,
    $80000,  $40000,  $20000,  $10000,
    $8000,   $4000,   $2000,   $1000,
    $800,    $400,    $200,    $100,
    $80,     $40,     $20,     $10,
    $8,      $4,      $2,      $1);

  pc1: array[0..55] of byte = (
    56, 48, 40, 32, 24, 16,  8,  0, 57, 49, 41, 33, 25, 17,
     9,  1, 58, 50, 42, 34, 26, 18, 10,  2, 59, 51, 43, 35,
    62, 54, 46, 38, 30, 22, 14,  6, 61, 53, 45, 37, 29, 21,
    13,  5, 60, 52, 44, 36, 28, 20, 12,  4, 27, 19, 11,  3);

  totrot: array[0..15] of byte = (1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28);

  pc2: array[0..47] of byte = (13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
    22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
    40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
    43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31);

  SP1: array[0..63] of Longword = (
    $01010400, $00000000, $00010000, $01010404,
    $01010004, $00010404, $00000004, $00010000,
    $00000400, $01010400, $01010404, $00000400,
    $01000404, $01010004, $01000000, $00000004,
    $00000404, $01000400, $01000400, $00010400,
    $00010400, $01010000, $01010000, $01000404,
    $00010004, $01000004, $01000004, $00010004,
    $00000000, $00000404, $00010404, $01000000,
    $00010000, $01010404, $00000004, $01010000,
    $01010400, $01000000, $01000000, $00000400,
    $01010004, $00010000, $00010400, $01000004,
    $00000400, $00000004, $01000404, $00010404,
    $01010404, $00010004, $01010000, $01000404,
    $01000004, $00000404, $00010404, $01010400,
    $00000404, $01000400, $01000400, $00000000,
    $00010004, $00010400, $00000000, $01010004);

  SP2: array[0..63] of Longword = (
    $80108020, $80008000, $00008000, $00108020,
    $00100000, $00000020, $80100020, $80008020,
    $80000020, $80108020, $80108000, $80000000,
    $80008000, $00100000, $00000020, $80100020,
    $00108000, $00100020, $80008020, $00000000,
    $80000000, $00008000, $00108020, $80100000,
    $00100020, $80000020, $00000000, $00108000,
    $00008020, $80108000, $80100000, $00008020,
    $00000000, $00108020, $80100020, $00100000,
    $80008020, $80100000, $80108000, $00008000,
    $80100000, $80008000, $00000020, $80108020,
    $00108020, $00000020, $00008000, $80000000,
    $00008020, $80108000, $00100000, $80000020,
    $00100020, $80008020, $80000020, $00100020,
    $00108000, $00000000, $80008000, $00008020,
    $80000000, $80100020, $80108020, $00108000);

  SP3: array[0..63] of Longword = (
    $00000208, $08020200, $00000000, $08020008,
    $08000200, $00000000, $00020208, $08000200,
    $00020008, $08000008, $08000008, $00020000,
    $08020208, $00020008, $08020000, $00000208,
    $08000000, $00000008, $08020200, $00000200,
    $00020200, $08020000, $08020008, $00020208,
    $08000208, $00020200, $00020000, $08000208,
    $00000008, $08020208, $00000200, $08000000,
    $08020200, $08000000, $00020008, $00000208,
    $00020000, $08020200, $08000200, $00000000,
    $00000200, $00020008, $08020208, $08000200,
    $08000008, $00000200, $00000000, $08020008,
    $08000208, $00020000, $08000000, $08020208,
    $00000008, $00020208, $00020200, $08000008,
    $08020000, $08000208, $00000208, $08020000,
    $00020208, $00000008, $08020008, $00020200);

  SP4: array[0..63] of Longword = (
    $00802001, $00002081, $00002081, $00000080,
    $00802080, $00800081, $00800001, $00002001,
    $00000000, $00802000, $00802000, $00802081,
    $00000081, $00000000, $00800080, $00800001,
    $00000001, $00002000, $00800000, $00802001,
    $00000080, $00800000, $00002001, $00002080,
    $00800081, $00000001, $00002080, $00800080,
    $00002000, $00802080, $00802081, $00000081,
    $00800080, $00800001, $00802000, $00802081,
    $00000081, $00000000, $00000000, $00802000,
    $00002080, $00800080, $00800081, $00000001,
    $00802001, $00002081, $00002081, $00000080,
    $00802081, $00000081, $00000001, $00002000,
    $00800001, $00002001, $00802080, $00800081,
    $00002001, $00002080, $00800000, $00802001,
    $00000080, $00800000, $00002000, $00802080);

  SP5: array[0..63] of Longword = (
    $00000100, $02080100, $02080000, $42000100,
    $00080000, $00000100, $40000000, $02080000,
    $40080100, $00080000, $02000100, $40080100,
    $42000100, $42080000, $00080100, $40000000,
    $02000000, $40080000, $40080000, $00000000,
    $40000100, $42080100, $42080100, $02000100,
    $42080000, $40000100, $00000000, $42000000,
    $02080100, $02000000, $42000000, $00080100,
    $00080000, $42000100, $00000100, $02000000,
    $40000000, $02080000, $42000100, $40080100,
    $02000100, $40000000, $42080000, $02080100,
    $40080100, $00000100, $02000000, $42080000,
    $42080100, $00080100, $42000000, $42080100,
    $02080000, $00000000, $40080000, $42000000,
    $00080100, $02000100, $40000100, $00080000,
    $00000000, $40080000, $02080100, $40000100);

  SP6: array[0..63] of Longword = (
    $20000010, $20400000, $00004000, $20404010,
    $20400000, $00000010, $20404010, $00400000,
    $20004000, $00404010, $00400000, $20000010,
    $00400010, $20004000, $20000000, $00004010,
    $00000000, $00400010, $20004010, $00004000,
    $00404000, $20004010, $00000010, $20400010,
    $20400010, $00000000, $00404010, $20404000,
    $00004010, $00404000, $20404000, $20000000,
    $20004000, $00000010, $20400010, $00404000,
    $20404010, $00400000, $00004010, $20000010,
    $00400000, $20004000, $20000000, $00004010,
    $20000010, $20404010, $00404000, $20400000,
    $00404010, $20404000, $00000000, $20400010,
    $00000010, $00004000, $20400000, $00404010,
    $00004000, $00400010, $20004010, $00000000,
    $20404000, $20000000, $00400010, $20004010);

  SP7: array[0..63] of Longword = (
    $00200000, $04200002, $04000802, $00000000,
    $00000800, $04000802, $00200802, $04200800,
    $04200802, $00200000, $00000000, $04000002,
    $00000002, $04000000, $04200002, $00000802,
    $04000800, $00200802, $00200002, $04000800,
    $04000002, $04200000, $04200800, $00200002,
    $04200000, $00000800, $00000802, $04200802,
    $00200800, $00000002, $04000000, $00200800,
    $04000000, $00200800, $00200000, $04000802,
    $04000802, $04200002, $04200002, $00000002,
    $00200002, $04000000, $04000800, $00200000,
    $04200800, $00000802, $00200802, $04200800,
    $00000802, $04000002, $04200802, $04200000,
    $00200800, $00000000, $00000002, $04200802,
    $00000000, $00200802, $04200000, $00000800,
    $04000002, $04000800, $00000800, $00200002);

  SP8: array[0..63] of Longword = (
    $10001040, $00001000, $00040000, $10041040,
    $10000000, $10001040, $00000040, $10000000,
    $00040040, $10040000, $10041040, $00041000,
    $10041000, $00041040, $00001000, $00000040,
    $10040000, $10000040, $10001000, $00001040,
    $00041000, $00040040, $10040040, $10041000,
    $00001040, $00000000, $00000000, $10040040,
    $10000040, $10001000, $00041040, $00040000,
    $00041040, $00040000, $10041000, $00001000,
    $00000040, $10040040, $00001000, $00041040,
    $10001000, $00000040, $10000040, $10040000,
    $10040040, $10000000, $00040000, $10001040,
    $00000000, $10041040, $00040040, $10000040,
    $10040000, $10001000, $10001040, $00000000,
    $10041040, $00041000, $00041000, $00001040,
    $00001040, $00040040, $10000000, $10041000);

var
  KnL: array[0..31] of Longword;

procedure usekey(from: PLongWord);
var
  ato, endp: PLongWord;
begin
  ato := @KnL[0];
  endp := @KnL[31];
  while ( ato <= endp ) do
  begin
    ato[0] := from[0];
    ato := @ato[1];
    from := @from[1];
  end;
end;

procedure cookey(raw1: PLongWord);
var
  cook, raw0: PLongWord;
  dough: array[0..31] of LongWord;
  i: Integer;
begin
  cook := @dough[0];
  for i := 0 to 15 do
  begin
    raw0 := raw1;
    raw1 := @raw1[1];
    cook[0] := (raw0[0] and $00fc0000) shl 6;
    cook[0] := cook[0] or (raw0[0] and $00000fc0) shl 10;
    cook[0] := cook[0] or (raw1[0] and $00fc0000) shr 10;
    cook[0] := cook[0] or (raw1[0] and $00000fc0) shr 6;
    cook := @cook[1];
    cook[0] := (raw0[0] and $0003f000) shl 12;
    cook[0] := cook[0] or (raw0[0] and $0000003f) shl 16;
    cook[0] := cook[0] or (raw1[0] and $0003f000) shr 4;
    cook[0] := cook[0] or (raw1[0] and $0000003f);
    cook := @cook[1];
    raw1 := @raw1[1];
  end;
  usekey(@dough);
end;

procedure deskey(key: PChar; edf: ShortInt);
var
  i, j, l, m, n: Integer;
  pc1m, pcr: array[0..55] of Byte;
  kn: array[0..31] of LongWord;
begin
  for j := 0 to 55 do
  begin
    l := pc1[j];
    m := l and 07;
    if (Byte(key[l shr 3]) and bytebit[m]) > 0 then
      pc1m[j] := 1
    else
      pc1m[j] := 0;
  end;
  for i := 0 to 15 do
  begin
    if (edf = DE1) then
      m := (15 - i) shl 1
    else
      m := i shl 1;
    n := m + 1;
    kn[m] := 0;
    kn[n] := 0;
    for j := 0 to 27 do
    begin
      l := j + totrot[i];
      if (l < 28) then
        pcr[j] := pc1m[l]
      else
        pcr[j] := pc1m[l - 28];
    end;
    for j := 28 to 55 do
    begin
      l := j + totrot[i];
      if (l < 56) then
        pcr[j] := pc1m[l]
      else
        pcr[j] := pc1m[l - 28];
    end;
    for j := 0 to 23 do
    begin
      if (pcr[pc2[j]] <> 0) then
        kn[m] := kn[m] or bigbyte[j];
      if (pcr[pc2[j+24]] <> 0) then
        kn[n] := kn[n] or bigbyte[j];
    end;
  end;
  cookey(@kn);
end;

procedure cpkey(into: PLongWord);
var
  from, endp: PLongWord;
begin
  from := KnL;
  endp := @KnL[31];
  while (from <= endp) do
  begin
    into[0] := from[0];
    into := @into[1];
    from := @from[1];
  end;
end;

procedure scrunch(outof: PByte; into: PLongWord);
begin
  into[0] := (outof[0] and $ff) shl 24;
  outof := @outof[1];
  into[0] := into[0] or (outof[0] and $ff) shl 16;
  outof := @outof[1];
  into[0] := into[0] or (outof[0] and $ff) shl 8;
  outof := @outof[1];
  into[0] := into[0] or (outof[0] and $ff);
  outof := @outof[1];
  into := @into[1];
  into[0] := (outof[0] and $ff) shl 24;
  outof := @outof[1];
  into[0] := into[0] or (outof[0] and $ff) shl 16;
  outof := @outof[1];
  into[0] := into[0] or (outof[0] and $ff) shl 8;
  outof := @outof[1];
  into[0] := into[0] or (outof[0] and $ff);
end;

procedure unscrun(outof: PLongWord; into: PByte);
begin
  into[0] := Byte((outof[0] shr 24) and $ff);
  into := @into[1];
  into[0] := Byte((outof[0] shr 16) and $ff);
  into := @into[1];
  into[0] := Byte((outof[0] shr 8) and $ff);
  into := @into[1];
  into[0] := Byte(outof[0] and $ff);
  outof := @outof[1];
  into := @into[1];
  into[0] := Byte((outof[0] shr 24) and $ff);
  into := @into[1];
  into[0] := Byte((outof[0] shr 16) and $ff);
  into := @into[1];
  into[0] := Byte((outof[0] shr 8) and $ff);
  into := @into[1];
  into[0] := Byte(outof[0] and $ff);
end;

procedure desfunc(block, keys: PLongWord);
var
  fval, work, right, leftt: LongWord;
  roundd: Integer;
begin
  leftt := block[0];
  right := block[1];
  work := ((leftt shr 4) xor right) and $0f0f0f0f;
  right := right xor work;
  leftt := leftt xor (work shl 4);
  work := ((leftt shr 16) xor right) and $0000ffff;
  right := right xor work;
  leftt := leftt xor (work shl 16);
  work := ((right shr 2) xor leftt) and $33333333;
  leftt := leftt xor work;
  right := right xor (work shl 2);
  work := ((right shr 8) xor leftt) and $00ff00ff;
  leftt := leftt xor work;
  right := right xor (work shl 8);
  right := ((right shl 1) or ((right shr 31) and 1)) and $ffffffff;
  work := (leftt xor right) and $aaaaaaaa;
  leftt := leftt xor work;
  right := right xor work;
  leftt := ((leftt shl 1) or ((leftt shr 31) and 1)) and $ffffffff;
  for roundd := 0 to 7 do
  begin
    work  := (right shl 28) or (right shr 4);
    work := work xor keys[0];
    keys := @keys[1];
    fval := SP7[work and $3f];
    fval := fval or SP5[(work shr  8) and $3f];
    fval := fval or SP3[(work shr 16) and $3f];
    fval := fval or SP1[(work shr 24) and $3f];
    work := right xor keys[0];
    keys := @keys[1];
    fval := fval or SP8[work and $3f];
    fval := fval or SP6[(work shr  8) and $3f];
    fval := fval or SP4[(work shr 16) and $3f];
    fval := fval or SP2[(work shr 24) and $3f];
    leftt := leftt xor fval;
    work := (leftt shl 28) or (leftt shr 4);
    work := work xor keys[0];
    keys := @keys[1];
    fval := SP7[work and $3f];
    fval := fval or SP5[(work shr  8) and $3f];
    fval := fval or SP3[(work shr 16) and $3f];
    fval := fval or SP1[(work shr 24) and $3f];
    work := leftt xor keys[0];
    keys := @keys[1];
    fval := fval or SP8[work and $3f];
    fval := fval or SP6[(work shr  8) and $3f];
    fval := fval or SP4[(work shr 16) and $3f];
    fval := fval or SP2[(work shr 24) and $3f];
    right := right xor fval;
  end;
  right := (right shl 31) or (right shr 1);
  work := (leftt xor right) and $aaaaaaaa;
  leftt := leftt xor work;
  right := right xor work;
  leftt := (leftt shl 31) or (leftt shr 1);
  work := ((leftt shr 8) xor right) and $00ff00ff;
  right := right xor work;
  leftt := leftt xor (work shl 8);
  work := ((leftt shr 2) xor right) and $33333333;
  right := right xor work;
  leftt := leftt xor (work shl 2);
  work := ((right shr 16) xor leftt) and $0000ffff;
  leftt := leftt xor work;
  right := right xor (work shl 16);
  work := ((right shr 4) xor leftt) and $0f0f0f0f;
  leftt := leftt xor work;
  right := right xor (work shl 4);
  block[0] := right;
  block[1] := leftt;
end;

procedure des(inblock, outblock: PChar);
var
  work: array[0..1] of LongWord;
begin
  scrunch(PByte(inblock), @work);
  desfunc(@work, @KnL);
  unscrun(@work, PByte(outblock));
end;

end.

和加密密码的功能

function CryptChal(AChal, APasswd: String): String;
const
  CHALLENGESIZE = 16;
var
  key, bytes, response: pChar;
  i: integer;
begin
  key := StrAlloc((CHALLENGESIZE div 2) + 1);
  response := StrAlloc(CHALLENGESIZE + 1);
  try
    for i := 0 to 7 do
    begin
      if (i < length(Apasswd)) then
        key[i] := Apasswd[i + 1]
      else
        key[i] := #0;
    end;
    if length(Apasswd)>8 then
      Key[8] := #0;

    deskey(key, 0);

    bytes := pChar(AChal);
    i := 0;
    while (i < CHALLENGESIZE) do
    begin
      des(bytes + i, response + i);
      inc(i, 8);
    end;
    Result := response;
    SetLength(Result, CHALLENGESIZE);
  finally
    StrDispose(response);
    StrDispose(key);
  end;
end;
于 2013-08-07T12:51:04.647 回答