Шифрование XTEA дает различный вывод в C и Delphi - PullRequest
3 голосов
/ 27 февраля 2011

Я кодирую приложение на C и Delphi, у меня XTEA Encryption на обоих, оно абсолютно одинаковое но проблема в том, что результат отличается, хотя дельта и N одинаковы. Я действительно не знаю, что не так

Вот код Delphi

type
  TTeaMsgBlock = array[0..1] of LongWord;
  TTeaKeyBlock = array[0..3] of LongWord;

const   
  DELTA = $9e3779b9;
  N = 32;

procedure XTeaCrypt(var V: TTeaMsgBlock; const K: TTeaKeyBlock);
var
  I: LongWord;
  S: Int64;
begin
  S := 0;
  for I := 0 to N - 1 do begin
    Inc(V[0], (((V[1] shl 4) xor (V[1] shr 5)) + V[1]) xor (S + K[S and 3]));
    Inc(S, DELTA);
    Inc(V[1], (((V[0] shl 4) xor (V[0] shr 5)) + V[0]) xor (S + K[(S shr 11) and 3]));
  end;
end;

function XTeaCryptStr(const Msg, Pwd: string): string;
var
  V: TTeaMsgBlock;
  K: TTeaKeyBlock;
  I, L, N: Integer;
begin
  L := Length(Pwd); if L > SizeOf(K) then L := SizeOf(K);
  K[0] := 0; K[1] := 0; K[2] := 0; K[3] := 0; Move(Pwd[1], K[0], L);

  I := 1; L := Length(Msg);
  if L > 0 then SetLength(Result, ((L - 1) div SizeOf(V) + 1) * SizeOf(V))
           else SetLength(Result, 0);
  while I <= L do begin
    V[0] := 0; V[1] := 0;
    N := L - I + 1; if N > SizeOf(V) then N := SizeOf(V);
    Move(Msg[I], V[0], N);
    XTeaCrypt(V, K);
    Move(V[0], Result[I], SizeOf(V));
    Inc(I, SizeOf(V))
  end;
end;

//Test
const Key: array [0..15] of char = (char($00), char($01), char($02), char($03), char($04), char($05), 
                                char($06), char($07), char($08), char($09), char($0a), char($0b), 
                                char($0c), char($0d), char($0e), char($0f));
const Msg: string = 'This Is#';

begin
 WriteLn('Encrypted: ' + pChar(XTeaCryptStr(Msg, Key)));
end.

и это код C (взято из PolarSSL)

typedef struct
{
    uint32_t k[4];       /*!< key */
} xtea_context;

#ifndef GET_ULONG_BE
#define GET_ULONG_BE(n,b,i)                             \
{                                                       \
    (n) = ( (unsigned long) (b)[(i)    ] << 24 )        \
        | ( (unsigned long) (b)[(i) + 1] << 16 )        \
        | ( (unsigned long) (b)[(i) + 2] <<  8 )        \
        | ( (unsigned long) (b)[(i) + 3]       );       \
}
#endif

#ifndef PUT_ULONG_BE
#define PUT_ULONG_BE(n,b,i)                             \
{                                                       \
    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
}
#endif

/*
 * XTEA key schedule
 */
void xtea_setup( xtea_context *ctx, unsigned char key[16] )
{
    int i;

    memset(ctx, 0, sizeof(xtea_context));

    for( i = 0; i < 4; i++ )
    {
        GET_ULONG_BE( ctx->k[i], key, i << 2 );
    }
}

/*
 * XTEA encrypt function
 */
int xtea_crypt_ecb( xtea_context *ctx, int mode, unsigned char input[8],
                     unsigned char output[8])
{
    uint32_t *k, v0, v1, i;

    k = ctx->k;

    GET_ULONG_BE( v0, input, 0 );
    GET_ULONG_BE( v1, input, 4 );

    if( mode == XTEA_ENCRYPT )
    {
        uint32_t sum = 0, delta = 0x9E3779B9;

        for( i = 0; i < 32; i++ )
        {
            v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
            sum += delta;
            v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);
        }
    }
    else /* XTEA_DECRYPT */
    {
        uint32_t delta = 0x9E3779B9, sum = delta * 32;

        for( i = 0; i < 32; i++ )
        {
            v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);
            sum -= delta;
            v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
        }
    }

    PUT_ULONG_BE( v0, output, 0 );
    PUT_ULONG_BE( v1, output, 4 );
    output[8] = '\0';

    return( 0 );
}

//test
int main()
{
    int i;
    unsigned char buf[8] = "This Is#";
    xtea_context ctx;
    xtea_setup( &ctx, (unsigned char *) xtea_test_key);
    xtea_crypt_ecb( &ctx, XTEA_ENCRYPT, buf, buf );
    printf("Encrypted = %s\n", buf);
    return 0;
}

но вывод совершенно другой: / Что я делаю не так?

Ответы [ 4 ]

