Ejemplo n.º 1
0
    def digest(self):
        """Return the **binary** (non-printable) MAC tag of the message
        that has been authenticated so far.

        :return: The MAC tag, computed over the data processed so far.
                 Binary form.
        :rtype: byte string
        """

        bs = self._block_size

        if self._mac_tag is not None and not self._update_after_digest:
            return self._mac_tag

        if self._data_size > self._max_size:
            raise ValueError("MAC is unsafe for this message")

        if self._cache_n == 0 and self._data_size > 0:
            # Last block was full
            pt = strxor(self._last_pt, self._k1)
        else:
            # Last block is partial (or message length is zero)
            partial = self._cache[:]
            partial[self.
                    _cache_n:] = b'\x80' + b'\x00' * (bs - self._cache_n - 1)
            pt = strxor(strxor(self._last_ct, partial), self._k2)

        self._mac_tag = self._ecb.encrypt(pt)[:self.digest_size]

        return self._mac_tag
Ejemplo n.º 2
0
    def digest(self):
        """Return the **binary** (non-printable) MAC tag of the message
        that has been authenticated so far.

        :return: The MAC tag, computed over the data processed so far.
                 Binary form.
        :rtype: byte string
        """

        if self._mac_tag is not None:
            return self._mac_tag[:self._mac_len]

        if self._data_size > self._max_size:
            raise ValueError("MAC is unsafe for this message")

        if len(self._cache) == 0 and self._before_last_ct is not None:
            # Last block was full
            pt = strxor(strxor(self._before_last_ct, self._k1), self._last_pt)
        else:
            # Last block is partial (or message length is zero)
            ext = self._cache + b'\x80' +\
                    b'\x00' * (self.digest_size - len(self._cache) - 1)
            pt = strxor(strxor(self._last_ct, self._k2), ext)

        cipher = self._factory.new(self._key, self._factory.MODE_ECB,
                                   **self._cipher_params)
        self._mac_tag = cipher.encrypt(pt)

        return self._mac_tag[:self._mac_len]
Ejemplo n.º 3
0
    def encrypt(self, message):
        """Encrypt a message with PKCS#1 OAEP.

        :param message:
            The message to encrypt, also known as plaintext. It can be of
            variable length, but not longer than the RSA modulus (in bytes)
            minus 2, minus twice the hash output size.
            For instance, if you use RSA 2048 and SHA-256, the longest message
            you can encrypt is 190 byte long.
        :type message: bytes/bytearray/memoryview

        :returns: The ciphertext, as large as the RSA modulus.
        :rtype: bytes

        :raises ValueError:
            if the message is too long.
        """

        # See 7.1.1 in RFC3447
        modBits = crypto.Util.number.size(self._key.n)
        k = ceil_div(modBits, 8)  # Convert from bits to bytes
        hLen = self._hashObj.digest_size
        mLen = len(message)

        # Step 1b
        ps_len = k - mLen - 2 * hLen - 2
        if ps_len < 0:
            raise ValueError("Plaintext is too long.")
        # Step 2a
        lHash = self._hashObj.new(self._label).digest()
        # Step 2b
        ps = b'\x00' * ps_len
        # Step 2c
        db = lHash + ps + b'\x01' + _copy_bytes(None, None, message)
        # Step 2d
        ros = self._randfunc(hLen)
        # Step 2e
        dbMask = self._mgf(ros, k - hLen - 1)
        # Step 2f
        maskedDB = strxor(db, dbMask)
        # Step 2g
        seedMask = self._mgf(maskedDB, hLen)
        # Step 2h
        maskedSeed = strxor(ros, seedMask)
        # Step 2i
        em = b'\x00' + maskedSeed + maskedDB
        # Step 3a (OS2IP)
        em_int = bytes_to_long(em)
        # Step 3b (RSAEP)
        m_int = self._key._encrypt(em_int)
        # Step 3c (I2OSP)
        c = long_to_bytes(m_int, k)
        return c
