@@ -28,7 +28,7 @@ This is the state machine for a cipher object:
2828.. figure :: aead.png
2929 :align: center
3030 :figwidth: 80%
31-
31+
3232 Generic state diagram for a AEAD cipher mode
3333
3434Beside the usual :meth: `encrypt() ` and :meth: `decrypt() ` already
@@ -550,3 +550,106 @@ Example (decryption with multiple chunks)::
550550 >>> except (ValueError, KeyError):
551551 >>> print("Incorrect decryption")
552552
553+ .. _kw_mode :
554+
555+ KW mode
556+ --------
557+ `Key Wrapping <https://datatracker.ietf.org/doc/html/rfc3394 >`_
558+ (or `NIST SP 800-38F <https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf >`_)
559+ is an ad-hoc authenticated cipher mode designed to wrap cryptographic keys,
560+ and not other types of data.
561+ It is deterministic (it doesn't use nonces or IVs) and
562+ only works with ciphers with a block size of 128 bits (like AES).
563+
564+ The cryptographic key to wrap must have a length multiple of 8.
565+
566+ There is no reason to prefer this ad-hoc mode to one like SIV.
567+
568+ The :func: `new ` function at the module level under ``Crypto.Cipher `` instantiates
569+ a new KW cipher object for the relevant base algorithm.
570+ In the following definition, ``<algorithm> `` can only be ``AES `` today:
571+
572+ .. function :: Crypto.Cipher.<algorithm>.new(key, <algorithm>.MODE_KW)
573+
574+ Create a new Key Wrapping (KW) cipher object,
575+ using <algorithm> as the base block cipher.
576+
577+ :param bytes key: the cryptographic key
578+ :return: a KW cipher object
579+
580+ The cipher object has one read-only attribute :attr: `block_size `,
581+ and two methods (``seal `` and ``unseal ``).
582+
583+ Example of encryption::
584+
585+ >>> from Crypto.Cipher import AES
586+ >>> from Crypto.Random import get_random_bytes
587+ >>>
588+ >>> key_to_wrap = b"1234567890123456"
589+ >>> wrapping_key = get_random_bytes(16)
590+ >>> cipher = AES.new(wrapping_key, AES.MODE_KW)
591+ >>> ciphertext = cipher.seal(key_to_wrap)
592+
593+ Example of decryption::
594+
595+ >>> from Crypto.Cipher import AES
596+ >>> from Crypto.Random import get_random_bytes
597+ >>>
598+ >>> wrapping_key = get_random_bytes(16)
599+ >>> cipher = AES.new(wrapping_key, AES.MODE_KW)
600+ >>> try:
601+ >>> unwrapped_key = cipher.unseal(ciphertext)
602+ >>> except ValueError:
603+ >>> print("Invalid decryption")
604+
605+ .. _kwp_mode :
606+
607+ KWP mode
608+ --------
609+ `Key Wrapping with Padding <https://datatracker.ietf.org/doc/html/rfc5649 >`_
610+ (or `NIST SP 800-38F <https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf >`_)
611+ is an ad-hoc authenticated cipher mode designed to wrap cryptographic keys,
612+ and not other types of data.
613+ It is deterministic (it doesn't use nonces or IVs) and
614+ only works with ciphers with a block size of 128 bits (like AES).
615+
616+ The cryptographic key to wrap can have any length.
617+
618+ There is no reason to prefer this ad-hoc mode to one like SIV.
619+
620+ The :func: `new ` function at the module level under ``Crypto.Cipher `` instantiates
621+ a new KWP cipher object for the relevant base algorithm.
622+ In the following definition, ``<algorithm> `` can only be ``AES `` today:
623+
624+ .. function :: Crypto.Cipher.<algorithm>.new(key, <algorithm>.MODE_KWP)
625+
626+ Create a new Key Wrapping with Padding (KWP) cipher object,
627+ using <algorithm> as the base block cipher.
628+
629+ :param bytes key: the cryptographic key
630+ :return: a KWP cipher object
631+
632+ The cipher object has one read-only attribute :attr: `block_size `,
633+ and two methods (``seal `` and ``unseal ``).
634+
635+ Example of encryption::
636+
637+ >>> from Crypto.Cipher import AES
638+ >>> from Crypto.Random import get_random_bytes
639+ >>>
640+ >>> key_to_wrap = b"1234567890123456"
641+ >>> wrapping_key = get_random_bytes(16)
642+ >>> cipher = AES.new(wrapping_key, AES.MODE_KWP)
643+ >>> ciphertext = cipher.seal(key_to_wrap)
644+
645+ Example of decryption::
646+
647+ >>> from Crypto.Cipher import AES
648+ >>> from Crypto.Random import get_random_bytes
649+ >>>
650+ >>> wrapping_key = get_random_bytes(16)
651+ >>> cipher = AES.new(wrapping_key, AES.MODE_KWP)
652+ >>> try:
653+ >>> unwrapped_key = cipher.unseal(ciphertext)
654+ >>> except ValueError:
655+ >>> print("Invalid decryption")
0 commit comments