and self.last_iv [1] != cnt - 1:
raise NonConsecutiveIV ("iv %s counter not successor of "
"last object (expected %d, found %d)"
- % (fixed, iv_fmt (self.last_iv [1]), cnt))
+ % (iv_fmt (iv), self.last_iv [1], cnt))
self.last_iv = (fixed, cnt)
_ = decryptor.done ()
+ def test_crypto_aes_gcm_dec_iv_gap (self):
+ """
+ Encrypt multiple objects using non-consecutive IVs and verify that the
+ decryptor errors out with an exception in strict mode but keeps quiet
+ otherwise.
+ """
+ cnksiz = 1 << 10
+ orig_pt_1 = fill_mod (1 << 10)
+ orig_pt_2 = fill_mod (1 << 10, 23)
+ orig_pt_3 = fill_mod (1 << 10, 42)
+ password = str (os.urandom (42))
+ encryptor = crypto.Encrypt (TEST_VERSION,
+ TEST_PARAMVERSION,
+ password=password,
+ nacl=TEST_STATIC_NACL)
+
+ def enc (pt):
+ header_dummy = encryptor.next (TEST_DUMMY_FILENAME)
+
+ off = 0
+ ct = b""
+ while off < len (pt):
+ upto = min (off + cnksiz, len (pt))
+ _n, cnk = encryptor.process (pt [off:upto])
+ ct += cnk
+ off += cnksiz
+ cnk, header, fixed = encryptor.done (header_dummy)
+ return ct + cnk, header, fixed
+
+ ct_1, hdr_1, _____ = enc (orig_pt_1)
+
+ ## Here we bump the iv of the encryptor, breaking the series.
+ encryptor.set_object_counter (encryptor.cnt + 1)
+ ct_2, hdr_2, fixed = enc (orig_pt_2)
+
+ ## IV of final object is again in-sequence.
+ ct_3, hdr_3, fixed = enc (orig_pt_3)
+
+ def decrypt (strict_ivs):
+ decryptor = crypto.Decrypt (password=password, fixedparts=fixed,
+ strict_ivs=strict_ivs)
+
+ def dec (hdr, ct):
+ decryptor.next (hdr)
+ off = 0
+ pt = b""
+ while off < len (ct):
+ upto = min (off + cnksiz, len (ct))
+ cnk = decryptor.process (ct [off:upto])
+ pt += cnk
+ off += cnksiz
+ return pt + decryptor.done ()
+
+ decr_pt_1 = dec (hdr_1, ct_1)
+ decr_pt_2 = dec (hdr_2, ct_2) ## ← good header, non-consecutive IV
+ decr_pt_3 = dec (hdr_3, ct_3)
+
+ assert decr_pt_1 == orig_pt_1
+ assert decr_pt_2 == orig_pt_2
+ assert decr_pt_3 == orig_pt_3
+
+ with self.assertRaises (crypto.NonConsecutiveIV):
+ decrypt (True)
+
+ decrypt (False) # Sequence passes
+
+
def test_crypto_aes_gcm_dec_iv_reuse (self):
"""
Meddle with encrypted content: extract the IV from one object