Пример #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
        """

        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]
Пример #2
0
    def digest(self):
        """Return the **binary** (non-printable) MAC of the message that has
        been authenticated so far.

        This method does not change the state of the MAC object.
        You can continue updating the object after calling this function.

        :Return: A byte string of `digest_size` bytes. It may contain non-ASCII
         characters, including null bytes.
        """

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

        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 + bchr(0x80) +\
                    bchr(0) * (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
Пример #3
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
Пример #4
0
def q1_dec_cbc_mode(key, ciphertext, iv, cipher=Sample_Cipher):
    """Question 1 (part 2): Implement CBC Mode **decryption** (with PKCS#7 padding, using the provided block cipher `cipher`)

    Your Task:
        The problem description is similar to the one in the previous problem, just note the different inputs and expected outputs

    Args:
        key         (str):      hex-encoded string (cipher.BLOCK_SIZE-bytes long)
        ciphertext  (str):      hex-encoded ciphertext (multiple cipher.BLOCK_SIZE-bytes long)
        iv          (str):      hex-encoded string of an IV that should be used for the CBC decryption (cipher.BLOCK_SIZE-bytes long)
        cipher      (Cipher):   Cipher class (check `sample_cipher.py`) that provides access to a sample block cipher.
                                +   cipher.decipher(key, ciphertext)
    Output:
        ret     (str):          ascii output string with an arbitrary length (with the padding removed)
    Test vectors:
        You can use the same test vectors from `q1_enc_cbc_mode` in the reverse order to double check your solution
    """
    message = []
    blocksToDecrypt = [
        ciphertext[i:i + cipher.BLOCK_SIZE * 2]
        for i in range(0, len(ciphertext), cipher.BLOCK_SIZE * 2)
    ]
    prev_cipher = blocksToDecrypt[0]
    temp_value = cipher.decipher(key, prev_cipher)
    m1 = strxor(bytes.fromhex(iv), bytes.fromhex(temp_value))
    message.append(m1.decode())
    for byte in blocksToDecrypt[1:]:
        temp_value = cipher.decipher(key, byte)
        m1 = strxor(bytes.fromhex(temp_value), bytes.fromhex(prev_cipher))
        message.append(m1.decode())
        prev_cipher = byte
    message[len(message) - 1] = unpadd(message[len(message) - 1])
    return ''.join(message)
Пример #5
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]
    def digest(self):
        """Return the **binary** (non-printable) MAC of the message that has
        been authenticated so far.

        This method does not change the state of the MAC object.
        You can continue updating the object after calling this function.

        :Return: A byte string of `digest_size` bytes. It may contain non-ASCII
         characters, including null bytes.
        """

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

        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 + bchr(0x80) +\
                    bchr(0) * (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
Пример #7
0
    def set_keys(self, keys):
        """ Initialisations des clés pour le chiffrement/déchiffrement,
        une clée doit être une suite de bytes de longeur 256, 512 ou 1024 bits
        
        :param keys: la clé pour le chiffrement
        :type keys: bytes"""

        # keys doit être du type bytes
        if isinstance(keys, bytes):
            # vérifie et sauvegarde la taille de keys
            self.set_block_size(len(keys) * 8)
            # on évalue N
            N = self.get_block_size() // 64  # ici notre N vaut 4, 8 ou 16
            # on affecte les valeurs à K
            K = []
            for i in range(N):  # découpage de keys en N mots
                K.append(keys[(i * (64 // 8)):((i + 1) * (64 // 8))])
            # on ajoute le dernier mot
            C = b'\x1b\xd1\x1b\xda\xa9\xfc\x1a\x22'
            K.append(C)
            for i in range(N):  # on apllique le xor sur tout les mots
                K[N] = strxor(K[N], K[i])
            # On calcul les tweaks
            tweak = self.get_tweak()
            t = [tweak[0:8], tweak[8:16], strxor(tweak[0:8], tweak[8:16])]
            # On détemine les sous-clés k
            k = []
            for s in range(20):  # s in [0;19]
                k.append([])
                for i in range(N):  # i in [0:N-1]
                    step_key = K[(i + s) % (N + 1)]
                    if i <= N - 4:  # on prend directment une sous-clé sans modification
                        ki = step_key
                    elif i == N - 3:  # on additionne avec un tweak
                        int_tweak = int.from_bytes(t[s % 3], sys.byteorder)
                        int_Key = int.from_bytes(step_key, sys.byteorder)
                        ki = (int_Key + int_tweak) % pow(2, 64)
                        # convert back to bytes
                        ki = ki.to_bytes(64 // 8, sys.byteorder)
                    elif i == N - 2:  # même chose mais avec un autre tweak
                        int_tweak = int.from_bytes(t[(s + 1) % 3],
                                                   sys.byteorder)
                        int_Key = int.from_bytes(step_key, sys.byteorder)
                        ki = (int_Key + int_tweak) % pow(2, 64)
                        # convert back to bytes
                        ki = ki.to_bytes(64 // 8, sys.byteorder)
                    elif i == N - 1:  # on additionne directement avec s
                        int_Key = int.from_bytes(step_key, sys.byteorder)
                        ki = (int_Key + s) % pow(2, 64)
                        # convert back to bytes
                        ki = ki.to_bytes(64 // 8, sys.byteorder)
                    else:
                        raise OverflowError('i gets > N')
                    k[s].append(ki)
        else:
            raise TypeError("keys must be bytes type")
        self.__keys = k
        self.__initial_key = keys
Пример #8
0
    def __TOY_inv(self, ciphertext, key):
        assert(len(key) == self.BLOCK_SIZE)
        assert(len(ciphertext) % self.BLOCK_SIZE == 0)

        post_xor = strxor(ciphertext, key)
        sub_word = b''.join(self.inv_sub_word(word)
                            for word in slice_into_block(post_xor, self.BLOCK_SIZE))
        pre_xor = strxor(sub_word, key)

        return pre_xor
Пример #9
0
    def __TOY(self, message, key):
        assert(len(key) == self.BLOCK_SIZE)
        assert(len(message) % self.BLOCK_SIZE == 0)

        pre_xor = strxor(message, key)
        sub_word = b''.join(self.sub_word(word)
                            for word in slice_into_block(pre_xor, self.BLOCK_SIZE))
        post_xor = strxor(sub_word, key)

        return post_xor
Пример #10
0
    def encrypt(self, message):
        """Produce the PKCS#1 OAEP encryption of a message.

        This function is named ``RSAES-OAEP-ENCRYPT``, and is specified in
        section 7.1.1 of RFC3447.

        :Parameters:
         message : byte string
                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.

        :Return: A byte string, the ciphertext in which the message is encrypted.
            It is as long as the RSA modulus (in bytes).
        :Raise ValueError:
            If the RSA key length is not sufficiently long to deal with the given
            message.
        """
        # TODO: Verify the key is RSA

        # See 7.1.1 in RFC3447
        modBits = Cryptodome.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 = bchr(0x00)*ps_len
        # Step 2c
        db = lHash + ps + bchr(0x01) + 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 = bchr(0x00) + 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
Пример #11
0
    def encrypt(self, message):
        """Produce the PKCS#1 OAEP encryption of a message.

        This function is named ``RSAES-OAEP-ENCRYPT``, and is specified in
        section 7.1.1 of RFC3447.

        :Parameters:
         message : byte string
                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.

        :Return: A byte string, the ciphertext in which the message is encrypted.
            It is as long as the RSA modulus (in bytes).
        :Raise ValueError:
            If the RSA key length is not sufficiently long to deal with the given
            message.
        """
        # TODO: Verify the key is RSA

        # See 7.1.1 in RFC3447
        modBits = Cryptodome.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 = bchr(0x00) * ps_len
        # Step 2c
        db = lHash + ps + bchr(0x01) + 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 = bchr(0x00) + 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
Пример #12
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: byte string

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

        :raises ValueError:
            if the message is too long.
        """
        # TODO: Verify the key is RSA

        # See 7.1.1 in RFC3447
        modBits = Cryptodome.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 = bchr(0x00)*ps_len
        # Step 2c
        db = lHash + ps + bchr(0x01) + 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 = bchr(0x00) + 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
Пример #13
0
    def __init__(self, key, msg=b(""), digestmod=None):
        """Create a new HMAC object.

        :Parameters:
          key : byte string
            secret key for the MAC object.
            It must be long enough to match the expected security level of the
            MAC. However, there is no benefit in using keys longer than the
            `digest_size` of the underlying hash algorithm.
          msg : byte string
            The very first chunk of the message to authenticate.
            It is equivalent to an early call to `update()`. Optional.
        :Parameter digestmod:
            The hash algorithm the HMAC is based on.
            Default is `Cryptodome.Hash.MD5`.
        :Type digestmod:
            A hash module or object instantiated from `Cryptodome.Hash`
        """

        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

        try:
            if len(key) <= digestmod.block_size:
                # Step 1 or 2
                key_0 = key + bchr(0) * (digestmod.block_size - len(key))
            else:
                # Step 3
                hash_k = digestmod.new(key).digest()
                key_0 = hash_k + bchr(0) * (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, bchr(0x36) * 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, bchr(0x5c) * len(key_0))

        # Start step 8 and 9
        self._outer = digestmod.new(key_0_opad)
Пример #14
0
    def __init__(self, key, msg=b(""), digestmod=None):
        """Create a new HMAC object.

        :Parameters:
          key : byte string
            secret key for the MAC object.
            It must be long enough to match the expected security level of the
            MAC. However, there is no benefit in using keys longer than the
            `digest_size` of the underlying hash algorithm.
          msg : byte string
            The very first chunk of the message to authenticate.
            It is equivalent to an early call to `update()`. Optional.
        :Parameter digestmod:
            The hash algorithm the HMAC is based on.
            Default is `Cryptodome.Hash.MD5`.
        :Type digestmod:
            A hash module or object instantiated from `Cryptodome.Hash`
        """

        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

        try:
            if len(key) <= digestmod.block_size:
                # Step 1 or 2
                key_0 = key + bchr(0) * (digestmod.block_size - len(key))
            else:
                # Step 3
                hash_k = digestmod.new(key).digest()
                key_0 = hash_k + bchr(0) * (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, bchr(0x36) * 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, bchr(0x5c) * len(key_0))

        # Start step 8 and 9
        self._outer = digestmod.new(key_0_opad)
Пример #15
0
def q3_block_cipher_timing_attack(
        leaky_encipher=lab6_helper.leaky_encipher_example):
    """Question 3: Collision timing attack on AES"""

    trials = []
    At = 14
    A1t = 0

    for _ in range(15):
        dic = {}

        for _ in range(200):
            Rand = urandom(At)
            Rand1 = urandom(A1t)
            mintrial = 17

            byte1 = "01"
            secondtrial = ""
            for i in range(0, 16**2):
                byte2 = "{:02x}".format(i)
                pt = binascii.unhexlify(byte1) + Rand1 + binascii.unhexlify(
                    byte2) + Rand
                trial, ct = leaky_encipher(pt)
                if trial <= mintrial:
                    mintrial = trial
                    secondtrial = [byte1, byte2]

                mainTrial = strxor(binascii.unhexlify(secondtrial[0]),
                                   binascii.unhexlify(secondtrial[1])).hex()

                if mainTrial not in dic:
                    dic[mainTrial] = 1
                else:
                    dic[mainTrial] += 1

        maxor = max(dic.items(), key=operator.itemgetter(1))[0]
        trials.append(maxor)
        At -= 1
        A1t += 1

    plaintext = "this is a adals!"
    tri, leaky = leaky_encipher(plaintext.encode())

    for j in range(0, 16**2):
        key = "{:02x}".format(j)
        poss1rd = key
        for t in trials:
            posskey = strxor(binascii.unhexlify(key),
                             binascii.unhexlify(t)).hex()
            poss1rd = posskey + poss1rd
        possCi = aes_(poss1rd, plaintext.encode())
        if possCi == leaky:
            return poss1rd
    return "NOPE"
Пример #16
0
 def crypt(self, block):
     """ Crypt le block"""
     # le vecteur doit être initilisé si on ne s'en ai jamais servi
     if self.get_vector() is None:
         self.init_vector(len(block))
     # premièrement on xor avec le vecteur
     crypted_block = strxor(self.get_vector(), block)
     # Puis on chiffre le tout
     crypted_block = self.get_encrypter().crypt(crypted_block)
     # enfin on sauvegarde le résultat dans le vecteur
     self.set_vector(strxor(crypted_block, block))
     # on retourne le résulat
     return crypted_block
Пример #17
0
 def uncrypt(self, block):
     """ Uncrypt le block"""
     # le vecteur doit être initilisé si on ne s'en ai jamais servi
     if self.get_vector() is None:
         self.init_vector(len(block))
     # Premièrement on déchiffre le block
     uncrypted_block = self.get_encrypter().uncrypt(block)
     # on xor le résultat avec notre vecteur
     uncrypted_block = strxor(self.get_vector(), uncrypted_block)
     # notre vecteur prend la valeur du block
     self.set_vector(strxor(block, uncrypted_block))
     # On retourne le texte claire
     return uncrypted_block
Пример #18
0
def _cipher(data):
    xorKey = io.BytesIO()
    digest = constants.msKey[:20]
    while xorKey.tell() < len(data):
        digest = SHA.new(digest + constants.msKey[20:40]).digest()
        xorKey.write(digest)
    return strxor(data, xorKey.getvalue()[:len(data)])
Пример #19
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.
        :Raise ValueError: when the component is empty
        """

        if not item:
            raise ValueError("A component cannot be empty")

        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 = item
Пример #20
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)
Пример #21
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)
Пример #22
0
 def decrypt(self, ct: bytes, iv: bytes) -> bytes:
     c = [iv] + iteration.blocks(ct, AES.block_size)
     p = [
         strxor.strxor(x, self.ecb.decrypt(y))
         for x, y in iteration.pairs(c)
     ]
     return self._unpad(b"".join(p))
Пример #23
0
def leaky_encipher(key, A):
    # Let me denote the state in AES as follows:
    # A = input to AES
    # Z = enciphering of A (aka, result after applying all 10 rounds)
    # Y = value just before the final AddRoundKey
    # X = value at the beginning of the 10th round, before ShiftRows and SubBytes as well (remember: the final round lacks MixColumns)
    
    # So the final round of AES looks like this:
    # X -> [SubBytes] -> [ShiftRows] -> Y -> [AddRoundKey, aka strxor with lastroundkey] -> Z
    
    # First, perform all 10 rounds of AES
    assert(len(A) == 16)
    permutation = AES.new(key, AES.MODE_ECB)
    Z = permutation.encrypt(A)               # This is the desired output! Now we just have to simulate the cache lines...
    
    # Now go back one round of AES, from the end back to the beginning. We begin with AddRoundKey, which is its own inverse.
    lastroundkey = aes128_lastroundkey(key)  # This is the key used in the final xor step of AES. You need the aeskeyexp helper file for this.
    Y = strxor(Z, lastroundkey)              # xor is its own inverse
    #print("key",lastroundkey)
    Yvec = [ord(i) for i in Y]               # Transform the string into a vector of bytes
    #print("Yvec",Yvec)
    
    sinv_yvec = [Sinv[y] for y in Yvec]
    
    # ShiftRows is irrelevant here because it merely permutes the order of bytes, and we won't care about that when we output a set.
    # So it remains to perform an inverse SubBytes operation.
    #X = frozenset(map(Sinv, Yvec)) # Apply Sinv to each byte of the state, and form the *set* of resulting values
    X = frozenset(sinv_yvec)
    
    # Return both the ciphertext and the set of bytes at the start of the 10th round
    return [Z, X]
Пример #24
0
def guess_block(block: bytes) -> bytes:
    deblock = bytearray([0] * BS)  # AES decrypted block
    for i in range(BS - 1, -1, -1):
        # guess deblock[i] knowing deblock[i+1:]
        pad_siz = BS - i
        # choosing the iv, we will force block[i+1:]
        # to be decrypted as the following pad -1 byte
        padding = bytes([pad_siz] * (pad_siz - 1))
        iv_suff = strxor(deblock[i + 1:], padding)
        # block[i] will have to be decrypted as pad_size
        # for the padding to be valid
        # except for the last byte which will require
        # a second request to confirm the pad '1'
        for b in range(256):
            # try iv[i] = b
            iv = bytes(i) + bytes([b]) + iv_suff
            if oracle(iv, block):
                if i == BS - 1:  # last byte
                    # check that it is not a false positive:
                    # make sure that the valid pad is '1' and
                    # not '22', '333', '4444', ...
                    # by changing the previous byte in the IV
                    iv = bytes(i - 1) + bytes([1, b])
                    if oracle(iv, block):
                        # confirmed
                        break
                else:
                    # block[i] was decrypted to pad_size
                    break
        deblock[i] = b ^ pad_siz
    return bytes(deblock)
Пример #25
0
def q2_cbc_mac(key, message, cipher=Sample_Cipher):
    """Question 2
        Args:
            key     (str):      ascii input string (1-byte long)
            message (str):      ascii input string with an arbitrary length
            cipher  (Cipher):   Cipher class (check `sample_cipher.py`) that provides access to the TOY cipher
                                    +   cipher.TOY(message, key)
        Your task:
            Implement CBC-MAC mode on top of the TOY cipher (from question 1). Using the TOY cipher will result in a 
            tag of length 1-byte, such a short tag limits the security guarantees, but we won't focus on that in this question.
        
        Your Output:
            Compute and return the 1-byte message tag as a hex-encoded string
        
        Test vectors:
            q2_cbc_mac("k", "This is a test message!", Sample_Cipher()) == "1f"
            q2_cbc_mac("a", "print(\"CBC-MAC is a very strong hash function!\")", Sample_Cipher()) == "a6"
            q2_cbc_mac("m", "short_msg", Sample_Cipher()) == "12"
    """ 
    """convert the string to hexadecimal representaion and store in array and just call the TOY for as many bytes in the array 
    the first one is done outside the loop and CBC mode is done inside the loop """
    enc_key = key.encode('ascii').hex()
    array = []
    for char in message:
        temp = ord(char)
        val = hex(temp)
        final_val = val[2:]
        array.append(final_val)
    final_tag = cipher.TOY(array[0],enc_key)
    for byte in array[1:]:
         intermediate_tag = strxor(bytes.fromhex(final_tag),bytes.fromhex(byte)).hex()
         final_tag = cipher.TOY(intermediate_tag,enc_key)
    return final_tag
Пример #26
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 xrange(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")
Пример #27
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)
Пример #28
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:
            final = self._last_string[:-16] + strxor(self._last_string[-16:], self._cache)
        else:
            padded = (self._last_string + bchr(0x80)+ bchr(0)*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()
Пример #29
0
 def token_key_pair(self, mac: str, ssid: str, pw: str):
     local_key = self.local_key(mac, ssid, pw)
     rand = get_random_bytes(32)
     key = strxor(rand, local_key)
     token = self.aes_cbc_encrypt(key, local_key)
     sign = sha256(key).digest()
     return (token + sign, key)
Пример #30
0
def q1_dec_cbc_mode(key, ciphertext, iv, cipher=Sample_Cipher):
    """Implement CBC Mode **decryption**"""
    
    pad = lambda s: s + (cipher.BLOCK_SIZE - len(s) % cipher.BLOCK_SIZE) * chr(cipher.BLOCK_SIZE - len(s) % cipher.BLOCK_SIZE)
    unpad = lambda s : s[0:-ord(s[-1])]
    cipher1=slice_into_block(ciphertext, cipher.BLOCK_SIZE*2)
    msg=cipher.decipher(key,cipher1[0])
    msgs=""
    first=binascii.hexlify(strxor(binascii.unhexlify(iv),binascii.unhexlify(msg))).decode()
    msgs+=first
    for i in range(1, len(cipher1)):
        msg=cipher.decipher(key,cipher1[i])
        last=binascii.hexlify(strxor(binascii.unhexlify(cipher1[i-1]),binascii.unhexlify(msg))).decode()
        msgs+=last
   
    return unpad(binascii.unhexlify(msgs).decode()) 
Пример #31
0
    def cbcmac(key, message, iv):
        BLOCK_SIZE = 16

        def Encipher(key, X):
            assert(len(key) == BLOCK_SIZE*2)
            assert(len(X)   == BLOCK_SIZE*2)        
            return bytes.fromhex(aes_encipher(key,X)) 

        def slice_into_blocks(message, block_size):
            len_message = len(message)
            assert(len_message >= block_size)
            return [message[i: i + block_size] for i in range(0 , len_message, block_size)]

        len_message = len(message)
        num_rounds = len_message//BLOCK_SIZE
        msg_blocks = slice_into_blocks(message, BLOCK_SIZE)

        assert(len(msg_blocks) == num_rounds)
        if not iv:
            iv = bytes([0 for _ in range(BLOCK_SIZE)]) # All zeros IV to start with

        for msg_block in msg_blocks:
            block_input = strxor(msg_block.encode('ascii'), iv)
            block_output = Encipher(key.encode('ascii').hex(), block_input.hex())
            iv = block_output
        return block_output.hex()
Пример #32
0
def leaky_encipher_example(plaintext):
    """performs an AES encipher on the input 16-bytes input `plaintext`
    
    Args:
        plaintext   (bytes)     : 16-bytes input to be passed to AES for enciphering
    Output:
        ret         (int, bytes): number of unique values in the intermidiate state
                                after the first round of substitutions, and the ciphertext
                                produced by running AES on the input.
    """

    key = TEST_KEY  # NOTE: Just as an example, a random key would be used to test your code

    # First, perform all 10 rounds of AES
    assert (len(plaintext) == 16)

    permutation = AES.new(bytes.fromhex(key), AES.MODE_ECB)
    Z = permutation.encrypt(plaintext)  # This is the desired output!

    mid_state = strxor(plaintext, bytes.fromhex(key))

    X = frozenset(map(Sbox,
                      mid_state))  # Apply Sbox to each byte of the state,
    # and form the *set* of resulting values

    return (len(X), Z)
Пример #33
0
    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
Пример #34
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:
            final = self._last_string[:-16] + strxor(self._last_string[-16:], self._cache)
        else:
            padded = (self._last_string + bchr(0x80)+ bchr(0)*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()
Пример #35
0
    def decrypt_data(self, given_key=None, file_name=None):
        # data parsing
        if file_name is not None:
            self.file_name = file_name
        with open(self.file_name, 'rb') as file:
            iv = file.read(AES.block_size)
            encrypted_data = file.read()

        # key setting
        raw_key = given_key
        if raw_key is None:
            raw_key = self.raw_key
        set_key = self.set_key(raw_key)
        encoded_key = set_key.encode()
        key = strxor.strxor(encoded_key, iv)

        # decrypt data
        cipher = AES.new(key, AES.MODE_CBC, iv)
        decrypted_data = cipher.decrypt(encrypted_data)
        unpadded_data = Padding.unpad(decrypted_data, AES.block_size)
        plain_data = unpadded_data.decode()
        parsed_data = plain_data.split(';')
        self.login_id = parsed_data[0]
        self.login_password = parsed_data[1]
        self.account_password = parsed_data[2]
        self.certificate_password = parsed_data[3]

        return parsed_data
Пример #36
0
    def encrypt_data(self, login_id, login_password, account_password, certificate_password, given_key=None, file_name=None):
        plain_data = ';'.join((login_id, login_password, account_password, certificate_password))
        if file_name is not None:
            self.file_name = file_name

        # key setting
        random = Random.new()
        raw_key = given_key
        if raw_key is None:
            raw_key = self.raw_key
        set_key = self.set_key(raw_key)
        iv = random.read(AES.block_size)
        encoded_key = set_key.encode()
        key = strxor.strxor(encoded_key, iv)

        # Encryption
        encoded_data = plain_data.encode()
        padded_data = Padding.pad(encoded_data, AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        encrypted_data = cipher.encrypt(padded_data)

        # File writing
        with open(self.file_name, 'wb') as file:
            file.write(iv)
            file.write(encrypted_data)
Пример #37
0
    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
Пример #38
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 : byte string/array
            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 = bchr(0) * self.block_size
            for i in xrange(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")
Пример #39
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.
        :Raise ValueError: when the component is empty
        """

        if not item:
            raise ValueError("A component cannot be empty")

        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 = item
Пример #40
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)
Пример #41
0
    def decrypt(cls, data, key):
        validate_key_size(key, cls.key_size, "Twofish")

        ctr = BlockCipher.generate_decrypt_counter(data, cls.block_size)
        tfish = twofish.Twofish(key)

        return strxor(data[cls.block_size:],
                      cls._gen_keystream(len(data[cls.block_size:]), tfish, ctr))
