uses
ClpISecureRandom,
ClpIKeyParameter, ClpIBufferedCipher,
ClpSecureRandom, ClpDigestUtilities, ClpCipherUtilities, ClpCryptoLibTypes,
ClpConverters, ClpEncoders, ClpParametersWithIV, ClpKeyParameter;
var
strListtest: TStringList;
csvtext: TStringStream;
procedure TfrmMain.btnSaveAsEncryptedClick(Sender: TObject);
begin
// Update strListtest with the current content of the dataset
csvtext := TStringStream.Create();
try
CSVDataset1.SaveToStream(csvtext, dfDefault);
strListtest.Text := csvtext.DataString;
finally
csvtext.Free;
end;
// Now encrypt and save the updated strListtest
EncryptStringListAndSave(strListtest, '3C6DB4EFEEBA0CB8CB1E8B39385FDE25E1DA5446F4918DF75538CFCF5A95C1C9', 'encryptedfile.txt');
end;
procedure TfrmMain.btnLoadEncryptedFileClick(Sender: TObject);
begin
strListtest:=TStringList.Create;
DecryptFileAndLoadToStringList('encryptedfile.txt','3C6DB4EFEEBA0CB8CB1E8B39385FDE25E1DA5446F4918DF75538CFCF5A95C1C9',strListtest);
csvtext:= TStringStream.Create(strListtest.Text);
CSVDataset1.LoadFromStream(csvtext,dfDefault);
CSVDataset1.Active:=True;
end;
// this all feels so wrong and not secure!!
procedure TfrmMain.EncryptStringListAndSave(const InputList: TStringList; const Key: String; const FileName: String);
var
secureRandom: ISecureRandom;
Cipher: IBufferedCipher;
KeyParam: IKeyParameter;
IV: TBytes;
InputBytes, CipherText: TBytes;
FileStream: TFileStream;
begin
// Generate a random "initialization vector" so if the same text is encrypted more than once
// it will still produce different encrypted data every time. (as i understand it)
secureRandom := TSecureRandom.Create();
SetLength(IV, 16);
SecureRandom.NextBytes(IV); // Use a secure random number generator
KeyParam := TKeyParameter.Create(THex.Decode(Key));
Cipher := TCipherUtilities.GetCipher('AES/CBC/PKCS7PADDING'); // i think this is right
Cipher.Init(True, TParametersWithIV.Create(KeyParam, IV)); // true for encryption
InputBytes := TConverters.ConvertStringToBytes(InputList.Text, TEncoding.UTF8);
CipherText := Cipher.DoFinal(InputBytes);
FileStream := TFileStream.Create(FileName, fmCreate);
try
FileStream.WriteBuffer(IV[0], Length(IV));// save the iv first so we can decrypt later
FileStream.WriteBuffer(CipherText[0], Length(CipherText));
finally
FileStream.Free;
end;
end;
procedure TfrmMain.DecryptFileAndLoadToStringList(const FileName: String; const Key: String; OutputList: TStringList);
var
Cipher: IBufferedCipher;
KeyParam: IKeyParameter;
IV, CipherText, DecryptedBytes: TBytes;
FileStream: TFileStream;
begin
FileStream := TFileStream.Create(FileName, fmOpenRead);
try
// Read the IV from the file (first 16 bytes for AES)
SetLength(IV, 16);
FileStream.ReadBuffer(IV[0], Length(IV));
// Read the rest of the file as encrypted data
SetLength(CipherText, FileStream.Size - FileStream.Position);
FileStream.ReadBuffer(CipherText[0], Length(CipherText));
finally
FileStream.Free;
end;
// Prepare the key
KeyParam := TKeyParameter.Create(THex.Decode(Key));
// Initialize the AES Cipher in CBC mode with PKCS7 Padding
Cipher := TCipherUtilities.GetCipher('AES/CBC/PKCS7PADDING');
Cipher.Init(False, TParametersWithIV.Create(KeyParam, IV)); // false for decryption
DecryptedBytes := Cipher.DoFinal(CipherText); // doing actual decryption
// Load decrypted data into the TStringList
OutputList.Text := TConverters.ConvertBytesToString(DecryptedBytes, TEncoding.UTF8);
// now the decrypted data stays in memory so i can assign to a CSVdataset... test ok so far
end;