feat(android): adopt the platform PBKDF2, record the timing and what follows from it

Measured on device: Android derives the same key as WebCrypto on a non-ASCII password, so PBEKeySpec does encode as UTF-8 - the doubt that justified the Pascal implementation was unfounded. It is barely faster though, 3869 ms against 4139 ms: PBKDF2 gets no hardware acceleration.

So 4 seconds per container is incompressible, and the iteration count belongs to the desktop format. The answer is not to speed up the derivation but to stop repeating it: derive once per snapshot, then keep the vault locally under an Android Keystore key. Written up in android-client/README.md.
This commit is contained in:
r-zakarya
2026-08-14 23:30:15 +01:00
parent 307bbeae83
commit c684d9073f
2 changed files with 73 additions and 1 deletions
+8 -1
View File
@@ -374,7 +374,14 @@ begin
if (Length(LSalt) = 0) or (Length(LIv) = 0) or (Length(LCt) = 0) then
raise EPMACrypto.Create('Container is missing salt, iv or ciphertext');
LKey := DeriveKeyPBKDF2(APassword, LSalt, LIterations, 32);
// Android's provider first — measured identical to WebCrypto on a
// non-ASCII password (so it does encode as UTF-8), and it is platform
// code rather than ours. Barely faster though: 3869 ms against 4139 ms,
// PBKDF2 gets no hardware acceleration. The Pascal path stays as the
// fallback, and is the only one outside Android.
LKey := DeriveKeyPBKDF2Native(APassword, LSalt, LIterations, 32);
if LKey = nil then
LKey := DeriveKeyPBKDF2(APassword, LSalt, LIterations, 32);
LPlain := AesGcmDecrypt(LKey, LIv, LCt);
Result := TEncoding.UTF8.GetString(LPlain);
finally