fix(storage): EncryptedFile.Decrypt must reject malformed containers cleanly
A tampered or corrupted wallet file could reach Decrypt with broken JSON, missing fields, invalid base64, or a wrong nonce/tag size, all of which previously escaped as raw JsonException/FormatException/ ArgumentNullException instead of the documented WrongPasswordException/ InvalidDataException contract. Worse, the iteration count is read straight from the (attacker-controlled) container with no upper bound: a tampered file demanding e.g. 2^31 PBKDF2 iterations would hang the wallet at open - a DoS via a file the user merely tries to open. Now every malformed shape maps to InvalidDataException and the iteration count is clamped to a sane maximum (10,000,000, well above the current 600,000 default).
This commit is contained in:
@@ -57,6 +57,22 @@ public class StorageTests
|
||||
Assert.NotEqual(c1, c2);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("not json at all")] // broken JSON
|
||||
[InlineData("null")] // JSON null
|
||||
[InlineData("""{"Format":"plm-wallet-aesgcm-v1"}""")] // missing fields → null strings
|
||||
[InlineData("""{"Format":"plm-wallet-aesgcm-v1","Iterations":600000,"Salt":"$$$","Nonce":"AAAAAAAAAAAAAAAA","Tag":"AAAAAAAAAAAAAAAAAAAAAA==","Data":""}""")] // bad base64
|
||||
[InlineData("""{"Format":"plm-wallet-aesgcm-v1","Iterations":600000,"Salt":"AA==","Nonce":"AA==","Tag":"AAAAAAAAAAAAAAAAAAAAAA==","Data":""}""")] // wrong nonce size
|
||||
[InlineData("""{"Format":"plm-wallet-aesgcm-v1","Iterations":0,"Salt":"AA==","Nonce":"AAAAAAAAAAAAAAAA","Tag":"AAAAAAAAAAAAAAAAAAAAAA==","Data":""}""")] // iterations 0
|
||||
[InlineData("""{"Format":"plm-wallet-aesgcm-v1","Iterations":2147483647,"Salt":"AA==","Nonce":"AAAAAAAAAAAAAAAA","Tag":"AAAAAAAAAAAAAAAAAAAAAA==","Data":""}""")] // PBKDF2 DoS
|
||||
public void Un_contenitore_malformato_produce_sempre_InvalidDataException(string container)
|
||||
{
|
||||
// A tampered/corrupted file must map to the two typed exceptions, never to a
|
||||
// raw JsonException/FormatException/ArgumentNullException (found by fuzzing);
|
||||
// the absurd iteration count would otherwise hang the wallet at open.
|
||||
Assert.Throws<InvalidDataException>(() => EncryptedFile.Decrypt(container, "pass"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Ogni_encrypt_produce_salt_diverso()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user