Exemple #1
0
    def test3(self):
        """Verify unwrapping with encryption"""

        for t in self.wrapped_enc_keys:
            res1, res2, res3 = PKCS8.unwrap(t[4], b("TestTest"))
            self.assertEqual(res1, self.oid_key)
            self.assertEqual(res2, self.clear_key)
Exemple #2
0
def _importKeyDER(extern_key, passphrase, verify_x509_cert):
    """Import an RSA key (public or private half), encoded in DER form."""

    try:

        der = DerSequence().decode(extern_key)

        # Try PKCS#1 first, for a private key
        if len(der) == 9 and der.hasOnlyInts() and der[0] == 0:
            # ASN.1 RSAPrivateKey element
            del der[6:]     # Remove d mod (p-1),
                            # d mod (q-1), and
                            # q^{-1} mod p
            der.append(Integer(der[4]).inverse(der[5]))  # Add p^{-1} mod q
            del der[0]      # Remove version
            return construct(der[:])

        # Keep on trying PKCS#1, but now for a public key
        if len(der) == 2:
            try:
                # The DER object is an RSAPublicKey SEQUENCE with
                # two elements
                if der.hasOnlyInts():
                    return construct(der[:])
                # The DER object is a SubjectPublicKeyInfo SEQUENCE
                # with two elements: an 'algorithmIdentifier' and a
                # 'subjectPublicKey'BIT STRING.
                # 'algorithmIdentifier' takes the value given at the
                # module level.
                # 'subjectPublicKey' encapsulates the actual ASN.1
                # RSAPublicKey element.
                if der[0] == algorithmIdentifier:
                    bitmap = DerBitString().decode(der[1])
                    rsaPub = DerSequence().decode(bitmap.value)
                    if len(rsaPub) == 2 and rsaPub.hasOnlyInts():
                        return construct(rsaPub[:])
            except (ValueError, EOFError):
                pass

        # Try to see if this is an X.509 DER certificate
        # (Certificate ASN.1 type)
        if len(der) == 3:
            from Crypto.PublicKey import _extract_sp_info
            try:
                sp_info = _extract_sp_info(der)
                if verify_x509_cert:
                    raise NotImplementedError("X.509 certificate validation is not supported")
                return _importKeyDER(sp_info, passphrase, False)
            except ValueError:
                pass

        # Try PKCS#8 (possibly encrypted)
        k = PKCS8.unwrap(extern_key, passphrase)
        if k[0] == oid:
            return _importKeyDER(k[1], passphrase, False)

    except (ValueError, EOFError):
        pass

    raise ValueError("RSA key format is not supported")
Exemple #3
0
def _import_pkcs8(encoded, passphrase, params):
    if params:
        raise ValueError("PKCS#8 already includes parameters")
    k = PKCS8.unwrap(encoded, passphrase)
    if k[0] != oid:
        raise ValueError("No PKCS#8 encoded DSA key")
    x = DerInteger().decode(k[1]).value
    p, q, g = list(DerSequence().decode(k[2]))
    tup = (pow(g, x, p), g, p, q, x)
    return construct(tup)
Exemple #4
0
def _import_pkcs8(encoded, passphrase, params):
    if params:
        raise ValueError("PKCS#8 already includes parameters")
    k = PKCS8.unwrap(encoded, passphrase)
    if k[0] != oid:
        raise ValueError("No PKCS#8 encoded DSA key")
    x = DerInteger().decode(k[1]).value
    p, q, g = list(DerSequence().decode(k[2]))
    tup = (pow(g, x, p), g, p, q, x)
    return construct(tup)
