Beispiel #1
0
 def testExportKey12(self):
     # Export and re-import the encrypted key. It must match.
     # PEM envelope, PKCS#8, old PEM encryption
     key = RSA.construct(
         [self.n, self.e, self.d, self.p, self.q, self.pInv])
     outkey = key.export_key('PEM', 'test', pkcs=8)
     self.assertTrue(tostr(outkey).find('4,ENCRYPTED') != -1)
     self.assertTrue(tostr(outkey).find('BEGIN PRIVATE KEY') != -1)
     inkey = RSA.importKey(outkey, 'test')
     self.assertEqual(key.n, inkey.n)
     self.assertEqual(key.e, inkey.e)
     self.assertEqual(key.d, inkey.d)
Beispiel #2
0
def encode(data, marker, passphrase=None, randfunc=None):
    """Encode a piece of binary data into PEM format.

    Args:
      data (byte string):
        The piece of binary data to encode.
      marker (string):
        The marker for the PEM block (e.g. "PUBLIC KEY").
        Note that there is no official master list for all allowed markers.
        Still, you can refer to the OpenSSL_ source code.
      passphrase (byte string):
        If given, the PEM block will be encrypted. The key is derived from
        the passphrase.
      randfunc (callable):
        Random number generation function; it accepts an integer N and returns
        a byte string of random data, N bytes long. If not given, a new one is
        instantiated.

    Returns:
      The PEM block, as a string.

    .. _OpenSSL: https://github.com/openssl/openssl/blob/master/include/openssl/pem.h
    """

    if randfunc is None:
        randfunc = get_random_bytes

    out = "-----BEGIN %s-----\n" % marker
    if passphrase:
        # We only support 3DES for encryption
        salt = randfunc(8)
        key = PBKDF1(passphrase, salt, 16, 1, MD5)
        key += PBKDF1(key + passphrase, salt, 8, 1, MD5)
        objenc = DES3.new(key, DES3.MODE_CBC, salt)
        out += "Proc-Type: 4,ENCRYPTED\nDEK-Info: DES-EDE3-CBC,%s\n\n" %\
            tostr(hexlify(salt).upper())
        # Encrypt with PKCS#7 padding
        data = objenc.encrypt(pad(data, objenc.block_size))
    elif passphrase is not None:
        raise ValueError("Empty password")

    # Each BASE64 line can take up to 64 characters (=48 bytes of data)
    # b2a_base64 adds a new line character!
    chunks = [
        tostr(b2a_base64(data[i:i + 48])) for i in range(0, len(data), 48)
    ]
    out += "".join(chunks)
    out += "-----END %s-----" % marker
    return out
Beispiel #3
0
def encode(data, marker, passphrase=None, randfunc=None):
    """Encode a piece of binary data into PEM format.

    Args:
      data (byte string):
        The piece of binary data to encode.
      marker (string):
        The marker for the PEM block (e.g. "PUBLIC KEY").
        Note that there is no official master list for all allowed markers.
        Still, you can refer to the OpenSSL_ source code.
      passphrase (byte string):
        If given, the PEM block will be encrypted. The key is derived from
        the passphrase.
      randfunc (callable):
        Random number generation function; it accepts an integer N and returns
        a byte string of random data, N bytes long. If not given, a new one is
        instantiated.

    Returns:
      The PEM block, as a string.

    .. _OpenSSL: https://github.com/openssl/openssl/blob/master/include/openssl/pem.h
    """

    if randfunc is None:
        randfunc = get_random_bytes

    out = "-----BEGIN %s-----\n" % marker
    if passphrase:
        # We only support 3DES for encryption
        salt = randfunc(8)
        key = PBKDF1(passphrase, salt, 16, 1, MD5)
        key += PBKDF1(key + passphrase, salt, 8, 1, MD5)
        objenc = DES3.new(key, DES3.MODE_CBC, salt)
        out += "Proc-Type: 4,ENCRYPTED\nDEK-Info: DES-EDE3-CBC,%s\n\n" %\
            tostr(hexlify(salt).upper())
        # Encrypt with PKCS#7 padding
        data = objenc.encrypt(pad(data, objenc.block_size))
    elif passphrase is not None:
        raise ValueError("Empty password")

    # Each BASE64 line can take up to 64 characters (=48 bytes of data)
    # b2a_base64 adds a new line character!
    chunks = [tostr(b2a_base64(data[i:i + 48]))
              for i in range(0, len(data), 48)]
    out += "".join(chunks)
    out += "-----END %s-----" % marker
    return out
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")
Beispiel #5
0
def _bcrypt_decode(data):
    s = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"

    bits = []
    for c in tostr(data):
        idx = s.find(c)
        bits6 = bin(idx)[2:].zfill(6)
        bits.append(bits6)
    bits = "".join(bits)

    modulo4 = len(data) % 4
    if modulo4 == 1:
        raise ValueError("Incorrect length")
    elif modulo4 == 2:
        bits = bits[:-4]
    elif modulo4 == 3:
        bits = bits[:-2]

    bits8 = [bits[idx:idx + 8] for idx in range(0, len(bits), 8)]

    result = []
    for g in bits8:
        result.append(bchr(int(g, 2)))
    result = b"".join(result)

    return result
