Am trying to encrypt a file using SynCrypto.pas with AES 256, but it fails if I try to encrypt a file whose size is not a multiple of 16 bytes. The decrypted data contains junk.
Example:
Original string in txt file
we are testing the file
Encrypted String
[ù[„|wáî}f *!4ìÙw¬•ü¨s
Decrypted String
we are testing tÝp?J
Here is my Encryption Code
procedure TForm1.Button1Click(Sender: TObject);
var
A: TAES;
Key: TSHA256Digest;
s, B: TAESBlock;
ks: integer;
st: RawByteString;
InStream, OutStream: TFileStream;
SuperNo, TheSize, StreamSize: Int64;
begin
InStream := TFileStream.Create('test.txt', fmOpenRead);
OutStream := TFileStream.Create('out.txt', fmCreate);
InStream.Position := 0;
OutStream.Position := 0;
st := '1234essai';
ks := 256;
SHA256Weak(st, Key);
A.EncryptInit(Key, ks);
StreamSize := InStream.Size;
while InStream.Position < StreamSize do
begin
TheSize := StreamSize - InStream.Position;
if TheSize < 16 then
begin
SuperNo := StreamSize - InStream.Position;
end
else
begin
SuperNo := 16;
end;
InStream.ReadBuffer(s, SuperNo);
A.Encrypt(s, B);
OutStream.WriteBuffer(B, SuperNo);
end;
A.Done;
ShowMessage('Finish');
InStream.Free;
OutStream.Free;
end;
Here is my Decryption Code
procedure TForm1.Button2Click(Sender: TObject);
var
A: TAES;
Key: TSHA256Digest;
s, B: TAESBlock;
ks: integer;
st: RawByteString;
InStream, OutStream: TFileStream;
SuperNo, TheSize, StreamSize: Int64;
begin
InStream := TFileStream.Create('out.txt', fmOpenRead);
OutStream := TFileStream.Create('in.txt', fmCreate);
InStream.Position := 0;
OutStream.Position := 0;
st := '1234essai';
ks := 256;
SHA256Weak(st, Key);
A.DecryptInit(Key, ks);
StreamSize := InStream.Size;
while InStream.Position < StreamSize do
begin
TheSize := StreamSize - InStream.Position;
if TheSize < 16 then
begin
SuperNo := StreamSize - InStream.Position;
end
else
begin
SuperNo := 16;
end;
InStream.ReadBuffer(s, SuperNo);
A.Decrypt(s, B);
OutStream.WriteBuffer(B, SuperNo);
end;
A.Done;
ShowMessage('Finish');
InStream.Free;
OutStream.Free;
end;
Using Delphi XE7.
AES is a block cipher algorithm. It means that it works by blocks that are 16 bytes in size for AES. So you need to use padding if your data does not fit in 16 bytes blocks (which is the case for your text).
Instead of trying to re-invent the wheel, and introduce mistakes, you would rather rely on existing padding algorithm. And you should add a block chaining mode. Currently the default algorithm you are using is ECB, which is known to be weak, since it does not use a chaining mode nor an Initialization Vector (IV).
The
SynCrypto
unit contains a safe block chaining mode like CFB and PKCS7 padding, so you could write:The above code is safe and fast, will generate the binary key using SHA-256 over the supplied
'privatekey'
, and will use AES-NI hardware instructions if you CPU supports it. You can use another chaining mode, just by changing theTAESCFB
class name to another type available.