Пример #1
0
    def verify(self, msg_hash, signature):
        """Verify that a certain PKCS#1 PSS signature is authentic.

        This function checks if the party holding the private half of the given
        RSA key has really signed the message.

        This function is called ``RSASSA-PSS-VERIFY``, and is specified in section
        8.1.2 of RFC3447.

        :Parameters:
          msg_hash : hash object
            The hash that was carried out over the message. This is an object
            belonging to the `Crypto.Hash` module.
          signature : byte string
            The signature that needs to be validated.
        :Raise ValueError:
            If the signature is not authentic.
        """
        # TODO: Verify the key is RSA

        # Set defaults for salt length and mask generation function
        if self._saltLen == None:
            sLen = msg_hash.digest_size
        else:
            sLen = self._saltLen
        if self._mgfunc:
            mgf = self._mgfunc
        else:
            mgf  = lambda x,y: MGF1(x,y,msg_hash)

        modBits = Crypto.Util.number.size(self._key.n)

        # See 8.1.2 in RFC3447
        k = ceil_div(modBits,8) # Convert from bits to bytes
        # Step 1
        if len(signature) != k:
            raise ValueError("The signature is not authentic")
        # Step 2a (O2SIP)
        signature_int = bytes_to_long(signature)
        # Step 2b (RSAVP1)
        em_int = self._key._encrypt(signature_int)
        # Step 2c (I2OSP)
        emLen = ceil_div(modBits - 1, 8)
        em = long_to_bytes(em_int, emLen)
        #bchr(0x00)*(emLen-len(em)) + em
        # Step 3
        failed = False
        try:
            failed = not EMSA_PSS_VERIFY(msg_hash, em, modBits-1, mgf, sLen)
        except ValueError:
            failed = True
        # Step 4
        if failed:
            raise ValueError("The signature is not authentic")
Пример #2
0
    def verify(self, msg_hash, signature):
        """Verify that a certain PKCS#1 PSS signature is authentic.

        This function checks if the party holding the private half of the given
        RSA key has really signed the message.

        This function is called ``RSASSA-PSS-VERIFY``, and is specified in section
        8.1.2 of RFC3447.

        :Parameters:
          msg_hash : hash object
            The hash that was carried out over the message. This is an object
            belonging to the `Crypto.Hash` module.
          signature : byte string
            The signature that needs to be validated.
        :Raise ValueError:
            If the signature is not authentic.
        """
        # TODO: Verify the key is RSA

        # Set defaults for salt length and mask generation function
        if self._saltLen == None:
            sLen = msg_hash.digest_size
        else:
            sLen = self._saltLen
        if self._mgfunc:
            mgf = self._mgfunc
        else:
            mgf  = lambda x,y: MGF1(x,y,msg_hash)

        modBits = Crypto.Util.number.size(self._key.n)

        # See 8.1.2 in RFC3447
        k = ceil_div(modBits,8) # Convert from bits to bytes
        # Step 1
        if len(signature) != k:
            raise ValueError("The signature is not authentic")
        # Step 2a (O2SIP)
        signature_int = bytes_to_long(signature)
        # Step 2b (RSAVP1)
        em_int = self._key._encrypt(signature_int)
        # Step 2c (I2OSP)
        emLen = ceil_div(modBits - 1, 8)
        em = long_to_bytes(em_int, emLen)
        #bchr(0x00)*(emLen-len(em)) + em
        # Step 3
        failed = False
        try:
            failed = not EMSA_PSS_VERIFY(msg_hash, em, modBits-1, mgf, sLen)
        except ValueError:
            failed = True
        # Step 4
        if failed:
            raise ValueError("The signature is not authentic")
Пример #3
0
    def verify(self, mhash, S):
        """Verify that a certain PKCS#1 PSS signature is authentic.
    
        This function checks if the party holding the private half of the given
        RSA key has really signed the message.
    
        This function is called ``RSASSA-PSS-VERIFY``, and is specified in section
        8.1.2 of RFC3447.
    
        :Parameters:
         mhash : hash object
                The hash that was carried out over the message. This is an object
                belonging to the `Crypto.Hash` module.
         S : string
                The signature that needs to be validated.
    
        :Return: True if verification is correct. False otherwise.
        """
        # TODO: Verify the key is RSA
    
        # Set defaults for salt length and mask generation function
        if self._saltLen == None:
            sLen = mhash.digest_size
        else:
            sLen = self._saltLen
        if self._mgfunc:
            mgf = self._mgfunc
        else:
            mgf  = lambda x,y: MGF1(x,y,mhash)

        modBits = Crypto.Util.number.size(self._key.n)
    
        # See 8.1.2 in RFC3447
        k = ceil_div(modBits,8) # Convert from bits to bytes
        # Step 1
        if len(S) != k:
            return False
        # Step 2a (O2SIP), 2b (RSAVP1), and partially 2c (I2OSP)
        # Note that signature must be smaller than the module
        # but RSA.py won't complain about it.
        # TODO: Fix RSA object; don't do it here.
        em = self._key.encrypt(S, 0)[0]
        # Step 2c
        emLen = ceil_div(modBits-1,8)
        em = bchr(0x00)*(emLen-len(em)) + em
        # Step 3
        try:
            result = EMSA_PSS_VERIFY(mhash, em, modBits-1, mgf, sLen)
        except ValueError:
            return False
        # Step 4
        return result
Пример #4
0
    def verify(self, mhash, S):
        """Verify that a certain PKCS#1 PSS signature is authentic.
    
        This function checks if the party holding the private half of the given
        RSA key has really signed the message.
    
        This function is called ``RSASSA-PSS-VERIFY``, and is specified in section
        8.1.2 of RFC3447.
    
        :Parameters:
         mhash : hash object
                The hash that was carried out over the message. This is an object
                belonging to the `Crypto.Hash` module.
         S : string
                The signature that needs to be validated.
    
        :Return: True if verification is correct. False otherwise.
        """
        # TODO: Verify the key is RSA
    
        # Set defaults for salt length and mask generation function
        if self._saltLen == None:
            sLen = mhash.digest_size
        else:
            sLen = self._saltLen
        if self._mgfunc:
            mgf = self._mgfunc
        else:
            mgf  = lambda x,y: MGF1(x,y,mhash)

        modBits = Crypto.Util.number.size(self._key.n)
    
        # See 8.1.2 in RFC3447
        k = ceil_div(modBits,8) # Convert from bits to bytes
        # Step 1
        if len(S) != k:
            return False
        # Step 2a (O2SIP), 2b (RSAVP1), and partially 2c (I2OSP)
        # Note that signature must be smaller than the module
        # but RSA.py won't complain about it.
        # TODO: Fix RSA object; don't do it here.
        em = self._key.encrypt(S, 0)[0]
        # Step 2c
        emLen = ceil_div(modBits-1,8)
        em = bchr(0x00)*(emLen-len(em)) + em
        # Step 3
        try:
            result = EMSA_PSS_VERIFY(mhash, em, modBits-1, mgf, sLen)
        except ValueError:
            return False
        # Step 4
        return result
