@@ -572,16 +572,29 @@ private static ProtectedBinary DecryptKey(ProtectedString QuickUnlockKey, Protec
572572
573573 private static byte [ ] AdjustQuickUnlockKey ( ProtectedString QuickUnlockKey , byte [ ] salt )
574574 {
575- byte [ ] bUtf8 = QuickUnlockKey . ReadUtf8 ( ) ; // must be wiped
576- byte [ ] derivedKey ;
577-
578- // use standard PBKDF2 to mitigate brute-forcing of short PINs
579- using ( var rfc2898 = new Rfc2898DeriveBytes ( bUtf8 , salt , 100000 ) )
575+ byte [ ] bUtf8 = QuickUnlockKey . ReadUtf8 ( ) ;
576+ byte [ ] derivedKey = null ;
577+
578+ try
580579 {
581- derivedKey = rfc2898 . GetBytes ( 32 ) ; // 256 bits required for ChaCha20
580+ KdfParameters kdfParams = new KdfParameters ( KeePassLib . Cryptography . KeyDerivation . KdfUuid . Argon2 ) ;
581+
582+ // these should be set to values that provide a good balance between security and performance for quick unlock scenarios
583+ kdfParams . SetUInt64 ( KdfParameters . KeyArgon2Iterations , 3 ) ;
584+ kdfParams . SetUInt64 ( KdfParameters . KeyArgon2Memory , 64 * 1024 * 1024 ) ; // memory cost (64 MiB)
585+ kdfParams . SetUInt32 ( KdfParameters . KeyArgon2Parallelism , 2 ) ; // thread count
586+ kdfParams . SetBytes ( "S" , salt ) ;
587+
588+ var argon2 = new KeePassLib . Cryptography . KeyDerivation . Argon2Kdf ( ) ;
589+ derivedKey = argon2 . Generate ( bUtf8 , kdfParams ) ;
582590 }
583-
584- MemUtil . ZeroByteArray ( bUtf8 ) ;
591+ finally
592+ {
593+ // Ensure the plaintext PIN is scrubbed from memory immediately
594+ MemUtil . ZeroByteArray ( bUtf8 ) ;
595+ }
596+
597+ // The returned derivedKey will naturally be 256 bits (32 bytes)
585598 return derivedKey ;
586599 }
587600 }
0 commit comments