Procedure EnCryptStream(
Var InFStream, OutFStream: TFileStream ;
Passphrase:
String) ;
Var
AHashValue, TmpFile:
String ;
Buffer: TBytes ;
i: Integer ;
Begin
InFStream.Position := 0 ;
OutFStream.Position := 0 ;
Try
AHashValue := GetHashFromStream(InFStream) ;
// CreateSalt;
For i := 0
To 7
Do
Begin
// just fill the salt with random values
// (crypto secure PRNG would be better but not _really_ necessary)
Salt[i] := 1 + Random(255) ;
End ;
// InitHashDiggest;
HashType.Init ;
// hash the salt
HashType.Update(Self.Salt[ Low(Salt)], High(Self.Salt) + 1) ;
HashType.UpdateStr(Passphrase) ;
// and the passphrase
// store the output in HashDigest
HashType.
Final(Self.HashDigest[0]) ;
// write the salt so we can encrypt!
OutFStream.WriteBuffer(Self.Salt[ Low(Salt)], High(Self.Salt) + 1) ;
// init the cipher with the hash
// if the cipher is a block cipher we need an initialisation vector(IV)
If (CipherType
Is TDCP_blockcipher)
Then
Begin
SetLength(CipherIV, TDCP_blockcipher(CipherType).BlockSize
Div 8);
// create random values for the IV
For i := 0
To High(Self.CipherIV)
Do
Self.CipherIV[i] := 1 + Random(255) ;
// write the IVector
OutFStream.WriteBuffer(Self.CipherIV[0], High(Self.CipherIV)
+ 1) ;
// initialise the cipher with the hash as key
CipherType.Init(Self.HashDigest[0], Min(CipherType.MaxKeySize,
HashType.HashSize), Self.CipherIV) ;
// use CBC chaining when encrypting
TDCP_blockcipher(CipherType).CipherMode := cmCBC ;
End
Else
// initialise the cipher with the hash as key
CipherType.Init(Self.HashDigest[0], Min(CipherType.MaxKeySize,
HashType.HashSize),
Nil) ;
// encrypt the entire file
CipherType.EnCryptStream(InFStream, OutFStream, InFStream.Size) ;
CipherType.Burn ;
// important! get rid of keying information
// write the hash of the not encrypted stream to check
Buffer := BytesOf(AHashValue) ;
OutFStream.WriteBuffer(Buffer[ Low(Buffer)], length(AHashValue)) ;
Except
On Exception Do
Raise ECryptEncryptStream ;
End ;
End ;
Function DeCryptStream(
Var AFStream: TFileStream ;
Passphrase:
String): TStringList ;
Var
TempStream: TFileStream ;
HashOfStream, HashInStream, TmpFile:
String ;
HashLength, PositionOfData, MinLengthStream: Cardinal ;
Buffer:
Array Of byte ;
AByte: byte ;
Begin
Try
AFStream.Position := 0 ;
// Get hash length with 2 diggits(hex value)
HashLength := HashType.GetHashSize
Div 8 * 2 ;
MinLengthStream := HashLength + ( High(Salt) + 1) +
( High(CipherIV) + 1) ;
If MinLengthStream > AFStream.Size
Then
Raise ECryptNoCryptedFile ;
// Search a free file and return the filename
TmpFile := TFuncs.GetUnusedTempFile(TempFile) ;
TempStream := TFileStream.Create(TmpFile, fmCreate) ;
// read the importend values from the stream
AFStream.ReadBuffer(Self.Salt[ Low(Salt)], High(Self.Salt) + 1);
InitHashDiggest(Passphrase) ;
SetLength(CipherIV, TDCP_blockcipher(CipherType).BlockSize
Div 8);
AFStream.ReadBuffer(Self.CipherIV[ Low(CipherIV)], High
(Self.CipherIV) + 1) ;
InitCipher ;
// decrypt!
TempStream.Position := 0;
CipherType.DeCryptStream(AFStream, TempStream,
AFStream.Size - HashLength - AFStream.Position) ;
CipherType.Burn ;
// Read the hash in the stream
AFStream.Position := AFStream.Size - HashLength ;
// hash at the EOF
SetLength(Buffer, HashLength) ;
AFStream.ReadBuffer(Pointer(Buffer)^, HashLength) ;
HashInStream := '
' ;
HashInStream := TFuncs.ByteArrayToStr(Buffer) ;
// get and check the hash in stream with the aktual hash of the stream
TempStream.Position := 0;
HashOfStream := Self.GetHashFromStream(TempStream) ;
// Auskommentiert um heraus zu finden ob es am Hash liegt ist auch keine gute
// gute Methode um eine sicher Entschlüsselung zu gewährleisten
//If HashInStream = HashOfStream Then
//Begin
HashWert := HashOfStream ;
Result := TStringList.Create ;
TempStream.Position := 0 ;
Result.LoadFromStream(TempStream, TEncoding.Unicode) ;
FreeAndNil(TempStream) ;
If FileExists(TmpFile)
Then
DeleteFile(TmpFile) ;
{End else
begin
FreeAndNil(TempStream) ;
If FileExists(TmpFile) Then
DeleteFile(TmpFile) ;
end;}
Except
On Exception Do
Begin
FreeAndNil(TempStream) ;
If FileExists(TmpFile)
Then
DeleteFile(TmpFile) ;
FreeAndNil(Result) ;
ECryptDecryptStream.
Message :=
ECryptDecryptStream.
Message + #13#10 + ExceptObject.ToString ;
Raise Exception.Create(ECryptDecryptStream.
Message) ;
End ;
End ;
End ;