Пример #5
0
    def sign(self, mhash):
        """Produce the PKCS#1 v1.5 signature of a message.
    
        This function is named ``RSASSA-PKCS1-V1_5-SIGN``, and is specified in
        section 8.2.1 of RFC3447.
    
        :Parameters:
         mhash : hash object
                The hash that was carried out over the message. This is an object
                belonging to the `Crypto.Hash` module.
    
        :Return: The signature encoded as a string.
        :Raise ValueError:
            If the RSA key length is not sufficiently long to deal with the given
            hash algorithm.
        :Raise TypeError:
            If the RSA key has no private half.
        """
        # TODO: Verify the key is RSA

        # See 8.2.1 in RFC3447
        modBits = Crypto.Util.number.size(self._key.n)
        k = ceil_div(modBits, 8)  # Convert from bits to bytes

        # Step 1
        em = EMSA_PKCS1_V1_5_ENCODE(mhash, k)
        # Step 2a (OS2IP) and 2b (RSASP1)
        m = self._key.decrypt(em)
        # Step 2c (I2OSP)
        S = bchr(0x00) * (k - len(m)) + m
        return S
Пример #6
0
    def randrange(self, *args):
        if len(args) == 3:
            start, stop, step = args
        elif len(args) == 2:
            start, stop = args
            step = 1
        elif len(args) == 1:
            stop = args
            start = 0
            step = 1
        else:
            raise TypeError('randrange expected at most 3 arguments, got %d' % (len(args),))
        if not isinstance(start, (int, long)) or not isinstance(stop, (int, long)) or not isinstance(step, (int, long)):
            raise TypeError('randrange requires integer arguments')
        if step == 0:
            raise ValueError('randrange step argument must not be zero')
        num_choices = ceil_div(stop - start, step)
        if num_choices < 0:
            num_choices = 0
        if num_choices < 1:
            raise ValueError('empty range for randrange(%r, %r, %r)' % (start, stop, step))
        r = num_choices
        while r >= num_choices:
            r = self.getrandbits(size(num_choices))

        return start + step * r
Пример #7
0
    def sign(self, msg_hash):
        """Produce the PKCS#1 v1.5 signature of a message.

        This function is named ``RSASSA-PKCS1-V1_5-SIGN``;
        it is specified in section 8.2.1 of RFC3447.

        :Parameters:
          msg_hash : hash object
            This is an object created with to the `Crypto.Hash` module.
            It was used used to hash the message to sign.

        :Return: The signature encoded as a byte string.
        :Raise ValueError:
            If the RSA key is not long enough when combined with the given
            hash algorithm.
        :Raise TypeError:
            If the RSA key has no private half.
        """

        # See 8.2.1 in RFC3447
        modBits = Crypto.Util.number.size(self._key.n)
        k = ceil_div(modBits,8) # Convert from bits to bytes

        # Step 1
        em = _EMSA_PKCS1_V1_5_ENCODE(msg_hash, k)
        # Step 2a (OS2IP)
        em_int = bytes_to_long(em)
        # Step 2b (RSASP1)
        m_int = self._key._decrypt(em_int)
        # Step 2c (I2OSP)
        signature = long_to_bytes(m_int, k)
        return signature
Пример #8
0
    def sign(self, mhash):
        """Produce the PKCS#1 v1.5 signature of a message.
    
        This function is named ``RSASSA-PKCS1-V1_5-SIGN``, and is specified in
        section 8.2.1 of RFC3447.
    
        :Parameters:
         mhash : hash object
                The hash that was carried out over the message. This is an object
                belonging to the `Crypto.Hash` module.
    
        :Return: The signature encoded as a string.
        :Raise ValueError:
            If the RSA key length is not sufficiently long to deal with the given
            hash algorithm.
        :Raise TypeError:
            If the RSA key has no private half.
        """
        # TODO: Verify the key is RSA

        # See 8.2.1 in RFC3447
        modBits = Crypto.Util.number.size(self._key.n)
        k = ceil_div(modBits, 8)  # Convert from bits to bytes

        # Step 1
        em = EMSA_PKCS1_V1_5_ENCODE(mhash, k)
        # Step 2a (OS2IP) and 2b (RSASP1)
        m = self._key.decrypt(em)
        # Step 2c (I2OSP)
        S = bchr(0x00) * (k - len(m)) + m
        return S
Пример #9
0
def MGF1(mgfSeed, maskLen, hash_gen):
    """Mask Generation Function, described in `B.2.1 of RFC8017
    <https://tools.ietf.org/html/rfc8017>`_.

    :param mfgSeed:
        seed from which the mask is generated
    :type mfgSeed: byte string

    :param maskLen:
        intended length in bytes of the mask
    :type maskLen: integer

    :param hash_gen:
        A module or a hash object from :mod:`Crypto.Hash`
    :type hash_object:

    :return: the mask, as a *byte string*
    """
    
    T = b""
    for counter in iter_range(ceil_div(maskLen, hash_gen.digest_size)):
        c = long_to_bytes(counter, 4)
        hobj = hash_gen.new()
        hobj.update(mgfSeed + c)
        T = T + hobj.digest()
    assert(len(T) >= maskLen)
    return T[:maskLen]
Пример #10
0
def EMSA_PSS_VERIFY(mhash, em, emBits, mgf, sLen):
    emLen = ceil_div(emBits, 8)
    lmask = 0
    for i in xrange(8 * emLen - emBits):
        lmask = lmask >> 1 | 128

    if emLen < mhash.digest_size + sLen + 2:
        return False
    if ord(em[-1:]) != 188:
        return False
    maskedDB = em[:emLen - mhash.digest_size - 1]
    h = em[emLen - mhash.digest_size - 1:-1]
    if lmask & bord(em[0]):
        return False
    dbMask = mgf(h, emLen - mhash.digest_size - 1)
    db = strxor(maskedDB, dbMask)
    db = bchr(bord(db[0]) & ~lmask) + db[1:]
    if not db.startswith(bchr(0) * (emLen - mhash.digest_size - sLen - 2) + bchr(1)):
        return False
    salt = b('')
    if sLen:
        salt = db[-sLen:]
    try:
        hp = mhash.new(bchr(0) * 8 + mhash.digest() + salt).digest()
    except AttributeError:
        hp = Hash_new(mhash, bchr(0) * 8 + mhash.digest() + salt).digest()

    return False if h != hp else True
