7 import deltatar.crypto as crypto
12 return s.encode("UTF-8")
17 TEST_PLAINTEXT = b("gentlemen don’t read each other’s mail")
18 TEST_PASSPHRASE = b"test1234"
19 TEST_AES_GCM_AAD = b"authenticated plain text"
20 TEST_DUMMY_FILENAME = "insurance-file.txt"
23 TEST_STATIC_NACL = os.urandom (CRYPTO_NACL_SIZE)
24 PLAIN_PARAMVERSION = 0
26 def faux_hdr (ctsize=1337, iv=None):
29 , "paramversion" : 2187
30 , "nacl" : binascii.unhexlify(b"0011223344556677"
32 , "iv" : iv or binascii.unhexlify(b"0011223344556677"
35 , "tag" : binascii.unhexlify(b"deadbeefbadb100d"
41 def fill_mod (n, off=0):
44 m = FILL_MOD_MEMO.get (k, None)
48 bufv = memoryview (buf)
52 struct.pack_into ("c", bufv, i, chr(c).encode("UTF-8"))
62 class CryptoLayerTest (unittest.TestCase):
66 class AESGCMTest (CryptoLayerTest):
68 os_urandom = os.urandom
71 """Reset globals altered for testing."""
72 _ = crypto._testing_set_AES_GCM_IV_CNT_MAX \
73 ("I am fully aware that this will void my warranty.")
74 _ = crypto._testing_set_PDTCRYPT_MAX_OBJ_SIZE \
75 ("I am fully aware that this will void my warranty.")
76 os.urandom = self.os_urandom
78 def test_crypto_aes_gcm_enc_ctor (self):
79 password = str (os.urandom (42))
80 encryptor = crypto.Encrypt (TEST_VERSION,
83 nacl=TEST_STATIC_NACL)
85 def test_crypto_aes_gcm_enc_ctor_bad_plainparams (self):
86 """Refuse plaintext passthrough mode by default."""
87 password = str (os.urandom (42))
88 with self.assertRaises (crypto.InvalidParameter):
89 encryptor = crypto.Encrypt (TEST_VERSION,
92 nacl=TEST_STATIC_NACL)
95 def test_crypto_aes_gcm_enc_ctor_ok_insecure_plainparams (self):
97 Comply with request for plaintext passthrough mode if the
98 *insecure* flag is passed.
100 password = str (os.urandom (42))
101 encryptor = crypto.Encrypt (TEST_VERSION,
104 nacl=TEST_STATIC_NACL,
108 def test_crypto_aes_gcm_enc_ctor_key (self):
109 key = os.urandom (42)
110 encryptor = crypto.Encrypt (TEST_VERSION,
113 nacl=TEST_STATIC_NACL)
116 def test_crypto_aes_gcm_enc_ctor_no_key_pw (self):
118 Either key (+nacl) or password must be supplied, not both.
120 with self.assertRaises (crypto.InvalidParameter): # neither key nor pw
121 encryptor = crypto.Encrypt (TEST_VERSION,
123 nacl=TEST_STATIC_NACL)
125 password = str (os.urandom (42))
126 key = os.urandom (16) # scrypt sized
127 with self.assertRaises (crypto.InvalidParameter): # both key and pw
128 encryptor = crypto.Encrypt (TEST_VERSION,
132 nacl=TEST_STATIC_NACL)
134 with self.assertRaises (crypto.InvalidParameter): # key, but salt missing
135 encryptor = crypto.Encrypt (TEST_VERSION,
140 with self.assertRaises (crypto.InvalidParameter): # empty pw
141 encryptor = crypto.Encrypt (TEST_VERSION,
144 nacl=TEST_STATIC_NACL)
147 def test_crypto_aes_gcm_enc_header_size (self):
148 password = str (os.urandom (42))
149 encryptor = crypto.Encrypt (TEST_VERSION,
152 nacl=TEST_STATIC_NACL)
154 header_dummy = encryptor.next (TEST_DUMMY_FILENAME)
155 assert len (header_dummy) == crypto.PDTCRYPT_HDR_SIZE
156 _, _ = encryptor.process (TEST_PLAINTEXT)
157 _, header, _ = encryptor.done (header_dummy)
158 assert len (header) == crypto.PDTCRYPT_HDR_SIZE
161 def test_crypto_aes_gcm_enc_chunk_size (self):
162 password = str (os.urandom (42))
163 encryptor = crypto.Encrypt (TEST_VERSION,
166 nacl=TEST_STATIC_NACL)
168 header_dummy = encryptor.next (TEST_DUMMY_FILENAME)
169 _, ciphertext = encryptor.process (TEST_PLAINTEXT)
170 assert len (ciphertext) == len (TEST_PLAINTEXT)
171 rest, header, fixed = encryptor.done (header_dummy)
172 assert len (rest) == 0
175 def test_crypto_aes_gcm_dec_ctor (self):
177 Ensure that only either key or password is accepted.
179 password = str (os.urandom (42))
180 key = os.urandom (16) # scrypt sized
182 decryptor = crypto.Decrypt (password=password)
183 decryptor = crypto.Decrypt (key=key)
185 with self.assertRaises (crypto.InvalidParameter): # both password and key
186 decryptor = crypto.Decrypt (password=password, key=key)
188 with self.assertRaises (crypto.InvalidParameter): # neither password nor key
189 decryptor = crypto.Decrypt (password=None, key=None)
191 with self.assertRaises (crypto.InvalidParameter): # # empty password
192 decryptor = crypto.Decrypt (password="")
195 def test_crypto_aes_gcm_dec_simple (self):
196 password = str (os.urandom (42))
197 encryptor = crypto.Encrypt (TEST_VERSION,
200 nacl=TEST_STATIC_NACL)
202 header_dummy = encryptor.next (TEST_DUMMY_FILENAME)
203 _, ciphertext = encryptor.process (TEST_PLAINTEXT)
204 rest, header, fixed = encryptor.done (header_dummy)
207 decryptor = crypto.Decrypt (password=password, fixedparts=fixed)
208 decryptor.next (header)
209 plaintext = decryptor.process (ciphertext)
210 rest = decryptor.done ()
213 assert plaintext == TEST_PLAINTEXT
216 def test_crypto_aes_gcm_dec_plain_bad (self):
218 Downgrade to plaintext must not be allowed in parameters
219 obtained from headers.
221 password = str (os.urandom (42))
222 encryptor = crypto.Encrypt (TEST_VERSION,
225 nacl=TEST_STATIC_NACL)
227 header_dummy = encryptor.next (TEST_DUMMY_FILENAME)
228 _, ciphertext = encryptor.process (TEST_PLAINTEXT)
229 rest, header, fixed = encryptor.done (header_dummy)
232 header = crypto.hdr_read (header)
233 header ["paramversion"] = PLAIN_PARAMVERSION
234 ok, header = crypto.hdr_make (header)
237 decryptor = crypto.Decrypt (password=password, fixedparts=fixed)
238 with self.assertRaises (crypto.InvalidParameter):
239 decryptor.next (header)
242 def test_crypto_aes_gcm_dec_plain_ok_insecure (self):
244 Allow plaintext crypto mode if *insecure* flag is passed.
246 password = str (os.urandom (42))
247 encryptor = crypto.Encrypt (TEST_VERSION,
250 nacl=TEST_STATIC_NACL,
253 header_dummy = encryptor.next (TEST_DUMMY_FILENAME)
254 _, ciphertext = encryptor.process (TEST_PLAINTEXT)
255 rest, header, fixed = encryptor.done (header_dummy)
258 header = crypto.hdr_read (header)
259 header ["paramversion"] = PLAIN_PARAMVERSION
260 ok, header = crypto.hdr_make (header)
263 decryptor = crypto.Decrypt (password=password,
266 decryptor.next (header)
267 plaintext = decryptor.process (ciphertext)
268 rest = decryptor.done ()
271 assert plaintext == TEST_PLAINTEXT
274 def test_crypto_aes_gcm_dec_bad_tag (self):
275 password = str (os.urandom (42))
276 encryptor = crypto.Encrypt (TEST_VERSION,
279 nacl=TEST_STATIC_NACL)
281 header_dummy = encryptor.next (TEST_DUMMY_FILENAME)
282 _, ciphertext = encryptor.process (TEST_PLAINTEXT)
283 ciphertext2, header, fixed = encryptor.done (header_dummy)
285 mut_header = bytearray (header)
286 mut_header_vw = memoryview (mut_header)
287 # replace one byte in the tag part of the header
288 second_byte = mut_header_vw [crypto.HDR_OFF_TAG + 2]
289 mut_header_vw [crypto.HDR_OFF_TAG + 2] = (second_byte + 0x2a) % 256
290 header = bytes (mut_header)
292 decryptor = crypto.Decrypt (password=password, fixedparts=fixed)
293 decryptor.next (header)
294 plaintext = decryptor.process (ciphertext)
295 with self.assertRaises (crypto.InvalidGCMTag):
296 _ = decryptor.done ()
299 def test_crypto_aes_gcm_enc_multicnk (self):
301 pt = fill_mod (1 << 14)
302 password = str (os.urandom (42))
303 encryptor = crypto.Encrypt (TEST_VERSION,
306 nacl=TEST_STATIC_NACL)
307 header_dummy = encryptor.next (TEST_DUMMY_FILENAME)
311 while off < len (pt):
312 upto = min (off + cnksiz, len (pt))
313 _, cnk = encryptor.process (pt [off:upto])
316 cnk, header, fixed = encryptor.done (header_dummy)
319 assert len (pt) == len (ct)
322 def test_crypto_aes_gcm_enc_multicnk_strict_ivs (self):
324 pt = fill_mod (1 << 14)
325 password = str (os.urandom (42))
326 encryptor = crypto.Encrypt (TEST_VERSION,
329 nacl=TEST_STATIC_NACL,
331 header_dummy = encryptor.next (TEST_DUMMY_FILENAME)
335 while off < len (pt):
336 upto = min (off + cnksiz, len (pt))
337 _, cnk = encryptor.process (pt [off:upto])
340 cnk, header, fixed = encryptor.done (header_dummy)
343 assert len (pt) == len (ct)
346 def test_crypto_aes_gcm_enc_multiobj (self):
348 password = str (os.urandom (42))
349 encryptor = crypto.Encrypt (TEST_VERSION,
352 nacl=TEST_STATIC_NACL,
356 pt = fill_mod (1 << 14, off=i)
357 header_dummy = encryptor.next ("%s_%d" % (TEST_DUMMY_FILENAME, i))
361 while off < len (pt):
362 upto = min (off + cnksiz, len (pt))
363 _, cnk = encryptor.process (pt [off:upto])
366 cnk, header, fixed = encryptor.done (header_dummy)
369 assert len (pt) == len (ct)
371 for i in range (5): addobj (i)
373 assert len (encryptor.fixed) == 1
376 def test_crypto_aes_gcm_enc_multiobj_strict_ivs (self):
378 password = str (os.urandom (42))
379 encryptor = crypto.Encrypt (TEST_VERSION,
382 nacl=TEST_STATIC_NACL,
384 curfixed = None # must remain constant after first
387 pt = fill_mod (1 << 14, off=i)
388 header_dummy = encryptor.next ("%s_%d" % (TEST_DUMMY_FILENAME, i))
392 while off < len (pt):
393 upto = min (off + cnksiz, len (pt))
394 _, cnk = encryptor.process (pt [off:upto])
397 cnk, header, fixed = encryptor.done (header_dummy)
402 assert fixed == curfixed
405 assert len (pt) == len (ct)
407 for i in range (5): addobj (i)
409 assert len (encryptor.fixed) == 1
412 def test_crypto_aes_gcm_enc_multiobj_cnt_wrap (self):
414 Test behavior when the file counter tops out.
416 Artificially lower the maximum possible file counter. Considering
417 invalid (0) and reserved (1, 2) values, the smallest possible file counter
418 for normal objects is 3. Starting from that, the header of the (max -
419 3)rd object must have both a different IV fixed part and a counter.
423 crypto._testing_set_AES_GCM_IV_CNT_MAX \
424 ("I am fully aware that this will void my warranty.", new_max)
426 password = str (os.urandom (42))
427 encryptor = crypto.Encrypt (TEST_VERSION,
430 nacl=TEST_STATIC_NACL,
436 def addobj (i, wrap=False):
439 pt = fill_mod (1 << 14, off=i)
440 header_dummy = encryptor.next ("%s_%d" % (TEST_DUMMY_FILENAME, i))
444 while off < len (pt):
445 upto = min (off + cnksiz, len (pt))
446 _, cnk = encryptor.process (pt [off:upto])
449 cnk, header, fixed = encryptor.done (header_dummy)
450 this_iv = crypto.hdr_read (header) ["iv"]
451 if last_iv is not None:
452 this_fixed, this_cnt = struct.unpack (crypto.FMT_I2N_IV, this_iv)
453 last_fixed, last_cnt = struct.unpack (crypto.FMT_I2N_IV, last_iv)
455 assert last_fixed == this_fixed
456 assert last_cnt == this_cnt - 1
458 assert last_fixed != this_fixed
459 assert this_cnt == minimum
463 assert len (pt) == len (ct)
465 for i in range (minimum, new_max + 1): addobj (i) # counter range: [3, 8]
466 addobj (i + 1, True) # counter wraps to 3
468 for j in range (i + 2, i + new_max - 1): addobj (j) # counter range: [4, 8]
469 addobj (j + 1, True) # counter wraps to 3 again
471 assert len (encryptor.fixed) == 3
474 def test_crypto_aes_gcm_enc_multiobj_cnt_wrap_badfixed (self):
476 Test behavior when the file counter tops out and the transition to
477 the next IV fixed part fails on account of a bad random generator.
479 Replaces the ``urandom`` reference in ``os`` with a deterministic
480 function. The encryptor context must communicate this condition with an
481 ``IVFixedPartError``.
485 crypto._testing_set_AES_GCM_IV_CNT_MAX \
486 ("I am fully aware that this will void my warranty.", new_max)
488 os.urandom = lambda n: bytes (bytearray ([n % 256] * n))
489 password = str (os.urandom (42))
490 encryptor = crypto.Encrypt (TEST_VERSION,
493 nacl=TEST_STATIC_NACL,
497 pt = fill_mod (1 << 14, off=i)
498 header_dummy = encryptor.next ("%s_%d" % (TEST_DUMMY_FILENAME, i))
501 while off < len (pt):
502 upto = min (off + cnksiz, len (pt))
503 _, cnk = encryptor.process (pt [off:upto])
506 for i in range (minimum, new_max): addobj (42 + i)
508 with self.assertRaises (crypto.IVFixedPartError):
513 def test_crypto_aes_gcm_enc_length_cap (self):
515 Artificially lower the maximum allowable data length and attempt to
516 encrypt a larger object. Verify that the crypto handler only encrypts
517 data up to the size limit. A downstream user detects that condition by
518 testing whether the encryption step yielded less bytes than the
521 The sibling to this test is test_restore_backup_max_file_length()
522 in test_delatar.py. Deltatar will transparently create a splitted object
523 with an increased IV file counter.
526 crypto._testing_set_PDTCRYPT_MAX_OBJ_SIZE \
527 ("I am fully aware that this will void my warranty.", new_max)
529 password = str (os.urandom (42))
530 encryptor = crypto.Encrypt (TEST_VERSION,
533 nacl=TEST_STATIC_NACL)
536 pt, ct = fill_mod (s), None
537 header_dummy = encryptor.next ("%s_%d" % (TEST_DUMMY_FILENAME, s))
539 n, ct = encryptor.process (pt)
540 rest, _, _ = encryptor.done (header_dummy)
542 # NB: If this check *ever* fails, then something changed in the
543 # encoding layer. AES-GCM is a stream cipher so each encoding
544 # step will yield the exact number of ciphertext bytes that
545 # was provided as plaintext. Thus there cannot be any encoded
546 # data left when calling the finalizers. None of the crypo code
547 # depends on that assumption but nevertheless we check it here
548 # in case anything changes upstream in the Cryptography
549 # library. In case there actually is a rest, replace the
550 # assertion below with ``ct += rest``.
551 assert (len (rest) == 0)
553 if len (pt) > new_max:
554 # If the plaintext was longer than the artificially lowered
555 # maximum, then the number of ciphertext bytes must be clamped
559 assert n == len (pt) == len (ct)
561 for i in range (16): encobj (1 << i)
564 def test_crypto_aes_gcm_dec_length_cap (self):
566 The decryptor must reject headers with an object size that exceeds
567 the PDTCRYPT maximum. Longer files split into multiple objects.
569 password = str (os.urandom (42))
571 meta ["ctsize"] = crypto.PDTCRYPT_MAX_OBJ_SIZE + 1
572 ok, header = crypto.hdr_make (meta)
576 # Set up decryption with bogus header.
577 decryptor = crypto.Decrypt (password=password, fixedparts=[])
579 with self.assertRaises (crypto.InvalidHeader):
580 decryptor.next (header)
583 def test_crypto_aes_gcm_dec_length_mismatch (self):
585 Catch attempts at decrypting more data than what was stated in the
589 orig_pt = fill_mod (1 << 14)
590 password = str (os.urandom (42))
591 encryptor = crypto.Encrypt (TEST_VERSION,
594 nacl=TEST_STATIC_NACL)
595 header_dummy = encryptor.next (TEST_DUMMY_FILENAME)
599 while off < len (orig_pt):
600 upto = min (off + cnksiz, len (orig_pt))
601 _n, cnk = encryptor.process (orig_pt [off:upto])
604 cnk, header, fixed = encryptor.done (header_dummy)
607 decryptor = crypto.Decrypt (password=password, fixedparts=fixed)
609 decryptor.next (header)
612 while off < len (orig_pt):
613 upto = min (off + cnksiz, len (orig_pt))
614 cnk = decryptor.process (ct [off:upto])
618 with self.assertRaises (crypto.CiphertextTooLong):
619 # Try and decrypt one byte more than was encrypted.
620 # This must be caught in crypto.py.
621 _ = decryptor.process (ct [0:1])
624 def test_crypto_aes_gcm_dec_multicnk (self):
626 orig_pt = fill_mod (1 << 14)
627 password = str (os.urandom (42))
628 encryptor = crypto.Encrypt (TEST_VERSION,
631 nacl=TEST_STATIC_NACL)
632 header_dummy = encryptor.next (TEST_DUMMY_FILENAME)
636 while off < len (orig_pt):
637 upto = min (off + cnksiz, len (orig_pt))
638 _n, cnk = encryptor.process (orig_pt [off:upto])
641 cnk, header, fixed = encryptor.done (header_dummy)
644 decryptor = crypto.Decrypt (password=password,
646 decryptor.next (header)
649 while off < len (orig_pt):
650 upto = min (off + cnksiz, len (orig_pt))
651 cnk = decryptor.process (ct [off:upto])
656 pt += decryptor.done ()
660 def test_crypto_aes_gcm_dec_multicnk_bad_tag (self):
662 orig_pt = fill_mod (1 << 14)
663 password = str (os.urandom (42))
664 encryptor = crypto.Encrypt (TEST_VERSION,
667 nacl=TEST_STATIC_NACL)
668 header_dummy = encryptor.next (TEST_DUMMY_FILENAME)
672 while off < len (orig_pt):
673 upto = min (off + cnksiz, len (orig_pt))
674 _n, cnk = encryptor.process (orig_pt [off:upto])
677 cnk, header, fixed = encryptor.done (header_dummy)
680 mut_header = bytearray (header)
681 mut_header_vw = memoryview (mut_header)
682 # replace one byte in the tag part of the header
683 second_byte = mut_header_vw [crypto.HDR_OFF_TAG + 2]
684 mut_header_vw [crypto.HDR_OFF_TAG + 2] = (second_byte + 0x2a) % 256
685 header = bytes (mut_header)
687 decryptor = crypto.Decrypt (password=password,
689 decryptor.next (header)
692 while off < len (orig_pt):
693 upto = min (off + cnksiz, len (orig_pt))
694 cnk = decryptor.process (ct [off:upto])
698 with self.assertRaises (crypto.InvalidGCMTag):
699 _ = decryptor.done ()
702 def test_crypto_aes_gcm_dec_iv_gap (self):
704 Encrypt multiple objects using non-consecutive IVs and verify that the
705 decryptor errors out with an exception in strict mode but keeps quiet
709 orig_pt_1 = fill_mod (1 << 10)
710 orig_pt_2 = fill_mod (1 << 10, 23)
711 orig_pt_3 = fill_mod (1 << 10, 42)
712 password = str (os.urandom (42))
713 encryptor = crypto.Encrypt (TEST_VERSION,
716 nacl=TEST_STATIC_NACL)
719 header_dummy = encryptor.next (TEST_DUMMY_FILENAME)
723 while off < len (pt):
724 upto = min (off + cnksiz, len (pt))
725 _n, cnk = encryptor.process (pt [off:upto])
728 cnk, header, fixed = encryptor.done (header_dummy)
729 return ct + cnk, header, fixed
731 ct_1, hdr_1, _____ = enc (orig_pt_1)
733 ## Here we bump the iv of the encryptor, breaking the series.
734 encryptor.set_object_counter (encryptor.cnt + 1)
735 ct_2, hdr_2, fixed = enc (orig_pt_2)
737 ## IV of final object is again in-sequence.
738 ct_3, hdr_3, fixed = enc (orig_pt_3)
740 def decrypt (strict_ivs):
741 decryptor = crypto.Decrypt (password=password, fixedparts=fixed,
742 strict_ivs=strict_ivs)
748 while off < len (ct):
749 upto = min (off + cnksiz, len (ct))
750 cnk = decryptor.process (ct [off:upto])
753 return pt + decryptor.done ()
755 decr_pt_1 = dec (hdr_1, ct_1)
756 decr_pt_2 = dec (hdr_2, ct_2) ## ← good header, non-consecutive IV
757 decr_pt_3 = dec (hdr_3, ct_3)
759 assert decr_pt_1 == orig_pt_1
760 assert decr_pt_2 == orig_pt_2
761 assert decr_pt_3 == orig_pt_3
763 with self.assertRaises (crypto.NonConsecutiveIV):
766 decrypt (False) # Sequence passes
769 def test_crypto_aes_gcm_dec_iv_reuse (self):
771 Meddle with encrypted content: extract the IV from one object
772 and inject it into the header of another. This must be rejected
776 orig_pt_1 = fill_mod (1 << 10)
777 orig_pt_2 = fill_mod (1 << 10, 42)
778 password = str (os.urandom (42))
779 encryptor = crypto.Encrypt (TEST_VERSION,
782 nacl=TEST_STATIC_NACL)
785 header_dummy = encryptor.next (TEST_DUMMY_FILENAME)
789 while off < len (pt):
790 upto = min (off + cnksiz, len (pt))
791 _n, cnk = encryptor.process (pt [off:upto])
794 cnk, header, fixed = encryptor.done (header_dummy)
795 return ct + cnk, header, fixed
797 ct_1, hdr_1, _____ = enc (orig_pt_1)
798 ct_2, hdr_2, fixed = enc (orig_pt_2)
800 mut_hdr_2 = bytearray (hdr_2)
801 mut_hdr_2_vw = memoryview (mut_hdr_2)
803 iv_lo = crypto.HDR_OFF_IV
804 iv_hi = crypto.HDR_OFF_IV + crypto.PDTCRYPT_HDR_SIZE_IV
805 iv_1 = hdr_1 [iv_lo : iv_hi]
806 # transplant into other header
807 mut_hdr_2_vw [iv_lo : iv_hi] = iv_1
808 hdr_2_mod = bytes (mut_hdr_2)
809 decryptor = crypto.Decrypt (password=password, fixedparts=fixed,
816 while off < len (ct):
817 upto = min (off + cnksiz, len (ct))
818 cnk = decryptor.process (ct [off:upto])
821 return pt + decryptor.done ()
823 decr_pt_1 = dec (hdr_1, ct_1)
824 decr_pt_2 = dec (hdr_2, ct_2) # good header, different IV
825 with self.assertRaises (crypto.DuplicateIV): # bad header, reuse detected
826 decr_pt_2 = dec (hdr_2_mod, ct_2)
829 class HeaderTest (CryptoLayerTest):
831 def test_crypto_fmt_hdr_make (self):
833 ok, hdr = crypto.hdr_make (meta)
835 assert len (hdr) == crypto.PDTCRYPT_HDR_SIZE
838 def test_crypto_fmt_hdr_make_useless (self):
839 ok, ret = crypto.hdr_make ({ 42: "x" })
841 assert ret.startswith ("error assembling header:")
844 def test_crypto_fmt_hdr_read (self):
846 ok, hdr = crypto.hdr_make (meta)
848 assert hdr is not None
849 mmeta = crypto.hdr_read (hdr)
850 assert mmeta is not None
852 if meta [k] != mmeta [k]:
853 raise "header mismatch after reading: expected %r, got %r" \
854 % (meta [k], mmeta [k])
857 def test_crypto_fmt_hdr_read_trailing_garbage (self):
859 ok, hdr = crypto.hdr_make (meta)
860 ok, hdr = crypto.hdr_make (meta)
862 assert hdr is not None
864 with self.assertRaises (crypto.InvalidHeader):
865 _ = crypto.hdr_read (hdr)
868 def test_crypto_fmt_hdr_read_leading_garbage (self):
870 ok, hdr = crypto.hdr_make (meta)
871 ok, hdr = crypto.hdr_make (meta)
873 assert hdr is not None
875 with self.assertRaises (crypto.InvalidHeader):
876 _ = crypto.hdr_read (hdr)
879 def test_crypto_fmt_hdr_inner_garbage (self):
881 ok, hdr = crypto.hdr_make (meta)
883 data = hdr[:len(hdr)//2] + b"junk-" + hdr[len(hdr)//2:]
884 with self.assertRaises (crypto.InvalidHeader):
885 _ = crypto.hdr_read (data)