5 голосов
/ 27 февраля 2011

Во-первых, я не пытался выполнить ваш код: мои комментарии основаны исключительно на проверке.

Я подозреваю корень вашей проблемы - путаница между старшим и младшимхранение данных в обратном порядке.

Макросы в коде C (GET_ULONG_BE и PUT_ULONG_BE) извлекают необработанные данные и преобразуют их в uint32 в формате BIG-endian.

В Delphi вы копируете необработанные данныеданные из байтов в формат LongWord без преобразования с прямым порядком байтов в старшие.

Кроме того, я не уверен в объявлении S как Int64, но это, вероятно, незначительно по сравнению спроблема big-end / little-end.

Редактировать: вам нужно выполнить преобразование big-endian в вашей подпрограмме XTeaCryptStr ().Вам необходимо применить его к 4 элементам структуры ключа и к вашему блоку данных - как до (данные поступают), так и после (результат выходит) вызова основной процедуры шифрования.

Редактировать: Начал пытаться запустить код Delphi.Первая проблема заключается в том, что ваш тестовый пароль начинается с нулевого символа.Вам нужно использовать другой пароль (без нулевых символов).

Еще одно редактирование:

Я вставил вызовы в SwapEndian (), как показано ниже:

function XTeaCryptStr(const Msg, Pwd: string): string;
    var
      V: TTeaMsgBlock;
      K: TTeaKeyBlock;
      I, L, N: Integer;
  begin
  L := Length(Pwd);
  if L > SizeOf(K) then
    L := SizeOf(K);
  K[0] := 0; K[1] := 0; K[2] := 0; K[3] := 0;
  Move(Pwd[1], K[0], L);
  for i := 0 to 3 do
    K[i] := SwapEndian( K[i] );

  I := 1; L := Length(Msg);
  if L > 0 then
    SetLength(Result, ((L - 1) div SizeOf(V) + 1) * SizeOf(V))
  else
    SetLength(Result, 0);
  while I <= L do
    begin
    V[0] := 0; V[1] := 0;
    N := L - I + 1;
    if N > SizeOf(V) then
      N := SizeOf(V);
    Move(Msg[I], V[0], N);

    V[0] := SwapEndian( V[0] );
    V[1] := SwapEndian( V[1] );

    XTeaCrypt(V, K);

    V[0] := SwapEndian( V[0] );
    V[1] := SwapEndian( V[1] );

    Move(V[0], Result[I], SizeOf(V));
    Inc(I, SizeOf(V))
    end;
  end;

С этим (и паролем, который не содержит нулевых символов), я получил тот же результат из кода C и Delphi.

4 голосов
/ 27 февраля 2011

Вам не удалось скопировать код из PolarSSL .

В исходном коде C есть несколько ошибок, которые были предупреждены.:)

Во-первых, ни один код шифрования ECB не будет EVER включать:

output[8] = '\0';

Весь смысл режима ECB состоит в изменении одного блокаввода в другой блок ввода.Эта строка не имеет места в процедуре ECB - она, очевидно, связана с выводом строки.(На самом деле, это также запись за пределами буфера; последняя доступная для записи позиция в array[n] - это array[n-1]. Так что вы просто пишете на несвязанной памяти. Эта строка, вероятно, была помещена вместо, потому что тестовый массив buf в main слишком короткий, чтобы содержать свой собственный ASCII NUL - замените его на buf[9].)

Я бы настоятельно рекомендовал проверить обоих вашегоC и Delphi кодируют против тестовых векторов (извините за ужасные цвета на этой странице, ничего с этим не поделаешь, кроме получения данных и быстрого закрытия окна снова! :), чтобы выяснить, какие из них, если они есть,ваши программы верны.

ПОЖАЛУЙСТА не используйте режим ECB напрямую .При неправильном использовании слишком просто обеспечить ноль конфиденциальность и гарантии целостности.Создание правильных протоколов и режимов работы вне ЕЦБ - очень трудная работа;используйте вместо этого OFB, CFB, CTR, CBC, PCBC или один из более новых аутентифицированных режимов шифрования .

EDIT : Это в вашем Delphi выглядит иначе: (V[1] xor S).Посмотрите еще раз на строки из C;Я думаю, что вы неправильно перевели версию Delphi в две ключевые строки процедуры. (Я неправильно прочитал. Извините.)

1 голос
/ 19 декабря 2012

Я не знаю, почему мой предыдущий ответ был отклонен, а затем удален.

Давайте попробуем еще раз.

Если вы используете один и тот же код C в приложении Windows и в микропроцессоре, то любойдолжно работать стандартное шифрование. Просто выберите один.

См.

http://www.drbob42.com/examines/examin92.htm
http://www.hflib.gov.cn/e_book/e_book_file/bcb/ch06.htm (Использование кода C ++ в Delphi)
http://edn.embarcadero.com/article/10156#H11