Пример #11
0
    def randrange(self, *args):
        """randrange([start,] stop[, step]):
        Return a randomly-selected element from range(start, stop, step)."""
        if len(args) == 3:
            (start, stop, step) = args
        elif len(args) == 2:
            (start, stop) = args
            step = 1
        elif len(args) == 1:
            (stop, ) = args
            start = 0
            step = 1
        else:
            raise TypeError("randrange expected at most 3 arguments, got %d" %
                            (len(args), ))
        if (not isinstance(start,
                           (int, long)) or not isinstance(stop, (int, long))
                or not isinstance(step, (int, long))):
            raise TypeError("randrange requires integer arguments")
        if step == 0:
            raise ValueError("randrange step argument must not be zero")

        num_choices = ceil_div(stop - start, step)
        if num_choices < 0:
            num_choices = 0
        if num_choices < 1:
            raise ValueError("empty range for randrange(%r, %r, %r)" %
                             (start, stop, step))

        # Pick a random number in the range of possible numbers
        r = num_choices
        while r >= num_choices:
            r = self.getrandbits(size(num_choices))

        return start + (step * r)
    def randrange(self, *args):
        """randrange([start,] stop[, step]):
        Return a randomly-selected element from range(start, stop, step)."""
        if len(args) == 3:
            (start, stop, step) = args
        elif len(args) == 2:
            (start, stop) = args
            step = 1
        elif len(args) == 1:
            (stop,) = args
            start = 0
            step = 1
        else:
            raise TypeError("randrange expected at most 3 arguments, got %d" % (len(args),))
        if not isinstance(start, (int, long)) or not isinstance(stop, (int, long)) or not isinstance(step, (int, long)):
            raise TypeError("randrange requires integer arguments")
        if step == 0:
            raise ValueError("randrange step argument must not be zero")

        num_choices = ceil_div(stop - start, step)
        if num_choices < 0:
            num_choices = 0
        if num_choices < 1:
            raise ValueError("empty range for randrange(%r, %r, %r)" % (start, stop, step))

        # Pick a random number in the range of possible numbers
        r = num_choices
        while r >= num_choices:
            r = self.getrandbits(size(num_choices))

        return start + (step * r)
Пример #13
0
    def getrandbits(self, k):
        """Return an integer with k random bits."""

        if self._randfunc is None:
            self._randfunc = Random.new().read
        mask = (1 << k) - 1
        return mask & bytes_to_long(self._randfunc(ceil_div(k, 8)))
Пример #14
0
    def randrange(self, *args):
        if len(args) == 3:
            start, stop, step = args
        elif len(args) == 2:
            start, stop = args
            step = 1
        elif len(args) == 1:
            stop, = args
            start = 0
            step = 1
        else:
            raise TypeError('randrange expected at most 3 arguments, got %d' % (len(args),))
        if not isinstance(start, (int, long)) or not isinstance(stop, (int, long)) or not isinstance(step, (int, long)):
            raise TypeError('randrange requires integer arguments')
        if step == 0:
            raise ValueError('randrange step argument must not be zero')
        num_choices = ceil_div(stop - start, step)
        if num_choices < 0:
            num_choices = 0
        if num_choices < 1:
            raise ValueError('empty range for randrange(%r, %r, %r)' % (start, stop, step))
        r = num_choices
        while r >= num_choices:
            r = self.getrandbits(size(num_choices))

        return start + step * r
Пример #15
0
def MGF1(mgfSeed, maskLen, hash_gen):
    """Mask Generation Function, described in `B.2.1 of RFC8017
    <https://tools.ietf.org/html/rfc8017>`_.

    :param mfgSeed:
        seed from which the mask is generated
    :type mfgSeed: byte string

    :param maskLen:
        intended length in bytes of the mask
    :type maskLen: integer

    :param hash_gen:
        A module or a hash object from :mod:`Crypto.Hash`
    :type hash_object:

    :return: the mask, as a *byte string*
    """

    T = b""
    for counter in iter_range(ceil_div(maskLen, hash_gen.digest_size)):
        c = long_to_bytes(counter, 4)
        hobj = hash_gen.new()
        hobj.update(mgfSeed + c)
        T = T + hobj.digest()
    assert (len(T) >= maskLen)
    return T[:maskLen]
Пример #16
0
    def sign(self, msg_hash):
        """Produce the PKCS#1 v1.5 signature of a message.

        This function is named ``RSASSA-PKCS1-V1_5-SIGN``;
        it is specified in section 8.2.1 of RFC3447.

        :Parameters:
          msg_hash : hash object
            This is an object created with to the `Crypto.Hash` module.
            It was used used to hash the message to sign.

        :Return: The signature encoded as a byte string.
        :Raise ValueError:
            If the RSA key is not long enough when combined with the given
            hash algorithm.
        :Raise TypeError:
            If the RSA key has no private half.
        """

        # See 8.2.1 in RFC3447
        modBits = Crypto.Util.number.size(self._key.n)
        k = ceil_div(modBits, 8)  # Convert from bits to bytes

        # Step 1
        em = _EMSA_PKCS1_V1_5_ENCODE(msg_hash, k)
        # Step 2a (OS2IP)
        em_int = bytes_to_long(em)
        # Step 2b (RSASP1)
        m_int = self._key._decrypt(em_int)
        # Step 2c (I2OSP)
        signature = long_to_bytes(m_int, k)
        return signature
Пример #17
0
    def getrandbits(self, k):
        """Return an integer with k random bits."""

        if self._randfunc is None:
            self._randfunc = Random.new().read
        mask = (1 << k) - 1
        return mask & bytes_to_long(self._randfunc(ceil_div(k, 8)))
Пример #18
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 xrange(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 = b("")
    if randFunc and sLen > 0:
        salt = randFunc(sLen)
    # Step 5 and 6
    h = mhash.new(bchr(0x00) * 8 + mhash.digest() + salt)
    # Step 7 and 8
    db = bchr(0x00) * (emLen - sLen - mhash.digest_size -
                       2) + bchr(0x01) + 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
 def decrypt(self, ct):
     modBits = Crypto.Util.number.size(self._key.n)
     k = ceil_div(modBits, 8)
     hLen = self._hashObj.digest_size
     if len(ct) != k or k < hLen + 2:
         raise ValueError('Ciphertext with incorrect length.')
     m = self._key.decrypt(ct)
     em = bchr(0) * (k - len(m)) + m
     lHash = self._hashObj.new(self._label).digest()
     y = em[0]
     maskedSeed = em[1:hLen + 1]
     maskedDB = em[hLen + 1:]
     seedMask = self._mgf(maskedDB, hLen)
     seed = strxor(maskedSeed, seedMask)
     dbMask = self._mgf(seed, k - hLen - 1)
     db = strxor(maskedDB, dbMask)
     valid = 1
     one = db[hLen:].find(bchr(1))
     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.')
     return db[hLen + one + 1:]
Пример #20
0
    def sign(self, msg_hash):
        """Create the PKCS#1 v1.5 signature of a message.

        This function is also called ``RSASSA-PKCS1-V1_5-SIGN`` and
        it is specified in
        `section 8.2.1 of RFC8017 <https://tools.ietf.org/html/rfc8017#page-36>`_.

        :parameter msg_hash:
            This is an object from the :mod:`Crypto.Hash` package.
            It has been used to digest the message to sign.
        :type msg_hash: hash object

        :return: the signature encoded as a *byte string*.
        :raise ValueError: if the RSA key is not long enough for the given hash algorithm.
        :raise TypeError: if the RSA key has no private half.
        """

        # See 8.2.1 in RFC3447
        modBits = Crypto.Util.number.size(self._key.n)
        k = ceil_div(modBits,8) # Convert from bits to bytes

        # Step 1
        em = _EMSA_PKCS1_V1_5_ENCODE(msg_hash, k)
        # Step 2a (OS2IP)
        em_int = bytes_to_long(em)
        # Step 2b (RSASP1)
        m_int = self._key._decrypt(em_int)
        # Step 2c (I2OSP)
        signature = long_to_bytes(m_int, k)
        return signature
Пример #21
0
 def private_encrypt(self, msg):
     modBits = Crypto.Util.number.size(self._key.n)
     k = ceil_div(modBits, 8)  # Convert from bits to bytes
     PS = bchr(0xFF) * (k - len(msg) - 3)
     m = self._key.decrypt(b("\x00\x01") + PS + bchr(0x00) + msg)
     S = bchr(0x00) * (k - len(m)) + m
     return S
Пример #22
0
 def rsa_long_decrypt(self, encrypted_str):
     """Decrypt an encrypted string
     :param encrypted_str: Encrypted string, type str
     :return: Decrypted string, type str
     """
     _msg = base64.b64decode(encrypted_str)
     length = len(_msg)
     # 1024/8=128, 1024 bits key
     # 2048/8=256, 2048 bits key
     mod_bits = size(rsa.importKey(self.private_key).n)
     default_length = ceil_div(mod_bits, 8)
     # Private key to decrypt
     private_obj = PKCS1_v1_5.new(rsa.importKey(self.private_key))
     # Fragment decryption is not required
     if length < default_length:
         return "".join(private_obj.decrypt(_msg, 'xyz'))
     # Fragment decryption
     offset = 0
     res = []
     while length - offset > 0:
         if length - offset > default_length:
             res.append(
                 private_obj.decrypt(_msg[offset:offset + default_length],
                                     'xyz'))
         else:
             res.append(private_obj.decrypt(_msg[offset:], 'xyz'))
         offset += default_length
     return "".join(res)
Пример #23
0
 def rsa_long_encrypt(self, plaintext_str):
     """Encrypt the string
     :param plaintext_str: Strings that need to be encrypted, type str
     :return: Encrypted string, type str
     """
     _msg = plaintext_str.encode('utf-8')
     length = len(_msg)
     # 1024/8 - 11=117, 1024 bits key
     # 2048/8 - 11=245, 2048 bits key
     mod_bits = size(rsa.importKey(self.public_key).n)
     default_length = ceil_div(mod_bits, 8) - 11
     # Public key encryption
     public_obj = PKCS1_v1_5.new(rsa.importKey(self.public_key))
     # Fragment encryption is not required
     if length < default_length:
         return base64.b64encode("".join(public_obj.encrypt(_msg)))
     # Fragment encryption
     offset = 0
     res = []
     while length - offset > 0:
         if length - offset > default_length:
             res.append(
                 public_obj.encrypt(_msg[offset:offset + default_length]))
         else:
             res.append(public_obj.encrypt(_msg[offset:]))
         offset += default_length
     return base64.b64encode("".join(res))
Пример #24
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 xrange(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 = b("")
    if randFunc and sLen>0:
        salt = randFunc(sLen)
    # Step 5 and 6
    h = mhash.new()
    h.update(bchr(0x00)*8 + mhash.digest() + salt)
    # Step 7 and 8
    db = bchr(0x00)*(emLen-sLen-mhash.digest_size-2) + bchr(0x01) + 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
Пример #25
0
    def _chunk_size(cipher: PKCS1OAEP_Cipher) -> int:
        key_n_in_bits = n_size(N=cipher._key.n)
        key_length = ceil_div(key_n_in_bits, 8)
        hash_length = cipher._hashObj.digest_size * 2

        max_chunk_size = key_length - hash_length - 2

        return max_chunk_size
Пример #26
0
def MGF1(mgfSeed, maskLen, hash):
    """Mask Generation Function, described in B.2.1"""
    T = b("")
    for counter in xrange(ceil_div(maskLen, hash.digest_size)):
        c = long_to_bytes(counter, 4)
        T = T + hash.new(mgfSeed + c).digest()
    assert(len(T)>=maskLen)
    return T[:maskLen]
Пример #27
0
def MGF1(mgfSeed, maskLen, hash):
    """Mask Generation Function, described in B.2.1"""
    T = b("")
    for counter in range(ceil_div(maskLen, hash.digest_size)):
        c = long_to_bytes(counter, 4)
        T = T + hash.new(mgfSeed + c).digest()
    assert len(T) >= maskLen
    return T[:maskLen]
Пример #28
0
    def verify(self, msg_hash, signature):
        """Check if the  PKCS#1 PSS signature over a message is valid.

        This function is also called ``RSASSA-PSS-VERIFY`` and
        it is specified in
        `section 8.1.2 of RFC8037 <https://tools.ietf.org/html/rfc8017#section-8.1.2>`_.

        :parameter msg_hash:
            The hash that was carried out over the message. This is an object
            belonging to the :mod:`Crypto.Hash` module.
        :type parameter: hash object

        :parameter signature:
            The signature that needs to be validated.
        :type signature: bytes

        :raise ValueError: if the signature is not valid.
        """

        # Set defaults for salt length and mask generation function
        if self._saltLen is None:
            sLen = msg_hash.digest_size
        else:
            sLen = self._saltLen
        if self._mgfunc:
            mgf = self._mgfunc
        else:
            mgf = lambda x, y: MGF1(x, y, msg_hash)

        modBits = Crypto.Util.number.size(self._key.n)

        # See 8.1.2 in RFC3447
        k = ceil_div(modBits, 8)  # Convert from bits to bytes
        # Step 1
        if len(signature) != k:
            raise ValueError("Incorrect signature")
        # Step 2a (O2SIP)
        signature_int = bytes_to_long(signature)
        # Step 2b (RSAVP1)
        em_int = self._key._encrypt(signature_int)
        # Step 2c (I2OSP)
        emLen = ceil_div(modBits - 1, 8)
        em = long_to_bytes(em_int, emLen)
        # Step 3/4
        _EMSA_PSS_VERIFY(msg_hash, em, modBits - 1, mgf, sLen)
Пример #29
0
    def verify(self, msg_hash, signature):
        """Check if the  PKCS#1 PSS signature over a message is valid.

        This function is also called ``RSASSA-PSS-VERIFY`` and
        it is specified in
        `section 8.1.2 of RFC8037 <https://tools.ietf.org/html/rfc8017#section-8.1.2>`_.

        :parameter msg_hash:
            The hash that was carried out over the message. This is an object
            belonging to the :mod:`Crypto.Hash` module.
        :type parameter: hash object

        :parameter signature:
            The signature that needs to be validated.
        :type signature: bytes

        :raise ValueError: if the signature is not valid.
        """

        # Set defaults for salt length and mask generation function
        if self._saltLen is None:
            sLen = msg_hash.digest_size
        else:
            sLen = self._saltLen
        if self._mgfunc:
            mgf = self._mgfunc
        else:
            mgf = lambda x, y: MGF1(x, y, msg_hash)

        modBits = Crypto.Util.number.size(self._key.n)

        # See 8.1.2 in RFC3447
        k = ceil_div(modBits, 8)  # Convert from bits to bytes
        # Step 1
        if len(signature) != k:
            raise ValueError("Incorrect signature")
        # Step 2a (O2SIP)
        signature_int = bytes_to_long(signature)
        # Step 2b (RSAVP1)
        em_int = self._key._encrypt(signature_int)
        # Step 2c (I2OSP)
        emLen = ceil_div(modBits - 1, 8)
        em = long_to_bytes(em_int, emLen)
        # Step 3/4
        _EMSA_PSS_VERIFY(msg_hash, em, modBits-1, mgf, sLen)
Пример #30
0
 def update_rsa_key_info(self, rsa_key, mode):
     """Stores info about the RSA key.
     """
     modBits = number.size(rsa_key._key.n)
     self.rsa_key_info[mode] = {"bits": modBits}
     k = number.ceil_div(modBits, 8)
     self.rsa_key_info[mode].update({"bytes": k})
     hLen = rsa_key._hashObj.digest_size
     self.rsa_key_info[mode].update({"max_message_length": k - (2 * hLen) - 2})
Пример #31
0
 def update_rsa_key_info(self, rsa_key, mode):
     """Stores info about the RSA key.
     """
     modBits = number.size(rsa_key._key.n)
     self.rsa_key_info[mode] = {'bits': modBits}
     k = number.ceil_div(modBits, 8)
     self.rsa_key_info[mode].update({'bytes': k})
     hLen = rsa_key._hashObj.digest_size
     self.rsa_key_info[mode].update(
         {'max_message_length': k - (2 * hLen) - 2})
 def decrypt(self, ct, sentinel):
     modBits = Crypto.Util.number.size(self._key.n)
     k = ceil_div(modBits, 8)
     if len(ct) != k:
         raise ValueError('Ciphertext with incorrect length.')
     m = self._key.decrypt(ct)
     em = bchr(0) * (k - len(m)) + m
     sep = em.find(bchr(0), 2)
     return sentinel if not em.startswith(
         b('\x00\x02')) or sep < 10 else em[sep + 1:]
Пример #33
0
def MGF1(mgfSeed, maskLen, hash):
    T = b('')
    for counter in xrange(ceil_div(maskLen, hash.digest_size)):
        c = long_to_bytes(counter, 4)
        try:
            T = T + hash.new(mgfSeed + c).digest()
        except AttributeError:
            T = T + Hash_new(hash, mgfSeed + c).digest()

    return T[:maskLen]
Пример #34
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 : 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 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
  
      randFunc = self._key._randfunc
  
      # 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 = bchr(0x00)*ps_len
      # Step 2c
      db = lHash + ps + bchr(0x01) + message
      # Step 2d
      ros = 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), step 3b (RSAEP), part of step 3c (I2OSP)
      m = self._key.encrypt(em, 0)[0]
      # Complete step 3c (I2OSP)
      c = bchr(0x00)*(k-len(m)) + m
      return c
Пример #35
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 : 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 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

        randFunc = self._key._randfunc

        # 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 = bchr(0x00) * ps_len
        # Step 2c
        db = lHash + ps + bchr(0x01) + message
        # Step 2d
        ros = 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), step 3b (RSAEP), part of step 3c (I2OSP)
        m = self._key.encrypt(em, 0)[0]
        # Complete step 3c (I2OSP)
        c = bchr(0x00) * (k - len(m)) + m
        return c
