I have been using the Lazarus/FPC Blowfish library to encrypt file streams a while, and it works very well for me.
Now I tried to adapt the library to encrypt and decrypt arbitrary memory structures (records, but also strings), and got a problem which I could not resolve in days, so please help.
Problem is that strings having a length beeing an exact multiple of the Blowfish block size (8 Bytes) are encrypted and decrypted properly. If a string does not end at an exact 8 Byte boundary, the characters exceeding the boundary are mangled.
Here is the code (for the complete Lazarus project please follow the link)
Procedure BlowfishEncrypt(var Contents;ContentsLength:Integer;var Key:String);
// chop Contents into 64 bit blocks and encrypt using key
var
arrShadowContent:Array of Byte absolute Contents;
objBlowfish: TBlowFish;
BlowfishBlock: TBFBlock;
ptrBlowfishKey:PBlowFishKey;
p1,count,maxP:integer;
begin
ptrBlowfishKey := addr(Key[1]);
objBlowfish := TBlowFish.Create(ptrBlowfishKey^,Length(Key));
p1 := 0;
maxP := ContentsLength - 1;
count := SizeOf(BlowfishBlock);
while p1 < maxP do
begin
fillChar(BlowfishBlock,SizeOf(BlowfishBlock),0); // only for debugging
if p1 + count > maxP then
count := ContentsLength - p1;
Move(arrShadowContent[p1],BlowfishBlock,count);
objBlowfish.Encrypt(BlowfishBlock);
Move(BlowfishBlock,arrShadowContent[p1],count);
p1 := p1 + count;
end;
FreeAndNil(objBlowfish);
end;
And this is the call ...
procedure TForm1.CryptButtonClick(Sender: TObject);
var
ContentsBuffer,Key:String;
begin
ContentsBuffer := PlainTextEdit.Text;
Key := KeyTextEdit.Text;
BlowFishEncrypt(ContentsBuffer,Length(ContentsBuffer),Key);
CryptOutEdit.Text := ContentsBuffer;
BlowFishDecrypt(ContentsBuffer,Length(ContentsBuffer),Key);
CryptCheckEdit.Text := ContentsBuffer;
end;
And here you see what's happening:
Resolved. The problem is that I am not allowed to truncate a TBFBlock. For Blowfish Decryption to work, ContetLength must be a multiple of TBFBlock size.