1# Copyright 2017 Donald Stufft and individual contributors
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14from typing import Optional
15
16from nacl import exceptions as exc
17from nacl._sodium import ffi, lib
18from nacl.exceptions import ensure
19
20"""
21Implementations of authenticated encription with associated data (*AEAD*)
22constructions building on the chacha20 stream cipher and the poly1305
23authenticator
24"""
25
26crypto_aead_chacha20poly1305_ietf_KEYBYTES: int = (
27 lib.crypto_aead_chacha20poly1305_ietf_keybytes()
28)
29crypto_aead_chacha20poly1305_ietf_NSECBYTES: int = (
30 lib.crypto_aead_chacha20poly1305_ietf_nsecbytes()
31)
32crypto_aead_chacha20poly1305_ietf_NPUBBYTES: int = (
33 lib.crypto_aead_chacha20poly1305_ietf_npubbytes()
34)
35crypto_aead_chacha20poly1305_ietf_ABYTES: int = (
36 lib.crypto_aead_chacha20poly1305_ietf_abytes()
37)
38crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX: int = (
39 lib.crypto_aead_chacha20poly1305_ietf_messagebytes_max()
40)
41_aead_chacha20poly1305_ietf_CRYPTBYTES_MAX = (
42 crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX
43 + crypto_aead_chacha20poly1305_ietf_ABYTES
44)
45
46crypto_aead_chacha20poly1305_KEYBYTES: int = (
47 lib.crypto_aead_chacha20poly1305_keybytes()
48)
49crypto_aead_chacha20poly1305_NSECBYTES: int = (
50 lib.crypto_aead_chacha20poly1305_nsecbytes()
51)
52crypto_aead_chacha20poly1305_NPUBBYTES: int = (
53 lib.crypto_aead_chacha20poly1305_npubbytes()
54)
55crypto_aead_chacha20poly1305_ABYTES: int = (
56 lib.crypto_aead_chacha20poly1305_abytes()
57)
58crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX: int = (
59 lib.crypto_aead_chacha20poly1305_messagebytes_max()
60)
61_aead_chacha20poly1305_CRYPTBYTES_MAX = (
62 crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX
63 + crypto_aead_chacha20poly1305_ABYTES
64)
65
66crypto_aead_xchacha20poly1305_ietf_KEYBYTES: int = (
67 lib.crypto_aead_xchacha20poly1305_ietf_keybytes()
68)
69crypto_aead_xchacha20poly1305_ietf_NSECBYTES: int = (
70 lib.crypto_aead_xchacha20poly1305_ietf_nsecbytes()
71)
72crypto_aead_xchacha20poly1305_ietf_NPUBBYTES: int = (
73 lib.crypto_aead_xchacha20poly1305_ietf_npubbytes()
74)
75crypto_aead_xchacha20poly1305_ietf_ABYTES: int = (
76 lib.crypto_aead_xchacha20poly1305_ietf_abytes()
77)
78crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX: int = (
79 lib.crypto_aead_xchacha20poly1305_ietf_messagebytes_max()
80)
81_aead_xchacha20poly1305_ietf_CRYPTBYTES_MAX = (
82 crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX
83 + crypto_aead_xchacha20poly1305_ietf_ABYTES
84)
85
86crypto_aead_aegis256_KEYBYTES: int = lib.crypto_aead_aegis256_keybytes()
87crypto_aead_aegis256_NSECBYTES: int = lib.crypto_aead_aegis256_nsecbytes()
88crypto_aead_aegis256_NPUBBYTES: int = lib.crypto_aead_aegis256_npubbytes()
89crypto_aead_aegis256_ABYTES: int = lib.crypto_aead_aegis256_abytes()
90crypto_aead_aegis256_MESSAGEBYTES_MAX: int = (
91 lib.crypto_aead_aegis256_messagebytes_max()
92)
93_aead_aegis256_CRYPTBYTES_MAX = (
94 crypto_aead_aegis256_MESSAGEBYTES_MAX + crypto_aead_aegis256_ABYTES
95)
96
97crypto_aead_aegis128l_KEYBYTES: int = lib.crypto_aead_aegis128l_keybytes()
98crypto_aead_aegis128l_NSECBYTES: int = lib.crypto_aead_aegis128l_nsecbytes()
99crypto_aead_aegis128l_NPUBBYTES: int = lib.crypto_aead_aegis128l_npubbytes()
100crypto_aead_aegis128l_ABYTES: int = lib.crypto_aead_aegis128l_abytes()
101crypto_aead_aegis128l_MESSAGEBYTES_MAX: int = (
102 lib.crypto_aead_aegis128l_messagebytes_max()
103)
104_aead_aegis256_CRYPTBYTES_MAX = (
105 crypto_aead_aegis128l_MESSAGEBYTES_MAX + crypto_aead_aegis128l_ABYTES
106)
107
108crypto_aead_aes256gcm_KEYBYTES: int = lib.crypto_aead_aes256gcm_keybytes()
109crypto_aead_aes256gcm_NSECBYTES: int = lib.crypto_aead_aes256gcm_nsecbytes()
110crypto_aead_aes256gcm_NPUBBYTES: int = lib.crypto_aead_aes256gcm_npubbytes()
111crypto_aead_aes256gcm_ABYTES: int = lib.crypto_aead_aes256gcm_abytes()
112crypto_aead_aes256gcm_MESSAGEBYTES_MAX: int = (
113 lib.crypto_aead_aes256gcm_messagebytes_max()
114)
115_aead_aegis256_CRYPTBYTES_MAX = (
116 crypto_aead_aes256gcm_MESSAGEBYTES_MAX + crypto_aead_aes256gcm_ABYTES
117)
118
119
120def crypto_aead_chacha20poly1305_ietf_encrypt(
121 message: bytes, aad: Optional[bytes], nonce: bytes, key: bytes
122) -> bytes:
123 """
124 Encrypt the given ``message`` using the IETF ratified chacha20poly1305
125 construction described in RFC7539.
126
127 :param message:
128 :type message: bytes
129 :param aad:
130 :type aad: Optional[bytes]
131 :param nonce:
132 :type nonce: bytes
133 :param key:
134 :type key: bytes
135 :return: authenticated ciphertext
136 :rtype: bytes
137 """
138 ensure(
139 isinstance(message, bytes),
140 "Input message type must be bytes",
141 raising=exc.TypeError,
142 )
143
144 mlen = len(message)
145
146 ensure(
147 mlen <= crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX,
148 "Message must be at most {} bytes long".format(
149 crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX
150 ),
151 raising=exc.ValueError,
152 )
153
154 ensure(
155 isinstance(aad, bytes) or (aad is None),
156 "Additional data must be bytes or None",
157 raising=exc.TypeError,
158 )
159
160 ensure(
161 isinstance(nonce, bytes)
162 and len(nonce) == crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
163 "Nonce must be a {} bytes long bytes sequence".format(
164 crypto_aead_chacha20poly1305_ietf_NPUBBYTES
165 ),
166 raising=exc.TypeError,
167 )
168
169 ensure(
170 isinstance(key, bytes)
171 and len(key) == crypto_aead_chacha20poly1305_ietf_KEYBYTES,
172 "Key must be a {} bytes long bytes sequence".format(
173 crypto_aead_chacha20poly1305_ietf_KEYBYTES
174 ),
175 raising=exc.TypeError,
176 )
177
178 if aad:
179 _aad = aad
180 aalen = len(aad)
181 else:
182 _aad = ffi.NULL
183 aalen = 0
184
185 mxout = mlen + crypto_aead_chacha20poly1305_ietf_ABYTES
186
187 clen = ffi.new("unsigned long long *")
188
189 ciphertext = ffi.new("unsigned char[]", mxout)
190
191 res = lib.crypto_aead_chacha20poly1305_ietf_encrypt(
192 ciphertext, clen, message, mlen, _aad, aalen, ffi.NULL, nonce, key
193 )
194
195 ensure(res == 0, "Encryption failed.", raising=exc.CryptoError)
196 return ffi.buffer(ciphertext, clen[0])[:]
197
198
199def crypto_aead_chacha20poly1305_ietf_decrypt(
200 ciphertext: bytes, aad: Optional[bytes], nonce: bytes, key: bytes
201) -> bytes:
202 """
203 Decrypt the given ``ciphertext`` using the IETF ratified chacha20poly1305
204 construction described in RFC7539.
205
206 :param ciphertext:
207 :type ciphertext: bytes
208 :param aad:
209 :type aad: Optional[bytes]
210 :param nonce:
211 :type nonce: bytes
212 :param key:
213 :type key: bytes
214 :return: message
215 :rtype: bytes
216 """
217 ensure(
218 isinstance(ciphertext, bytes),
219 "Input ciphertext type must be bytes",
220 raising=exc.TypeError,
221 )
222
223 clen = len(ciphertext)
224
225 ensure(
226 clen <= _aead_chacha20poly1305_ietf_CRYPTBYTES_MAX,
227 "Ciphertext must be at most {} bytes long".format(
228 _aead_chacha20poly1305_ietf_CRYPTBYTES_MAX
229 ),
230 raising=exc.ValueError,
231 )
232
233 ensure(
234 isinstance(aad, bytes) or (aad is None),
235 "Additional data must be bytes or None",
236 raising=exc.TypeError,
237 )
238
239 ensure(
240 isinstance(nonce, bytes)
241 and len(nonce) == crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
242 "Nonce must be a {} bytes long bytes sequence".format(
243 crypto_aead_chacha20poly1305_ietf_NPUBBYTES
244 ),
245 raising=exc.TypeError,
246 )
247
248 ensure(
249 isinstance(key, bytes)
250 and len(key) == crypto_aead_chacha20poly1305_ietf_KEYBYTES,
251 "Key must be a {} bytes long bytes sequence".format(
252 crypto_aead_chacha20poly1305_ietf_KEYBYTES
253 ),
254 raising=exc.TypeError,
255 )
256
257 mxout = clen - crypto_aead_chacha20poly1305_ietf_ABYTES
258
259 mlen = ffi.new("unsigned long long *")
260 message = ffi.new("unsigned char[]", mxout)
261
262 if aad:
263 _aad = aad
264 aalen = len(aad)
265 else:
266 _aad = ffi.NULL
267 aalen = 0
268
269 res = lib.crypto_aead_chacha20poly1305_ietf_decrypt(
270 message, mlen, ffi.NULL, ciphertext, clen, _aad, aalen, nonce, key
271 )
272
273 ensure(res == 0, "Decryption failed.", raising=exc.CryptoError)
274
275 return ffi.buffer(message, mlen[0])[:]
276
277
278def crypto_aead_chacha20poly1305_encrypt(
279 message: bytes, aad: Optional[bytes], nonce: bytes, key: bytes
280) -> bytes:
281 """
282 Encrypt the given ``message`` using the "legacy" construction
283 described in draft-agl-tls-chacha20poly1305.
284
285 :param message:
286 :type message: bytes
287 :param aad:
288 :type aad: Optional[bytes]
289 :param nonce:
290 :type nonce: bytes
291 :param key:
292 :type key: bytes
293 :return: authenticated ciphertext
294 :rtype: bytes
295 """
296 ensure(
297 isinstance(message, bytes),
298 "Input message type must be bytes",
299 raising=exc.TypeError,
300 )
301
302 mlen = len(message)
303
304 ensure(
305 mlen <= crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX,
306 "Message must be at most {} bytes long".format(
307 crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX
308 ),
309 raising=exc.ValueError,
310 )
311
312 ensure(
313 isinstance(aad, bytes) or (aad is None),
314 "Additional data must be bytes or None",
315 raising=exc.TypeError,
316 )
317
318 ensure(
319 isinstance(nonce, bytes)
320 and len(nonce) == crypto_aead_chacha20poly1305_NPUBBYTES,
321 "Nonce must be a {} bytes long bytes sequence".format(
322 crypto_aead_chacha20poly1305_NPUBBYTES
323 ),
324 raising=exc.TypeError,
325 )
326
327 ensure(
328 isinstance(key, bytes)
329 and len(key) == crypto_aead_chacha20poly1305_KEYBYTES,
330 "Key must be a {} bytes long bytes sequence".format(
331 crypto_aead_chacha20poly1305_KEYBYTES
332 ),
333 raising=exc.TypeError,
334 )
335
336 if aad:
337 _aad = aad
338 aalen = len(aad)
339 else:
340 _aad = ffi.NULL
341 aalen = 0
342
343 mxout = mlen + crypto_aead_chacha20poly1305_ietf_ABYTES
344
345 clen = ffi.new("unsigned long long *")
346
347 ciphertext = ffi.new("unsigned char[]", mxout)
348
349 res = lib.crypto_aead_chacha20poly1305_encrypt(
350 ciphertext, clen, message, mlen, _aad, aalen, ffi.NULL, nonce, key
351 )
352
353 ensure(res == 0, "Encryption failed.", raising=exc.CryptoError)
354 return ffi.buffer(ciphertext, clen[0])[:]
355
356
357def crypto_aead_chacha20poly1305_decrypt(
358 ciphertext: bytes, aad: Optional[bytes], nonce: bytes, key: bytes
359) -> bytes:
360 """
361 Decrypt the given ``ciphertext`` using the "legacy" construction
362 described in draft-agl-tls-chacha20poly1305.
363
364 :param ciphertext: authenticated ciphertext
365 :type ciphertext: bytes
366 :param aad:
367 :type aad: Optional[bytes]
368 :param nonce:
369 :type nonce: bytes
370 :param key:
371 :type key: bytes
372 :return: message
373 :rtype: bytes
374 """
375 ensure(
376 isinstance(ciphertext, bytes),
377 "Input ciphertext type must be bytes",
378 raising=exc.TypeError,
379 )
380
381 clen = len(ciphertext)
382
383 ensure(
384 clen <= _aead_chacha20poly1305_CRYPTBYTES_MAX,
385 "Ciphertext must be at most {} bytes long".format(
386 _aead_chacha20poly1305_CRYPTBYTES_MAX
387 ),
388 raising=exc.ValueError,
389 )
390
391 ensure(
392 isinstance(aad, bytes) or (aad is None),
393 "Additional data must be bytes or None",
394 raising=exc.TypeError,
395 )
396
397 ensure(
398 isinstance(nonce, bytes)
399 and len(nonce) == crypto_aead_chacha20poly1305_NPUBBYTES,
400 "Nonce must be a {} bytes long bytes sequence".format(
401 crypto_aead_chacha20poly1305_NPUBBYTES
402 ),
403 raising=exc.TypeError,
404 )
405
406 ensure(
407 isinstance(key, bytes)
408 and len(key) == crypto_aead_chacha20poly1305_KEYBYTES,
409 "Key must be a {} bytes long bytes sequence".format(
410 crypto_aead_chacha20poly1305_KEYBYTES
411 ),
412 raising=exc.TypeError,
413 )
414
415 mxout = clen - crypto_aead_chacha20poly1305_ABYTES
416
417 mlen = ffi.new("unsigned long long *")
418 message = ffi.new("unsigned char[]", mxout)
419
420 if aad:
421 _aad = aad
422 aalen = len(aad)
423 else:
424 _aad = ffi.NULL
425 aalen = 0
426
427 res = lib.crypto_aead_chacha20poly1305_decrypt(
428 message, mlen, ffi.NULL, ciphertext, clen, _aad, aalen, nonce, key
429 )
430
431 ensure(res == 0, "Decryption failed.", raising=exc.CryptoError)
432
433 return ffi.buffer(message, mlen[0])[:]
434
435
436def crypto_aead_xchacha20poly1305_ietf_encrypt(
437 message: bytes, aad: Optional[bytes], nonce: bytes, key: bytes
438) -> bytes:
439 """
440 Encrypt the given ``message`` using the long-nonces xchacha20poly1305
441 construction.
442
443 :param message:
444 :type message: bytes
445 :param aad:
446 :type aad: Optional[bytes]
447 :param nonce:
448 :type nonce: bytes
449 :param key:
450 :type key: bytes
451 :return: authenticated ciphertext
452 :rtype: bytes
453 """
454 ensure(
455 isinstance(message, bytes),
456 "Input message type must be bytes",
457 raising=exc.TypeError,
458 )
459
460 mlen = len(message)
461
462 ensure(
463 mlen <= crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX,
464 "Message must be at most {} bytes long".format(
465 crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX
466 ),
467 raising=exc.ValueError,
468 )
469
470 ensure(
471 isinstance(aad, bytes) or (aad is None),
472 "Additional data must be bytes or None",
473 raising=exc.TypeError,
474 )
475
476 ensure(
477 isinstance(nonce, bytes)
478 and len(nonce) == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
479 "Nonce must be a {} bytes long bytes sequence".format(
480 crypto_aead_xchacha20poly1305_ietf_NPUBBYTES
481 ),
482 raising=exc.TypeError,
483 )
484
485 ensure(
486 isinstance(key, bytes)
487 and len(key) == crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
488 "Key must be a {} bytes long bytes sequence".format(
489 crypto_aead_xchacha20poly1305_ietf_KEYBYTES
490 ),
491 raising=exc.TypeError,
492 )
493
494 if aad:
495 _aad = aad
496 aalen = len(aad)
497 else:
498 _aad = ffi.NULL
499 aalen = 0
500
501 mxout = mlen + crypto_aead_xchacha20poly1305_ietf_ABYTES
502
503 clen = ffi.new("unsigned long long *")
504
505 ciphertext = ffi.new("unsigned char[]", mxout)
506
507 res = lib.crypto_aead_xchacha20poly1305_ietf_encrypt(
508 ciphertext, clen, message, mlen, _aad, aalen, ffi.NULL, nonce, key
509 )
510
511 ensure(res == 0, "Encryption failed.", raising=exc.CryptoError)
512 return ffi.buffer(ciphertext, clen[0])[:]
513
514
515def crypto_aead_xchacha20poly1305_ietf_decrypt(
516 ciphertext: bytes, aad: Optional[bytes], nonce: bytes, key: bytes
517) -> bytes:
518 """
519 Decrypt the given ``ciphertext`` using the long-nonces xchacha20poly1305
520 construction.
521
522 :param ciphertext: authenticated ciphertext
523 :type ciphertext: bytes
524 :param aad:
525 :type aad: Optional[bytes]
526 :param nonce:
527 :type nonce: bytes
528 :param key:
529 :type key: bytes
530 :return: message
531 :rtype: bytes
532 """
533 ensure(
534 isinstance(ciphertext, bytes),
535 "Input ciphertext type must be bytes",
536 raising=exc.TypeError,
537 )
538
539 clen = len(ciphertext)
540
541 ensure(
542 clen <= _aead_xchacha20poly1305_ietf_CRYPTBYTES_MAX,
543 "Ciphertext must be at most {} bytes long".format(
544 _aead_xchacha20poly1305_ietf_CRYPTBYTES_MAX
545 ),
546 raising=exc.ValueError,
547 )
548
549 ensure(
550 isinstance(aad, bytes) or (aad is None),
551 "Additional data must be bytes or None",
552 raising=exc.TypeError,
553 )
554
555 ensure(
556 isinstance(nonce, bytes)
557 and len(nonce) == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
558 "Nonce must be a {} bytes long bytes sequence".format(
559 crypto_aead_xchacha20poly1305_ietf_NPUBBYTES
560 ),
561 raising=exc.TypeError,
562 )
563
564 ensure(
565 isinstance(key, bytes)
566 and len(key) == crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
567 "Key must be a {} bytes long bytes sequence".format(
568 crypto_aead_xchacha20poly1305_ietf_KEYBYTES
569 ),
570 raising=exc.TypeError,
571 )
572
573 mxout = clen - crypto_aead_xchacha20poly1305_ietf_ABYTES
574 mlen = ffi.new("unsigned long long *")
575 message = ffi.new("unsigned char[]", mxout)
576
577 if aad:
578 _aad = aad
579 aalen = len(aad)
580 else:
581 _aad = ffi.NULL
582 aalen = 0
583
584 res = lib.crypto_aead_xchacha20poly1305_ietf_decrypt(
585 message, mlen, ffi.NULL, ciphertext, clen, _aad, aalen, nonce, key
586 )
587
588 ensure(res == 0, "Decryption failed.", raising=exc.CryptoError)
589
590 return ffi.buffer(message, mlen[0])[:]
591
592
593def crypto_aead_aegis256_encrypt(
594 message: bytes, aad: Optional[bytes], nonce: bytes, key: bytes
595) -> bytes:
596 """
597 Encrypt the given ``message`` using the AEGIS-256
598 construction.
599
600 :param message:
601 :type message: bytes
602 :param aad:
603 :type aad: Optional[bytes]
604 :param nonce:
605 :type nonce: bytes
606 :param key:
607 :type key: bytes
608 :return: authenticated ciphertext
609 :rtype: bytes
610 """
611 ensure(
612 isinstance(message, bytes),
613 "Input message type must be bytes",
614 raising=exc.TypeError,
615 )
616
617 mlen = len(message)
618
619 ensure(
620 mlen <= crypto_aead_aegis256_MESSAGEBYTES_MAX,
621 "Message must be at most {} bytes long".format(
622 crypto_aead_aegis256_MESSAGEBYTES_MAX
623 ),
624 raising=exc.ValueError,
625 )
626
627 ensure(
628 isinstance(aad, bytes) or (aad is None),
629 "Additional data must be bytes or None",
630 raising=exc.TypeError,
631 )
632
633 ensure(
634 isinstance(nonce, bytes)
635 and len(nonce) == crypto_aead_aegis256_NPUBBYTES,
636 "Nonce must be a {} bytes long bytes sequence".format(
637 crypto_aead_aegis256_NPUBBYTES
638 ),
639 raising=exc.TypeError,
640 )
641
642 ensure(
643 isinstance(key, bytes) and len(key) == crypto_aead_aegis256_KEYBYTES,
644 "Key must be a {} bytes long bytes sequence".format(
645 crypto_aead_aegis256_KEYBYTES
646 ),
647 raising=exc.TypeError,
648 )
649
650 if aad:
651 _aad = aad
652 aalen = len(aad)
653 else:
654 _aad = ffi.NULL
655 aalen = 0
656
657 mxout = mlen + crypto_aead_aegis256_ABYTES
658
659 clen = ffi.new("unsigned long long *")
660
661 ciphertext = ffi.new("unsigned char[]", mxout)
662
663 res = lib.crypto_aead_aegis256_encrypt(
664 ciphertext, clen, message, mlen, _aad, aalen, ffi.NULL, nonce, key
665 )
666
667 ensure(res == 0, "Encryption failed.", raising=exc.CryptoError)
668 return ffi.buffer(ciphertext, clen[0])[:]
669
670
671def crypto_aead_aegis256_decrypt(
672 ciphertext: bytes, aad: Optional[bytes], nonce: bytes, key: bytes
673) -> bytes:
674 """
675 Decrypt the given ``ciphertext`` using the AEGIS-256
676 construction.
677
678 :param ciphertext: authenticated ciphertext
679 :type ciphertext: bytes
680 :param aad:
681 :type aad: Optional[bytes]
682 :param nonce:
683 :type nonce: bytes
684 :param key:
685 :type key: bytes
686 :return: message
687 :rtype: bytes
688 """
689 ensure(
690 isinstance(ciphertext, bytes),
691 "Input ciphertext type must be bytes",
692 raising=exc.TypeError,
693 )
694
695 clen = len(ciphertext)
696
697 ensure(
698 clen <= _aead_aegis256_CRYPTBYTES_MAX,
699 "Ciphertext must be at most {} bytes long".format(
700 _aead_aegis256_CRYPTBYTES_MAX
701 ),
702 raising=exc.ValueError,
703 )
704
705 ensure(
706 isinstance(aad, bytes) or (aad is None),
707 "Additional data must be bytes or None",
708 raising=exc.TypeError,
709 )
710
711 ensure(
712 isinstance(nonce, bytes)
713 and len(nonce) == crypto_aead_aegis256_NPUBBYTES,
714 "Nonce must be a {} bytes long bytes sequence".format(
715 crypto_aead_aegis256_NPUBBYTES
716 ),
717 raising=exc.TypeError,
718 )
719
720 ensure(
721 isinstance(key, bytes) and len(key) == crypto_aead_aegis256_KEYBYTES,
722 "Key must be a {} bytes long bytes sequence".format(
723 crypto_aead_aegis256_KEYBYTES
724 ),
725 raising=exc.TypeError,
726 )
727
728 mxout = clen - crypto_aead_aegis256_ABYTES
729 mlen = ffi.new("unsigned long long *")
730 message = ffi.new("unsigned char[]", mxout)
731
732 if aad:
733 _aad = aad
734 aalen = len(aad)
735 else:
736 _aad = ffi.NULL
737 aalen = 0
738
739 res = lib.crypto_aead_aegis256_decrypt(
740 message, mlen, ffi.NULL, ciphertext, clen, _aad, aalen, nonce, key
741 )
742
743 ensure(res == 0, "Decryption failed.", raising=exc.CryptoError)
744
745 return ffi.buffer(message, mlen[0])[:]
746
747
748def crypto_aead_aegis128l_encrypt(
749 message: bytes, aad: Optional[bytes], nonce: bytes, key: bytes
750) -> bytes:
751 """
752 Encrypt the given ``message`` using the AEGIS-128L
753 construction.
754
755 :param message:
756 :type message: bytes
757 :param aad:
758 :type aad: Optional[bytes]
759 :param nonce:
760 :type nonce: bytes
761 :param key:
762 :type key: bytes
763 :return: authenticated ciphertext
764 :rtype: bytes
765 """
766 ensure(
767 isinstance(message, bytes),
768 "Input message type must be bytes",
769 raising=exc.TypeError,
770 )
771
772 mlen = len(message)
773
774 ensure(
775 mlen <= crypto_aead_aegis128l_MESSAGEBYTES_MAX,
776 "Message must be at most {} bytes long".format(
777 crypto_aead_aegis128l_MESSAGEBYTES_MAX
778 ),
779 raising=exc.ValueError,
780 )
781
782 ensure(
783 isinstance(aad, bytes) or (aad is None),
784 "Additional data must be bytes or None",
785 raising=exc.TypeError,
786 )
787
788 ensure(
789 isinstance(nonce, bytes)
790 and len(nonce) == crypto_aead_aegis128l_NPUBBYTES,
791 "Nonce must be a {} bytes long bytes sequence".format(
792 crypto_aead_aegis128l_NPUBBYTES
793 ),
794 raising=exc.TypeError,
795 )
796
797 ensure(
798 isinstance(key, bytes) and len(key) == crypto_aead_aegis128l_KEYBYTES,
799 "Key must be a {} bytes long bytes sequence".format(
800 crypto_aead_aegis128l_KEYBYTES
801 ),
802 raising=exc.TypeError,
803 )
804
805 if aad:
806 _aad = aad
807 aalen = len(aad)
808 else:
809 _aad = ffi.NULL
810 aalen = 0
811
812 mxout = mlen + crypto_aead_aegis128l_ABYTES
813
814 clen = ffi.new("unsigned long long *")
815
816 ciphertext = ffi.new("unsigned char[]", mxout)
817
818 res = lib.crypto_aead_aegis128l_encrypt(
819 ciphertext, clen, message, mlen, _aad, aalen, ffi.NULL, nonce, key
820 )
821
822 ensure(res == 0, "Encryption failed.", raising=exc.CryptoError)
823 return ffi.buffer(ciphertext, clen[0])[:]
824
825
826def crypto_aead_aegis128l_decrypt(
827 ciphertext: bytes, aad: Optional[bytes], nonce: bytes, key: bytes
828) -> bytes:
829 """
830 Decrypt the given ``ciphertext`` using the AEGIS-128L
831 construction.
832
833 :param ciphertext: authenticated ciphertext
834 :type ciphertext: bytes
835 :param aad:
836 :type aad: Optional[bytes]
837 :param nonce:
838 :type nonce: bytes
839 :param key:
840 :type key: bytes
841 :return: message
842 :rtype: bytes
843 """
844 ensure(
845 isinstance(ciphertext, bytes),
846 "Input ciphertext type must be bytes",
847 raising=exc.TypeError,
848 )
849
850 clen = len(ciphertext)
851
852 ensure(
853 clen <= _aead_aegis256_CRYPTBYTES_MAX,
854 "Ciphertext must be at most {} bytes long".format(
855 _aead_aegis256_CRYPTBYTES_MAX
856 ),
857 raising=exc.ValueError,
858 )
859
860 ensure(
861 isinstance(aad, bytes) or (aad is None),
862 "Additional data must be bytes or None",
863 raising=exc.TypeError,
864 )
865
866 ensure(
867 isinstance(nonce, bytes)
868 and len(nonce) == crypto_aead_aegis128l_NPUBBYTES,
869 "Nonce must be a {} bytes long bytes sequence".format(
870 crypto_aead_aegis128l_NPUBBYTES
871 ),
872 raising=exc.TypeError,
873 )
874
875 ensure(
876 isinstance(key, bytes) and len(key) == crypto_aead_aegis128l_KEYBYTES,
877 "Key must be a {} bytes long bytes sequence".format(
878 crypto_aead_aegis128l_KEYBYTES
879 ),
880 raising=exc.TypeError,
881 )
882
883 mxout = clen - crypto_aead_aegis128l_ABYTES
884 mlen = ffi.new("unsigned long long *")
885 message = ffi.new("unsigned char[]", mxout)
886
887 if aad:
888 _aad = aad
889 aalen = len(aad)
890 else:
891 _aad = ffi.NULL
892 aalen = 0
893
894 res = lib.crypto_aead_aegis128l_decrypt(
895 message, mlen, ffi.NULL, ciphertext, clen, _aad, aalen, nonce, key
896 )
897
898 ensure(res == 0, "Decryption failed.", raising=exc.CryptoError)
899
900 return ffi.buffer(message, mlen[0])[:]
901
902
903def crypto_aead_aes256gcm_encrypt(
904 message: bytes, aad: Optional[bytes], nonce: bytes, key: bytes
905) -> bytes:
906 """
907 Encrypt the given ``message`` using the AES-256-GCM
908 construction. Requires the Intel AES-NI extensions,
909 or the ARM Crypto extensions.
910
911 :param message:
912 :type message: bytes
913 :param aad:
914 :type aad: Optional[bytes]
915 :param nonce:
916 :type nonce: bytes
917 :param key:
918 :type key: bytes
919 :return: authenticated ciphertext
920 :rtype: bytes
921 """
922 ensure(
923 lib.crypto_aead_aes256gcm_is_available() == 1,
924 "Construction requires hardware acceleration",
925 raising=exc.UnavailableError,
926 )
927
928 ensure(
929 isinstance(message, bytes),
930 "Input message type must be bytes",
931 raising=exc.TypeError,
932 )
933
934 mlen = len(message)
935
936 ensure(
937 mlen <= crypto_aead_aes256gcm_MESSAGEBYTES_MAX,
938 "Message must be at most {} bytes long".format(
939 crypto_aead_aes256gcm_MESSAGEBYTES_MAX
940 ),
941 raising=exc.ValueError,
942 )
943
944 ensure(
945 isinstance(aad, bytes) or (aad is None),
946 "Additional data must be bytes or None",
947 raising=exc.TypeError,
948 )
949
950 ensure(
951 isinstance(nonce, bytes)
952 and len(nonce) == crypto_aead_aes256gcm_NPUBBYTES,
953 "Nonce must be a {} bytes long bytes sequence".format(
954 crypto_aead_aes256gcm_NPUBBYTES
955 ),
956 raising=exc.TypeError,
957 )
958
959 ensure(
960 isinstance(key, bytes) and len(key) == crypto_aead_aes256gcm_KEYBYTES,
961 "Key must be a {} bytes long bytes sequence".format(
962 crypto_aead_aes256gcm_KEYBYTES
963 ),
964 raising=exc.TypeError,
965 )
966
967 if aad:
968 _aad = aad
969 aalen = len(aad)
970 else:
971 _aad = ffi.NULL
972 aalen = 0
973
974 mxout = mlen + crypto_aead_aes256gcm_ABYTES
975
976 clen = ffi.new("unsigned long long *")
977
978 ciphertext = ffi.new("unsigned char[]", mxout)
979
980 res = lib.crypto_aead_aes256gcm_encrypt(
981 ciphertext, clen, message, mlen, _aad, aalen, ffi.NULL, nonce, key
982 )
983
984 ensure(res == 0, "Encryption failed.", raising=exc.CryptoError)
985 return ffi.buffer(ciphertext, clen[0])[:]
986
987
988def crypto_aead_aes256gcm_decrypt(
989 ciphertext: bytes, aad: Optional[bytes], nonce: bytes, key: bytes
990) -> bytes:
991 """
992 Decrypt the given ``ciphertext`` using the AES-256-GCM
993 construction. Requires the Intel AES-NI extensions,
994 or the ARM Crypto extensions.
995
996 :param ciphertext: authenticated ciphertext
997 :type ciphertext: bytes
998 :param aad:
999 :type aad: Optional[bytes]
1000 :param nonce:
1001 :type nonce: bytes
1002 :param key:
1003 :type key: bytes
1004 :return: message
1005 :rtype: bytes
1006 """
1007 ensure(
1008 lib.crypto_aead_aes256gcm_is_available() == 1,
1009 "Construction requires hardware acceleration",
1010 raising=exc.UnavailableError,
1011 )
1012
1013 ensure(
1014 isinstance(ciphertext, bytes),
1015 "Input ciphertext type must be bytes",
1016 raising=exc.TypeError,
1017 )
1018
1019 clen = len(ciphertext)
1020
1021 ensure(
1022 clen <= _aead_aegis256_CRYPTBYTES_MAX,
1023 "Ciphertext must be at most {} bytes long".format(
1024 _aead_aegis256_CRYPTBYTES_MAX
1025 ),
1026 raising=exc.ValueError,
1027 )
1028
1029 ensure(
1030 isinstance(aad, bytes) or (aad is None),
1031 "Additional data must be bytes or None",
1032 raising=exc.TypeError,
1033 )
1034
1035 ensure(
1036 isinstance(nonce, bytes)
1037 and len(nonce) == crypto_aead_aes256gcm_NPUBBYTES,
1038 "Nonce must be a {} bytes long bytes sequence".format(
1039 crypto_aead_aes256gcm_NPUBBYTES
1040 ),
1041 raising=exc.TypeError,
1042 )
1043
1044 ensure(
1045 isinstance(key, bytes) and len(key) == crypto_aead_aes256gcm_KEYBYTES,
1046 "Key must be a {} bytes long bytes sequence".format(
1047 crypto_aead_aes256gcm_KEYBYTES
1048 ),
1049 raising=exc.TypeError,
1050 )
1051
1052 mxout = clen - crypto_aead_aes256gcm_ABYTES
1053 mlen = ffi.new("unsigned long long *")
1054 message = ffi.new("unsigned char[]", mxout)
1055
1056 if aad:
1057 _aad = aad
1058 aalen = len(aad)
1059 else:
1060 _aad = ffi.NULL
1061 aalen = 0
1062
1063 res = lib.crypto_aead_aes256gcm_decrypt(
1064 message, mlen, ffi.NULL, ciphertext, clen, _aad, aalen, nonce, key
1065 )
1066
1067 ensure(res == 0, "Decryption failed.", raising=exc.CryptoError)
1068
1069 return ffi.buffer(message, mlen[0])[:]