Ejemplo n.º 4
0
    def test_memoryview(self):
        term1 = unhexlify(b"ff339a83e5cd4cdf5649")
        term1_mv = memoryview(term1)
        term2 = unhexlify(b"383d4ba020573314395b")
        result = unhexlify(b"c70ed123c59a7fcb6f12")

        self.assertEqual(strxor(term1_mv, term2), result)
    def _digest(self):
        if self._mac_tag:
            return self._mac_tag

        if self._assoc_len is None:
            assert (isinstance(self._cache, list))
            self._assoc_len = sum([len(x) for x in self._cache])
            if self._msg_len is not None:
                self._start_mac()
        else:
            if self._cumul_assoc_len < self._assoc_len:
                raise ValueError("Associated data is too short")

        if self._msg_len is None:
            self._msg_len = 0
            self._start_mac()

        if self._cumul_msg_len != self._msg_len:
            raise ValueError("Message is too short")

        # Both associated data and payload are concatenated with the least
        # number of zero bytes (possibly none) that align it to the
        # 16 byte boundary (A.2.2 and A.2.3)
        self._pad_cache_and_update()

        # Step 8 in 6.1 (T xor MSB_Tlen(S_0))
        self._mac_tag = strxor(self._t, self._s_0)[:self._mac_len]

        return self._mac_tag
Ejemplo n.º 6
0
    def verify(self, received_mac_tag):
        """Validate the *binary* MAC tag.

        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:
          received_mac_tag : bytes/bytearray/memoryview
            This is the *binary* MAC, as received from the sender.
        :Raises MacMismatchError:
            if the MAC does not match. The message has been tampered with
            or the key is incorrect.
        """

        if self.verify not in self._next:
            raise TypeError("verify() cannot be called"
                            " when encrypting a message")
        self._next = [self.verify]

        if not self._mac_tag:
            tag = b'\x00' * self.block_size
            for i in range(3):
                tag = strxor(tag, self._omac[i].digest())
            self._mac_tag = tag[:self._mac_len]

        secret = get_random_bytes(16)

        mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag)
        mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag)

        if mac1.digest() != mac2.digest():
            raise ValueError("MAC check failed")
Ejemplo n.º 7
0
    def test_bytearray(self):
        term1 = unhexlify(b"ff339a83e5cd4cdf5649")
        term1_ba = bytearray(term1)
        term2 = unhexlify(b"383d4ba020573314395b")
        result = unhexlify(b"c70ed123c59a7fcb6f12")

        self.assertEqual(strxor(term1_ba, term2), result)
 def test_corrupt_decrypt(self, tv):
     self._id = "Wycheproof Corrupt Decrypt GCM Test #" + str(tv.id)
     if len(tv.iv) == 0 or len(tv.ct) < 1:
         return
     cipher = AES.new(tv.key, AES.MODE_GCM, tv.iv, mac_len=tv.tag_size,
             **self._extra_params)
     cipher.update(tv.aad)
     ct_corrupt = strxor(tv.ct, b"\x00" * (len(tv.ct) - 1) + b"\x01")
     self.assertRaises(ValueError, cipher.decrypt_and_verify, ct_corrupt, tv.tag)
Ejemplo n.º 9
0
    def derive(self):
        """"Derive a secret from the vector of components.

        :Return: a byte string, as long as the block length of the cipher.
        """

        if len(self._last_string) >= 16:
            # xorend
            final = self._last_string[:-16] + strxor(self._last_string[-16:],
                                                     self._cache)
        else:
            # zero-pad & xor
            padded = (self._last_string + b'\x80' + b'\x00' * 15)[:16]
            final = strxor(padded, self._double(self._cache))
        mac = CMAC.new(self._key,
                       msg=final,
                       ciphermod=self._ciphermod,
                       cipher_params=self._cipher_params)
        return mac.digest()
Ejemplo n.º 10
0
    def runTest(self):
        key = RSA.importKey(PKCS1_15_NoParams.rsakey)
        hashed = SHA1.new(b("Test"))
        good_signature = PKCS1_v1_5.new(key).sign(hashed)
        verifier = PKCS1_v1_5.new(key.publickey())

        self.assertEqual(verifier.verify(hashed, good_signature), True)

        # Flip a few bits in the signature
        bad_signature = strxor(good_signature, bchr(1) * len(good_signature))
        self.assertEqual(verifier.verify(hashed, bad_signature), False)
Ejemplo n.º 11
0
    def runTest(self):
        key = RSA.generate(1024)
        hashed = SHA1.new(b("Test"))
        good_signature = PKCS1_PSS.new(key).sign(hashed)
        verifier = PKCS1_PSS.new(key.publickey())

        self.assertEqual(verifier.verify(hashed, good_signature), True)

        # Flip a few bits in the signature
        bad_signature = strxor(good_signature, bchr(1) * len(good_signature))
        self.assertEqual(verifier.verify(hashed, bad_signature), False)