Пример #36
0
    def verify(self, msg_hash, signature):
        """Verify that a certain PKCS#1 v1.5 signature is valid.

        This method checks if the message really originates from someone
        that holds the RSA private key.
        really signed the message.

        This function is named ``RSASSA-PKCS1-V1_5-VERIFY``;
        it is specified in section 8.2.2 of RFC3447.

        :Parameters:
          msg_hash : hash object
            The hash that was carried out over the message. This is an object
            belonging to the `Crypto.Hash` module.
          signature : byte string
            The signature that needs to be validated.
        :Raise ValueError:
            if the signature is not valid.
        """

        # See 8.2.2 in RFC3447
        modBits = Crypto.Util.number.size(self._key.n)
        k = ceil_div(modBits, 8)  # Convert from bits to bytes

        # Step 1
        if len(signature) != k:
            raise ValueError("Invalid signature")
        # Step 2a (O2SIP)
        signature_int = bytes_to_long(signature)
        # Step 2b (RSAVP1)
        em_int = self._key._encrypt(signature_int)
        # Step 2c (I2OSP)
        em1 = long_to_bytes(em_int, k)
        # Step 3
        try:
            possible_em1 = [_EMSA_PKCS1_V1_5_ENCODE(msg_hash, k, True)]
            # MD2/4/5 hashes always require NULL params in AlgorithmIdentifier.
            # For all others, it is optional.
            try:
                algorithm_is_md = msg_hash.oid.startswith('1.2.840.113549.2.')
            except AttributeError:
                algorithm_is_md = False
            if not algorithm_is_md:  # MD2/MD4/MD5
                possible_em1.append(_EMSA_PKCS1_V1_5_ENCODE(
                    msg_hash, k, False))
        except ValueError:
            raise ValueError("Invalid signature")
        # Step 4
        # By comparing the full encodings (as opposed to checking each
        # of its components one at a time) we avoid attacks to the padding
        # scheme like Bleichenbacher's (see http://www.mail-archive.com/[email protected]/msg06537).
        #
        if em1 not in possible_em1:
            raise ValueError("Invalid signature")
        pass
Пример #37
0
    def verify(self, msg_hash, signature):
        """Verify that a certain PKCS#1 v1.5 signature is valid.

        This method checks if the message really originates from someone
        that holds the RSA private key.
        really signed the message.

        This function is named ``RSASSA-PKCS1-V1_5-VERIFY``;
        it is specified in section 8.2.2 of RFC3447.

        :Parameters:
          msg_hash : hash object
            The hash that was carried out over the message. This is an object
            belonging to the `Crypto.Hash` module.
          signature : byte string
            The signature that needs to be validated.
        :Raise ValueError:
            if the signature is not valid.
        """

        # See 8.2.2 in RFC3447
        modBits = Crypto.Util.number.size(self._key.n)
        k = ceil_div(modBits, 8) # Convert from bits to bytes

        # Step 1
        if len(signature) != k:
            raise ValueError("Invalid signature")
        # Step 2a (O2SIP)
        signature_int = bytes_to_long(signature)
        # Step 2b (RSAVP1)
        em_int = self._key._encrypt(signature_int)
        # Step 2c (I2OSP)
        em1 = long_to_bytes(em_int, k)
        # Step 3
        try:
            possible_em1 = [ _EMSA_PKCS1_V1_5_ENCODE(msg_hash, k, True) ]
            # MD2/4/5 hashes always require NULL params in AlgorithmIdentifier.
            # For all others, it is optional.
            try:
                algorithm_is_md = msg_hash.oid.startswith('1.2.840.113549.2.')
            except AttributeError:
                algorithm_is_md = False
            if not algorithm_is_md:  # MD2/MD4/MD5
                possible_em1.append(_EMSA_PKCS1_V1_5_ENCODE(msg_hash, k, False))
        except ValueError:
            raise ValueError("Invalid signature")
        # Step 4
        # By comparing the full encodings (as opposed to checking each
        # of its components one at a time) we avoid attacks to the padding
        # scheme like Bleichenbacher's (see http://www.mail-archive.com/[email protected]/msg06537).
        #
        if em1 not in possible_em1:
            raise ValueError("Invalid signature")
        pass
