Your length calculations are all wrong as has been pointed out in comments.
szaStream := (astream.size + 2) div (3 * 4);
This means that your encoded stream is 1/12th the size of the input stream. But it needs to be larger. You meant:
szaStream := ((astream.size * 4) div 3) + 2;
I also do not see the point of using a string here. You can write directly to the stream.
And, it's worth repeating that with base 64 you are encoding and not encrypting.
In my opinion, there is little point writing all this yourself when Delphi ships with a base 64 implementation. The unit is called EncdDecd, or Soap.EncdDecd if you are using namespaces. And the only function you need is
procedure EncodeStream(Input, Output: TStream);
Create two file streams, one for reading, one for writing, and pass them to that function. For example:
procedure EncodeFileBase64(const InFileName, OutFileName:string);
var
Input, Output: TStream;
begin
Input := TFileStream.Create(InFileName, fmOpenRead);
try
Output := TFileStream.Create(InFileName, fmCreate);
try
EncodeStream(Input, Output);
finally
Output.Free;
end;
finally
Input.Free;
end;
end;
Should you need to reverse the process, do so with, you guessed it, DecodeStream.
If performance matters then you may need to use a buffered stream rather than TFileStream. For example: Buffered files (for faster disk access)