Check those two programs ======= Program A =====
Program A; Uses Classes, BlowFish; Var lSource, lIntermediate : TMemoryStream; lEncrypter : TBlowfishEncryptStream; Begin lSource := TMemoryStream.Create; lSource.LoadFromFile('test7.pas'); WriteLn(lSource.Size); lIntermediate := TMemoryStream.Create; lEncrypter := TBlowfishEncryptStream.Create('123', lIntermediate); lEncrypter.CopyFrom(lSource, lSource.Size); lEncrypter.Free; WriteLn(lIntermediate.Size); // SendStreamViaSocket(lIntermediate); { Lets pretend this function automatically checks the size of the stream } lIntermediate.Free; lSource.Free; End. ====== EOF ===== ====== Program B ===== Program B; Uses Classes, Blowfish; Var lIntermediate, lDestination : TMemoryStream; lDecrypter : TBlowfishDecryptStream; Begin lIntermediate := TMemoryStream.Create; lDestination := TMemoryStream.Create; // ReceiveStreamViaSocket(lIntermediate); { Lets pretend this function can check the socket for the size of the last UDP packet } WriteLn(lIntermediate.Size); lIntermediate.Seek(0, soFromBeginning); lDecrypter := TBlowfishDecryptStream.Create('123', lIntermediate); lDestination.CopyFrom(lDecrypter, lIntermediate.Size); { Read how much ??? } lDecrypter.Free; WriteLn(lDestination.Size); lDestination.SaveToFile('test7.txt'); lSource.Free; lIntermediate.Free; lDestination.Free; End. ===== EOF ===== The problem consists that, if lIntermediate.Size is not equal to lSource.Size, i will not know how much bytes to "copyfrom" from the decrypter. For one, if a 10 bytes lSource generates a 20 bytes lIntermediate, and no clear rule show what are the mathematical relationship of those sizes, then asking 20 bytes (as lIntermediate.Size will show) will yield wrong results (Worse if the result at lIntermediate is smaller than the original lSource.Size). But, if TBlowfishDecryptStream worked backwards (the create parameters being the key and the DESTINATION stream, not the source) then this would makes sense. The problem ends up to be that by having a source parameter instead of a destination paramater this makes you have to read out bytes from the decrypter (you push out instead of pushing in), while at the same time you cannot know how many bytes you really have to read by just looking at the decrypter current state. Thats a set of mutually exclusive assumptions. Now this : ===== Program C ==== Program B; Uses Classes, Blowfish; Var lIntermediate, lDestination : TMemoryStream; lDecrypter : TBlowfishDecryptStream; Begin lIntermediate := TMemoryStream.Create; lDestination := TMemoryStream.Create; // ReceiveStreamViaSocket(lIntermediate); { Lets pretend this function can check the socket for the size of the last UDP packet } WriteLn(lIntermediate.Size); lIntermediate.Seek(0, soFromBeginning); lDecrypter := TBlowfishDecryptStream.Create('123', lDestination); lDecrypter.CopyFrom(lIntermediate, lIntermediate.Size); lDecrypter.Free; WriteLn(lDestination.Size); lDestination.SaveToFile('test7.txt'); lSource.Free; lIntermediate.Free; lDestination.Free; End. === EOF === This would work better, cause now you just need to know how much bytes to push into the decrypter, something that is readily available at the lIntermediate stream. While i bet that the blowfish algorithm has an input to output size relationship of one to one (as most stream cyphers), this is not a good choice for other algorithms wich could yield different output sizes for a given input... 2011/3/6 Michael Van Canneyt <mich...@freepascal.org>: > > > On Sat, 5 Mar 2011, Jorge Aldo G. de F. Junior wrote: > >> i have a problem with TBlowfishDecryptStream : > > [snip] >> >> The problem now is that it eats chars at the end of the generated >> lBuffer (tested by taking a tmemorystream thru tblowfishencryptstream, >> then taking the result to this tblowfishdecryptstream, than back to a >> tmemorystream and comparing the results, the original tmemorystream >> shows to be bigger than the resulting tmemorystream)... >> >> Basically i need : >> >> 1 - That TBlowfishEncryptStream guarantees that the same ammount of >> bytes feed to it, ends up at the output of it > > That should be the case. See below for an explanation why you get different > results. > >> 2 - That TBlowfishDecryptStream simply allows us to use Size property >> (Well, sometimes i receive a tmemorystream in an unrelated part of the >> code so i cannot read the original size the buffer had before >> encrypting)... > > This is impossible by definition. > > You should always design your algorithms so they don't need size. > Compression and encryption streams cannot have size, since they do not know > the size of the input data. > > There are only 3 streams that have guaranteed size: > - Memory stream > - File stream > - String stream (a variant of memory stream) > All other streams do not have size. > > Your second mistake is that the output of the BlowFish encryption stream is > only fully known when it is destroyed. You should FIRST destroy the blowfish > encryptor/decryptor stream. Only then, all characters that are in the > internal encryption buffer are written to the output buffer. > > Alternatively, call Flush() to write the remains of the internal buffer to > the output buffer. Note that after a call to flush(), no more data can be > written to the stream, because the output will then be wrong. > > Michael. > _______________________________________________ > fpc-pascal maillist - fpc-pascal@lists.freepascal.org > http://lists.freepascal.org/mailman/listinfo/fpc-pascal > _______________________________________________ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal