Exemplo n.º 1
0
    def __init__(self, key, msg, ciphermod, cipher_params, mac_len,
                 update_after_digest):

        self.digest_size = mac_len

        self._key = _copy_bytes(None, None, key)
        self._factory = ciphermod
        self._cipher_params = cipher_params
        self._block_size = bs = ciphermod.block_size
        self._mac_tag = None
        self._update_after_digest = update_after_digest

        # Section 5.3 of NIST SP 800 38B and Appendix B
        if bs == 8:
            const_Rb = 0x1B
            self._max_size = 8 * (2 ** 21)
        elif bs == 16:
            const_Rb = 0x87
            self._max_size = 16 * (2 ** 48)
        else:
            raise TypeError("CMAC requires a cipher with a block size"
                            " of 8 or 16 bytes, not %d" % bs)

        # Compute sub-keys
        zero_block = b'\x00' * bs
        self._ecb = ciphermod.new(key,
                                  ciphermod.MODE_ECB,
                                  **self._cipher_params)
        L = self._ecb.encrypt(zero_block)
        if bord(L[0]) & 0x80:
            self._k1 = _shift_bytes(L, const_Rb)
        else:
            self._k1 = _shift_bytes(L)
        if bord(self._k1[0]) & 0x80:
            self._k2 = _shift_bytes(self._k1, const_Rb)
        else:
            self._k2 = _shift_bytes(self._k1)

        # Initialize CBC cipher with zero IV
        self._cbc = ciphermod.new(key,
                                  ciphermod.MODE_CBC,
                                  zero_block,
                                  **self._cipher_params)

        # Cache for outstanding data to authenticate
        self._cache = bytearray(bs)
        self._cache_n = 0

        # Last piece of ciphertext produced
        self._last_ct = zero_block

        # Last block that was encrypted with AES
        self._last_pt = None

        # Counter for total message size
        self._data_size = 0

        if msg:
            self.update(msg)
Exemplo n.º 2
0
        def _decodeFromStream(self, s):
                """Decode a complete DER INTEGER from a file."""

                # Fill up self.payload
                DerObject._decodeFromStream(self, s)

                # Derive self.value from self.payload
                self.value = 0
                bits = 1
                for i in self.payload:
                    self.value *= 256
                    self.value += bord(i)
                    bits <<= 8
                if self.payload and bord(self.payload[0]) & 0x80:
                    self.value -= bits
Exemplo n.º 3
0
def adjust_key_parity(key_in):
    """Set the parity bits in a TDES key.

    :param key_in: the TDES key whose bits need to be adjusted
    :type key_in: byte string

    :returns: a copy of ``key_in``, with the parity bits correctly set
    :rtype: byte string

    :raises ValueError: if the TDES key is not 16 or 24 bytes long
    :raises ValueError: if the TDES key degenerates into Single DES
    """

    def parity_byte(key_byte):
        parity = 1
        for i in range(1, 8):
            parity ^= (key_byte >> i) & 1
        return (key_byte & 0xFE) | parity

    if len(key_in) not in key_size:
        raise ValueError("Not a valid TDES key")

    key_out = b"".join([ bchr(parity_byte(bord(x))) for x in key_in ])

    if key_out[:8] == key_out[8:16] or key_out[-16:-8] == key_out[-8:]:
        raise ValueError("Triple DES key degenerates to single DES")

    return key_out
Exemplo n.º 4
0
def import_key(encoded, passphrase=None):
    """Import an ECC key (public or private).

    :Parameters:
      encoded : bytes or a (multi-line) string
        The ECC key to import.

        An ECC public key can be:

        - An X.509 certificate, binary (DER) or ASCII (PEM)
        - An X.509 ``subjectPublicKeyInfo``, binary (DER) or ASCII (PEM)
        - An OpenSSH line (e.g. the content of ``~/.ssh/id_ecdsa``, ASCII)

        An ECC private key can be:

        - In binary format (DER, see section 3 of `RFC5915`_ or `PKCS#8`_)
        - In ASCII format (PEM or OpenSSH)

        Private keys can be in the clear or password-protected.

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

    :Keywords:
      passphrase : byte string
        The passphrase to use for decrypting a private key.
        Encryption may be applied protected at the PEM level or at the PKCS#8 level.
        This parameter is ignored if the key in input is not encrypted.

    :Return: An ECC key object (`EccKey`)

    :Raise ValueError:
        When the given key cannot be parsed (possibly because
        the pass phrase is wrong).

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _RFC5915: http://www.ietf.org/rfc/rfc5915.txt
    .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
    """

    encoded = tobytes(encoded)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    # PEM
    if encoded.startswith(b('-----')):
        der_encoded, marker, enc_flag = PEM.decode(tostr(encoded), passphrase)
        if enc_flag:
            passphrase = None
        return _import_der(der_encoded, passphrase)

    # OpenSSH
    if encoded.startswith(b('ecdsa-sha2-')):
        return _import_openssh(encoded)

    # DER
    if bord(encoded[0]) == 0x30:
        return _import_der(encoded, passphrase)

    raise ValueError("ECC key format is not supported")
    def hexdigest(self):
        """Compute the *printable* authentication tag (MAC).

        This method is like :meth:`digest`.

        :Return: the MAC tag, as a hexadecimal string.
        """
        return "".join(["%02x" % bord(x) for x in self.digest()])
Exemplo n.º 6
0
    def hexdigest(self):
        """Compute the *printable* MAC tag.

        This method is like `digest`.

        :Return: the MAC, as a hexadecimal string.
        """
        return "".join(["%02x" % bord(x) for x in self.digest()])
Exemplo n.º 7
0
    def hexdigest(self):
        """Return the **printable** digest of the message that has been hashed so far.

        :return: The hash digest, computed over the data processed so far.
                 Hexadecimal encoded.
        :rtype: string
        """

        return "".join(["%02x" % bord(x) for x in self.digest()])
Exemplo n.º 8
0
    def hexdigest(self):
        """Return the **printable** MAC tag of the message authenticated so far.

        :return: The MAC tag, computed over the data processed so far.
                 Hexadecimal encoded.
        :rtype: string
        """

        return "".join(["%02x" % bord(x)
                        for x in tuple(self.digest())])
Exemplo n.º 9
0
    def hexdigest(self):
        """Return the **printable** digest of the message that has been hashed so far.

        This method does not change the state of the hash object.

        :Return: A string of 2* `digest_size` characters. It contains only
         hexadecimal ASCII digits.
        """

        return "".join(["%02x" % bord(x) for x in self.digest()])
def create_ref_keys():
    key_lines = load_file("ecc_p256.txt").splitlines()
    private_key_d = bytes_to_long(compact(key_lines[2:5]))
    public_key_xy = compact(key_lines[6:11])
    assert bord(public_key_xy[0]) == 4  # Uncompressed
    public_key_x = bytes_to_long(public_key_xy[1:33])
    public_key_y = bytes_to_long(public_key_xy[33:])

    return (ECC.construct(curve="P-256", d=private_key_d),
            ECC.construct(curve="P-256", point_x=public_key_x, point_y=public_key_y))
Exemplo n.º 11
0
    def hexdigest(self):
        """Return the **printable** MAC of the message that has been
        authenticated so far.

        This method does not change the state of the MAC object.

        :Return: A string of 2* `digest_size` bytes. It contains only
         hexadecimal ASCII digits.
        """
        return "".join(["%02x" % bord(x)
                        for x in tuple(self.digest())])
Exemplo n.º 12
0
 def _convertTag(self, tag):
         """Check if *tag* is a real DER tag.
         Convert it from a character to number if necessary.
         """
         if not _is_number(tag):
             if len(tag) == 1:
                 tag = bord(tag[0])
         # Ensure that tag is a low tag
         if not (_is_number(tag) and 0 <= tag < 0x1F):
             raise ValueError("Wrong DER tag")
         return tag
Exemplo n.º 13
0
        def _decodeFromStream(self, s, strict):
                """Decode a complete DER INTEGER from a file."""

                # Fill up self.payload
                DerObject._decodeFromStream(self, s, strict)

                if strict:
                    if len(self.payload) == 0:
                        raise ValueError("Invalid encoding for DER INTEGER: empty payload")
                    if len(self.payload) >= 2 and struct.unpack('>H', self.payload[:2])[0] < 0x80:
                        raise ValueError("Invalid encoding for DER INTEGER: leading zero")

                # Derive self.value from self.payload
                self.value = 0
                bits = 1
                for i in self.payload:
                    self.value *= 256
                    self.value += bord(i)
                    bits <<= 8
                if self.payload and bord(self.payload[0]) & 0x80:
                    self.value -= bits
Exemplo n.º 14
0
    def _decodeFromStream(self, s):
        """Decode a complete DER BIT STRING DER from a file."""

        # Fill-up self.payload
        DerObject._decodeFromStream(self, s)

        if self.payload and bord(self.payload[0]) != 0:
            raise ValueError("Not a valid BIT STRING")

        # Fill-up self.value
        self.value = b('')
        # Remove padding count byte
        if self.payload:
            self.value = self.payload[1:]
Exemplo n.º 15
0
    def test_asn1_encoding(self):
        """Verify ASN.1 encoding"""

        self.description = "ASN.1 encoding test"
        hash_obj = SHA1.new()
        signer = DSS.new(self.key_priv, 'fips-186-3', 'der')
        signature = signer.sign(hash_obj)

        # Verify that output looks like a SEQUENCE
        self.assertEqual(bord(signature[0]), 48)
        signer.verify(hash_obj, signature)

        # Verify that ASN.1 parsing fails as expected
        signature = bchr(7) + signature[1:]
        self.assertRaises(ValueError, signer.verify, hash_obj, signature)
Exemplo n.º 16
0
def _import_public_der(curve_name, publickey):

    # We only support P-256 named curves for now
    if curve_name != _curve.oid:
        raise ValueError("Unsupport curve")

    # ECPoint ::= OCTET STRING

    # We support only uncompressed points
    order_bytes = _curve.order.size_in_bytes()
    if len(publickey) != (1 + 2 * order_bytes) or bord(publickey[0]) != 4:
        raise ValueError("Only uncompressed points are supported")

    point_x = Integer.from_bytes(publickey[1:order_bytes+1])
    point_y = Integer.from_bytes(publickey[order_bytes+1:])
    return construct(curve="P-256", point_x=point_x, point_y=point_y)
Exemplo n.º 17
0
    def random(cls, **kwargs):
        """Generate a random natural integer of a certain size.

        :Keywords:
          exact_bits : positive integer
            The length in bits of the resulting random Integer number.
            The number is guaranteed to fulfil the relation:

                2^bits > result >= 2^(bits - 1)

          max_bits : positive integer
            The maximum length in bits of the resulting random Integer number.
            The number is guaranteed to fulfil the relation:

                2^bits > result >=0

          randfunc : callable
            A function that returns a random byte string. The length of the
            byte string is passed as parameter. Optional.
            If not provided (or ``None``), randomness is read from the system RNG.

        :Return: a Integer object
        """

        exact_bits = kwargs.pop("exact_bits", None)
        max_bits = kwargs.pop("max_bits", None)
        randfunc = kwargs.pop("randfunc", None)

        if randfunc is None:
            randfunc = Random.new().read

        if exact_bits is None and max_bits is None:
            raise ValueError("Either 'exact_bits' or 'max_bits' must be specified")

        if exact_bits is not None and max_bits is not None:
            raise ValueError("'exact_bits' and 'max_bits' are mutually exclusive")

        bits = exact_bits or max_bits
        bytes_needed = ((bits - 1) // 8) + 1
        significant_bits_msb = 8 - (bytes_needed * 8 - bits)
        msb = bord(randfunc(1)[0])
        if exact_bits is not None:
            msb |= 1 << (significant_bits_msb - 1)
        msb &= (1 << significant_bits_msb) - 1

        return cls.from_bytes(bchr(msb) + randfunc(bytes_needed - 1))
Exemplo n.º 18
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 = Cryptodome.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
Exemplo n.º 19
0
def adjust_key_parity(key_in):
    """Return the TDES key with parity bits correctly set"""

    def parity_byte(key_byte):
        parity = 1
        for i in xrange(1, 8):
            parity ^= (key_byte >> i) & 1
        return (key_byte & 0xFE) | parity

    if len(key_in) not in key_size:
        raise ValueError("Not a valid TDES key")

    key_out = b("").join([ bchr(parity_byte(bord(x)) )for x in key_in ])

    if key_out[:8] == key_out[8:16] or key_out[-16:-8] == key_out[-8:]:
        raise ValueError("Triple DES key degenerates to single DES")

    return key_out
Exemplo n.º 20
0
def _import_public_der(curve_oid, ec_point):
    """Convert an encoded EC point into an EccKey object

    curve_name: string with the OID of the curve
    ec_point: byte string with the EC point (not DER encoded)

    """

    # We only support P-256 named curves for now
    if curve_oid != _curve.oid:
        raise UnsupportedEccFeature("Unsupported ECC curve (OID: %s)" % curve_oid)

    # See 2.2 in RFC5480 and 2.3.3 in SEC1
    # The first byte is:
    # - 0x02:   compressed, only X-coordinate, Y-coordinate is even
    # - 0x03:   compressed, only X-coordinate, Y-coordinate is odd
    # - 0x04:   uncompressed, X-coordinate is followed by Y-coordinate
    #
    # PAI is in theory encoded as 0x00.

    order_bytes = _curve.order.size_in_bytes()
    point_type = bord(ec_point[0])
    
    # Uncompressed point
    if point_type == 0x04:
        if len(ec_point) != (1 + 2 * order_bytes):
            raise ValueError("Incorrect EC point length")
        x = Integer.from_bytes(ec_point[1:order_bytes+1])
        y = Integer.from_bytes(ec_point[order_bytes+1:])
    # Compressed point
    elif point_type in (0x02, 0x3):
        if len(ec_point) != (1 + order_bytes):
            raise ValueError("Incorrect EC point length")
        x = Integer.from_bytes(ec_point[1:])
        y = (x**3 - x*3 + _curve.b).sqrt(_curve.p)    #  Short Weierstrass
        if point_type == 0x02 and y.is_odd():
            y = _curve.p - y
        if point_type == 0x03 and y.is_even():
            y = _curve.p - y
    else:
        raise ValueError("Incorrect EC point encoding")

    return construct(curve="P-256", point_x=x, point_y=y)
Exemplo n.º 21
0
    def add(self, elem):
        """Add an element to the set.

        :Parameters:
            elem : byte string or integer
              An element of the same type of objects already in the set.
              It can be an integer or a DER encoded object.
        """

        if _is_number(elem):
            eo = 0x02
        elif isinstance(elem, DerObject):
            eo = self._tag_octet
        else:
            eo = bord(elem[0])

        if self._elemOctet != eo:
            if self._elemOctet is not None:
                raise ValueError("New element does not belong to the set")
            self._elemOctet = eo

        if elem not in self._seq:
            self._seq.append(elem)
def _key2bin(s):
    "Convert a key into a string of binary digits"
    kl = map(lambda x: bord(x), s)
    kl = map(lambda x: binary[x >> 4] + binary[x & 15], kl)
    return ''.join(kl)
Exemplo n.º 23
0
Arquivo: RSA.py Projeto: ZurTor/TorMe
def import_key(extern_key, passphrase=None):
    """Import an RSA key (public or private).

    Args:
      extern_key (string or byte string):
        The RSA key to import.

        The following formats are supported for an RSA **public key**:

        - X.509 certificate (binary or PEM format)
        - X.509 ``subjectPublicKeyInfo`` DER SEQUENCE (binary or PEM
          encoding)
        - `PKCS#1`_ ``RSAPublicKey`` DER SEQUENCE (binary or PEM encoding)
        - An OpenSSH line (e.g. the content of ``~/.ssh/id_ecdsa``, ASCII)

        The following formats are supported for an RSA **private key**:

        - PKCS#1 ``RSAPrivateKey`` DER SEQUENCE (binary or PEM encoding)
        - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo``
          DER SEQUENCE (binary or PEM encoding)
        - OpenSSH (text format, introduced in `OpenSSH 6.5`_)

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

      passphrase (string or byte string):
        For private keys only, the pass phrase that encrypts the key.

    Returns: An RSA key object (:class:`RsaKey`).

    Raises:
      ValueError/IndexError/TypeError:
        When the given key cannot be parsed (possibly because the pass
        phrase is wrong).

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt
    .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
    .. _`OpenSSH 6.5`: https://flak.tedunangst.com/post/new-openssh-key-format-and-bcrypt-pbkdf
    """

    from Cryptodome.IO import PEM

    extern_key = tobytes(extern_key)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    if extern_key.startswith(b'-----BEGIN OPENSSH PRIVATE KEY'):
        text_encoded = tostr(extern_key)
        openssh_encoded, marker, enc_flag = PEM.decode(text_encoded,
                                                       passphrase)
        result = _import_openssh_private_rsa(openssh_encoded, passphrase)
        return result

    if extern_key.startswith(b'-----'):
        # This is probably a PEM encoded key.
        (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase)
        if enc_flag:
            passphrase = None
        return _import_keyDER(der, passphrase)

    if extern_key.startswith(b'ssh-rsa '):
        # This is probably an OpenSSH key
        keystring = binascii.a2b_base64(extern_key.split(b' ')[1])
        keyparts = []
        while len(keystring) > 4:
            length = struct.unpack(">I", keystring[:4])[0]
            keyparts.append(keystring[4:4 + length])
            keystring = keystring[4 + length:]
        e = Integer.from_bytes(keyparts[1])
        n = Integer.from_bytes(keyparts[2])
        return construct([n, e])

    if len(extern_key) > 0 and bord(extern_key[0]) == 0x30:
        # This is probably a DER encoded key
        return _import_keyDER(extern_key, passphrase)

    raise ValueError("RSA key format is not supported")
Exemplo n.º 24
0
    def exportKey(self, format='PEM', passphrase=None, pkcs=1,
                   protection=None, randfunc=None):
        """Export this RSA key.

        :Parameters:
          format : string
            The format to use for wrapping the key:

            - *'DER'*. Binary encoding.
            - *'PEM'*. Textual encoding, done according to `RFC1421`_/`RFC1423`_.
            - *'OpenSSH'*. Textual encoding, done according to OpenSSH specification.
              Only suitable for public keys (not private keys).

          passphrase : string
            For private keys only. The pass phrase used for deriving the encryption
            key.

          pkcs : integer
            For *DER* and *PEM* format only.
            The PKCS standard to follow for assembling the components of the key.
            You have two choices:

            - **1** (default): the public key is embedded into
              an X.509 ``SubjectPublicKeyInfo`` DER SEQUENCE.
              The private key is embedded into a `PKCS#1`_
              ``RSAPrivateKey`` DER SEQUENCE.
            - **8**: the private key is embedded into a `PKCS#8`_
              ``PrivateKeyInfo`` DER SEQUENCE. This value cannot be used
              for public keys.

          protection : string
            The encryption scheme to use for protecting the private key.

            If ``None`` (default), the behavior depends on ``format``:

            - For *DER*, the *PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC*
              scheme is used. The following operations are performed:

                1. A 16 byte Triple DES key is derived from the passphrase
                   using `Cryptodome.Protocol.KDF.PBKDF2` with 8 bytes salt,
                   and 1 000 iterations of `Cryptodome.Hash.HMAC`.
                2. The private key is encrypted using CBC.
                3. The encrypted key is encoded according to PKCS#8.

            - For *PEM*, the obsolete PEM encryption scheme is used.
              It is based on MD5 for key derivation, and Triple DES for encryption.

            Specifying a value for ``protection`` is only meaningful for PKCS#8
            (that is, ``pkcs=8``) and only if a pass phrase is present too.

            The supported schemes for PKCS#8 are listed in the
            `Cryptodome.IO.PKCS8` module (see ``wrap_algo`` parameter).

          randfunc : callable
            A function that provides random bytes. Only used for PEM encoding.
            The default is `Cryptodome.Random.get_random_bytes`.

        :Return: A byte string with the encoded public or private half
          of the key.
        :Raise ValueError:
            When the format is unknown or when you try to encrypt a private
            key with *DER* format and PKCS#1.
        :attention:
            If you don't provide a pass phrase, the private key will be
            exported in the clear!

        .. _RFC1421:    http://www.ietf.org/rfc/rfc1421.txt
        .. _RFC1423:    http://www.ietf.org/rfc/rfc1423.txt
        .. _`PKCS#1`:   http://www.ietf.org/rfc/rfc3447.txt
        .. _`PKCS#8`:   http://www.ietf.org/rfc/rfc5208.txt
        """

        if passphrase is not None:
            passphrase = tobytes(passphrase)

        if randfunc is None:
            randfunc = Random.get_random_bytes

        if format == 'OpenSSH':
            e_bytes, n_bytes = [x.to_bytes() for x in (self._e, self._n)]
            if bord(e_bytes[0]) & 0x80:
                e_bytes = bchr(0) + e_bytes
            if bord(n_bytes[0]) & 0x80:
                n_bytes = bchr(0) + n_bytes
            keyparts = [b('ssh-rsa'), e_bytes, n_bytes]
            keystring = b('').join([struct.pack(">I", len(kp)) + kp for kp in keyparts])
            return b('ssh-rsa ') + binascii.b2a_base64(keystring)[:-1]

        # DER format is always used, even in case of PEM, which simply
        # encodes it into BASE64.
        if self.has_private():
            binary_key = DerSequence([0,
                                      self.n,
                                      self.e,
                                      self.d,
                                      self.p,
                                      self.q,
                                      self.d % (self.p-1),
                                      self.d % (self.q-1),
                                      Integer(self.q).inverse(self.p)
                                      ]).encode()
            if pkcs == 1:
                key_type = 'RSA PRIVATE KEY'
                if format == 'DER' and passphrase:
                    raise ValueError("PKCS#1 private key cannot be encrypted")
            else:  # PKCS#8
                if format == 'PEM' and protection is None:
                    key_type = 'PRIVATE KEY'
                    binary_key = PKCS8.wrap(binary_key, oid, None)
                else:
                    key_type = 'ENCRYPTED PRIVATE KEY'
                    if not protection:
                        protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC'
                    binary_key = PKCS8.wrap(binary_key, oid,
                                            passphrase, protection)
                    passphrase = None
        else:
            key_type = "RSA PUBLIC KEY"
            binary_key = _create_subject_public_key_info(oid,
                                                         DerSequence([self.n,
                                                                      self.e])
                                                         )

        if format == 'DER':
            return binary_key
        if format == 'PEM':
            pem_str = PEM.encode(binary_key, key_type, passphrase, randfunc)
            return tobytes(pem_str)

        raise ValueError("Unknown key format '%s'. Cannot export the RSA key." % format)
Exemplo n.º 25
0
    def hexdigest(self):

        return "".join(["%02x" % bord(x) for x in tuple(self.digest())])
Exemplo n.º 26
0
def check_padding(pad):
    for v, x in enumerate(pad):
        if bord(x) != ((v + 1) & 0xFF):
            raise ValueError("Incorrect padding")
Exemplo n.º 27
0
    def decrypt(self, ciphertext):
        """Decrypt a message with PKCS#1 OAEP.

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

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

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

        # See 7.1.2 in RFC3447
        modBits = 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(ciphertext) != k or k<hLen+2:
            raise ValueError("Ciphertext with incorrect length.")
        # Step 2a (O2SIP)
        ct_int = bytes_to_long(ciphertext)
        # Step 2b (RSADP)
        m_int = self._key._decrypt(ct_int)
        # Complete step 2c (I2OSP)
        em = long_to_bytes(m_int, k)
        # Step 3a
        lHash = self._hashObj.new(self._label).digest()
        # Step 3b
        y = em[0]
        # y must be 0, but we MUST NOT check it here in order not to
        # allow attacks like Manger's (http://dl.acm.org/citation.cfm?id=704143)
        maskedSeed = em[1:hLen+1]
        maskedDB = em[hLen+1:]
        # Step 3c
        seedMask = self._mgf(maskedDB, hLen)
        # Step 3d
        seed = strxor(maskedSeed, seedMask)
        # Step 3e
        dbMask = self._mgf(seed, k-hLen-1)
        # Step 3f
        db = strxor(maskedDB, dbMask)
        # Step 3g
        one_pos = hLen + db[hLen:].find(b'\x01')
        lHash1 = db[:hLen]
        invalid = bord(y) | int(one_pos < hLen)
        hash_compare = strxor(lHash1, lHash)
        for x in hash_compare:
            invalid |= bord(x)
        for x in db[hLen:one_pos]:
            invalid |= bord(x)
        if invalid != 0:
            raise ValueError("Incorrect decryption.")
        # Step 4
        return db[one_pos + 1:]
Exemplo n.º 28
0
    def __init__(self, factory, nonce, mac_len, cipher_params):

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

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

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

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

        # Cache for MAC tag
        self._mac_tag = None

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

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

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

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

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

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

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

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

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

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

        # Memory allocated for the underlying block cipher is now owed
        # by the cipher mode
        raw_cipher.release()
Exemplo n.º 29
0
def import_key(extern_key, passphrase=None):
    """Import an RSA key (public or private half), encoded in standard
    form.

    Args:
      extern_key (string or byte string):
        The RSA key to import.

        The following formats are supported for an RSA **public key**:

        - X.509 certificate (binary or PEM format)
        - X.509 ``subjectPublicKeyInfo`` DER SEQUENCE (binary or PEM
          encoding)
        - `PKCS#1`_ ``RSAPublicKey`` DER SEQUENCE (binary or PEM encoding)
        - OpenSSH (textual public key only)

        The following formats are supported for an RSA **private key**:

        - PKCS#1 ``RSAPrivateKey`` DER SEQUENCE (binary or PEM encoding)
        - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo``
          DER SEQUENCE (binary or PEM encoding)
        - OpenSSH (textual public key only)

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

        The private key may be encrypted by means of a certain pass phrase
        either at the PEM level or at the PKCS#8 level.

      passphrase (string):
        In case of an encrypted private key, this is the pass phrase from
        which the decryption key is derived.

    Returns: An RSA key object (:class:`RsaKey`).

    Raises:
      ValueError/IndexError/TypeError:
        When the given key cannot be parsed (possibly because the pass
        phrase is wrong).

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt
    .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
    """

    extern_key = tobytes(extern_key)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    if extern_key.startswith(b('-----')):
        # This is probably a PEM encoded key.
        (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase)
        if enc_flag:
            passphrase = None
        return _import_keyDER(der, passphrase)

    if extern_key.startswith(b('ssh-rsa ')):
        # This is probably an OpenSSH key
        keystring = binascii.a2b_base64(extern_key.split(b(' '))[1])
        keyparts = []
        while len(keystring) > 4:
            l = struct.unpack(">I", keystring[:4])[0]
            keyparts.append(keystring[4:4 + l])
            keystring = keystring[4 + l:]
        e = Integer.from_bytes(keyparts[1])
        n = Integer.from_bytes(keyparts[2])
        return construct([n, e])

    if bord(extern_key[0]) == 0x30:
        # This is probably a DER encoded key
        return _import_keyDER(extern_key, passphrase)

    raise ValueError("RSA key format is not supported")
Exemplo n.º 30
0
def import_key(extern_key, passphrase=None):
    """Import an RSA key (public or private half), encoded in standard
    form.

    :Parameter extern_key:
        The RSA key to import, encoded as a byte string.

        An RSA public key can be in any of the following formats:

        - X.509 certificate (binary or PEM format)
        - X.509 ``subjectPublicKeyInfo`` DER SEQUENCE (binary or PEM
          encoding)
        - `PKCS#1`_ ``RSAPublicKey`` DER SEQUENCE (binary or PEM encoding)
        - OpenSSH (textual public key only)

        An RSA private key can be in any of the following formats:

        - PKCS#1 ``RSAPrivateKey`` DER SEQUENCE (binary or PEM encoding)
        - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo``
          DER SEQUENCE (binary or PEM encoding)
        - OpenSSH (textual public key only)

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

        The private key may be encrypted by means of a certain pass phrase
        either at the PEM level or at the PKCS#8 level.
    :Type extern_key: string

    :Parameter passphrase:
        In case of an encrypted private key, this is the pass phrase from
        which the decryption key is derived.
    :Type passphrase: string

    :Return: An RSA key object (`RsaKey`).

    :Raise ValueError/IndexError/TypeError:
        When the given key cannot be parsed (possibly because the pass
        phrase is wrong).

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt
    .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
    """
    extern_key = tobytes(extern_key)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    if extern_key.startswith(b('-----')):
        # This is probably a PEM encoded key.
        (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase)
        if enc_flag:
            passphrase = None
        return _import_keyDER(der, passphrase)

    if extern_key.startswith(b('ssh-rsa ')):
            # This is probably an OpenSSH key
            keystring = binascii.a2b_base64(extern_key.split(b(' '))[1])
            keyparts = []
            while len(keystring) > 4:
                l = struct.unpack(">I", keystring[:4])[0]
                keyparts.append(keystring[4:4 + l])
                keystring = keystring[4 + l:]
            e = Integer.from_bytes(keyparts[1])
            n = Integer.from_bytes(keyparts[2])
            return construct([n, e])

    if bord(extern_key[0]) == 0x30:
            # This is probably a DER encoded key
            return _import_keyDER(extern_key, passphrase)

    raise ValueError("RSA key format is not supported")
Exemplo n.º 31
0
    def exportKey(self, format='PEM', passphrase=None, pkcs=1,
                   protection=None, randfunc=None):
        """Export this RSA key.

        :Parameters:
          format : string
            The format to use for wrapping the key:

            - *'DER'*. Binary encoding.
            - *'PEM'*. Textual encoding, done according to `RFC1421`_/`RFC1423`_.
            - *'OpenSSH'*. Textual encoding, done according to OpenSSH specification.
              Only suitable for public keys (not private keys).

          passphrase : string
            For private keys only. The pass phrase used for deriving the encryption
            key.

          pkcs : integer
            For *DER* and *PEM* format only.
            The PKCS standard to follow for assembling the components of the key.
            You have two choices:

            - **1** (default): the public key is embedded into
              an X.509 ``SubjectPublicKeyInfo`` DER SEQUENCE.
              The private key is embedded into a `PKCS#1`_
              ``RSAPrivateKey`` DER SEQUENCE.
            - **8**: the private key is embedded into a `PKCS#8`_
              ``PrivateKeyInfo`` DER SEQUENCE. This value cannot be used
              for public keys.

          protection : string
            The encryption scheme to use for protecting the private key.

            If ``None`` (default), the behavior depends on ``format``:

            - For *DER*, the *PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC*
              scheme is used. The following operations are performed:

                1. A 16 byte Triple DES key is derived from the passphrase
                   using `Cryptodome.Protocol.KDF.PBKDF2` with 8 bytes salt,
                   and 1 000 iterations of `Cryptodome.Hash.HMAC`.
                2. The private key is encrypted using CBC.
                3. The encrypted key is encoded according to PKCS#8.

            - For *PEM*, the obsolete PEM encryption scheme is used.
              It is based on MD5 for key derivation, and Triple DES for encryption.

            Specifying a value for ``protection`` is only meaningful for PKCS#8
            (that is, ``pkcs=8``) and only if a pass phrase is present too.

            The supported schemes for PKCS#8 are listed in the
            `Cryptodome.IO.PKCS8` module (see ``wrap_algo`` parameter).

          randfunc : callable
            A function that provides random bytes. Only used for PEM encoding.
            The default is `Cryptodome.Random.get_random_bytes`.

        :Return: A byte string with the encoded public or private half
          of the key.
        :Raise ValueError:
            When the format is unknown or when you try to encrypt a private
            key with *DER* format and PKCS#1.
        :attention:
            If you don't provide a pass phrase, the private key will be
            exported in the clear!

        .. _RFC1421:    http://www.ietf.org/rfc/rfc1421.txt
        .. _RFC1423:    http://www.ietf.org/rfc/rfc1423.txt
        .. _`PKCS#1`:   http://www.ietf.org/rfc/rfc3447.txt
        .. _`PKCS#8`:   http://www.ietf.org/rfc/rfc5208.txt
        """

        if passphrase is not None:
            passphrase = tobytes(passphrase)

        if randfunc is None:
            randfunc = Random.get_random_bytes

        if format == 'OpenSSH':
            e_bytes, n_bytes = [x.to_bytes() for x in (self._e, self._n)]
            if bord(e_bytes[0]) & 0x80:
                e_bytes = bchr(0) + e_bytes
            if bord(n_bytes[0]) & 0x80:
                n_bytes = bchr(0) + n_bytes
            keyparts = [b('ssh-rsa'), e_bytes, n_bytes]
            keystring = b('').join([struct.pack(">I", len(kp)) + kp for kp in keyparts])
            return b('ssh-rsa ') + binascii.b2a_base64(keystring)[:-1]

        # DER format is always used, even in case of PEM, which simply
        # encodes it into BASE64.
        if self.has_private():
            binary_key = DerSequence([0,
                                      self.n,
                                      self.e,
                                      self.d,
                                      self.p,
                                      self.q,
                                      self.d % (self.p-1),
                                      self.d % (self.q-1),
                                      Integer(self.q).inverse(self.p)
                                      ]).encode()
            if pkcs == 1:
                key_type = 'RSA PRIVATE KEY'
                if format == 'DER' and passphrase:
                    raise ValueError("PKCS#1 private key cannot be encrypted")
            else:  # PKCS#8
                if format == 'PEM' and protection is None:
                    key_type = 'PRIVATE KEY'
                    binary_key = PKCS8.wrap(binary_key, oid, None)
                else:
                    key_type = 'ENCRYPTED PRIVATE KEY'
                    if not protection:
                        protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC'
                    binary_key = PKCS8.wrap(binary_key, oid,
                                            passphrase, protection)
                    passphrase = None
        else:
            key_type = "RSA PUBLIC KEY"
            binary_key = _create_subject_public_key_info(oid,
                                                         DerSequence([self.n,
                                                                      self.e])
                                                         )

        if format == 'DER':
            return binary_key
        if format == 'PEM':
            pem_str = PEM.encode(binary_key, key_type, passphrase, randfunc)
            return tobytes(pem_str)

        raise ValueError("Unknown key format '%s'. Cannot export the RSA key." % format)
Exemplo n.º 32
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")
Exemplo n.º 33
0
def import_key(encoded, passphrase=None, curve_name=None):
    """Import an ECC key (public or private).

    Args:
      encoded (bytes or multi-line string):
        The ECC key to import.

        An ECC **public** key can be:

        - An X.509 certificate, binary (DER) or ASCII (PEM)
        - An X.509 ``subjectPublicKeyInfo``, binary (DER) or ASCII (PEM)
        - A SEC1_ (or X9.62) byte string. You must also provide the
          ``curve_name``.
        - An OpenSSH line (e.g. the content of ``~/.ssh/id_ecdsa``, ASCII)

        An ECC **private** key can be:

        - In binary format (DER, see section 3 of `RFC5915`_ or `PKCS#8`_)
        - In ASCII format (PEM or `OpenSSH 6.5+`_)

        Private keys can be in the clear or password-protected.

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

      passphrase (byte string):
        The passphrase to use for decrypting a private key.
        Encryption may be applied protected at the PEM level or at the PKCS#8 level.
        This parameter is ignored if the key in input is not encrypted.

      curve_name (string):
        For a SEC1 byte string only. This is the name of the ECC curve,
        as defined in :numref:`curve_names`.

    Returns:
      :class:`EccKey` : a new ECC key object

    Raises:
      ValueError: when the given key cannot be parsed (possibly because
        the pass phrase is wrong).

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _RFC5915: http://www.ietf.org/rfc/rfc5915.txt
    .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
    .. _`OpenSSH 6.5+`: https://flak.tedunangst.com/post/new-openssh-key-format-and-bcrypt-pbkdf
    .. _SEC1: https://www.secg.org/sec1-v2.pdf
    """

    from Cryptodome.IO import PEM

    encoded = tobytes(encoded)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    # PEM
    if encoded.startswith(b'-----BEGIN OPENSSH PRIVATE KEY'):
        text_encoded = tostr(encoded)
        openssh_encoded, marker, enc_flag = PEM.decode(text_encoded,
                                                       passphrase)
        result = _import_openssh_private_ecc(openssh_encoded, passphrase)
        return result

    elif encoded.startswith(b'-----'):

        text_encoded = tostr(encoded)

        # Remove any EC PARAMETERS section
        # Ignore its content because the curve type must be already given in the key
        ecparams_start = "-----BEGIN EC PARAMETERS-----"
        ecparams_end = "-----END EC PARAMETERS-----"
        text_encoded = re.sub(ecparams_start + ".*?" + ecparams_end,
                              "",
                              text_encoded,
                              flags=re.DOTALL)

        der_encoded, marker, enc_flag = PEM.decode(text_encoded, passphrase)
        if enc_flag:
            passphrase = None
        try:
            result = _import_der(der_encoded, passphrase)
        except UnsupportedEccFeature as uef:
            raise uef
        except ValueError:
            raise ValueError("Invalid DER encoding inside the PEM file")
        return result

    # OpenSSH
    if encoded.startswith(b'ecdsa-sha2-'):
        return _import_openssh_public(encoded)

    # DER
    if len(encoded) > 0 and bord(encoded[0]) == 0x30:
        return _import_der(encoded, passphrase)

    # SEC1
    if len(encoded) > 0 and bord(encoded[0]) in b'\x02\x03\x04':
        if curve_name is None:
            raise ValueError("No curve name was provided")
        return _import_public_der(encoded, curve_name=curve_name)

    raise ValueError("ECC key format is not supported")
Exemplo n.º 34
0
        if enc_flag:
            passphrase = None
        try:
            result = _import_der(der_encoded, passphrase)
        except UnsupportedEccFeature, uef:
            raise uef
        except ValueError:
            raise ValueError("Invalid DER encoding inside the PEM file")
        return result

    # OpenSSH
    if encoded.startswith(b('ecdsa-sha2-')):
        return _import_openssh(encoded)

    # DER
    if bord(encoded[0]) == 0x30:
        return _import_der(encoded, passphrase)

    raise ValueError("ECC key format is not supported")


if __name__ == "__main__":
    import time
    d = 0xc51e4753afdec1e6b6c6a5b992f43f8dd0c7a8933072708b6522468b2ffb06fd

    point = generate(curve="P-256").pointQ
    start = time.time()
    count = 30
    for x in xrange(count):
        _ = point * d
    print(time.time() - start) / count * 1000, "ms"
Exemplo n.º 35
0
    def __init__(self, key, msg, ciphermod, cipher_params, mac_len):

        if ciphermod is None:
            raise TypeError("ciphermod must be specified (try AES)")

        self._key = _copy_bytes(None, None, key)
        self._factory = ciphermod
        if cipher_params is None:
            self._cipher_params = {}
        else:
            self._cipher_params = dict(cipher_params)
        self._mac_len = mac_len or ciphermod.block_size

        if self._mac_len < 4:
            raise ValueError("MAC tag length must be at least 4 bytes long")
        if self._mac_len > ciphermod.block_size:
            raise ValueError(
                "MAC tag length cannot be larger than a cipher block (%d) bytes"
                % ciphermod.block_size)

        # Section 5.3 of NIST SP 800 38B and Appendix B
        if ciphermod.block_size == 8:
            const_Rb = 0x1B
            self._max_size = 8 * (2**21)
        elif ciphermod.block_size == 16:
            const_Rb = 0x87
            self._max_size = 16 * (2**48)
        else:
            raise TypeError("CMAC requires a cipher with a block size"
                            "of 8 or 16 bytes, not %d" %
                            (ciphermod.block_size, ))

        # Size of the final MAC tag, in bytes
        self.digest_size = ciphermod.block_size
        self._mac_tag = None

        # Compute sub-keys
        zero_block = b'\x00' * ciphermod.block_size
        cipher = ciphermod.new(key, ciphermod.MODE_ECB, **self._cipher_params)
        l = cipher.encrypt(zero_block)
        if bord(l[0]) & 0x80:
            self._k1 = _shift_bytes(l, const_Rb)
        else:
            self._k1 = _shift_bytes(l)
        if bord(self._k1[0]) & 0x80:
            self._k2 = _shift_bytes(self._k1, const_Rb)
        else:
            self._k2 = _shift_bytes(self._k1)

        # Initialize CBC cipher with zero IV
        self._cbc = ciphermod.new(key, ciphermod.MODE_CBC, zero_block,
                                  **self._cipher_params)

        # Cache for outstanding data to authenticate
        self._cache = b""

        # Last two pieces of ciphertext produced
        self._last_ct = self._last_pt = zero_block
        self._before_last_ct = None

        # Counter for total message size
        self._data_size = 0

        if msg:
            self.update(msg)
Exemplo n.º 36
0
    def hexdigest(self):

        return "".join(["%02x" % bord(x)
                        for x in tuple(self.digest())])
Exemplo n.º 37
0
    def export_key(self,
                   format='PEM',
                   passphrase=None,
                   pkcs=1,
                   protection=None,
                   randfunc=None):
        """Export this RSA key.

        Args:
          format (string):
            The format to use for wrapping the key:

            - *'PEM'*. (*Default*) Text encoding, done according to `RFC1421`_/`RFC1423`_.
            - *'DER'*. Binary encoding.
            - *'OpenSSH'*. Textual encoding, done according to OpenSSH specification.
              Only suitable for public keys (not private keys).

          passphrase (string):
            (*For private keys only*) The pass phrase used for protecting the output.

          pkcs (integer):
            (*For private keys only*) The ASN.1 structure to use for
            serializing the key. Note that even in case of PEM
            encoding, there is an inner ASN.1 DER structure.

            With ``pkcs=1`` (*default*), the private key is encoded in a
            simple `PKCS#1`_ structure (``RSAPrivateKey``).

            With ``pkcs=8``, the private key is encoded in a `PKCS#8`_ structure
            (``PrivateKeyInfo``).

            .. note::
                This parameter is ignored for a public key.
                For DER and PEM, an ASN.1 DER ``SubjectPublicKeyInfo``
                structure is always used.

          protection (string):
            (*For private keys only*)
            The encryption scheme to use for protecting the private key.

            If ``None`` (default), the behavior depends on :attr:`format`:

            - For *'DER'*, the *PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC*
              scheme is used. The following operations are performed:

                1. A 16 byte Triple DES key is derived from the passphrase
                   using :func:`Cryptodome.Protocol.KDF.PBKDF2` with 8 bytes salt,
                   and 1 000 iterations of :mod:`Cryptodome.Hash.HMAC`.
                2. The private key is encrypted using CBC.
                3. The encrypted key is encoded according to PKCS#8.

            - For *'PEM'*, the obsolete PEM encryption scheme is used.
              It is based on MD5 for key derivation, and Triple DES for encryption.

            Specifying a value for :attr:`protection` is only meaningful for PKCS#8
            (that is, ``pkcs=8``) and only if a pass phrase is present too.

            The supported schemes for PKCS#8 are listed in the
            :mod:`Cryptodome.IO.PKCS8` module (see :attr:`wrap_algo` parameter).

          randfunc (callable):
            A function that provides random bytes. Only used for PEM encoding.
            The default is :func:`Cryptodome.Random.get_random_bytes`.

        Returns:
          byte string: the encoded key

        Raises:
          ValueError:when the format is unknown or when you try to encrypt a private
            key with *DER* format and PKCS#1.

        .. warning::
            If you don't provide a pass phrase, the private key will be
            exported in the clear!

        .. _RFC1421:    http://www.ietf.org/rfc/rfc1421.txt
        .. _RFC1423:    http://www.ietf.org/rfc/rfc1423.txt
        .. _`PKCS#1`:   http://www.ietf.org/rfc/rfc3447.txt
        .. _`PKCS#8`:   http://www.ietf.org/rfc/rfc5208.txt
        """

        if passphrase is not None:
            passphrase = tobytes(passphrase)

        if randfunc is None:
            randfunc = Random.get_random_bytes

        if format == 'OpenSSH':
            e_bytes, n_bytes = [x.to_bytes() for x in (self._e, self._n)]
            if bord(e_bytes[0]) & 0x80:
                e_bytes = bchr(0) + e_bytes
            if bord(n_bytes[0]) & 0x80:
                n_bytes = bchr(0) + n_bytes
            keyparts = [b('ssh-rsa'), e_bytes, n_bytes]
            keystring = b('').join(
                [struct.pack(">I", len(kp)) + kp for kp in keyparts])
            return b('ssh-rsa ') + binascii.b2a_base64(keystring)[:-1]

        # DER format is always used, even in case of PEM, which simply
        # encodes it into BASE64.
        if self.has_private():
            binary_key = DerSequence([
                0, self.n, self.e, self.d, self.p, self.q,
                self.d % (self.p - 1), self.d % (self.q - 1),
                Integer(self.q).inverse(self.p)
            ]).encode()
            if pkcs == 1:
                key_type = 'RSA PRIVATE KEY'
                if format == 'DER' and passphrase:
                    raise ValueError("PKCS#1 private key cannot be encrypted")
            else:  # PKCS#8
                if format == 'PEM' and protection is None:
                    key_type = 'PRIVATE KEY'
                    binary_key = PKCS8.wrap(binary_key, oid, None)
                else:
                    key_type = 'ENCRYPTED PRIVATE KEY'
                    if not protection:
                        protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC'
                    binary_key = PKCS8.wrap(binary_key, oid, passphrase,
                                            protection)
                    passphrase = None
        else:
            key_type = "PUBLIC KEY"
            binary_key = _create_subject_public_key_info(
                oid, DerSequence([self.n, self.e]))

        if format == 'DER':
            return binary_key
        if format == 'PEM':
            pem_str = PEM.encode(binary_key, key_type, passphrase, randfunc)
            return tobytes(pem_str)

        raise ValueError(
            "Unknown key format '%s'. Cannot export the RSA key." % format)
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
Exemplo n.º 39
0
 def read_byte(self):
     return bord(self.read(1)[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")
    def __init__(self, key, msg=None, ciphermod=None, cipher_params=None):
        """Create a new CMAC object.

        :Parameters:
          key : byte string
            secret key for the CMAC object.
            The key must be valid for the underlying cipher algorithm.
            For instance, it must be 16 bytes long for AES-128.
          msg : byte string
            The very first chunk of the message to authenticate.
            It is equivalent to an early call to `update`. Optional.
          ciphermod : module
            A cipher module from `Cryptodome.Cipher`.
            The cipher's block size has to be 128 bits.
            It is recommended to use `Cryptodome.Cipher.AES`.
          cipher_params : dictionary
            Extra keywords to use when creating a new cipher.
        """

        if ciphermod is None:
            raise TypeError("ciphermod must be specified (try AES)")

        self._key = key
        self._factory = ciphermod
        if cipher_params is None:
            self._cipher_params = {}
        else:
            self._cipher_params = dict(cipher_params)

        # Section 5.3 of NIST SP 800 38B and Appendix B
        if ciphermod.block_size == 8:
            const_Rb = 0x1B
            self._max_size = 8 * (2**21)
        elif ciphermod.block_size == 16:
            const_Rb = 0x87
            self._max_size = 16 * (2**48)
        else:
            raise TypeError("CMAC requires a cipher with a block size"
                            "of 8 or 16 bytes, not %d" %
                            (ciphermod.block_size, ))

        # Size of the final MAC tag, in bytes
        self.digest_size = ciphermod.block_size
        self._mac_tag = None

        # Compute sub-keys
        zero_block = bchr(0) * ciphermod.block_size
        cipher = ciphermod.new(key, ciphermod.MODE_ECB, **self._cipher_params)
        l = cipher.encrypt(zero_block)
        if bord(l[0]) & 0x80:
            self._k1 = _shift_bytes(l, const_Rb)
        else:
            self._k1 = _shift_bytes(l)
        if bord(self._k1[0]) & 0x80:
            self._k2 = _shift_bytes(self._k1, const_Rb)
        else:
            self._k2 = _shift_bytes(self._k1)

        # Initialize CBC cipher with zero IV
        self._cbc = ciphermod.new(key, ciphermod.MODE_CBC, zero_block,
                                  **self._cipher_params)

        # Cache for outstanding data to authenticate
        self._cache = b("")

        # Last two pieces of ciphertext produced
        self._last_ct = self._last_pt = zero_block
        self._before_last_ct = None

        # Counter for total message size
        self._data_size = 0

        if msg:
            self.update(msg)
Exemplo n.º 42
0
def import_key(extern_key, passphrase=None):
    """Import a DSA key.

    Args:
      extern_key (string or byte string):
        The DSA key to import.

        The following formats are supported for a DSA **public** key:

        - X.509 certificate (binary DER or PEM)
        - X.509 ``subjectPublicKeyInfo`` (binary DER or PEM)
        - OpenSSH (ASCII one-liner, see `RFC4253`_)

        The following formats are supported for a DSA **private** key:

        - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo``
          DER SEQUENCE (binary or PEM)
        - OpenSSL/OpenSSH custom format (binary or PEM)

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

      passphrase (string):
        In case of an encrypted private key, this is the pass phrase
        from which the decryption key is derived.

        Encryption may be applied either at the `PKCS#8`_ or at the PEM level.

    Returns:
      :class:`DsaKey` : a DSA key object

    Raises:
      ValueError : when the given key cannot be parsed (possibly because
        the pass phrase is wrong).

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt
    .. _PKCS#8: http://www.ietf.org/rfc/rfc5208.txt
    """

    extern_key = tobytes(extern_key)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    if extern_key.startswith(b'-----'):
        # This is probably a PEM encoded key
        (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase)
        if enc_flag:
            passphrase = None
        return _import_key_der(der, passphrase, None)

    if extern_key.startswith(b'ssh-dss '):
        # This is probably a public OpenSSH key
        keystring = binascii.a2b_base64(extern_key.split(b' ')[1])
        keyparts = []
        while len(keystring) > 4:
            length = struct.unpack(">I", keystring[:4])[0]
            keyparts.append(keystring[4:4 + length])
            keystring = keystring[4 + length:]
        if keyparts[0] == b"ssh-dss":
            tup = [Integer.from_bytes(keyparts[x]) for x in (4, 3, 1, 2)]
            return construct(tup)

    if bord(extern_key[0]) == 0x30:
        # This is probably a DER encoded key
        return _import_key_der(extern_key, passphrase, None)

    raise ValueError("DSA key format is not supported")
Exemplo n.º 43
0
def import_key(encoded, passphrase=None):
    """Import an ECC key (public or private).

    Args:
      encoded (bytes or multi-line string):
        The ECC key to import.

        An ECC **public** key can be:

        - An X.509 certificate, binary (DER) or ASCII (PEM)
        - An X.509 ``subjectPublicKeyInfo``, binary (DER) or ASCII (PEM)
        - An OpenSSH line (e.g. the content of ``~/.ssh/id_ecdsa``, ASCII)

        An ECC **private** key can be:

        - In binary format (DER, see section 3 of `RFC5915`_ or `PKCS#8`_)
        - In ASCII format (PEM or OpenSSH)

        Private keys can be in the clear or password-protected.

        For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.

      passphrase (byte string):
        The passphrase to use for decrypting a private key.
        Encryption may be applied protected at the PEM level or at the PKCS#8 level.
        This parameter is ignored if the key in input is not encrypted.

    Returns:
      :class:`EccKey` : a new ECC key object

    Raises:
      ValueError: when the given key cannot be parsed (possibly because
        the pass phrase is wrong).

    .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
    .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
    .. _RFC5915: http://www.ietf.org/rfc/rfc5915.txt
    .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
    """

    encoded = tobytes(encoded)
    if passphrase is not None:
        passphrase = tobytes(passphrase)

    # PEM
    if encoded.startswith(b('-----')):
        der_encoded, marker, enc_flag = PEM.decode(tostr(encoded), passphrase)
        if enc_flag:
            passphrase = None
        try:
            result = _import_der(der_encoded, passphrase)
        except UnsupportedEccFeature as uef:
            raise uef
        except ValueError:
            raise ValueError("Invalid DER encoding inside the PEM file")
        return result

    # OpenSSH
    if encoded.startswith(b('ecdsa-sha2-')):
        return _import_openssh(encoded)

    # DER
    if bord(encoded[0]) == 0x30:
        return _import_der(encoded, passphrase)

    raise ValueError("ECC key format is not supported")
Exemplo n.º 44
0
 def func(x):
     if (bord(x[0]) & 0x80):
         return bchr(0) + x
     else:
         return x
Exemplo n.º 45
0
 def read_byte(self):
     return bord(self.read(1)[0])
Exemplo n.º 46
0
 def _double(self, bs):
     doubled = bytes_to_long(bs) << 1
     if bord(bs[0]) & 0x80:
         doubled ^= 0x87
     return long_to_bytes(doubled, len(bs))[-len(bs):]
Exemplo n.º 47
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
Exemplo n.º 48
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()