Exemple #5
0
    def _importKeyDER(self, key_data, passphrase=None, params=None):
        """Import a DSA key (public or private half), encoded in DER form."""

        try:
            #
            # Dss-Parms  ::=  SEQUENCE  {
            #       p       OCTET STRING,
            #       q       OCTET STRING,
            #       g       OCTET STRING
            # }
            #

            # Try a simple private key first
            if params:
                x = decode_der(DerInteger, key_data).value
                params = decode_der(DerSequence, params)  # Dss-Parms
                p, q, g = list(params)
                y = pow(g, x, p)
                tup = (y, g, p, q, x)
                return self.construct(tup)

            der = decode_der(DerSequence, key_data)

            # Try OpenSSL format for private keys
            if len(der) == 6 and der.hasOnlyInts() and der[0] == 0:
                tup = [der[comp] for comp in (4, 3, 1, 2, 5)]
                return self.construct(tup)

            # Try SubjectPublicKeyInfo
            if len(der) == 2:
                try:
                    algo = decode_der(DerSequence, der[0])
                    algo_oid = decode_der(DerObjectId, algo[0]).value
                    params = decode_der(DerSequence, algo[1])  # Dss-Parms

                    if algo_oid == oid and len(params) == 3 and\
                            params.hasOnlyInts():
                        bitmap = decode_der(DerBitString, der[1])
                        pub_key = decode_der(DerInteger, bitmap.value)
                        tup = [pub_key.value]
                        tup += [params[comp] for comp in (2, 0, 1)]
                        return self.construct(tup)
                except (ValueError, EOFError):
                    pass

            # Try unencrypted PKCS#8
            p8_pair = PKCS8.unwrap(key_data, passphrase)
            if p8_pair[0] == oid:
                return self._importKeyDER(p8_pair[1], passphrase, p8_pair[2])

        except (ValueError, EOFError):
            pass

        raise KeyFormatError("DSA key format is not supported")
Exemple #6
0
    def _importKeyDER(self, key_data, passphrase=None, params=None):
        """Import a DSA key (public or private half), encoded in DER form."""

        try:
            #
            # Dss-Parms  ::=  SEQUENCE  {
            #       p       OCTET STRING,
            #       q       OCTET STRING,
            #       g       OCTET STRING
            # }
            #

            # Try a simple private key first
            if params:
                x = decode_der(DerInteger, key_data).value
                params = decode_der(DerSequence, params)    # Dss-Parms
                p, q, g = list(params)
                y = pow(g, x, p)
                tup = (y, g, p, q, x)
                return self.construct(tup)

            der = decode_der(DerSequence, key_data)

            # Try OpenSSL format for private keys
            if len(der) == 6 and der.hasOnlyInts() and der[0] == 0:
                tup = [der[comp] for comp in (4, 3, 1, 2, 5)]
                return self.construct(tup)

            # Try SubjectPublicKeyInfo
            if len(der) == 2:
                try:
                    algo = decode_der(DerSequence, der[0])
                    algo_oid = decode_der(DerObjectId, algo[0]).value
                    params = decode_der(DerSequence, algo[1])  # Dss-Parms

                    if algo_oid == oid and len(params) == 3 and\
                            params.hasOnlyInts():
                        bitmap = decode_der(DerBitString, der[1])
                        pub_key = decode_der(DerInteger, bitmap.value)
                        tup = [pub_key.value]
                        tup += [params[comp] for comp in (2, 0, 1)]
                        return self.construct(tup)
                except (ValueError, EOFError):
                    pass

            # Try unencrypted PKCS#8
            p8_pair = PKCS8.unwrap(key_data, passphrase)
            if p8_pair[0] == oid:
                return self._importKeyDER(p8_pair[1], passphrase, p8_pair[2])

        except (ValueError, EOFError):
            pass

        raise KeyFormatError("DSA key format is not supported")
Exemple #7
0
    def _parse_key_pkcs8(self, data: bytes) -> bytes:
        parsed = pem.parse(data)
        if parsed and len(parsed) == 1:
            data = base64.b64decode(''.join(
                parsed[0].as_text().strip().split("\n")[1:-1]))

        try:
            (_, key, _) = pkcs8.unwrap(data, self.password.encode("utf-8"))
        except ValueError as error:
            raise X509AdapterError(
                "invalid password or PKCS#8 data") from error

        return key
