1037 lines
40 KiB
Python
1037 lines
40 KiB
Python
# -*- coding: utf-8 -*-
|
|
#
|
|
# Cipher/blockalgo.py
|
|
#
|
|
# ===================================================================
|
|
# The contents of this file are dedicated to the public domain. To
|
|
# the extent that dedication to the public domain is not available,
|
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
|
# non-exclusive license to exercise all rights associated with the
|
|
# contents of this file for any purpose whatsoever.
|
|
# No rights are reserved.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
# SOFTWARE.
|
|
# ===================================================================
|
|
"""Module with definitions common to all block ciphers."""
|
|
|
|
import sys
|
|
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
|
from Crypto.Util.py21compat import *
|
|
|
|
from Crypto.Util.py3compat import *
|
|
|
|
from binascii import unhexlify
|
|
|
|
from Crypto.Util import Counter
|
|
from Crypto.Util.strxor import strxor
|
|
from Crypto.Util.number import long_to_bytes, bytes_to_long
|
|
import Crypto.Util.Counter
|
|
from Crypto.Hash import CMAC
|
|
from Crypto.Hash.CMAC import _SmoothMAC
|
|
from Crypto.Protocol.KDF import _S2V
|
|
|
|
from Crypto.Util import galois
|
|
|
|
#: *Electronic Code Book (ECB)*.
|
|
#: This is the simplest encryption mode. Each of the plaintext blocks
|
|
#: is directly encrypted into a ciphertext block, independently of
|
|
#: any other block. This mode exposes frequency of symbols
|
|
#: in your plaintext. Other modes (e.g. *CBC*) should be used instead.
|
|
#:
|
|
#: See `NIST SP800-38A`_ , Section 6.1 .
|
|
#:
|
|
#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
|
MODE_ECB = 1
|
|
|
|
#: *Cipher-Block Chaining (CBC)*. Each of the ciphertext blocks depends
|
|
#: on the current and all previous plaintext blocks. An Initialization Vector
|
|
#: (*IV*) is required.
|
|
#:
|
|
#: The *IV* is a data block to be transmitted to the receiver.
|
|
#: The *IV* can be made public, but it must be authenticated by the receiver
|
|
#: and it should be picked randomly.
|
|
#:
|
|
#: See `NIST SP800-38A`_ , Section 6.2 .
|
|
#:
|
|
#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
|
MODE_CBC = 2
|
|
|
|
#: *Cipher FeedBack (CFB)*. This mode is similar to CBC, but it transforms
|
|
#: the underlying block cipher into a stream cipher. Plaintext and ciphertext
|
|
#: are processed in *segments* of **s** bits. The mode is therefore sometimes
|
|
#: labelled **s**-bit CFB. An Initialization Vector (*IV*) is required.
|
|
#:
|
|
#: When encrypting, each ciphertext segment contributes to the encryption of
|
|
#: the next plaintext segment.
|
|
#:
|
|
#: This *IV* is a data block to be transmitted to the receiver.
|
|
#: The *IV* can be made public, but it should be picked randomly.
|
|
#: Reusing the same *IV* for encryptions done with the same key lead to
|
|
#: catastrophic cryptographic failures.
|
|
#:
|
|
#: See `NIST SP800-38A`_ , Section 6.3 .
|
|
#:
|
|
#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
|
MODE_CFB = 3
|
|
|
|
#: This mode should not be used.
|
|
MODE_PGP = 4
|
|
|
|
#: *Output FeedBack (OFB)*. This mode is very similar to CBC, but it
|
|
#: transforms the underlying block cipher into a stream cipher.
|
|
#: The keystream is the iterated block encryption of an
|
|
#: Initialization Vector (*IV*).
|
|
#:
|
|
#: The *IV* is a data block to be transmitted to the receiver.
|
|
#: The *IV* can be made public, but it should be picked randomly.
|
|
#:
|
|
#: Reusing the same *IV* for encryptions done with the same key lead to
|
|
#: catastrophic cryptograhic failures.
|
|
#:
|
|
#: See `NIST SP800-38A`_ , Section 6.4 .
|
|
#:
|
|
#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
|
MODE_OFB = 5
|
|
|
|
#: *CounTeR (CTR)*. This mode is very similar to ECB, in that
|
|
#: encryption of one block is done independently of all other blocks.
|
|
#: Unlike ECB, the block *position* contributes to the encryption and no
|
|
#: information leaks about symbol frequency.
|
|
#:
|
|
#: Each message block is associated to a *counter* which must be unique
|
|
#: across all messages that get encrypted with the same key (not just within
|
|
#: the same message). The counter is as big as the block size.
|
|
#:
|
|
#: Counters can be generated in several ways. The most straightword one is
|
|
#: to choose an *initial counter block* (which can be made public, similarly
|
|
#: to the *IV* for the other modes) and increment its lowest **m** bits by
|
|
#: one (modulo *2^m*) for each block. In most cases, **m** is chosen to be half
|
|
#: the block size.
|
|
#:
|
|
#: Reusing the same *initial counter block* for encryptions done with the same
|
|
#: key lead to catastrophic cryptograhic failures.
|
|
#:
|
|
#: See `NIST SP800-38A`_ , Section 6.5 (for the mode) and Appendix B (for how
|
|
#: to manage the *initial counter block*).
|
|
#:
|
|
#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
|
MODE_CTR = 6
|
|
|
|
#: *OpenPGP CFB*. This mode is a variant of CFB, and it is only used in PGP and
|
|
#: OpenPGP_ applications. An Initialization Vector (*IV*) is required.
|
|
#:
|
|
#: Unlike CFB, the IV is not transmitted to the receiver.
|
|
#: Instead, the *encrypted* IV is.
|
|
#: The IV is a random data block. Two of its bytes are duplicated to act
|
|
#: as a checksum for the correctness of the key. The encrypted IV is
|
|
#: therefore 2 bytes longer than the clean IV.
|
|
#:
|
|
#: .. _OpenPGP: http://tools.ietf.org/html/rfc4880
|
|
MODE_OPENPGP = 7
|
|
|
|
#: *Counter with CBC-MAC (CCM)*. This is an Authenticated Encryption with
|
|
#: Associated Data (`AEAD`_) mode. It provides both confidentiality and
|
|
#: authenticity.
|
|
#: The header of the message may be left in the clear, if needed, and it will
|
|
#: still be subject to authentication. The decryption step tells the receiver
|
|
#: if the message comes from a source that really knowns the secret key.
|
|
#: Additionally, decryption detects if any part of the message - including the
|
|
#: header - has been modified or corrupted.
|
|
#:
|
|
#: This mode requires a nonce. The nonce shall never repeat for two
|
|
#: different messages encrypted with the same key, but it does not need
|
|
#: to be random.
|
|
#: Note that there is a trade-off between the size of the nonce and the
|
|
#: maximum size of a single message you can encrypt.
|
|
#:
|
|
#: It is important to use a large nonce if the key is reused across several
|
|
#: messages and the nonce is chosen randomly.
|
|
#:
|
|
#: It is acceptable to us a short nonce if the key is only used a few times or
|
|
#: if the nonce is taken from a counter.
|
|
#:
|
|
#: The following table shows the trade-off when the nonce is chosen at
|
|
#: random. The column on the left shows how many messages it takes
|
|
#: for the keystream to repeat **on average**. In practice, you will want to
|
|
#: stop using the key way before that.
|
|
#:
|
|
#: +--------------------+---------------+-------------------+
|
|
#: | Avg. # of messages | nonce | Max. message |
|
|
#: | before keystream | size | size |
|
|
#: | repeats | (bytes) | (bytes) |
|
|
#: +====================+===============+===================+
|
|
#: | 2**52 | 13 | 64K |
|
|
#: +--------------------+---------------+-------------------+
|
|
#: | 2**48 | 12 | 16M |
|
|
#: +--------------------+---------------+-------------------+
|
|
#: | 2**44 | 11 | 4G |
|
|
#: +--------------------+---------------+-------------------+
|
|
#: | 2**40 | 10 | 1T |
|
|
#: +--------------------+---------------+-------------------+
|
|
#: | 2**36 | 9 | 64P |
|
|
#: +--------------------+---------------+-------------------+
|
|
#: | 2**32 | 8 | 16E |
|
|
#: +--------------------+---------------+-------------------+
|
|
#:
|
|
#: This mode is only available for ciphers that operate on 128 bits blocks
|
|
#: (e.g. AES but not TDES).
|
|
#:
|
|
#: See `NIST SP800-38C`_ or RFC3610_ .
|
|
#:
|
|
#: .. _`NIST SP800-38C`: http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C.pdf
|
|
#: .. _RFC3610: https://tools.ietf.org/html/rfc3610
|
|
#: .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html
|
|
MODE_CCM = 8
|
|
|
|
#: *EAX*. This is an Authenticated Encryption with Associated Data
|
|
#: (`AEAD`_) mode. It provides both confidentiality and authenticity.
|
|
#:
|
|
#: The header of the message may be left in the clear, if needed, and it will
|
|
#: still be subject to authentication.
|
|
#:
|
|
#: The decryption step tells the receiver if the message comes from a source
|
|
#: that really knowns the secret key.
|
|
#: Additionally, decryption detects if any part of the message - including the
|
|
#: header - has been modified or corrupted.
|
|
#:
|
|
#: This mode requires a nonce. The nonce shall never repeat for two
|
|
#: different messages encrypted with the same key, but it does not need to
|
|
#: be random.
|
|
#
|
|
#: This mode is only available for ciphers that operate on 64 or
|
|
#: 128 bits blocks.
|
|
#:
|
|
#: There are no official standards defining EAX. The implementation is based on
|
|
#: `a proposal`__ that was presented to NIST.
|
|
#:
|
|
#: .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html
|
|
#: .. __: http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/eax/eax-spec.pdf
|
|
MODE_EAX = 9
|
|
|
|
#: *Synthetic Initialization Vector*. This is an Authenticated Encryption with
|
|
#: Associated Data (`AEAD`_) mode. It provides both confidentiality and
|
|
#: authenticity.
|
|
#: The header of the message may be left in the clear, if needed, and it will
|
|
#: still be subject to authentication. The decryption step tells the receiver
|
|
#: if the message comes from a source that really knowns the secret key.
|
|
#: Additionally, decryption detects if any part of the message - including the
|
|
#: header - has been modified or corrupted.
|
|
#:
|
|
#: If the data being encrypted is completely unpredictable to an adversary
|
|
#: (e.g. a secret key, for key wrapping purposes) a nonce is not strictly
|
|
#: required.
|
|
#:
|
|
#: Otherwise, a nonce has to be provided; the nonce shall never repeat
|
|
#: for two different messages encrypted with the same key, but it does not
|
|
#: need to be random.
|
|
#:
|
|
#: Unlike other AEAD modes such as CCM, EAX or GCM, accidental reuse of a
|
|
#: nonce is not catastrophic for the confidentiality of the message. The only
|
|
#: effect is that an attacker can tell when the same plaintext (and same
|
|
#: associated data) is protected with the same key.
|
|
#:
|
|
#: The length of the MAC is fixed to the block size of the underlying cipher.
|
|
#: The key size is twice the length of the key of the underlying cipher.
|
|
#:
|
|
#: This mode is only available for AES ciphers.
|
|
#:
|
|
#: +--------------------+---------------+-------------------+
|
|
#: | Cipher | SIV MAC size | SIV key length |
|
|
#: | | (bytes) | (bytes) |
|
|
#: +====================+===============+===================+
|
|
#: | AES-128 | 16 | 32 |
|
|
#: +--------------------+---------------+-------------------+
|
|
#: | AES-192 | 16 | 48 |
|
|
#: +--------------------+---------------+-------------------+
|
|
#: | AES-256 | 16 | 64 |
|
|
#: +--------------------+---------------+-------------------+
|
|
#:
|
|
#: See `RFC5297`_ and the `original paper`__.
|
|
#:
|
|
#: .. _RFC5297: https://tools.ietf.org/html/rfc5297
|
|
#: .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html
|
|
#: .. __: http://www.cs.ucdavis.edu/~rogaway/papers/keywrap.pdf
|
|
MODE_SIV = 10
|
|
|
|
#: *Galois/Counter Mode (GCM)*. This is an Authenticated Encryption with
|
|
#: Associated Data (`AEAD`_) mode. It provides both confidentiality and
|
|
#: authenticity.
|
|
#: The header of the message may be left in the clear, if needed, and it will
|
|
#: still be subject to authentication. The decryption step tells the receiver
|
|
#: if the message comes from a source that really knowns the secret key.
|
|
#: Additionally, decryption detects if any part of the message - including the
|
|
#: header - has been modified or corrupted.
|
|
#:
|
|
#: This mode requires a nonce. The nonce shall never repeat for two
|
|
#: different messages encrypted with the same key, but it does not need to
|
|
#: be random.
|
|
#:
|
|
#: This mode is only available for ciphers that operate on 128 bits blocks
|
|
#: (e.g. AES but not TDES).
|
|
#:
|
|
#: See `NIST SP800-38D`_ .
|
|
#:
|
|
#: .. _`NIST SP800-38D`: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
|
|
#: .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html
|
|
MODE_GCM = 11
|
|
|
|
|
|
def _getParameter(name, index, args, kwargs, default=None):
|
|
"""Find a parameter in tuple and dictionary arguments a function receives"""
|
|
|
|
param = kwargs.get(name)
|
|
if len(args) > index:
|
|
if param:
|
|
raise TypeError("Parameter '%s' is specified twice" % name)
|
|
param = args[index]
|
|
return param or default
|
|
|
|
|
|
class _CBCMAC(_SmoothMAC):
|
|
|
|
def __init__(self, key, ciphermod):
|
|
_SmoothMAC.__init__(self, ciphermod.block_size, None, 0)
|
|
self._key = key
|
|
self._factory = ciphermod
|
|
|
|
def _ignite(self, data):
|
|
if self._mac:
|
|
raise TypeError("_ignite() cannot be called twice")
|
|
|
|
self._buffer.insert(0, data)
|
|
self._buffer_len += len(data)
|
|
self._mac = self._factory.new(self._key, MODE_CBC, bchr(0) * 16)
|
|
self.update(b(""))
|
|
|
|
def _update(self, block_data):
|
|
self._t = self._mac.encrypt(block_data)[-16:]
|
|
|
|
def _digest(self, left_data):
|
|
return self._t
|
|
|
|
|
|
class _GHASH(_SmoothMAC):
|
|
"""GHASH function defined in NIST SP 800-38D, Algorithm 2.
|
|
|
|
If X_1, X_2, .. X_m are the blocks of input data, the function
|
|
computes:
|
|
|
|
X_1*H^{m} + X_2*H^{m-1} + ... + X_m*H
|
|
|
|
in the Galois field GF(2^256) using the reducing polynomial
|
|
(x^128 + x^7 + x^2 + x + 1).
|
|
"""
|
|
|
|
def __init__(self, hash_subkey, block_size, table_size='64K'):
|
|
_SmoothMAC.__init__(self, block_size, None, 0)
|
|
if table_size == '64K':
|
|
self._hash_subkey = galois._ghash_expand(hash_subkey)
|
|
else:
|
|
self._hash_subkey = hash_subkey
|
|
self._last_y = bchr(0) * 16
|
|
self._mac = galois._ghash
|
|
|
|
def copy(self):
|
|
clone = _GHASH(self._hash_subkey, self._bs, table_size='0K')
|
|
_SmoothMAC._deep_copy(self, clone)
|
|
clone._last_y = self._last_y
|
|
return clone
|
|
|
|
def _update(self, block_data):
|
|
self._last_y = galois._ghash(block_data, self._last_y,
|
|
self._hash_subkey)
|
|
|
|
def _digest(self, left_data):
|
|
return self._last_y
|
|
|
|
|
|
class BlockAlgo:
|
|
"""Class modelling an abstract block cipher."""
|
|
|
|
def __init__(self, factory, key, *args, **kwargs):
|
|
self.mode = _getParameter('mode', 0, args, kwargs, default=MODE_ECB)
|
|
self.block_size = factory.block_size
|
|
self._factory = factory
|
|
self._tag = None
|
|
|
|
if self.mode == MODE_CCM:
|
|
if self.block_size != 16:
|
|
raise TypeError("CCM mode is only available for ciphers that operate on 128 bits blocks")
|
|
|
|
self._mac_len = kwargs.get('mac_len', 16) # t
|
|
if self._mac_len not in (4, 6, 8, 10, 12, 14, 16):
|
|
raise ValueError("Parameter 'mac_len' must be even and in the range 4..16")
|
|
|
|
self.nonce = _getParameter('nonce', 1, args, kwargs) # N
|
|
if not (self.nonce and 7 <= len(self.nonce) <= 13):
|
|
raise ValueError("Length of parameter 'nonce' must be"
|
|
" in the range 7..13 bytes")
|
|
|
|
self._key = key
|
|
self._msg_len = kwargs.get('msg_len', None) # p
|
|
self._assoc_len = kwargs.get('assoc_len', None) # a
|
|
|
|
self._cipherMAC = _CBCMAC(key, factory)
|
|
self._done_assoc_data = False # True when all associated data
|
|
# has been processed
|
|
|
|
# Allowed transitions after initialization
|
|
self._next = [self.update, self.encrypt, self.decrypt,
|
|
self.digest, self.verify]
|
|
|
|
# Try to start CCM
|
|
self._start_ccm()
|
|
|
|
elif self.mode == MODE_OPENPGP:
|
|
self._start_PGP(factory, key, *args, **kwargs)
|
|
elif self.mode == MODE_EAX:
|
|
self._start_eax(factory, key, *args, **kwargs)
|
|
elif self.mode == MODE_SIV:
|
|
self._start_siv(factory, key, *args, **kwargs)
|
|
elif self.mode == MODE_GCM:
|
|
self._start_gcm(factory, key, *args, **kwargs)
|
|
else:
|
|
self._cipher = factory.new(key, *args, **kwargs)
|
|
self.IV = self._cipher.IV
|
|
|
|
def _start_gcm(self, factory, key, *args, **kwargs):
|
|
|
|
if self.block_size != 16:
|
|
raise TypeError("GCM mode is only available for ciphers that operate on 128 bits blocks")
|
|
|
|
self.nonce = _getParameter('nonce', 1, args, kwargs)
|
|
if not self.nonce:
|
|
raise TypeError("MODE_GCM requires a nonce")
|
|
|
|
self._mac_len = kwargs.get('mac_len', 16)
|
|
if not (self._mac_len and 4 <= self._mac_len <= 16):
|
|
raise ValueError("Parameter 'mac_len' must not be larger than 16 bytes")
|
|
|
|
# Allowed transitions after initialization
|
|
self._next = [self.update, self.encrypt, self.decrypt,
|
|
self.digest, self.verify]
|
|
|
|
self._done_assoc_data = False
|
|
|
|
# Length of the ciphertext or plaintext
|
|
self._msg_len = 0
|
|
|
|
# Step 1 in SP800-38D, Algorithm 4 (encryption) - Compute H
|
|
# See also Algorithm 5 (decryption)
|
|
hash_subkey = factory.new(key).encrypt(bchr(0) * 16)
|
|
|
|
# Step 2 - Compute J0 (integer, not byte string!)
|
|
if len(self.nonce) == 12:
|
|
self._j0 = bytes_to_long(self.nonce + b("\x00\x00\x00\x01"))
|
|
else:
|
|
fill = (16 - (len(self.nonce) % 16)) % 16 + 8
|
|
ghash_in = (self.nonce +
|
|
bchr(0) * fill +
|
|
long_to_bytes(8 * len(self.nonce), 8))
|
|
|
|
mac = _GHASH(hash_subkey, factory.block_size, '0K')
|
|
mac.update(ghash_in)
|
|
self._j0 = bytes_to_long(mac.digest())
|
|
|
|
# Step 3 - Prepare GCTR cipher for encryption/decryption
|
|
ctr = Counter.new(128, initial_value=self._j0 + 1,
|
|
allow_wraparound=True)
|
|
self._cipher = self._factory.new(key, MODE_CTR, counter=ctr)
|
|
|
|
# Step 5 - Bootstrat GHASH
|
|
self._cipherMAC = _GHASH(hash_subkey, factory.block_size, '64K')
|
|
|
|
# Step 6 - Prepare GCTR cipher for GMAC
|
|
ctr = Counter.new(128, initial_value=self._j0, allow_wraparound=True)
|
|
self._tag_cipher = self._factory.new(key, MODE_CTR, counter=ctr)
|
|
|
|
def _start_siv(self, factory, key, *args, **kwargs):
|
|
|
|
subkey_size, rem = divmod(len(key), 2)
|
|
if rem:
|
|
raise ValueError("MODE_SIV requires a key twice as long as for the underlying cipher")
|
|
|
|
# IV is optional
|
|
self.nonce = _getParameter('nonce', 1, args, kwargs)
|
|
|
|
self._cipherMAC = _S2V(key[:subkey_size], ciphermod=factory)
|
|
self._subkey_ctr = key[subkey_size:]
|
|
self._mac_len = factory.block_size
|
|
|
|
self._cipherMAC = self._cipherMAC
|
|
|
|
# Allowed transitions after initialization
|
|
self._next = [self.update, self.encrypt, self.decrypt,
|
|
self.digest, self.verify]
|
|
|
|
def _siv_ctr_cipher(self, tag):
|
|
"""Create a new CTR cipher from the MAC in SIV mode"""
|
|
|
|
tag_int = bytes_to_long(tag)
|
|
init_counter = tag_int ^ (tag_int & 0x8000000080000000L)
|
|
ctr = Counter.new(self._factory.block_size * 8,
|
|
initial_value=init_counter,
|
|
allow_wraparound=True)
|
|
|
|
return self._factory.new(self._subkey_ctr, MODE_CTR, counter=ctr)
|
|
|
|
def _start_eax(self, factory, key, *args, **kwargs):
|
|
|
|
self.nonce = _getParameter('nonce', 1, args, kwargs)
|
|
if not self.nonce:
|
|
raise TypeError("MODE_EAX requires a nonce")
|
|
|
|
# Allowed transitions after initialization
|
|
self._next = [self.update, self.encrypt, self.decrypt,
|
|
self.digest, self.verify]
|
|
|
|
self._mac_len = kwargs.get('mac_len', self.block_size)
|
|
if not (self._mac_len and 4 <= self._mac_len <= self.block_size):
|
|
raise ValueError("Parameter 'mac_len' must not be larger than %d"
|
|
% self.block_size)
|
|
|
|
self._omac = [
|
|
CMAC.new(key, bchr(0) * (self.block_size - 1) + bchr(i),
|
|
ciphermod=factory)
|
|
for i in xrange(0, 3)
|
|
]
|
|
|
|
# Compute MAC of nonce
|
|
self._omac[0].update(self.nonce)
|
|
|
|
self._cipherMAC = self._omac[1]
|
|
|
|
# MAC of the nonce is also the initial counter for CTR encryption
|
|
counter_int = bytes_to_long(self._omac[0].digest())
|
|
counter_obj = Crypto.Util.Counter.new(
|
|
self.block_size * 8,
|
|
initial_value=counter_int,
|
|
allow_wraparound=True)
|
|
self._cipher = factory.new(key, MODE_CTR, counter=counter_obj)
|
|
|
|
def _start_PGP(self, factory, key, *args, **kwargs):
|
|
# OPENPGP mode. For details, see 13.9 in RCC4880.
|
|
#
|
|
# A few members are specifically created for this mode:
|
|
# - _encrypted_iv, set in this constructor
|
|
# - _done_first_block, set to True after the first encryption
|
|
# - _done_last_block, set to True after a partial block is processed
|
|
|
|
self._done_first_block = False
|
|
self._done_last_block = False
|
|
self.IV = _getParameter('IV', 1, args, kwargs)
|
|
if self.IV is None:
|
|
# TODO: Decide whether 'IV' or 'iv' should be used going forward,
|
|
# and deprecate the other. 'IV' is consistent with the rest of
|
|
# PyCrypto, but 'iv' is more common in Python generally. For now,
|
|
# we'll support both here. When in doubt, use a positional
|
|
# parameter for now.
|
|
self.IV = _getParameter('iv', 1, args, kwargs)
|
|
if not self.IV:
|
|
raise ValueError("MODE_OPENPGP requires an IV")
|
|
|
|
# Instantiate a temporary cipher to process the IV
|
|
IV_cipher = factory.new(
|
|
key,
|
|
MODE_CFB,
|
|
b('\x00') * self.block_size, # IV for CFB
|
|
segment_size=self.block_size * 8)
|
|
|
|
# The cipher will be used for...
|
|
if len(self.IV) == self.block_size:
|
|
# ... encryption
|
|
self._encrypted_IV = IV_cipher.encrypt(
|
|
self.IV + self.IV[-2:] + # Plaintext
|
|
b('\x00') * (self.block_size - 2) # Padding
|
|
)[:self.block_size + 2]
|
|
elif len(self.IV) == self.block_size + 2:
|
|
# ... decryption
|
|
self._encrypted_IV = self.IV
|
|
self.IV = IV_cipher.decrypt(
|
|
self.IV + # Ciphertext
|
|
b('\x00') * (self.block_size - 2) # Padding
|
|
)[:self.block_size + 2]
|
|
if self.IV[-2:] != self.IV[-4:-2]:
|
|
raise ValueError("Failed integrity check for OPENPGP IV")
|
|
self.IV = self.IV[:-2]
|
|
else:
|
|
raise ValueError("Length of IV must be %d or %d bytes for MODE_OPENPGP"
|
|
% (self.block_size, self.block_size+2))
|
|
|
|
# Instantiate the cipher for the real PGP data
|
|
self._cipher = factory.new(
|
|
key,
|
|
MODE_CFB,
|
|
self._encrypted_IV[-self.block_size:],
|
|
segment_size=self.block_size * 8
|
|
)
|
|
|
|
def _start_ccm(self, assoc_len=None, msg_len=None):
|
|
# CCM mode. This method creates the 2 ciphers used for the MAC
|
|
# (self._cipherMAC) and for the encryption/decryption (self._cipher).
|
|
#
|
|
# Member _assoc_buffer may already contain user data that needs to be
|
|
# authenticated.
|
|
|
|
if self._cipherMAC.can_reduce():
|
|
# Already started
|
|
return
|
|
if assoc_len is not None:
|
|
self._assoc_len = assoc_len
|
|
if msg_len is not None:
|
|
self._msg_len = msg_len
|
|
if None in (self._assoc_len, self._msg_len):
|
|
return
|
|
|
|
# q is the length of Q, the encoding of the message length
|
|
q = 15 - len(self.nonce)
|
|
|
|
## Compute B_0
|
|
flags = (
|
|
64 * (self._assoc_len > 0) +
|
|
8 * divmod(self._mac_len - 2, 2)[0] +
|
|
(q - 1)
|
|
)
|
|
b_0 = bchr(flags) + self.nonce + long_to_bytes(self._msg_len, q)
|
|
|
|
# Start CBC MAC with zero IV
|
|
assoc_len_encoded = b('')
|
|
if self._assoc_len > 0:
|
|
if self._assoc_len < (2 ** 16 - 2 ** 8):
|
|
enc_size = 2
|
|
elif self._assoc_len < (2L ** 32):
|
|
assoc_len_encoded = b('\xFF\xFE')
|
|
enc_size = 4
|
|
else:
|
|
assoc_len_encoded = b('\xFF\xFF')
|
|
enc_size = 8
|
|
assoc_len_encoded += long_to_bytes(self._assoc_len, enc_size)
|
|
self._cipherMAC._ignite(b_0 + assoc_len_encoded)
|
|
|
|
# Start CTR cipher
|
|
prefix = bchr(q - 1) + self.nonce
|
|
ctr = Counter.new(128 - len(prefix) * 8, prefix, initial_value=0)
|
|
self._cipher = self._factory.new(self._key, MODE_CTR, counter=ctr)
|
|
# Will XOR against CBC MAC
|
|
self._s_0 = self._cipher.encrypt(bchr(0) * 16)
|
|
|
|
def update(self, assoc_data):
|
|
"""Protect associated data
|
|
|
|
When using an AEAD mode like CCM, EAX, GCM or SIV, and
|
|
if there is any associated data, the caller has to invoke
|
|
this function one or more times, before using
|
|
``decrypt`` or ``encrypt``.
|
|
|
|
By *associated data* it is meant any data (e.g. packet headers) that
|
|
will not be encrypted and will be transmitted in the clear.
|
|
However, the receiver is still able to detect any modification to it.
|
|
In CCM and GCM, the *associated data* is also called
|
|
*additional authenticated data* (AAD).
|
|
In EAX, the *associated data* is called *header*.
|
|
|
|
If there is no associated data, this method must not be called.
|
|
|
|
The caller may split associated data in segments of any size, and
|
|
invoke this method multiple times, each time with the next segment.
|
|
|
|
:Parameters:
|
|
assoc_data : byte string
|
|
A piece of associated data. There are no restrictions on its size.
|
|
"""
|
|
|
|
if self.mode not in (MODE_CCM, MODE_EAX, MODE_SIV, MODE_GCM):
|
|
raise TypeError("update() not supported by this mode of operation")
|
|
|
|
if self.update not in self._next:
|
|
raise TypeError("update() can only be called immediately after initialization")
|
|
|
|
self._next = [self.update, self.encrypt, self.decrypt,
|
|
self.digest, self.verify]
|
|
|
|
return self._cipherMAC.update(assoc_data)
|
|
|
|
def encrypt(self, plaintext):
|
|
"""Encrypt data with the key and the parameters set at initialization.
|
|
|
|
A cipher object is stateful: once you have encrypted a message
|
|
you cannot encrypt (or decrypt) another message using the same
|
|
object.
|
|
|
|
For `MODE_SIV` (always) and `MODE_CCM` (when ``msg_len`` was not
|
|
passed at initialization), this method can be called only **once**.
|
|
|
|
For all other modes, the data to encrypt can be broken up in two or
|
|
more pieces and `encrypt` can be called multiple times.
|
|
|
|
That is, the statement:
|
|
|
|
>>> c.encrypt(a) + c.encrypt(b)
|
|
|
|
is equivalent to:
|
|
|
|
>>> c.encrypt(a+b)
|
|
|
|
That also means that you cannot reuse an object for encrypting
|
|
or decrypting other data with the same key.
|
|
|
|
This function does not add any padding to the plaintext.
|
|
|
|
- For `MODE_ECB` and `MODE_CBC`, *plaintext* length (in bytes) must be
|
|
a multiple of *block_size*.
|
|
|
|
- For `MODE_CFB`, *plaintext* length (in bytes) must be a multiple
|
|
of *segment_size*/8.
|
|
|
|
- For `MODE_OFB`, `MODE_CTR` and all AEAD modes
|
|
*plaintext* can be of any length.
|
|
|
|
- For `MODE_OPENPGP`, *plaintext* must be a multiple of *block_size*,
|
|
unless it is the last chunk of the message.
|
|
|
|
:Parameters:
|
|
plaintext : byte string
|
|
The piece of data to encrypt.
|
|
:Return:
|
|
the encrypted data, as a byte string. It is as long as
|
|
*plaintext* with one exception: when encrypting the first message
|
|
chunk with `MODE_OPENPGP`, the encypted IV is prepended to the
|
|
returned ciphertext.
|
|
"""
|
|
|
|
if self.mode == MODE_OPENPGP:
|
|
padding_length = (self.block_size - len(plaintext) % self.block_size) % self.block_size
|
|
if padding_length > 0:
|
|
# CFB mode requires ciphertext to have length multiple
|
|
# of block size,
|
|
# but PGP mode allows the last block to be shorter
|
|
if self._done_last_block:
|
|
raise ValueError("Only the last chunk is allowed to have length not multiple of %d bytes",
|
|
self.block_size)
|
|
self._done_last_block = True
|
|
padded = plaintext + b('\x00') * padding_length
|
|
res = self._cipher.encrypt(padded)[:len(plaintext)]
|
|
else:
|
|
res = self._cipher.encrypt(plaintext)
|
|
if not self._done_first_block:
|
|
res = self._encrypted_IV + res
|
|
self._done_first_block = True
|
|
return res
|
|
|
|
if self.mode in (MODE_CCM, MODE_EAX, MODE_SIV, MODE_GCM):
|
|
if self.encrypt not in self._next:
|
|
raise TypeError("encrypt() can only be called after initialization or an update()")
|
|
self._next = [self.encrypt, self.digest]
|
|
|
|
if self.mode == MODE_CCM:
|
|
if self._assoc_len is None:
|
|
self._start_ccm(assoc_len=self._cipherMAC.get_len())
|
|
if self._msg_len is None:
|
|
self._start_ccm(msg_len=len(plaintext))
|
|
self._next = [self.digest]
|
|
if not self._done_assoc_data:
|
|
self._cipherMAC.zero_pad()
|
|
self._done_assoc_data = True
|
|
|
|
self._cipherMAC.update(plaintext)
|
|
|
|
if self.mode == MODE_SIV:
|
|
self._next = [self.digest]
|
|
|
|
if self.nonce:
|
|
self._cipherMAC.update(self.nonce)
|
|
|
|
self._cipherMAC.update(plaintext)
|
|
self._cipher = self._siv_ctr_cipher(self._cipherMAC.derive())
|
|
|
|
ct = self._cipher.encrypt(plaintext)
|
|
|
|
if self.mode == MODE_EAX:
|
|
self._omac[2].update(ct)
|
|
|
|
if self.mode == MODE_GCM:
|
|
if not self._done_assoc_data:
|
|
self._cipherMAC.zero_pad()
|
|
self._done_assoc_data = True
|
|
self._cipherMAC.update(ct)
|
|
self._msg_len += len(plaintext)
|
|
|
|
return ct
|
|
|
|
def decrypt(self, ciphertext):
|
|
"""Decrypt data with the key and the parameters set at initialization.
|
|
|
|
A cipher object is stateful: once you have decrypted a message
|
|
you cannot decrypt (or encrypt) another message with the same
|
|
object.
|
|
|
|
For `MODE_SIV` (always) and `MODE_CCM` (when ``msg_len`` was not
|
|
passed at initialization), this method can be called only **once**.
|
|
|
|
For all other modes, the data to decrypt can be broken up in two or
|
|
more pieces and `decrypt` can be called multiple times.
|
|
|
|
That is, the statement:
|
|
|
|
>>> c.decrypt(a) + c.decrypt(b)
|
|
|
|
is equivalent to:
|
|
|
|
>>> c.decrypt(a+b)
|
|
|
|
That also means that you cannot reuse an object for encrypting
|
|
or decrypting other data with the same key.
|
|
|
|
This function does not remove any padding from the plaintext.
|
|
|
|
- For `MODE_ECB` and `MODE_CBC`, *ciphertext* length (in bytes) must
|
|
be a multiple of *block_size*.
|
|
|
|
- For `MODE_CFB`, *ciphertext* length (in bytes) must be a multiple
|
|
of *segment_size*/8.
|
|
|
|
- For `MODE_OFB`, `MODE_CTR` and all AEAD modes
|
|
*ciphertext* can be of any length.
|
|
|
|
- For `MODE_OPENPGP`, *plaintext* must be a multiple of *block_size*,
|
|
unless it is the last chunk of the message.
|
|
|
|
- For `MODE_SIV`, *ciphertext* can be of any length, but it must also
|
|
include the MAC (concatenated at the end).
|
|
|
|
:Parameters:
|
|
ciphertext : byte string
|
|
The piece of data to decrypt (plus the MAC, for `MODE_SIV` only).
|
|
|
|
:Return: the decrypted data (byte string).
|
|
"""
|
|
|
|
if self.mode == MODE_OPENPGP:
|
|
padding_length = (self.block_size - len(ciphertext) % self.block_size) % self.block_size
|
|
if padding_length > 0:
|
|
# CFB mode requires ciphertext to have length multiple
|
|
# of block size,
|
|
# but PGP mode allows the last block to be shorter
|
|
if self._done_last_block:
|
|
raise ValueError("Only the last chunk is allowed to have length not multiple of %d bytes",
|
|
self.block_size)
|
|
self._done_last_block = True
|
|
padded = ciphertext + b('\x00') * padding_length
|
|
res = self._cipher.decrypt(padded)[:len(ciphertext)]
|
|
else:
|
|
res = self._cipher.decrypt(ciphertext)
|
|
return res
|
|
|
|
if self.mode == MODE_SIV:
|
|
raise TypeError("decrypt() not allowed for SIV mode."
|
|
" Use decrypt_and_verify() instead.")
|
|
|
|
if self.mode in (MODE_CCM, MODE_EAX, MODE_GCM):
|
|
|
|
if self.decrypt not in self._next:
|
|
raise TypeError("decrypt() can only be called after initialization or an update()")
|
|
self._next = [self.decrypt, self.verify]
|
|
|
|
if self.mode == MODE_CCM:
|
|
if self._assoc_len is None:
|
|
self._start_ccm(assoc_len=self._cipherMAC.get_len())
|
|
if self._msg_len is None:
|
|
self._start_ccm(msg_len=len(ciphertext))
|
|
self._next = [self.verify]
|
|
if not self._done_assoc_data:
|
|
self._cipherMAC.zero_pad()
|
|
self._done_assoc_data = True
|
|
|
|
if self.mode == MODE_GCM:
|
|
if not self._done_assoc_data:
|
|
self._cipherMAC.zero_pad()
|
|
self._done_assoc_data = True
|
|
|
|
self._cipherMAC.update(ciphertext)
|
|
self._msg_len += len(ciphertext)
|
|
|
|
if self.mode == MODE_EAX:
|
|
self._omac[2].update(ciphertext)
|
|
|
|
pt = self._cipher.decrypt(ciphertext)
|
|
|
|
if self.mode == MODE_CCM:
|
|
self._cipherMAC.update(pt)
|
|
|
|
return pt
|
|
|
|
def digest(self):
|
|
"""Compute the *binary* MAC tag in an AEAD mode.
|
|
|
|
When using an AEAD mode like CCM or EAX, the caller invokes
|
|
this function at the very end.
|
|
|
|
This method returns the MAC that shall be sent to the receiver,
|
|
together with the ciphertext.
|
|
|
|
:Return: the MAC, as a byte string.
|
|
"""
|
|
|
|
if self.mode not in (MODE_CCM, MODE_EAX, MODE_SIV, MODE_GCM):
|
|
raise TypeError("digest() not supported by this mode of operation")
|
|
|
|
if self.digest not in self._next:
|
|
raise TypeError("digest() cannot be called when decrypting or validating a message")
|
|
self._next = [self.digest]
|
|
|
|
return self._compute_mac()
|
|
|
|
def _compute_mac(self):
|
|
"""Compute MAC without any FSM checks."""
|
|
|
|
if self._tag:
|
|
return self._tag
|
|
|
|
if self.mode == MODE_CCM:
|
|
|
|
if self._assoc_len is None:
|
|
self._start_ccm(assoc_len=self._cipherMAC.get_len())
|
|
if self._msg_len is None:
|
|
self._start_ccm(msg_len=0)
|
|
self._cipherMAC.zero_pad()
|
|
self._tag = strxor(self._cipherMAC.digest(),
|
|
self._s_0)[:self._mac_len]
|
|
|
|
if self.mode == MODE_GCM:
|
|
|
|
# Step 5 in NIST SP 800-38D, Algorithm 4 - Compute S
|
|
self._cipherMAC.zero_pad()
|
|
auth_len = self._cipherMAC.get_len() - self._msg_len
|
|
for tlen in (auth_len, self._msg_len):
|
|
self._cipherMAC.update(long_to_bytes(8 * tlen, 8))
|
|
s_tag = self._cipherMAC.digest()
|
|
|
|
# Step 6 - Compute T
|
|
self._tag = self._tag_cipher.encrypt(s_tag)[:self._mac_len]
|
|
|
|
if self.mode == MODE_EAX:
|
|
tag = bchr(0) * self.block_size
|
|
for i in xrange(3):
|
|
tag = strxor(tag, self._omac[i].digest())
|
|
self._tag = tag[:self._mac_len]
|
|
|
|
if self.mode == MODE_SIV:
|
|
self._tag = self._cipherMAC.derive()
|
|
|
|
return self._tag
|
|
|
|
def hexdigest(self):
|
|
"""Compute the *printable* MAC tag in an AEAD mode.
|
|
|
|
This method is like `digest`.
|
|
|
|
:Return: the MAC, as a hexadecimal string.
|
|
"""
|
|
return "".join(["%02x" % bord(x) for x in self.digest()])
|
|
|
|
def verify(self, mac_tag):
|
|
"""Validate the *binary* MAC tag in an AEAD mode.
|
|
|
|
When using an AEAD mode like CCM or EAX, the caller invokes
|
|
this function at the very end.
|
|
|
|
This method checks if the decrypted message is indeed valid
|
|
(that is, if the key is correct) and it has not been
|
|
tampered with while in transit.
|
|
|
|
:Parameters:
|
|
mac_tag : byte string
|
|
This is the *binary* MAC, as received from the sender.
|
|
:Raises ValueError:
|
|
if the MAC does not match. The message has been tampered with
|
|
or the key is incorrect.
|
|
"""
|
|
|
|
if self.mode not in (MODE_CCM, MODE_EAX, MODE_SIV, MODE_GCM):
|
|
raise TypeError("verify() not supported by this mode of operation")
|
|
|
|
if self.verify not in self._next:
|
|
raise TypeError("verify() cannot be called when encrypting a message")
|
|
self._next = [self.verify]
|
|
|
|
res = 0
|
|
# Constant-time comparison
|
|
for x, y in zip(self._compute_mac(), mac_tag):
|
|
res |= bord(x) ^ bord(y)
|
|
if res or len(mac_tag) != self._mac_len:
|
|
raise ValueError("MAC check failed")
|
|
|
|
def hexverify(self, hex_mac_tag):
|
|
"""Validate the *printable* MAC tag in an AEAD mode.
|
|
|
|
This method is like `verify`.
|
|
|
|
:Parameters:
|
|
hex_mac_tag : string
|
|
This is the *printable* MAC, as received from the sender.
|
|
:Raises ValueError:
|
|
if the MAC does not match. The message has been tampered with
|
|
or the key is incorrect.
|
|
"""
|
|
|
|
self.verify(unhexlify(hex_mac_tag))
|
|
|
|
def encrypt_and_digest(self, plaintext):
|
|
"""Perform encrypt() and digest() in one step.
|
|
|
|
:Parameters:
|
|
plaintext : byte string
|
|
The piece of data to encrypt.
|
|
:Return:
|
|
a tuple with two byte strings:
|
|
|
|
- the encrypted data
|
|
- the MAC
|
|
"""
|
|
|
|
return self.encrypt(plaintext), self.digest()
|
|
|
|
def decrypt_and_verify(self, ciphertext, mac_tag):
|
|
"""Perform decrypt() and verify() in one step.
|
|
|
|
:Parameters:
|
|
ciphertext : byte string
|
|
The piece of data to decrypt.
|
|
mac_tag : byte string
|
|
This is the *binary* MAC, as received from the sender.
|
|
|
|
:Return: the decrypted data (byte string).
|
|
:Raises ValueError:
|
|
if the MAC does not match. The message has been tampered with
|
|
or the key is incorrect.
|
|
"""
|
|
|
|
if self.mode == MODE_SIV:
|
|
if self.decrypt not in self._next:
|
|
raise TypeError("decrypt() can only be called"
|
|
" after initialization or an update()")
|
|
self._next = [self.verify]
|
|
|
|
# Take the MAC and start the cipher for decryption
|
|
self._mac = mac_tag
|
|
self._cipher = self._siv_ctr_cipher(self._mac)
|
|
|
|
pt = self._cipher.decrypt(ciphertext)
|
|
|
|
if self.nonce:
|
|
self._cipherMAC.update(self.nonce)
|
|
if pt:
|
|
self._cipherMAC.update(pt)
|
|
else:
|
|
pt = self.decrypt(ciphertext)
|
|
|
|
self.verify(mac_tag)
|
|
return pt
|