Пример #42
0
 def test_corrupt_decrypt(self, tv):
     self._id = "Wycheproof Corrupt Decrypt EAX Test #" + str(tv.id)
     if len(tv.iv) == 0 or len(tv.ct) < 1:
         return
     cipher = AES.new(tv.key, AES.MODE_EAX, tv.iv, mac_len=tv.tag_size)
     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)
Пример #43
0
    def encrypt(cls, data, key, iv_data):
        validate_key_size(key, cls.key_size, "Twofish")

        iv, ctr = iv_data
        tfish = twofish.Twofish(key)
        ciphertext = strxor(data, cls._gen_keystream(len(data), tfish, ctr))

        return iv + ciphertext
 def test_corrupt_decrypt(self, tv):
     self._id = "Wycheproof Corrupt Decrypt ChaCha20-Poly1305 Test #" + str(tv.id)
     if len(tv.iv) == 0 or len(tv.ct) < 1:
         return
     cipher = ChaCha20_Poly1305.new(key=tv.key, nonce=tv.iv)
     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)
Пример #45
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)
    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)
Пример #47
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)
Пример #48
0
    def test_output_overlapping_memoryview(self):
        """Verify result can be stored in overlapping memory"""

        term1 = memoryview(bytearray(unhexlify(b"ff339a83e5cd4cdf5649")))
        term2 = unhexlify(b"383d4ba020573314395b")
        original_term2 = term2[:]
        expected_xor = unhexlify(b"c70ed123c59a7fcb6f12")
        
        result = strxor(term1, term2, output=term1)
        
        self.assertEqual(result, None)
        self.assertEqual(term1, expected_xor)
        self.assertEqual(term2, original_term2)
