2011-08-08 3 views
5

私は2つのアプリケーション(CとDelphi)の間で暗号化された通信が必要なので、PolarSSLからDelphiへのRC4実装を移植しましたが、問題は暗号化されたデータは決して同じではなく、彼ら自身は成功裏に成功したが、他者によって暗号化されたデータはなかった。DelphiとCのRC4?

Cコード(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; 
} 

私のDelphiコード:ここで

は、両方のコードがある

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

翻訳は優れた見えること。あなたの質問は何ですか? –

+0

暗号化されたデータは決して同じではないので、Cコードで暗号化されたデータはDelphiコードで暗号化できません。 – killercode

+0

配列のインデックスに問題があるとは確信しています。 Delphiの配列は常にゼロベースですか? – Milan

答えて

10

私は(最後に)2つのコードの違いを発見しました。

パスカル翻訳の次の行が正しくありません:

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

Cバージョンを読み取り:上記パスカルバージョンはm[a + b]言う一方a + bを、単一unsigned charに切り捨てられること

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

a + bのインデックスは255を超えることがあります。

この行をranslate:

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

私は化粧品の変更ですが、私は、彼らがきれいと感じるChrordを使用するように変更しました。本質的な変更はm[Byte(a+b)]にあります。私はa+bの追加をバイトデータ型のコンテキストに強制します。

このバグの結果、配列mの範囲外の配列アクセスが発生します。範囲チェックを有効にして実行していた場合、そのバグはすぐに強調表示されます。デルファイのレンジチェック機能がどれほど価値があるかを十分に強調することはできません。ここで

+1

+1 +10の持続性と検出!レンジチェックの重要性を強調するため。 –

0

Why reinvent the wheel? *

私はDCPCryptはRC4をサポートしていることを知っています。削除学術目的

編集に許さ

*)。

+1

@David意味がある。 –

1

提案:両方のシステムのm[]アレイの内容を見てください。キーを処理した後、データを暗号化する前です。明らかに両者は同一でなければならない。そうでなければ、問題はキー処理にある。

2つの異なる出力をXORして、問題を指摘する可能性のあるパターンがあるかどうかを確認することもできます。

1

は、.NETから翻訳、アルゴリズムのDelphiの実装です:

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.