當我設計,其存儲數據的塊的系統,發送壓縮的和由多個客戶端加密。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算法的建議,我會研究它! –
以十六進制(使用驗證的十六進制編碼器)打印或記錄加密算法的所有二進制輸入和輸出。一個不正確的位就足以使加密完全失敗。 –