Ejemplo n.º 12
0
    def __init__(self, key, msg=b"", digestmod=None):

        if digestmod is None:
            digestmod = MD5

        if msg is None:
            msg = b""

        # Size of the MAC tag
        self.digest_size = digestmod.digest_size

        self._digestmod = digestmod

        if isinstance(key, _memoryview):
            key = key.tobytes()

        try:
            if len(key) <= digestmod.block_size:
                # Step 1 or 2
                key_0 = key + b"\x00" * (digestmod.block_size - len(key))
            else:
                # Step 3
                hash_k = digestmod.new(key).digest()
                key_0 = hash_k + b"\x00" * (digestmod.block_size - len(hash_k))
        except AttributeError:
            # Not all hash types have "block_size"
            raise ValueError("Hash type incompatible to HMAC")

        # Step 4
        key_0_ipad = strxor(key_0, b"\x36" * len(key_0))

        # Start step 5 and 6
        self._inner = digestmod.new(key_0_ipad)
        self._inner.update(msg)

        # Step 7
        key_0_opad = strxor(key_0, b"\x5c" * len(key_0))

        # Start step 8 and 9
        self._outer = digestmod.new(key_0_opad)
Ejemplo n.º 13
0
    def _update(self, data_block):
        """Update a block aligned to the block boundary"""

        bs = self._block_size
        assert len(data_block) % bs == 0

        if len(data_block) == 0:
            return

        ct = self._cbc.encrypt(data_block)
        if len(data_block) == bs:
            second_last = self._last_ct
        else:
            second_last = ct[-bs * 2:-bs]
        self._last_ct = ct[-bs:]
        self._last_pt = strxor(second_last, data_block[-bs:])
Ejemplo n.º 14
0
    def update(self, item):
        """Pass the next component of the vector.

        The maximum number of components you can pass is equal to the block
        length of the cipher (in bits) minus 1.

        :Parameters:
          item : byte string
            The next component of the vector.
        :Raise TypeError: when the limit on the number of components has been reached.
        """

        if self._n_updates == 0:
            raise TypeError("Too many components passed to S2V")
        self._n_updates -= 1

        mac = CMAC.new(self._key,
                       msg=self._last_string,
                       ciphermod=self._ciphermod,
                       cipher_params=self._cipher_params)
        self._cache = strxor(self._double(self._cache), mac.digest())
        self._last_string = _copy_bytes(None, None, item)