Beispiel #6
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
        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")
Beispiel #7
0
 def testExportKey13(self):
     # Export and re-import the encrypted key. It must match.
     # PEM envelope, PKCS#8, PKCS#8 encryption
     key = RSA.construct(
         [self.n, self.e, self.d, self.p, self.q, self.pInv])
     outkey = key.export_key(
         'PEM',
         'test',
         pkcs=8,
         protection='PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC')
     self.assertTrue(tostr(outkey).find('4,ENCRYPTED') == -1)
     self.assertTrue(
         tostr(outkey).find('BEGIN ENCRYPTED PRIVATE KEY') != -1)
     inkey = RSA.importKey(outkey, 'test')
     self.assertEqual(key.n, inkey.n)
     self.assertEqual(key.e, inkey.e)
     self.assertEqual(key.d, inkey.d)
Beispiel #8
0
    def test_import_private_pem_encrypted(self):
        for algo in "des3", :  # TODO: , "aes128", "aes192", "aes256_gcm":
            key_file = load_file("ecc_p256_private_enc_%s.pem" % algo)

            key = ECC.import_key(key_file, "secret")
            self.assertEqual(ref_private, key)

            key = ECC.import_key(tostr(key_file), b"secret")
            self.assertEqual(ref_private, key)
    def test_import_private_pem_encrypted(self):
        for algo in "des3", : # TODO: , "aes128", "aes192", "aes256_gcm":
            key_file = load_file("ecc_p256_private_enc_%s.pem" % algo)

            key = ECC.import_key(key_file, "secret")
            self.assertEqual(ref_private, key)

            key = ECC.import_key(tostr(key_file), b("secret"))
            self.assertEqual(ref_private, key)
Beispiel #10
0
    def _export_openssh(self):
        assert not self.has_private()

        desc = "ecdsa-sha2-nistp256"

        # Uncompressed form
        order_bytes = _curve.order.size_in_bytes()
        public_key = (bchr(4) + self.pointQ.x.to_bytes(order_bytes) +
                      self.pointQ.y.to_bytes(order_bytes))

        comps = (tobytes(desc), b("nistp256"), public_key)
        blob = b("").join([struct.pack(">I", len(x)) + x for x in comps])
        return desc + " " + tostr(binascii.b2a_base64(blob))
Beispiel #11
0
    def _export_openssh(self):
        assert not self.has_private()

        desc = "ecdsa-sha2-nistp256"

        # Uncompressed form
        order_bytes = _curve.order.size_in_bytes()
        public_key = (bchr(4) +
                      self.pointQ.x.to_bytes(order_bytes) +
                      self.pointQ.y.to_bytes(order_bytes))

        comps = (tobytes(desc), b("nistp256"), public_key)
        blob = b("").join([ struct.pack(">I", len(x)) + x for x in comps])
        return desc + " " + tostr(binascii.b2a_base64(blob))
Beispiel #12
0
    def _export_openssh(self, compress):
        if self.has_private():
            raise ValueError("Cannot export OpenSSH private keys")

        desc = "ecdsa-sha2-nistp256"
        order_bytes = _curve.order.size_in_bytes()

        if compress:
            first_byte = 2 + self.pointQ.y.is_odd()
            public_key = (bchr(first_byte) +
                          self.pointQ.x.to_bytes(order_bytes))
        else:
            public_key = (b'\x04' + self.pointQ.x.to_bytes(order_bytes) +
                          self.pointQ.y.to_bytes(order_bytes))

        comps = (tobytes(desc), b"nistp256", public_key)
        blob = b"".join([struct.pack(">I", len(x)) + x for x in comps])
        return desc + " " + tostr(binascii.b2a_base64(blob))
Beispiel #13
0
    def _export_openssh(self, compress):
        if self.has_private():
            raise ValueError("Cannot export OpenSSH private keys")

        desc = "ecdsa-sha2-nistp256"
        order_bytes = _curve.order.size_in_bytes()
        
        if compress:
            first_byte = 2 + self.pointQ.y.is_odd()
            public_key = (bchr(first_byte) +
                          self.pointQ.x.to_bytes(order_bytes))
        else:
            public_key = (b'\x04' +
                          self.pointQ.x.to_bytes(order_bytes) +
                          self.pointQ.y.to_bytes(order_bytes))

        comps = (tobytes(desc), b"nistp256", public_key)
        blob = b"".join([ struct.pack(">I", len(x)) + x for x in comps])
        return desc + " " + tostr(binascii.b2a_base64(blob))