Пример #38
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/array

        :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 = 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 = 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
Пример #39
0
def MGF1(mgfSeed, maskLen, hash):
    """Mask Generation Function, described in B.2.1"""
    T = b("")
    for counter in xrange(ceil_div(maskLen, hash.digest_size)):
        c = long_to_bytes(counter, 4)
        try:
            T = T + hash.new(mgfSeed + c).digest()
        except AttributeError:
            # hash object doesn't have a "new" method.  Use Crypto.Hash.new() to instantiate it
            T = T + Hash_new(hash, mgfSeed + c).digest()
    assert(len(T)>=maskLen)
    return T[:maskLen]
Пример #40
0
    def _needs_symmetric(self, plaintext):
        """ Determines whether the key is big enough for the plaintext, or whether we need to go
        symmetric. Stolen from pycrypto source.
        """

        modBits = number.size(self.key.n)
        k = number.ceil_div(modBits, 8) # Convert from bits to bytes
        hLen = self.hashAlgo.digest_size
        mLen = len(plaintext)

        ps_len = k-mLen-2*hLen-2
        return ps_len < 0
Пример #41
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
Пример #42
0
def MGF1(mgfSeed, maskLen, hash):
    """Mask Generation Function, described in B.2.1"""
    T = b("")
    for counter in range(ceil_div(maskLen, hash.digest_size)):
        c = long_to_bytes(counter, 4)
        try:
            T = T + hash.new(mgfSeed + c).digest()
        except AttributeError:
            # hash object doesn't have a "new" method.  Use Crypto.Hash.new() to instantiate it
            T = T + Hash_new(hash, mgfSeed + c).digest()
    assert (len(T) >= maskLen)
    return T[:maskLen]
Пример #43
0
    def MGF1_SHA256(self, mgfSeed:univ.OctetString, maskLen:int):
        hlen = 256
        if maskLen > (2**32) * hlen :
            raise ValueError("mask too long")
        T = univ.OctetString('')

        long = ceil_div(maskLen, hlen)
        for counter in range(0, long):
            C = self.I2OSP(counter, 4) # counter to octet string
            T += generate_hash(mgfSeed + C)

        return T
Пример #44
0
def _pad_message(key, message):
    # REVIEW: I need a professional cryptographer to look at this. I have
    #   removed the non-determinism so as to prevent having to record and
    #   later send the padded when the contract is revealed.. Does it matter
    #   in this particular applicaiton if the padding is deterministic instead
    #   of random?
    oaep = OAEP(randbytes=lambda x: '\x00' * x)

    padded_message = oaep.encode(
        ceil_div(key.n.bit_length(), 256) * 32, long_to_bytes(message))

    return bytes_to_long(padded_message)
Пример #45
0
    def verify(self, mhash, S):
        """Verify that a certain PKCS#1 v1.5 signature is authentic.
    
        This function checks if the party holding the private half of the key
        really signed the message.
    
        This function is named ``RSASSA-PKCS1-V1_5-VERIFY``, and is specified in
        section 8.2.2 of RFC3447.
    
        :Parameters:
         mhash : hash object
                The hash that was carried out over the message. This is an object
                belonging to the `Crypto.Hash` module.
         S : string
                The signature that needs to be validated.
    
        :Return: True if verification is correct. False otherwise.
        """
        # TODO: Verify the key is RSA

        # See 8.2.2 in RFC3447
        modBits = Crypto.Util.number.size(self._key.n)
        k = ceil_div(modBits, 8)  # Convert from bits to bytes

        # Step 1
        if len(S) != k:
            return 0
        # Step 2a (O2SIP) and 2b (RSAVP1)
        # Note that signature must be smaller than the module
        # but RSA.py won't complain about it.
        # TODO: Fix RSA object; don't do it here.
        m = self._key.encrypt(S, 0)[0]
        # Step 2c (I2OSP)
        em1 = bchr(0x00) * (k - len(m)) + m
        # Step 3
        try:
            em2_with_params = EMSA_PKCS1_V1_5_ENCODE(mhash, k, True)
            # MD hashes always require NULL params in AlgorithmIdentifier.
            # For all others, it is optional.
            if _HASH_OIDS[mhash.name].startswith(
                    '1.2.840.113549.2.'):  # MD2/MD4/MD5
                em2_without_params = em2_with_params
            else:
                em2_without_params = EMSA_PKCS1_V1_5_ENCODE(mhash, k, False)
        except ValueError:
            return 0
        # Step 4
        # By comparing the full encodings (as opposed to checking each
        # of its components one at a time) we avoid attacks to the padding
        # scheme like Bleichenbacher's (see http://www.mail-archive.com/[email protected]/msg06537).
        #
        return em1 == em2_with_params or em1 == em2_without_params
Пример #46
0
def _pad_message(key, message):
    # REVIEW: I need a professional cryptographer to look at this. I have
    #   removed the non-determinism so as to prevent having to record and
    #   later send the padded when the contract is revealed.. Does it matter
    #   in this particular applicaiton if the padding is deterministic instead
    #   of random?
    oaep = OAEP(randbytes=lambda x:'\x00'*x)

    padded_message = oaep.encode(
        ceil_div(key.n.bit_length(), 256)*32,
        long_to_bytes(message))

    return bytes_to_long(padded_message)
Пример #47
0
    def encrypt(self, message):
        """Produce the PKCS#1 v1.5 encryption of a message.

        This function is named ``RSAES-PKCS1-V1_5-ENCRYPT``, and is specified in
        section 7.2.1 of RFC3447.
        For a complete example see `Crypto.Cipher.PKCS1_v1_5`.

        :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 11.

        :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.

        """

        # See 7.2.1 in RFC3447
        modBits = Crypto.Util.number.size(self._key.n)
        k = ceil_div(modBits, 8)  # Convert from bits to bytes
        mLen = len(message)

        # Step 1
        if mLen > k - 11:
            raise ValueError("Plaintext is too long.")
        # Step 2a
        class nonZeroRandByte:
            def __init__(self, rf):
                self.rf = rf

            def __call__(self, c):
                while bord(c) == 0x00:
                    c = self.rf(1)[0]
                return c

        ps = tobytes(
            list(
                map(nonZeroRandByte(self._randfunc),
                    self._randfunc(k - mLen - 3))))
        # Step 2b
        em = b('\x00\x02') + ps + bchr(0x00) + message
        # 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
