assert len (header) == crypto.PDTCRYPT_HDR_SIZE
+ def test_crypto_aes_gcm_enc_multi_ivs_ok_explicit_counter (self):
+ """
+ Access the list of IVs used during encryption and check reuse. Start
+ from explicit counters so the inputs don’t overlap. IVs must not have
+ been reused.
+ """
+
+ def enc (start_count, data):
+ password = str (os.urandom (42))
+ encryptor = crypto.Encrypt (TEST_VERSION,
+ TEST_PARAMVERSION,
+ password=password,
+ nacl=TEST_STATIC_NACL,
+ counter=start_count)
+
+ for i, blob in enumerate (data, 1):
+ fname = "%s_%d" % (TEST_DUMMY_FILENAME, i)
+ header_dummy = encryptor.next (fname)
+ _, _ = encryptor.process (blob)
+ _, header, _ = encryptor.done (header_dummy)
+ assert len (encryptor.get_used_ivs ()) == i
+
+ return encryptor.get_used_ivs ()
+
+ ivs1 = enc (0x0042, [TEST_PLAINTEXT, b"none of your business"])
+ ivs2 = enc (0x1337, [b"read me if you can", b"for British eyes only!"])
+
+ # No reuse in general.
+ assert len (ivs1 & ivs2) == 0
+
+ ivs1 = list (ivs1)
+ ivs2 = list (ivs2)
+
+ # Counters of used IVs must match what we passed explicitly.
+ def extract_counters (ivs):
+ def getcount (iv):
+ _, cnt = struct.unpack (crypto.FMT_I2N_IV, iv)
+ return cnt
+ return list (map (getcount, ivs))
+
+ cnt1 = extract_counters (ivs1)
+ cnt2 = extract_counters (ivs2)
+
+ assert 0x0042 in cnt1
+ assert 0x0043 in cnt1
+
+ assert 0x1337 in cnt2
+ assert 0x1338 in cnt2
+
+
def test_crypto_aes_gcm_enc_chunk_size (self):
password = str (os.urandom (42))
encryptor = crypto.Encrypt (TEST_VERSION,
return ct + cnk, header, fixed
ct_1, hdr_1, _____ = enc (orig_pt_1)
- ct_2, hdr_2, fixed = enc (orig_pt_2)
-
- mut_hdr_2 = bytearray (hdr_2)
- mut_hdr_2_vw = memoryview (mut_hdr_2)
- # get IV
- iv_lo = crypto.HDR_OFF_IV
- iv_hi = crypto.HDR_OFF_IV + crypto.PDTCRYPT_HDR_SIZE_IV
- iv_1 = hdr_1 [iv_lo : iv_hi]
- # transplant into other header
- mut_hdr_2_vw [iv_lo : iv_hi] = iv_1
- hdr_2_mod = bytes (mut_hdr_2)
- decryptor = crypto.Decrypt (password=password, fixedparts=fixed,
- strict_ivs=True)
-
- 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 ()
+ encryptor.cnt -= 1 # induce error by forcing an identical IV on next step
- decr_pt_1 = dec (hdr_1, ct_1)
- decr_pt_2 = dec (hdr_2, ct_2) # good header, different IV
- with self.assertRaises (crypto.DuplicateIV): # bad header, reuse detected
- decr_pt_2 = dec (hdr_2_mod, ct_2)
+ with self.assertRaises (crypto.DuplicateIV): # reuse detected
+ ct_2, hdr_2, fixed = enc (orig_pt_2)
class HeaderTest (CryptoLayerTest):