我在C和Delphi上编写应用程序,我在两者中都有XTEA加密,它完全一样 但问题是输出是不同的,即使delta和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;
}
但输出完全不同:/ 我做错了什么?
答案 0 :(得分:5)
首先,我没有尝试执行您的代码:我的评论完全基于检查。
我怀疑问题的根源是big-endian和little-endian数据存储之间的混淆。
C代码中的宏(GET_ULONG_BE和PUT_ULONG_BE)正在提取原始数据并以BIG-endian格式转换为uint32。
在Delphi中,您将原始数据从字节复制到LongWord格式,而不需要对big-endian进行小端转换。
除此之外,我不确定S作为Int64的声明,但与大端/小端问题相比,这可能是次要的。
编辑: 您需要在XTeaCryptStr()例程中执行big-endian转换。您需要将它应用于密钥结构的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代码得到了相同的结果。
答案 1 :(得分:4)
您无法从PolarSSL复制代码。
C源代码中存在多个漏洞。 :)
首先, EVER 的ECB加密代码不包括:
output[8] = '\0';
ECB模式的重点是将一个输入块更改为另一个输入块。这条线在ECB例程中没有位置 - 它显然与字符串输出有关。 (事实上,这是也写入超出缓冲区的末尾; array[n]
中的最后一个可写位置是array[n-1]
。所以你只是在不相关的内存上涂鸦。由于buf
中的测试数组main
太短而无法保存自己的ASCII NUL - 将其更改为buf[9]
,因此可能会使用该行。
我强烈建议针对test vectors测试两个你的C和Delphi代码(对不起该页面上的可怕颜色,除了获取数据并关闭之外没有什么可做的窗口再次快速!:)发现你的程序中哪一个是正确的。
请不要使用ECB mode directly。如果使用不当,则很容易提供零隐私和完整性保证。在ECB之外构建适当的协议和操作模式是非常困难的工作;请改用OFB, CFB, CTR, CBC, PCBC或其中一种较新的authenticated encryption模式。
编辑:您的Delphi中的内容看起来不同:(我误读了。抱歉。)(V[1] xor S)
。再看一下C的线条;我认为你在例程的两个关键行中错误地翻译了Delphi版本。
答案 2 :(得分:1)
我不知道为什么我之前的回答是downvotedm然后被删除。
我们再试一次。
如果您在Windows应用程序和微处理器上使用相同的C代码,那么任何标准加密都应该工作只需选择一个。
见
http://www.drbob42.com/examines/examin92.htm
http://www.hflib.gov.cn/e_book/e_book_file/bcb/ch06.htm(在Delphi中使用C ++代码)
http://edn.embarcadero.com/article/10156#H11
看起来您需要使用DLL,但如果您不想分发它,可以静态链接它
答案 3 :(得分:0)
这是工作代码。我已经从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.