Пример #49
0
def _scryptROMix(blocks, n):
    """Sequential memory-hard function for scrypt."""

    x = [blocks[i:i + 64] for i in xrange(0, len(blocks), 64)]
    len_x = len(x)
    v = [None]*n
    load_le_uint32 = _raw_salsa20_lib.load_le_uint32
    for i in xrange(n):
        v[i] = x
        x = _scryptBlockMix(x, len_x)
    for i in xrange(n):
        j = load_le_uint32(x[-1]) & (n - 1)
        t = [strxor(x[idx], v[j][idx]) for idx in xrange(len_x)]
        x = _scryptBlockMix(t, len_x)
    return b("").join([get_raw_buffer(y) for y in x])
Пример #50
0
 def test_output_memoryview(self):
     """Verify result can be stored in pre-allocated memory"""
     
     term1 = unhexlify(b"ff339a83e5cd4cdf5649")
     term2 = unhexlify(b"383d4ba020573314395b")
     original_term1 = term1[:]
     original_term2 = term2[:]
     expected_xor = unhexlify(b"c70ed123c59a7fcb6f12")
     output = memoryview(bytearray(len(term1)))
     
     result = strxor(term1, term2, output=output)
     
     self.assertEqual(result, None)
     self.assertEqual(output, expected_xor)
     self.assertEqual(term1, original_term1)
     self.assertEqual(term2, original_term2)