Похоже, вам нужно использовать DLL, но вы можете статически связать ее, если не хотите ее распространять

0 голосов
/ 28 октября 2016

Вот рабочий код.Я конвертировал из кода C ++.ура ..;)

unit SuatXTEA;

interface

uses SysUtils;

function EncryptXTEA(Data, Key:AnsiString):AnsiString;
function DecryptXTEA(Data, Key:AnsiString):AnsiString;

implementation

function FourCharsToLong(const V: AnsiString):LongWord;
var j, k:Integer;
begin
 Result:=0;
 for j:=0 to Length(V)-1 do
 begin
  k:=(3-(j mod 4))*8;
  Result:=Result or ((Ord(V[j+1]) shl k));
 end;//for j...
end;//FourCharsToLong

function LongToFourChars(const V: Longword):AnsiString;
var j, k:Integer;
begin
 Result:='';
 for j:=0 to 3 do
 begin
  k:=(3-(j mod 4))*8;
  Result:=Result+AnsiChar(V shr k);
 end;//for j...
end;//LongToFourChars

function HexToDec(Hex:AnsiString):LongWord;
 var j:Integer;
     k:Byte;
     Base:LongWord;
begin
 Result:=0;
 Hex:=UpperCase(Hex);
 Base:=1;
 for j:=Length(Hex) downto 1 do
 begin
  k:=Ord(Hex[j])-48;
  if k>9 then k:=k-7;
  Result:=Result+k*Base;
  Base:=Base*16;
 end;
end;//HexToDec

function EncryptXTEA(Data, Key:AnsiString):AnsiString;
const
 Delta = $9e3779b9;
 NumRounds=32;
var j:Integer;
 B_Key:array [0..3] of LongWord;
 Sum, v0, v1: LongWord;
 B_Result:AnsiString;
begin
 B_Result:='';
 //--- Set Key --------------
 FillChar(B_Key, SizeOf(B_Key), 0);
 j:=0;
 while Key<>'' do
 begin
  B_Key[j]:=FourCharsToLong(Copy(Key, 1, 4));
  Key:=Copy(Key, 5, 1024);
  inc(j);
 end;//while
 //-----
 while Data<>'' do
 begin
  v0:=FourCharsToLong(Copy(Data, 1, 4));
  v1:=FourCharsToLong(Copy(Data, 5, 4));
  Data:=Copy(Data, 9, 1024);
  //---
  Sum:=0;
  for j:= 0 to NumRounds-1 do
  begin
   Inc(v0, (((v1 shl 4) xor (v1 shr 5)) + v1) xor (Sum + B_Key[Sum and 3]));
   Inc(Sum, Delta);
   Inc(v1, (((v0 shl 4) xor (v0 shr 5)) + v0) xor (Sum + B_Key[Sum shr 11 and 3]));
  end;//for j...
  B_Result:=B_Result+LongToFourChars(v0)+LongToFourChars(v1);
 end;//while Data<>''
 //---
 Result:='';
 for j:=0 to Length(B_Result)-1 do
 begin
  Result:=Result+IntToHex(ord(B_Result[j+1]), 2);
 end;
 Result:=Lowercase(Result);
end;//EncryptXTEA

function DecryptXTEA(Data, Key:AnsiString):AnsiString;
const
 Delta = $9e3779b9;
 NumRounds=32;
var j:Integer;
 B_Key:array [0..3] of LongWord;
 Sum, v0, v1: LongWord;
 B_Result:AnsiString;
begin
 //--- Set Key --------------
 FillChar(B_Key, SizeOf(B_Key), 0);
 j:=0;
 while Key<>'' do
 begin
  B_Key[j]:=FourCharsToLong(Copy(Key, 1, 4));
  Key:=Copy(Key, 5, 1024);
  inc(j);
 end;//while
 //-----
 B_Result:='';
 for j:=0 to (Length(Data) div 2)-1 do
 begin
  B_Result:=B_Result+AnsiChar(HexToDec(Copy(Data, (j*2)+1, 2)));
 end;
 //----
 Result:='';
 while B_Result<>'' do
 begin
  v0:=FourCharsToLong(Copy(B_Result, 1, 4));
  v1:=FourCharsToLong(Copy(B_Result, 5, 4));
  B_Result:=Copy(B_Result, 9, 1024);
  //---
  Sum:=$C6EF3720;//Delta*NumRounds = Delta shl 5
  for j:=0 to NumRounds-1 do
  begin
   Dec(v1, (((v0 shl 4) xor (v0 shr 5)) + v0) xor (Sum + B_Key[(Sum shr 11) and 3]));
   Dec(Sum, Delta);
   Dec(v0, (((v1 shl 4) xor (v1 shr 5)) + v1) xor (Sum + B_Key[Sum and 3]));
  end;//for j...
  Result:=Result+LongToFourChars(v0)+LongToFourChars(v1);
 end;//while Data<>''
end;//DecryptXTEA

end.
...