Exemple #8
0
 def _load_private_key(self):
     """Load the private key used to sign HTTP requests.
         The private key is used to sign HTTP requests as defined in
         https://datatracker.ietf.org/doc/draft-cavage-http-signatures/.
     """
     if self.private_key is not None:
         return
     with open(self.private_key_path, 'r') as f:
         pem_data = f.read()
         # Verify PEM Pre-Encapsulation Boundary
         r = re.compile(r"\s*-----BEGIN (.*)-----\s+")
         m = r.match(pem_data)
         if not m:
             raise ValueError("Not a valid PEM pre boundary")
         pem_header = m.group(1)
         if pem_header == 'RSA PRIVATE KEY':
             self.private_key = RSA.importKey(pem_data,
                                              self.private_key_passphrase)
         elif pem_header == 'EC PRIVATE KEY':
             self.private_key = ECC.import_key(pem_data,
                                               self.private_key_passphrase)
         elif pem_header in {'PRIVATE KEY', 'ENCRYPTED PRIVATE KEY'}:
             # Key is in PKCS8 format, which is capable of holding many different
             # types of private keys, not just EC keys.
             (key_binary, pem_header, is_encrypted) = \
                 PEM.decode(pem_data, self.private_key_passphrase)
             (oid, privkey, params) = \
                 PKCS8.unwrap(key_binary, passphrase=self.private_key_passphrase)
             if oid == '1.2.840.10045.2.1':
                 self.private_key = ECC.import_key(
                     pem_data, self.private_key_passphrase)
             else:
                 raise Exception("Unsupported key: {0}. OID: {1}".format(
                     pem_header, oid))
         else:
             raise Exception("Unsupported key: {0}".format(pem_header))
         # Validate the specified signature algorithm is compatible with the private key.
         if self.signing_algorithm is not None:
             supported_algs = None
             if isinstance(self.private_key, RSA.RsaKey):
                 supported_algs = {
                     ALGORITHM_RSASSA_PSS, ALGORITHM_RSASSA_PKCS1v15
                 }
             elif isinstance(self.private_key, ECC.EccKey):
                 supported_algs = ALGORITHM_ECDSA_KEY_SIGNING_ALGORITHMS
             if supported_algs is not None and self.signing_algorithm not in supported_algs:
                 raise Exception(
                     "Signing algorithm {0} is not compatible with private key"
                     .format(self.signing_algorithm))
Exemple #9
0
    def _importKeyDER(self, extern_key, passphrase=None):
        """Import an RSA key (public or private half), encoded in DER form."""

        try:

            der = decode_der(DerSequence, extern_key)

            # Try PKCS#1 first, for a private key
            if len(der) == 9 and der.hasOnlyInts() and der[0] == 0:
                # ASN.1 RSAPrivateKey element
                del der[6:]  # Remove d mod (p-1),
                # d mod (q-1), and
                # q^{-1} mod p
                der.append(inverse(der[4], der[5]))  # Add p^{-1} mod q
                del der[0]  # Remove version
                return self.construct(der[:])

            # Keep on trying PKCS#1, but now for a public key
            if len(der) == 2:
                try:
                    # The DER object is an RSAPublicKey SEQUENCE with
                    # two elements
                    if der.hasOnlyInts():
                        return self.construct(der[:])
                    # The DER object is a SubjectPublicKeyInfo SEQUENCE
                    # with two elements: an 'algorithmIdentifier' and a
                    # 'subjectPublicKey'BIT STRING.
                    # 'algorithmIdentifier' takes the value given at the
                    # module level.
                    # 'subjectPublicKey' encapsulates the actual ASN.1
                    # RSAPublicKey element.
                    if der[0] == algorithmIdentifier:
                        bitmap = decode_der(DerBitString, der[1])
                        rsaPub = decode_der(DerSequence, bitmap.value)
                        if len(rsaPub) == 2 and rsaPub.hasOnlyInts():
                            return self.construct(rsaPub[:])
                except (ValueError, EOFError):
                    pass

            # Try PKCS#8 (possibly encrypted)
            k = PKCS8.unwrap(extern_key, passphrase)
            if k[0] == oid:
                return self._importKeyDER(k[1], passphrase)

        except (ValueError, EOFError):
            pass

        raise ValueError("RSA key format is not supported")