Пример #51
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:])
Пример #52
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 = bchr(0) * self.block_size
            for i in xrange(3):
                tag = strxor(tag, self._omac[i].digest())
            self._mac_tag = tag[: self._mac_len]

        return self._mac_tag
Пример #53
0
def _EMSA_PSS_ENCODE(mhash, emBits, randFunc, mgf, sLen):
    """
    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
Пример #54
0
    def decrypt(self, ct):
        """Decrypt a PKCS#1 OAEP ciphertext.

        This function is named ``RSAES-OAEP-DECRYPT``, and is specified in
        section 7.1.2 of RFC3447.

        :Parameters:
         ct : byte string
                The ciphertext that contains the message to recover.

        :Return: A byte string, the original message.
        :Raise ValueError:
            If the ciphertext length is incorrect, or if the decryption does not
            succeed.
        :Raise TypeError:
            If the RSA key has no private half.
        """

        # See 7.1.2 in RFC3447
        modBits = Cryptodome.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(ct) != k or k<hLen+2:
            raise ValueError("Ciphertext with incorrect length.")
        # Step 2a (O2SIP)
        ct_int = bytes_to_long(ct)
        # 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
        valid = 1
        one = db[hLen:].find(bchr(0x01))
        lHash1 = db[:hLen]
        if lHash1!=lHash:
            valid = 0
        if one<0:
            valid = 0
        if bord(y)!=0:
            valid = 0
        if not valid:
            raise ValueError("Incorrect decryption.")
        # Step 4
        return db[hLen+one+1:]
Пример #55
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 = nonce
        """Nonce used for this session."""
        if len(nonce) not in range(1, 16):
            raise ValueError("Nonce must be at most 15 bytes long")

        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 = (bchr(self._mac_len << 4 & 0xFF) +
                 bchr(0) * (14 - len(self.nonce)) +
                 bchr(1) +
                 self.nonce)
        bottom = bord(nonce[15]) & 0x3F   # 6 bits, 0..63
        ktop = factory.new(key, factory.MODE_ECB, **params_without_key)\
                      .encrypt(nonce[:15] + bchr(bord(nonce[15]) & 0xC0))
        stretch = ktop + strxor(ktop[:8], ktop[1:9])    # 192 bits
        offset_0 = long_to_bytes(bytes_to_long(stretch) >>
                                 (64 - bottom), 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()
 def test3(self):
     term1 = unhexlify(b("ff339a83e5cd4cdf5649"))
     all_zeros = bchr(0) * len(term1)
     self.assertEqual(strxor(term1, term1), all_zeros)
 def test2(self):
     es = b("")
     self.assertEqual(strxor(es, es), es)
 def test1(self):
     term1 = unhexlify(b("ff339a83e5cd4cdf5649"))
     term2 = unhexlify(b("383d4ba020573314395b"))
     result = unhexlify(b("c70ed123c59a7fcb6f12"))
     self.assertEqual(strxor(term1, term2), result)
     self.assertEqual(strxor(term2, term1), result)
Пример #59
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:
        return False
    # 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")