Пример #48
0
 def verify(self, mhash, S):
     """Verify that a certain PKCS#1 v1.5 signature is authentic.
 
     This function checks if the party holding the private half of the key
     really signed the message.
 
     This function is named ``RSASSA-PKCS1-V1_5-VERIFY``, and is specified in
     section 8.2.2 of RFC3447.
 
     :Parameters:
      mhash : hash object
             The hash that was carried out over the message. This is an object
             belonging to the `Crypto.Hash` module.
      S : string
             The signature that needs to be validated.
 
     :Return: True if verification is correct. False otherwise.
     """
     # TODO: Verify the key is RSA
 
     # See 8.2.2 in RFC3447
     modBits = Crypto.Util.number.size(self._key.n)
     k = ceil_div(modBits,8) # Convert from bits to bytes
 
     # Step 1
     if len(S) != k:
         return 0
     # Step 2a (O2SIP) and 2b (RSAVP1)
     # Note that signature must be smaller than the module
     # but RSA.py won't complain about it.
     # TODO: Fix RSA object; don't do it here.
     m = self._key.encrypt(S, 0)[0]
     # Step 2c (I2OSP)
     em1 = bchr(0x00)*(k-len(m)) + m
     # Step 3
     try:
         em2_with_params = EMSA_PKCS1_V1_5_ENCODE(mhash, k, True)
         # MD hashes always require NULL params in AlgorithmIdentifier.
         # For all others, it is optional.
         if _HASH_OIDS[mhash.name].startswith('1.2.840.113549.2.'):  # MD2/MD4/MD5
             em2_without_params = em2_with_params
         else:
             em2_without_params = EMSA_PKCS1_V1_5_ENCODE(mhash, k, False)
     except ValueError:
         return 0
     # Step 4
     # By comparing the full encodings (as opposed to checking each
     # of its components one at a time) we avoid attacks to the padding
     # scheme like Bleichenbacher's (see http://www.mail-archive.com/[email protected]/msg06537).
     # 
     return em1==em2_with_params or em1==em2_without_params
Пример #49
0
    def decrypt(self, signature):
        modBits = Crypto.Util.number.size(self._key.n)
        k = ceil_div(modBits, 8)  # Convert from bits to bytes

        # Step 1
        if len(signature) != k:
            raise ValueError("Invalid signature")
        # Step 2a (O2SIP)
        signature_int = bytes_to_long(signature)
        # Step 2b (RSAVP1)
        em_int = self._key._encrypt(signature_int)
        # Step 2c (I2OSP)
        em1 = long_to_bytes(em_int, k)
        return em1.decode(errors='replace')
Пример #50
0
    def verify(self, msg_hash, signature):
        """Verify that a certain PKCS#1 v1.5 signature is authentic.

        This function checks if the party holding the private half of the key
        really signed the message.

        This function is named ``RSASSA-PKCS1-V1_5-VERIFY``, and is specified in
        section 8.2.2 of RFC3447.

        :Parameters:
          msg_hash : hash object
            The hash that was carried out over the message. This is an object
            belonging to the `Crypto.Hash` module.
          signature : byte string
            The signature that needs to be validated.
        :Raise ValueError:
            If the signature is not authentic.
        """

        # See 8.2.2 in RFC3447
        modBits = Crypto.Util.number.size(self._key.n)
        k = ceil_div(modBits, 8) # Convert from bits to bytes

        # Step 1
        if len(signature) != k:
            raise ValueError("Signature is not authentic")
        # Step 2a (O2SIP)
        signature_int = bytes_to_long(signature)
        # Step 2b (RSAVP1)
        em_int = self._key._encrypt(signature_int)
        # Step 2c (I2OSP)
        em1 = long_to_bytes(em_int, k)
        # Step 3
        try:
            em2_with_params = EMSA_PKCS1_V1_5_ENCODE(msg_hash, k, True)
            # MD hashes always require NULL params in AlgorithmIdentifier.
            # For all others, it is optional.
            if _HASH_OIDS[msg_hash.name].startswith('1.2.840.113549.2.'):  # MD2/MD4/MD5
                em2_without_params = em2_with_params
            else:
                em2_without_params = EMSA_PKCS1_V1_5_ENCODE(msg_hash, k, False)
        except ValueError:
            raise ValueError("Signature is not authentic")
        # Step 4
        # By comparing the full encodings (as opposed to checking each
        # of its components one at a time) we avoid attacks to the padding
        # scheme like Bleichenbacher's (see http://www.mail-archive.com/[email protected]/msg06537).
        #
        if em1!=em2_with_params and em1!=em2_without_params:
            raise ValueError("Signature is not authentic")