Exemple #10
0
    def _importKeyDER(self, extern_key, passphrase=None):
        """Import an RSA key (public or private half), encoded in DER form."""

        try:

            der = decode_der(DerSequence, extern_key)

            # Try PKCS#1 first, for a private key
            if len(der) == 9 and der.hasOnlyInts() and der[0] == 0:
                # ASN.1 RSAPrivateKey element
                del der[6:]     # Remove d mod (p-1),
                                # d mod (q-1), and
                                # q^{-1} mod p
                der.append(inverse(der[4], der[5]))  # Add p^{-1} mod q
                del der[0]      # Remove version
                return self.construct(der[:])

            # Keep on trying PKCS#1, but now for a public key
            if len(der) == 2:
                try:
                    # The DER object is an RSAPublicKey SEQUENCE with
                    # two elements
                    if der.hasOnlyInts():
                        return self.construct(der[:])
                    # The DER object is a SubjectPublicKeyInfo SEQUENCE
                    # with two elements: an 'algorithmIdentifier' and a
                    # 'subjectPublicKey'BIT STRING.
                    # 'algorithmIdentifier' takes the value given at the
                    # module level.
                    # 'subjectPublicKey' encapsulates the actual ASN.1
                    # RSAPublicKey element.
                    if der[0] == algorithmIdentifier:
                        bitmap = decode_der(DerBitString, der[1])
                        rsaPub = decode_der(DerSequence, bitmap.value)
                        if len(rsaPub) == 2 and rsaPub.hasOnlyInts():
                            return self.construct(rsaPub[:])
                except (ValueError, EOFError):
                    pass

            # Try PKCS#8 (possibly encrypted)
            k = PKCS8.unwrap(extern_key, passphrase)
            if k[0] == oid:
                return self._importKeyDER(k[1], passphrase)

        except (ValueError, EOFError):
            pass

        raise ValueError("RSA key format is not supported")
Exemple #11
0
def _import_pkcs8(encoded, passphrase):

    # From RFC5915, Section 1:
    #
    # Distributing an EC private key with PKCS#8 [RFC5208] involves including:
    # a) id-ecPublicKey, id-ecDH, or id-ecMQV (from [RFC5480]) with the
    #    namedCurve as the parameters in the privateKeyAlgorithm field; and
    # b) ECPrivateKey in the PrivateKey field, which is an OCTET STRING.

    algo_oid, private_key, params = PKCS8.unwrap(encoded, passphrase)

    # We accept id-ecPublicKey, id-ecDH, id-ecMQV without making any
    # distiction for now.
    unrestricted_oid = "1.2.840.10045.2.1"
    ecdh_oid = "1.3.132.1.12"
    ecmqv_oid = "1.3.132.1.13"

    if algo_oid not in (unrestricted_oid, ecdh_oid, ecmqv_oid):
        raise UnsupportedEccFeature("Unsupported ECC purpose (OID: %s)" % oid)

    curve_name = DerObjectId().decode(params).value

    return _import_private_der(private_key, passphrase, curve_name)
Exemple #12
0
def _import_pkcs8(encoded, passphrase):

    # From RFC5915, Section 1:
    #
    # Distributing an EC private key with PKCS#8 [RFC5208] involves including:
    # a) id-ecPublicKey, id-ecDH, or id-ecMQV (from [RFC5480]) with the
    #    namedCurve as the parameters in the privateKeyAlgorithm field; and
    # b) ECPrivateKey in the PrivateKey field, which is an OCTET STRING.

    algo_oid, private_key, params = PKCS8.unwrap(encoded, passphrase)

    # We accept id-ecPublicKey, id-ecDH, id-ecMQV without making any
    # distiction for now.
    unrestricted_oid = "1.2.840.10045.2.1"
    ecdh_oid = "1.3.132.1.12"
    ecmqv_oid = "1.3.132.1.13"

    if algo_oid not in (unrestricted_oid, ecdh_oid, ecmqv_oid):
        raise ValueError("No PKCS#8 encoded ECC key")

    curve_name = DerObjectId().decode(params).value

    return _import_private_der(private_key, passphrase, curve_name)
