Einzelnen Beitrag anzeigen

itblumi

Registriert seit: 28. Mär 2009
73 Beiträge
 
Delphi XE6 Professional
 
#9

Re: Gecrypteter FileStream WinXP(De) <> FileStream Win

  Alt 28. Apr 2010, 19:43
Wow, erstmal Danke das sich so viele daran beteiligen.

Problem Beschreibung:
Ein FileStream der nur aus Sonderzeichen besteht(gecryptet) hat unterschiedliche Hash-Werte im russischen und im deutschen Windows.
Dh. die Streams sind unterschiedlich. Der Hash dient mir dazu um die entschlüsselten Daten auf ihre Korrektheit zu überprüfen.
Hier meine Methode wie ich den Hash-Werte bilde:

Delphi-Quellcode:
         Function GetHashFromStream(AFileStream: TFileStream): String ;
            Var
               AHash: TDCP_Hash ;
               i, Read, allreaded, willread: Integer ;
               s: String ;
               Buffer: Array [0 .. 16383] Of byte ;
            Begin
               Result := '' ;
               AHash := TDCP_Hash(TDCP_SHA512) ;
               AHash.Init ;
               Try
                  Read := 0 ;
                  allreaded := 0 ;
                  AFileStream.Position := 0 ;
                  Repeat
                     // read into the buffer
                     willread := AFileStream.Size - AFileStream.Position ;
                     If willread > High(Buffer) Then
                        Read := AFileStream.Read(Buffer[0], High(Buffer) + 1)
                     Else
                        Read := AFileStream.Read(Buffer[0], willread) ;
                     inc(allreaded, Read) ;
                     // hash the buffer with each of the selected hashes
                     AHash.Update(Buffer, Read) ;
                  Until allreaded >= AFileStream.Size ;
                  SetLength(HashDigest, AHash.GetHashSize Div 8) ;
                  AHash.Final(HashDigest[0]) ; // get the output
                  // cast HashDigest to String (ByteToStr)
                  Result := HashDigestToStr ;
               Except
                  On Exception Do
                     Raise ECryptGetHash ;
               End ;
            End ;
Nicht gecryptete Zeichenketten sind gleich da keine Sonderzeichen enthalten sind.

Zitat:
Dann könnte es also doch am Unicode liegen, oder genauer gesagt vermutlich irgendwo an einer Ansi<>Unicodeumwandlung, bei welcher die die aktuelle CodePage des Systems verwendet wird.
Daran habe ich auch schon gedacht, doch normalerweise kommt das doch nur bei Zeichensätzen vor und nicht bei Bytes oder irre ich mich da?

Zitat:
Das wäre allerdings eine völlige Bankrotterklärung für Verschlüsselungstechniken! Wenn Du jedoch meinst, daß Delphi-Programmierer mit ihrer häufigen Stringfixierung so etwas produzieren, kann man zu stimmen. Die Abhilfe ist allerdings auch schon lange bekannt: Ver/entschlüsselt werden nur Binärdaten, was ja wohl gerade bei Dateien auch kein großes Problem ist.
So mache ich es auch, trotzdem sind die Hash-Werte unterschiedlich! Das sollte eigentlich die Überschrift verdeutlichen das es sich hier bei nur um Binär Daten handelt.
Hier noch meine Ent- und Verschlüsselungsmethoden:
Die Funktionen stammen aus einer Klasse, es kann also durchaus sein das einige Variablen nicht initialisert sind, da ich das
in anderen Methoden schon getan habe. Die Funktionen funktionieren auch einwandfrei in einem deutsch sprachigen Windows.

Delphi-Quellcode:
         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 ;
Den einzigen Strings die ich bei den Methoden verwende sind die Passphrase(Zum testen im Quellcode also Unicode) und der HashWert der ans Dateiende geschrieben wird ist auch im RU-Win gleich.
Jan
Ein neuer Tag bringt so einiges mit sich. Was auch immer es ist, es bleibt ein kleines Abenteuer.
  Mit Zitat antworten Zitat