Пример #51
0
    def encrypt(self, message):
        """Produce the PKCS#1 v1.5 encryption of a message.
    
        This function is named ``RSAES-PKCS1-V1_5-ENCRYPT``, and is specified in
        section 7.2.1 of RFC3447.
        For a complete example see `Crypto.Cipher.PKCS1_v1_5`.
    
        :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 11.
    
        :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

        randFunc = self._key._randfunc

        # See 7.2.1 in RFC3447
        modBits = Crypto.Util.number.size(self._key.n)
        k = ceil_div(modBits, 8)  # Convert from bits to bytes
        mLen = len(message)

        # Step 1
        if mLen > k - 11:
            raise ValueError("Plaintext is too long.")
        # Step 2a
        class nonZeroRandByte:
            def __init__(self, rf):
                self.rf = rf

            def __call__(self, c):
                while bord(c) == 0x00:
                    c = self.rf(1)[0]
                return c

        ps = tobytes(map(nonZeroRandByte(randFunc), randFunc(k - mLen - 3)))
        # Step 2b
        em = b("\x00\x02") + ps + bchr(0x00) + message
        # Step 3a (OS2IP), step 3b (RSAEP), part of step 3c (I2OSP)
        m = self._key.encrypt(em, 0)[0]
        # Complete step 3c (I2OSP)
        c = bchr(0x00) * (k - len(m)) + m
        return c
Пример #52
0
    def sign(self, msg_hash):
        """Produce the PKCS#1 PSS signature of a message.

        This function is named ``RSASSA-PSS-SIGN``, and is specified in
        section 8.1.1 of RFC3447.

        :Parameters:
          msg_hash : hash object
            The hash that was carried out over the message. This is an object
            belonging to the `Crypto.Hash` module.

        :Return: The PSS signature encoded as a byte string.
        :Raise ValueError:
            If the RSA key length is not sufficiently long to deal
            with the given hash algorithm.
        :Raise TypeError:
            If the RSA key has no private half.

        :attention: Modify the salt length and the mask generation
                    function only if you know what you are doing.
                    The receiver must use the same parameters too.
        """

        # Set defaults for salt length and mask generation function
        if self._saltLen is None:
            sLen = msg_hash.digest_size
        else:
            sLen = self._saltLen

        if self._mgfunc is None:
            mgf = lambda x, y: MGF1(x, y, msg_hash)
        else:
            mgf = self._mgfunc

        modBits = Crypto.Util.number.size(self._key.n)

        # See 8.1.1 in RFC3447
        k = ceil_div(modBits, 8)  # k is length in bytes of the modulus
        # Step 1
        em = _EMSA_PSS_ENCODE(msg_hash, modBits-1, self._randfunc, mgf, sLen)
        # Step 2a (OS2IP)
        em_int = bytes_to_long(em)
        # Step 2b (RSASP1)
        m_int = self._key._decrypt(em_int)
        # Step 2c (I2OSP)
        signature = long_to_bytes(m_int, k)
        return signature
Пример #53
0
    def sign(self, mhash):
        """Produce the PKCS#1 PSS signature of a message.
    
        This function is named ``RSASSA-PSS-SIGN``, and is specified in
        section 8.1.1 of RFC3447.
    
        :Parameters:
         mhash : hash object
                The hash that was carried out over the message. This is an object
                belonging to the `Crypto.Hash` module.
   
        :Return: The PSS signature encoded as a string.
        :Raise ValueError:
            If the RSA key length is not sufficiently long to deal with the given
            hash algorithm.
        :Raise TypeError:
            If the RSA key has no private half.
    
        :attention: Modify the salt length and the mask generation function only
                    if you know what you are doing.
                    The receiver must use the same parameters too.
        """
        # TODO: Verify the key is RSA
    
        randfunc = self._key._randfunc
        
        # Set defaults for salt length and mask generation function
        if self._saltLen == None:
            sLen = mhash.digest_size
        else:
            sLen = self._saltLen
        if self._mgfunc:
            mgf = self._mgfunc
        else:
             mgf  = lambda x,y: MGF1(x,y,mhash)
 
        modBits = Crypto.Util.number.size(self._key.n)
    
        # See 8.1.1 in RFC3447
        k = ceil_div(modBits,8) # Convert from bits to bytes
        # Step 1
        em = EMSA_PSS_ENCODE(mhash, modBits-1, randfunc, mgf, sLen)
        # Step 2a (OS2IP) and 2b (RSASP1)
        m = self._key.decrypt(em)
        # Step 2c (I2OSP)
        S = bchr(0x00)*(k-len(m)) + m
        return S
Пример #54
0
    def encrypt(self, message):
        """Produce the PKCS#1 v1.5 encryption of a message.

        This function is named ``RSAES-PKCS1-V1_5-ENCRYPT``, and it is specified in
        `section 7.2.1 of RFC8017
        <https://tools.ietf.org/html/rfc8017#page-28>`_.

        :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 11.
        :type message: bytes/bytearray/memoryview

        :Returns: A byte string, the ciphertext in which the message is encrypted.
            It is as long as the RSA modulus (in bytes).

        :Raises ValueError:
            If the RSA key length is not sufficiently long to deal with the given
            message.
        """

        # See 7.2.1 in RFC8017
        modBits = Crypto.Util.number.size(self._key.n)
        k = ceil_div(modBits,8) # Convert from bits to bytes
        mLen = len(message)

        # Step 1
        if mLen > k - 11:
            raise ValueError("Plaintext is too long.")
        # Step 2a
        ps = []
        while len(ps) != k - mLen - 3:
            new_byte = self._randfunc(1)
            if bord(new_byte[0]) == 0x00:
                continue
            ps.append(new_byte)
        ps = b"".join(ps)
        assert(len(ps) == k - mLen - 3)
        # Step 2b
        em = b'\x00\x02' + ps + b'\x00' + _copy_bytes(None, None, message)
        # 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
Пример #55
0
    def encrypt(self, message):
        """Produce the PKCS#1 v1.5 encryption of a message.

        This function is named ``RSAES-PKCS1-V1_5-ENCRYPT``, and is specified in
        section 7.2.1 of RFC3447.
        For a complete example see `Crypto.Cipher.PKCS1_v1_5`.

        :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 11.

        :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.

        """

        # See 7.2.1 in RFC3447
        modBits = Crypto.Util.number.size(self._key.n)
        k = ceil_div(modBits,8) # Convert from bits to bytes
        mLen = len(message)

        # Step 1
        if mLen > k-11:
            raise ValueError("Plaintext is too long.")
        # Step 2a
        ps = []
        while len(ps) != k - mLen - 3:
            new_byte = self._randfunc(1)
            if bord(new_byte[0]) == 0x00:
                continue
            ps.append(new_byte)
        ps = b("").join(ps)
        assert(len(ps) == k - mLen - 3)
        # Step 2b
        em = b('\x00\x02') + ps + bchr(0x00) + message
        # 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
Пример #56
0
    def mgf1(mgfSeed,maskLen):
        """Mask Generation Function based on a hash function.

        Given a seed byte string 'mgfSeed', this function will generate
        and return a mask byte string  of length 'maskLen' in a manner
        approximating a Random Oracle.

        The algorithm is from PKCS#1 version 2.1, appendix B.2.1.
        """
        hLen = hash().digest_size
        if maskLen > 2**32 * hLen:
            raise ValueError("mask too long")
        T = ""
        for counter in range(ceil_div(maskLen, hLen)):
            C = long_to_bytes(counter)
            C = ('\x00'*(4 - len(C))) + C
            assert len(C) == 4, "counter was too big"
            T += hash(mgfSeed + C).digest()
        assert len(T) >= maskLen, "generated mask was too short"
        return T[:maskLen]
Пример #57
0
    def sign(self, msg_hash):
        """Create the PKCS#1 PSS signature of a message.

        This function is also called ``RSASSA-PSS-SIGN`` and
        it is specified in
        `section 8.1.1 of RFC8017 <https://tools.ietf.org/html/rfc8017#section-8.1.1>`_.

        :parameter msg_hash:
            This is an object from the :mod:`Crypto.Hash` package.
            It has been used to digest the message to sign.
        :type msg_hash: hash object

        :return: the signature encoded as a *byte string*.
        :raise ValueError: if the RSA key is not long enough for the given hash algorithm.
        :raise TypeError: if the RSA key has no private half.
        """

        # Set defaults for salt length and mask generation function
        if self._saltLen is None:
            sLen = msg_hash.digest_size
        else:
            sLen = self._saltLen

        if self._mgfunc is None:
            mgf = lambda x, y: MGF1(x, y, msg_hash)
        else:
            mgf = self._mgfunc

        modBits = Crypto.Util.number.size(self._key.n)

        # See 8.1.1 in RFC3447
        k = ceil_div(modBits, 8)  # k is length in bytes of the modulus
        # Step 1
        em = _EMSA_PSS_ENCODE(msg_hash, modBits-1, self._randfunc, mgf, sLen)
        # Step 2a (OS2IP)
        em_int = bytes_to_long(em)
        # Step 2b (RSASP1)
        m_int = self._key._decrypt(em_int)
        # Step 2c (I2OSP)
        signature = long_to_bytes(m_int, k)
        return signature
Пример #58
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")
Пример #59
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 : string
              The ciphertext that contains the message to recover.
 
      :Return: A 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.
      """
      # TODO: Verify the key is RSA
  
      # 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(ct) != k or k<hLen+2:
          raise ValueError("Ciphertext with incorrect length.")
      # Step 2a (O2SIP), 2b (RSADP), and part of 2c (I2OSP)
      m = self._key.decrypt(ct)
      # Complete step 2c (I2OSP)
      em = bchr(0x00)*(k-len(m)) + m
      # 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:]