Exemple #13
0
def _importKeyDER(key_data, passphrase, params):
    """Import a DSA key (public or private half), encoded in DER form."""

    try:
        #
        # Dss-Parms  ::=  SEQUENCE  {
        #       p       OCTET STRING,
        #       q       OCTET STRING,
        #       g       OCTET STRING
        # }
        #

        # Try a simple private key first
        if params:
            x = DerInteger().decode(key_data).value
            p, q, g = list(DerSequence().decode(params))    # Dss-Parms
            tup = (pow(g, x, p), g, p, q, x)
            return construct(tup)

        der = DerSequence().decode(key_data)

        # Try OpenSSL format for private keys
        if len(der) == 6 and der.hasOnlyInts() and der[0] == 0:
            tup = [der[comp] for comp in (4, 3, 1, 2, 5)]
            return construct(tup)

        # Try SubjectPublicKeyInfo
        if len(der) == 2:
            try:
                algo = DerSequence().decode(der[0])
                algo_oid = DerObjectId().decode(algo[0]).value
                params = DerSequence().decode(algo[1])  # Dss-Parms

                if algo_oid == oid and len(params) == 3 and\
                        params.hasOnlyInts():
                    bitmap = DerBitString().decode(der[1])
                    pub_key = DerInteger().decode(bitmap.value)
                    tup = [pub_key.value]
                    tup += [params[comp] for comp in (2, 0, 1)]
                    return construct(tup)
            except (ValueError, EOFError):
                pass

        # Try to see if this is an X.509 DER certificate
        # (Certificate ASN.1 type)
        if len(der) == 3:
            from Crypto.PublicKey import _extract_sp_info
            try:
                sp_info = _extract_sp_info(der)
                return _importKeyDER(sp_info, passphrase, None)
            except ValueError:
                pass

        # Try unencrypted PKCS#8
        p8_pair = PKCS8.unwrap(key_data, passphrase)
        if p8_pair[0] == oid:
            return _importKeyDER(p8_pair[1], passphrase, p8_pair[2])

    except (ValueError, EOFError):
        pass

    raise ValueError("DSA key format is not supported")
Exemple #14
0
 def test2(self):
     """Verify wrapping w/o encryption"""
     wrapped = PKCS8.wrap(self.clear_key, self.oid_key)
     res1, res2, res3 = PKCS8.unwrap(wrapped)
     self.assertEqual(res1, self.oid_key)
     self.assertEqual(res2, self.clear_key)
Exemple #15
0
 def test1(self):
     """Verify unwrapping w/o encryption"""
     res1, res2, res3 = PKCS8.unwrap(self.wrapped_clear_key)
     self.assertEqual(res1, self.oid_key)
     self.assertEqual(res2, self.clear_key)
Exemple #16
0
def _import_pkcs8(encoded, passphrase):
    k = PKCS8.unwrap(encoded, passphrase)
    if k[0] != oid:
        raise ValueError("No PKCS#8 encoded RSA key")
    return _import_keyDER(k[1], passphrase)
Exemple #17
0
 def test2(self):
     """Verify wrapping w/o encryption"""
     wrapped = PKCS8.wrap(self.clear_key, self.oid_key)
     res1, res2, res3 = PKCS8.unwrap(wrapped)
     self.assertEqual(res1, self.oid_key)
     self.assertEqual(res2, self.clear_key)
Exemple #18
0
 def test1(self):
     """Verify unwrapping w/o encryption"""
     res1, res2, res3 = PKCS8.unwrap(self.wrapped_clear_key)
     self.assertEqual(res1, self.oid_key)
     self.assertEqual(res2, self.clear_key)
Exemple #19
0
def _import_pkcs8(encoded, passphrase):
    k = PKCS8.unwrap(encoded, passphrase)
    if k[0] != oid:
        raise ValueError("No PKCS#8 encoded RSA key")
    return _import_keyDER(k[1], passphrase)