Ejemplo n.º 15
0
    def digest(self):
        """Compute the *binary* MAC tag.

        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.digest not in self._next:
            raise TypeError("digest() cannot be called when decrypting"
                            " or validating a message")
        self._next = [self.digest]

        if not self._mac_tag:
            tag = b'\x00' * self.block_size
            for i in range(3):
                tag = strxor(tag, self._omac[i].digest())
            self._mac_tag = tag[:self._mac_len]

        return self._mac_tag
Ejemplo n.º 16
0
def _EMSA_PSS_ENCODE(mhash, emBits, randFunc, mgf, sLen):
    r"""
    Implement the ``EMSA-PSS-ENCODE`` function, as defined
    in PKCS#1 v2.1 (RFC3447, 9.1.1).

    The original ``EMSA-PSS-ENCODE`` actually accepts the message ``M``
    as input, and hash it internally. Here, we expect that the message
    has already been hashed instead.

    :Parameters:
      mhash : hash object
        The hash object that holds the digest of the message being signed.
      emBits : int
        Maximum length of the final encoding, in bits.
      randFunc : callable
        An RNG function that accepts as only parameter an int, and returns
        a string of random bytes, to be used as salt.
      mgf : callable
        A mask generation function that accepts two parameters: a string to
        use as seed, and the lenth of the mask to generate, in bytes.
      sLen : int
        Length of the salt, in bytes.

    :Return: An ``emLen`` byte long string that encodes the hash
      (with ``emLen = \ceil(emBits/8)``).

    :Raise ValueError:
        When digest or salt length are too big.
    """

    emLen = ceil_div(emBits, 8)

    # Bitmask of digits that fill up
    lmask = 0
    for i in iter_range(8 * emLen - emBits):
        lmask = lmask >> 1 | 0x80

    # Step 1 and 2 have been already done
    # Step 3
    if emLen < mhash.digest_size + sLen + 2:
        raise ValueError("Digest or salt length are too long"
                         " for given key size.")
    # Step 4
    salt = randFunc(sLen)
    # Step 5
    m_prime = bchr(0) * 8 + mhash.digest() + salt
    # Step 6
    h = mhash.new()
    h.update(m_prime)
    # Step 7
    ps = bchr(0) * (emLen - sLen - mhash.digest_size - 2)
    # Step 8
    db = ps + bchr(1) + salt
    # Step 9
    dbMask = mgf(h.digest(), emLen - mhash.digest_size - 1)
    # Step 10
    maskedDB = strxor(db, dbMask)
    # Step 11
    maskedDB = bchr(bord(maskedDB[0]) & ~lmask) + maskedDB[1:]
    # Step 12
    em = maskedDB + h.digest() + bchr(0xBC)
    return em
Ejemplo n.º 17
0
    def __init__(self, factory, nonce, mac_len, cipher_params):

        if factory.block_size != 16:
            raise ValueError("OCB mode is only available for ciphers"
                             " that operate on 128 bits blocks")

        self.block_size = 16
        """The block size of the underlying cipher, in bytes."""

        self.nonce = _copy_bytes(None, None, nonce)
        """Nonce used for this session."""
        if len(nonce) not in range(1, 16):
            raise ValueError("Nonce must be at most 15 bytes long")
        if not is_buffer(nonce):
            raise TypeError("Nonce must be bytes, bytearray or memoryview")

        self._mac_len = mac_len
        if not 8 <= mac_len <= 16:
            raise ValueError("MAC tag must be between 8 and 16 bytes long")

        # Cache for MAC tag
        self._mac_tag = None

        # Cache for unaligned associated data
        self._cache_A = b""

        # Cache for unaligned ciphertext/plaintext
        self._cache_P = b""

        # Allowed transitions after initialization
        self._next = [
            self.update, self.encrypt, self.decrypt, self.digest, self.verify
        ]

        # Compute Offset_0
        params_without_key = dict(cipher_params)
        key = params_without_key.pop("key")
        nonce = (struct.pack('B', self._mac_len << 4 & 0xFF) + b'\x00' *
                 (14 - len(nonce)) + b'\x01' + self.nonce)

        bottom_bits = bord(nonce[15]) & 0x3F  # 6 bits, 0..63
        top_bits = bord(nonce[15]) & 0xC0  # 2 bits

        ktop_cipher = factory.new(key, factory.MODE_ECB, **params_without_key)
        ktop = ktop_cipher.encrypt(struct.pack('15sB', nonce[:15], top_bits))

        stretch = ktop + strxor(ktop[:8], ktop[1:9])  # 192 bits
        offset_0 = long_to_bytes(
            bytes_to_long(stretch) >> (64 - bottom_bits), 24)[8:]

        # Create low-level cipher instance
        raw_cipher = factory._create_base_cipher(cipher_params)
        if cipher_params:
            raise TypeError("Unknown keywords: " + str(cipher_params))

        self._state = VoidPointer()
        result = _raw_ocb_lib.OCB_start_operation(raw_cipher.get(), offset_0,
                                                  c_size_t(len(offset_0)),
                                                  self._state.address_of())
        if result:
            raise ValueError("Error %d while instantiating the OCB mode" %
                             result)

        # Ensure that object disposal of this Python object will (eventually)
        # free the memory allocated by the raw library for the cipher mode
        self._state = SmartPointer(self._state.get(),
                                   _raw_ocb_lib.OCB_stop_operation)

        # Memory allocated for the underlying block cipher is now owed
        # by the cipher mode
        raw_cipher.release()
Ejemplo n.º 18
0
 def test3(self):
     term1 = unhexlify(b"ff339a83e5cd4cdf5649")
     all_zeros = b"\x00" * len(term1)
     self.assertEqual(strxor(term1, term1), all_zeros)
Ejemplo n.º 19
0
 def test2(self):
     es = b""
     self.assertEqual(strxor(es, es), es)
Ejemplo n.º 20
0
    def decrypt(self, ciphertext):
        """Decrypt a message with PKCS#1 OAEP.

        :param ciphertext: The encrypted message.
        :type ciphertext: bytes/bytearray/memoryview

        :returns: The original message (plaintext).
        :rtype: bytes

        :raises ValueError:
            if the ciphertext has the wrong length, or if decryption
            fails the integrity check (in which case, the decryption
            key is probably wrong).
        :raises TypeError:
            if the RSA key has no private half (i.e. you are trying
            to decrypt using a public key).
        """

        # See 7.1.2 in RFC3447
        modBits = crypto.Util.number.size(self._key.n)
        k = ceil_div(modBits, 8)  # Convert from bits to bytes
        hLen = self._hashObj.digest_size

        # Step 1b and 1c
        if len(ciphertext) != k or k < hLen + 2:
            raise ValueError("Ciphertext with incorrect length.")
        # Step 2a (O2SIP)
        ct_int = bytes_to_long(ciphertext)
        # Step 2b (RSADP)
        m_int = self._key._decrypt(ct_int)
        # Complete step 2c (I2OSP)
        em = long_to_bytes(m_int, k)
        # Step 3a
        lHash = self._hashObj.new(self._label).digest()
        # Step 3b
        y = em[0]
        # y must be 0, but we MUST NOT check it here in order not to
        # allow attacks like Manger's (http://dl.acm.org/citation.cfm?id=704143)
        maskedSeed = em[1:hLen + 1]
        maskedDB = em[hLen + 1:]
        # Step 3c
        seedMask = self._mgf(maskedDB, hLen)
        # Step 3d
        seed = strxor(maskedSeed, seedMask)
        # Step 3e
        dbMask = self._mgf(seed, k - hLen - 1)
        # Step 3f
        db = strxor(maskedDB, dbMask)
        # Step 3g
        one_pos = db[hLen:].find(b'\x01')
        lHash1 = db[:hLen]
        invalid = bord(y) | int(one_pos < 0)
        hash_compare = strxor(lHash1, lHash)
        for x in hash_compare:
            invalid |= bord(x)
        for x in db[hLen:one_pos]:
            invalid |= bord(x)
        if invalid != 0:
            raise ValueError("Incorrect decryption.")
        # Step 4
        return db[hLen + one_pos + 1:]
Ejemplo n.º 21
0
def _EMSA_PSS_VERIFY(mhash, em, emBits, mgf, sLen):
    """
    Implement the ``EMSA-PSS-VERIFY`` function, as defined
    in PKCS#1 v2.1 (RFC3447, 9.1.2).

    ``EMSA-PSS-VERIFY`` actually accepts the message ``M`` as input,
    and hash it internally. Here, we expect that the message has already
    been hashed instead.

    :Parameters:
      mhash : hash object
        The hash object that holds the digest of the message to be verified.
      em : string
        The signature to verify, therefore proving that the sender really
        signed the message that was received.
      emBits : int
        Length of the final encoding (em), in bits.
      mgf : callable
        A mask generation function that accepts two parameters: a string to
        use as seed, and the lenth of the mask to generate, in bytes.
      sLen : int
        Length of the salt, in bytes.

    :Raise ValueError:
        When the encoding is inconsistent, or the digest or salt lengths
        are too big.
    """

    emLen = ceil_div(emBits, 8)

    # Bitmask of digits that fill up
    lmask = 0
    for i in iter_range(8 * emLen - emBits):
        lmask = lmask >> 1 | 0x80

    # Step 1 and 2 have been already done
    # Step 3
    if emLen < mhash.digest_size + sLen + 2:
        raise ValueError("Incorrect signature")
    # Step 4
    if ord(em[-1:]) != 0xBC:
        raise ValueError("Incorrect signature")
    # Step 5
    maskedDB = em[:emLen - mhash.digest_size - 1]
    h = em[emLen - mhash.digest_size - 1:-1]
    # Step 6
    if lmask & bord(em[0]):
        raise ValueError("Incorrect signature")
    # Step 7
    dbMask = mgf(h, emLen - mhash.digest_size - 1)
    # Step 8
    db = strxor(maskedDB, dbMask)
    # Step 9
    db = bchr(bord(db[0]) & ~lmask) + db[1:]
    # Step 10
    if not db.startswith(
            bchr(0) * (emLen - mhash.digest_size - sLen - 2) + bchr(1)):
        raise ValueError("Incorrect signature")
    # Step 11
    if sLen > 0:
        salt = db[-sLen:]
    else:
        salt = b""
    # Step 12
    m_prime = bchr(0) * 8 + mhash.digest() + salt
    # Step 13
    hobj = mhash.new()
    hobj.update(m_prime)
    hp = hobj.digest()
    # Step 14
    if h != hp:
        raise ValueError("Incorrect signature")