386bf74a2a
Two stages tested separately, because a global failure says nothing about where: PBKDF2 against the known derived key - which also runs on Win64, so that stage validates in seconds without deploying to a phone - then AES-GCM against the plaintext hash, Android only. The vector is embedded as a unit rather than read from a file: no network, no deployment, so a first-run failure can only come from the decryption itself. Work runs on a thread; 600k HMAC rounds on the UI thread would have Android kill the app for not responding.
39 lines
2.2 KiB
ObjectPascal
39 lines
2.2 KiB
ObjectPascal
unit PMA.TestVector;
|
|
{
|
|
The testvector.json container, embedded verbatim.
|
|
|
|
Generated by a script - do not edit by hand. It exists for the very first
|
|
run on a device, where the point is to isolate the crypto: no network, no
|
|
file to deploy, so a failure can only come from the decryption itself.
|
|
}
|
|
|
|
interface
|
|
|
|
const
|
|
// Vector password. NON-ASCII on purpose: that is the only case telling a
|
|
// correct PBKDF2 from an approximate one (see testvector.md). Written as
|
|
// escapes so this file stays pure ASCII and no editor can mangle it.
|
|
// e-acute = U+00E9, a-grave = U+00E0, u-diaeresis = U+00FC
|
|
TESTVECTOR_PASSWORD = 'sync-test-password-'#$00E9#$00E0#$00FC;
|
|
|
|
// Expected values, to be checked IN THIS ORDER: the key first, the plaintext
|
|
// second. A wrong key points at PBKDF2 or the password encoding; a correct
|
|
// key with a failed decryption points at AES-GCM.
|
|
TESTVECTOR_KEY_HEX = '6bd7683ea78e163062f02681b03f2906fcf5a3a25025005af4e71982e6e2b286';
|
|
TESTVECTOR_PLAIN_SHA = 'ddaee44f8ac8374f1ece6d9ee2abd104d59cd283556f1c4c07afa95ae1dbd2a7';
|
|
TESTVECTOR_PLAIN_LEN = 572; // UTF-8 bytes
|
|
|
|
TESTVECTOR_JSON =
|
|
'{' +
|
|
' "format": "pm-encrypted-export-v1",' +
|
|
' "kdf": "pbkdf2-sha256",' +
|
|
' "kdf_iterations": 600000,' +
|
|
' "kdf_salt": "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=",' +
|
|
' "iv": "yMnKy8zNzs/Q0dLT",' +
|
|
' "ciphertext": "31AqOJ83L2TEFOcYaKEdpqKWGY42I4NUq+jdO7pA3j8+v023ECxjSaEnB0NvbufW6dMCgkK9oFwRvoQlLVSvK6bNBwBinJ4ltlbwKqATR2HGHh5eqiqGZayNNdRIFNJZw/jw9lYy28R6uK421uaMRx+mUBs4LGX9U+F2ayFfVF/VlsaHb5I3YMhLCN2zyMxs3j7Y1s69N09Uonm0LGKQ+SiteuXTHWJzAvHFIduLlxPJhCfEKUap4PolQ5PMohJeJYt+sutg7UY6i0QclxpmF2MY2qpbh3gA2mmSntoI2LN8Q41NMqyVn6JY6kXXpEfD1aNVw6dDCqAw2FQJ9HxE+/GBirt009rdS/l59KEnIYRvgBFnQqRTJZNNncHXXh3TsnQ3opKEyYe5qCxnX6E7wGzRawD/sQn2NNWjR8wwQQ68Cs74/RR8stAeuD/VJhJnkwxXPh8eBXHWFjLgFZuan+Ja2FwkjMhkHvIqbfJpbNwnu1mJ8ABtbGqmEHYSGUvLovIwCoQWjBqewlCFvRg0l4h63mUxuLaXx0SrIA3xhS7HqnYVTBp5/EVAu715jKmeDHviiZw6iws5ujd/u0IDUtJY1uANaF1xTBwcfkCnuonBlI8eMbIlcndrLSUN2slm6KxeUjZ3RSpiE9Izh5ix4kann8lygCAZVGkjswB83LmB1dFNH3oqG3+4qUgv7qR0TRZUSMoopCaSxhsVRd6/uBWu+82Nkbij1jMIzaB1+vTxBEHi5DGBNDfV/0evTgoIkC9wJtlEbz/OVCwC",' +
|
|
' "created_at": "2026-08-14T12:00:00.000Z"' +
|
|
'}';
|
|
|
|
implementation
|
|
|
|
end. |