Beispiel #14
0
    def _export_openssh(self, compress):
        if self.has_private():
            raise ValueError("Cannot export OpenSSH private keys")

        desc = self._curve.openssh
        modulus_bytes = self.pointQ.size_in_bytes()

        if compress:
            first_byte = 2 + self.pointQ.y.is_odd()
            public_key = (bchr(first_byte) +
                          self.pointQ.x.to_bytes(modulus_bytes))
        else:
            public_key = (b'\x04' + self.pointQ.x.to_bytes(modulus_bytes) +
                          self.pointQ.y.to_bytes(modulus_bytes))

        middle = desc.split("-")[2]
        comps = (tobytes(desc), tobytes(middle), public_key)
        blob = b"".join([struct.pack(">I", len(x)) + x for x in comps])
        return desc + " " + tostr(binascii.b2a_base64(blob))
Beispiel #15
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")
Beispiel #16
0
def xl(text):
    return tostr(hexlify(tobytes(text)))
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'-----'):

        text_encoded = tostr(encoded)

        # Remove any EC PARAMETERS section
        # Ignore its content because the curve type must be already given in the key
        if sys.version_info[:2] != (2, 6):
            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(encoded)

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

    raise ValueError("ECC key format is not supported")
Beispiel #18
0
def read_string(data):
    s, d = read_bytes(data)
    return tostr(s), d
Beispiel #19
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")
nist_tdes_mmt_files = ("TECBMMT2.rsp", "TECBMMT3.rsp")

for tdes_file in nist_tdes_mmt_files:
    test_vectors = load_tests(("Cryptodome", "SelfTest", "Cipher", "test_vectors", "TDES"),
                                  tdes_file,
                                  "TDES ECB (%s)" % tdes_file,
                                  { "count" : lambda x: int(x) } )
    assert(test_vectors)
    for index, tv in enumerate(test_vectors):

        # The test vector file contains some directive lines
        if isinstance(tv, basestring):
            continue

        key = tv.key1 + tv.key2 + tv.key3
        test_data_item = (tostr(hexlify(tv.plaintext)),
                          tostr(hexlify(tv.ciphertext)),
                          tostr(hexlify(key)),
                          "%s (%s)" % (tdes_file, index))
        test_data.append(test_data_item)


class CheckParity(unittest.TestCase):

    def test_parity_option2(self):
        before_2k = unhexlify("CABF326FA56734324FFCCABCDEFACABF")
        after_2k = DES3.adjust_key_parity(before_2k)
        self.assertEqual(after_2k,
                         unhexlify("CBBF326EA46734324FFDCBBCDFFBCBBF"))

    def test_parity_option3(self):
Beispiel #21
0
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")
Beispiel #22
0
nist_tdes_mmt_files = ("TECBMMT2.rsp", "TECBMMT3.rsp")

for tdes_file in nist_tdes_mmt_files:

    test_vectors = load_test_vectors(
        ("Cipher", "TDES"), tdes_file, "TDES ECB (%s)" % tdes_file,
        {"count": lambda x: int(x)}) or []

    for index, tv in enumerate(test_vectors):

        # The test vector file contains some directive lines
        if isinstance(tv, str):
            continue

        key = tv.key1 + tv.key2 + tv.key3
        test_data_item = (tostr(hexlify(tv.plaintext)),
                          tostr(hexlify(tv.ciphertext)), tostr(hexlify(key)),
                          "%s (%s)" % (tdes_file, index))
        test_data.append(test_data_item)


class CheckParity(unittest.TestCase):
    def test_parity_option2(self):
        before_2k = unhexlify("CABF326FA56734324FFCCABCDEFACABF")
        after_2k = DES3.adjust_key_parity(before_2k)
        self.assertEqual(after_2k,
                         unhexlify("CBBF326EA46734324FFDCBBCDFFBCBBF"))

    def test_parity_option3(self):
        before_3k = unhexlify(
            "AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCC")
Beispiel #23
0
def xl(text):
    return tostr(hexlify(tobytes(text)))
Beispiel #24
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")
def compact(lines):
    ext = b("").join(lines)
    return unhexlify(tostr(ext).replace(" ", "").replace(":", ""))
Beispiel #26
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")
Beispiel #27
0
def compact(lines):
    ext = b"".join(lines)
    return unhexlify(tostr(ext).replace(" ", "").replace(":", ""))
Beispiel #28
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")