当我设计,其存储数据的块的系统,发送压缩的和由多个客户端加密。DCPCrypt(DELPHI)+了ZLib /“数据错误”解压缩解密的数据
当试图获取存储的数据块(我需要解压缩和解密)特定的计算机上,一个zlib的“数据错误”异常数据解压缩过程中提出的。似乎很清楚,该流没有被正确解密,所以输入流不是有效的ZLib流,导致这样的问题。
经过一番研究,我发现对于同样存储的源数据块,这个有问题的块包含了所有不同的数据,所以很明显加密或压缩算法存在问题。
然而,事实上,我不能轻易地重现该问题意味着,如果有一个错误,这远不是什么东西被明显。所以我在这里发布代码,希望有人会发现我没有看到的东西。
首先,数据块AStream
压缩:
function CompressStream(AStream: TMemoryStream;
ACompressionLevel:
TCompressionLevel): Boolean;
var
LTempStream: TMemoryStream;
LCompressedStream: TCompressionStream;
begin
LTempStream := TMemoryStream.create;
try
try
AStream.Seek(0, soBeginning);
LCompressedStream := TCompressionStream.Create(ACompressionLevel, LTempStream);
try
try
LCompressedStream.CopyFrom(AStream, AStream.Size);
finally
LCompressedStream.free;
end;
finally
AStream.Clear;
AStream.CopyFrom(LTempStream, 0);
AStream.Seek(0, soBeginning);
Result := True;
end;
finally
LTempStream.free;
end;
except
Result := False;
end;
end;
然后,它的加密:
function EncryptStream(AStream: TMemoryStream; const AParameters: AnsiString): Boolean;
var
LModifiedStream: TMemoryStream;
LRijndaelCipher: TDCP_rijndael;
begin
try
LRijndaelCipher := TDCP_rijndael.Create(nil);
LModifiedStream := TMemoryStream.Create;
InitCipherWithKey(LRijndaelCipher, AParameters);
try
AStream.Seek(0, soBeginning);
LRijndaelCipher.EncryptStream(AStream, LModifiedStream, AStream.Size);
TMemoryStream(AStream).Clear;
AStream.CopyFrom(LModifiedStream, 0);
Result := True;
finally
LRijndaelCipher.Burn;
LRijndaelCipher.Free;
LModifiedStream.Free;
end;
except
Result := False;
end;
end;
...并保存在某个地方。
当取出一个数据块,它的第一解密:
function DecryptStream(AStream: TMemoryStream; const AParameters: AnsiString): Boolean;
var
LModifiedStream: TMemoryStream;
LRijndaelCipher: TDCP_rijndael;
begin
try
LRijndaelCipher := TDCP_rijndael.Create(nil);
LModifiedStream := TMemoryStream.Create;
InitCipherWithKey(LRijndaelCipher, AParameters);
try
AStream.Seek(0, soBeginning);
LRijndaelCipher.DecryptStream(AStream, LModifiedStream, AStream.Size);
TMemoryStream(AStream).Clear;
AStream.CopyFrom(LModifiedStream, 0);
Result := True;
finally
LRijndaelCipher.Burn;
LRijndaelCipher.Free;
LModifiedStream.Free;
end;
except
Result := False;
end;
end;
然后未压缩:
function DecompressStream(AStream: TMemoryStream): Boolean;
var
LTempStream: TMemoryStream;
LCompressedStream: TDecompressionStream;
begin
LTempStream := TMemoryStream.create;
try
try
AStream.Seek(0, soBeginning);
LCompressedStream := TDecompressionStream.Create(AStream);
try
try
LTempStream.CopyFrom(LCompressedStream, LCompressedStream.size);
finally
LCompressedStream.Free;
end;
finally
AStream.Clear;
AStream.CopyFrom(LTempStream, 0);
AStream.Seek(0, soBeginning);
Result := True;
end;
finally
LTempStream.free;
end;
except
Result := False;
end;
end;
的加密是使用InitCipherWithKey()
方法初始化。它被设计用来将MD5哈希转换成它的二进制表示形式,包含在LMD5Hash
变量中(是的,数组的长度是64字节,但只有前16个将被密码使用,因为我用128值调用Init()
(这意味着128位/ 16字节的密钥长度):
procedure InitCipherWithKey(ACipher: TDCP_cipher; const AKey: AnsiString);
var
LMD5Hash: array [0..63] of Byte;
S: AnsiString;
begin
//We use a 128 bit key
ZeroMemory(@LMD5Hash, SizeOf(LMD5Hash));
S := AKey;
HexToBin(PAnsiChar(S), LMD5Hash, Length(LMD5Hash) -1);
ACipher.Init(LMD5Hash[0], 128, nil);
ZeroMemory(@LMD5Hash, SizeOf(LMD5Hash));
end;
在此先感谢
非常感谢您的回答。InitCipherWithKey通过Init()函数直接将二进制值分配给密码。没有从二进制到字符串的转换,并且Init()需要二进制缓冲区,所以我不确定这里有什么问题。感谢您提供使用PBKDF2算法的建议,我会研究它! –
以十六进制(使用验证的十六进制编码器)打印或记录加密算法的所有二进制输入和输出。一个不正确的位就足以使加密完全失败。 –