2011-08-08 18 views
5

Tôi đã quản lý cổng RC4 từ PolarSSL sang delphi, vì tôi cần một giao tiếp mã hóa giữa 2 ứng dụng (C và Delphi), nhưng vấn đề là, dữ liệu mã hóa không bao giờ giống nhau, cả mã hóa và giải mã dữ liệu trên thành công của riêng họ nhưng không phải dữ liệu được mã hóa bởi người khác.RC4 trong Delphi và C?

Dưới đây là cả hai mã:

C Mã (Trích từ PolarSSL)

typedef struct 
{ 
    int x;      /*!< permutation index */ 
    int y;      /*!< permutation index */ 
    unsigned char m[256];  /*!< permutation table */ 
} 
arc4_context; 

void arc4_setup(arc4_context *ctx, unsigned char *key, int keylen) 
{ 
    int i, j, k, a; 
    ctx->x = 0; 
    ctx->y = 0; 
    for(i = 0; i < 256; i++) ctx->m[i] = (unsigned char) i; 
    j = k = 0; 
    for(i = 0; i < 256; i++, k++) 
    { 
     if(k >= keylen) k = 0; 
     a = ctx->m[i]; 
     j = (j + a + key[k]) & 0xFF; 
     ctx->m[i] = ctx->m[j]; 
     ctx->m[j] = (unsigned char) a; 
    } 
    return; 
} 

void arc4_crypt(arc4_context *ctx, unsigned char *buf, int buflen) 
{ 
    int i, x, y, a, b; 
    unsigned char m[256]; 

    x = ctx->x; 
    y = ctx->y; 

    for (i = 0; i < 256; i++) m[i] = ctx->m[i]; 
    for(i = 0; i < buflen; i++) 
    { 
     x = (x + 1) & 0xFF; a = m[x]; 
     y = (y + a) & 0xFF; b = m[y]; 

     m[x] = (unsigned char) b; 
     m[y] = (unsigned char) a; 

     buf[i] = (unsigned char) 
      (buf[i]^m[(unsigned char)(a + b)]); 
    } 
    return; 
} 

Mã Delphi của tôi:

type 
    arc4_context = packed record 
    x, y: integer; 
    m: array[0..255] of byte; 
    end; 

procedure arc4_setup(var ctx: arc4_context; key: PChar; keylen: Integer); 
var 
i, j, k, a: Integer; 
begin 
ctx.x := 0; 
ctx.y := 0; 
for i := 0 to 255 do ctx.m[i] := Byte(i); 
j := 0; 
k := 0; 
for i := 0 to 255 do 
begin 
    if (k >= keylen) then k := 0; 
    a := ctx.m[i]; 
    j := (j + a + Byte(key[k])) and $FF; 
    ctx.m[i] := ctx.m[j]; 
    ctx.m[j] := a; 
    Inc(k); 
end; 
end; 


procedure arc4_crypt(ctx:arc4_context; var buf:string; buflen:integer); 
var 
i, x, y, a, b: Integer; 
m: array [0..255] of byte; 
begin 
x := ctx.x; 
y := ctx.y; 
for i := 0 to 255 do m[i] := ctx.m[i]; 
i := 0; 
while (i < buflen) do 
begin 
    x := (x + 1) and $FF; 
    a := m[x]; 
    y := (y + a) and $FF; 
    b := m[y]; 

    m[x] := b; 
    m[y] := a; 

    buf[i+1] := Char(Byte(buf[i+1]) xor Byte(m[a + b])); 
    inc(i); 
end 
end; 
+0

Đó dịch trông tuyệt vời. Câu hỏi của bạn là gì? –

+0

Dữ liệu được mã hóa không bao giờ giống nhau, vì vậy Dữ liệu được mã hóa bằng mã C không thể được giải mã bằng mã Delphi. – killercode

+0

Tôi khá chắc chắn có một số vấn đề về chỉ mục mảng. Các mảng Delphi có luôn dựa trên không? – Milan

Trả lời

10

Tôi đã (cuối cùng) đã tìm thấy sự khác biệt giữa hai mã.

Các dòng sau của bản dịch Pascal là không chính xác:

buf[i+1] := Char(Byte(buf[i+1]) xor Byte(m[a + b])); 

Phiên bản C đọc:

buf[i] = (unsigned char) (buf[i]^m[(unsigned char)(a + b)]); 

Lưu ý rằng a + b được cắt ngắn thành một đơn unsigned char, trong khi phiên bản Pascal trên nói m[a + b] và do đó, chỉ mục của a + b có thể vượt quá 255.

Bạn nên t ranslate dòng này như:

buf[i+1] := chr(ord(buf[i+1]) xor ord(m[Byte(a+b)])); 

Tôi đã thay đổi để sử dụng Chrord mà là thay đổi mỹ phẩm nhưng tôi cảm thấy họ là sạch hơn. Thay đổi nội dung là ở m[Byte(a+b)] nơi tôi buộc bổ sung a+b để ở trong ngữ cảnh của loại dữ liệu byte.

Thay vào đó, lỗi này dẫn đến truy cập mảng ngoài giới hạn của mảng m. Nếu bạn đã chạy với kiểm tra phạm vi được bật, lỗi sẽ được đánh dấu ngay lập tức. Tôi không thể nhấn mạnh đủ về tính năng kiểm tra phạm vi của Delphi.

+1

+1 +10 để duy trì và phát hiện! Và để nhấn mạnh tầm quan trọng của việc kiểm tra phạm vi. –

0

Why reinvent the wheel? *

Tôi biết rằng DCPCrypt hỗ trợ RC4 .

*) cho phép cho các mục đích học tập

Sửa gỡ bỏ.

+1

@David Làm cho tinh thần. –

1

Đề xuất: xem nội dung của các mảng m[] trên cả hai hệ thống sau khi bạn đã xử lý khóa nhưng trước khi bạn đã mã hóa bất kỳ dữ liệu nào. Rõ ràng là hai nên giống hệt nhau. Nếu không thì vấn đề nằm trong quá trình xử lý khóa.

Bạn cũng có thể muốn XOR hai đầu ra khác nhau để xem liệu có bất kỳ mẫu nào xuất hiện có thể chỉ cho bạn sự cố không.

1

Đây là một thực hiện delphi của thuật toán, dịch từ Net:

unit uRC4; 

interface 

uses Windows; 

type 
    TuRC4 = class 
    public 
     class function RC4(data, key:string):string; 
    end; 

implementation 

class function TuRC4.RC4(data, key:string):string; 
var 
    x, y, j: Integer; 
    box: array[0..255] of Integer; 
    i: Integer; 
    s: String; 

begin 
    for i := 0 to 255 do 
     begin 
     box[i] := i; 
     end; 

    for i := 0 to 255 do 
     begin 
     j := (Ord(key[i Mod Length(key) + 1]) + box[i] + j) Mod 256; 
     x := box[i]; 
     box[i] := box[j]; 
     box[j] := x; 
     end; 

    for i := 0 to Length(data)-1 do 
     begin 
     y := i Mod 256; 
     j := (box[y] + j) Mod 256; 
     x := box[y]; 
     box[y] := box[j]; 
     box[j] := x; 
     s := Char(Ord(data[i + 1]) xor box[(box[y] + box[j]) Mod 256]); 
     Result := Concat(Result, s); 
     end; 
end; 

end.