I have a package with a Delphi component that needs to store a TStrings property encrypted. The planned encryption/decryption process is described below:
A custom strings editor will handle encrypting the value at design time using the key. "Key" is not the actual key used for encryption. Argon2 will derive the actual key from the "Key" property.
DESIGN TIME: When the custom editor executes, the Lines property will be decrypted into a TMemo. On save, the TMemo.text will be encrypted back into the Lines property. Decryption/Encryption does not occur when there is no content.
RUNTIME: The GetText function will decrypt the Lines property for use.
Questions:
"Key" is not the actual crypto key. The plan is to use Argon2 to create the actual key from this value. The SetKey procedure will re-encrypt LINES if the "key" value changes.
Can this actually work?
At creation, the value of "key" needs to be randomly generated. How should I generate this value?
The text size is not large. Encryption/Decryption occurs at design time when "Lines" is edited. In most instances, it will only be decrypted once at runtime. What crypto method would be best to encrypt/decrypt "Lines"?
This is beyond pure TMS Crypto support, but here are a few thoughts.
You can derive a key from an input string in Argon2, a password. And you may have to convert the resulting key in hex or base64, for instance, if you want to share/exchange/store it (it would be a very good idea to encrypt it too).
You may still have the issue of keeping the password secret depending on how you want to share the key.
If you want to decrypt or encrypt lines, I recommend that you bundle them together in a single string.Then you can use the previously derived key with the AES to encrypt/decrypt this string or its corresponding cryptogram.
I sometimes get "Invalid Operation: -207." running my test program. I have text in a TMemo on the form. When I press Encrypt followed by Decrypt. It seems if I do this too fast, I get the -207 error.
Is this a timing issue or do I need to make a change to my code?
Main Program
procedure TfmComponentEditors.btnDecryptClick(Sender: TObject);
var
v_Key: String;
begin
v_Key := GetKeyFromPassword('abcdefghijklmnop',32);
MainMemo.Text := AESDecryptString(v_Key,MainMemo.Text);
end;
procedure TfmComponentEditors.btnEncryptClick(Sender: TObject);
var
v_Key: String;
begin
v_Key := GetKeyFromPassword('abcdefghijklmnop',32);
MainMemo.Text := AESEncryptString(v_Key,MainMemo.Text);
end;
Functions
function GetKeyFromPassword (const p_Password: String;
const p_Length: Integer): String;
var
A2D: TArgon2dClass;
begin
A2D := TArgon2dClass.Create (nil);
try
A2D.Counter := 10;
A2D.Memory := p_Length;
A2D.OutputSizeBytes := p_Length;
A2D.OutputFormat := TConvertType.raw;
Result := A2D.GenerateKey(p_Password);
finally
A2D.Free;
end;
end;
function AESEncryptString(const p_Key, p_Text: string): string;
var
AES: TAESEncryption;
begin
AES := TAESEncryption.Create(nil);
try
AES.AType := atCBC;
AES.KeyLength := kl256;
AES.Key := p_Key;
AES.IVMode := TIVMode.rand;
Result := AES.Encrypt(p_Text);
finally
AES.Free;
end;
end;
function AESDecryptString(const p_Key, p_EncryptedText: string): string;
var
AES: TAESEncryption;
begin
AES := TAESEncryption.Create(nil);
try
AES.AType := atCBC;
AES.KeyLength := kl256;
AES.Key := p_Key;
AES.IVMode := TIVMode.rand;
Result := AES.Decrypt(p_EncryptedText);
finally
AES.Free;
end;
end;