Esempio n. 1
0
    def new(cls, alias, certs, key, key_format='pkcs8'):
        """
        Helper function to create a new PrivateKeyEntry.

        :param str alias: The alias for the Private Key Entry
        :param list certs: An list of certificates, as byte strings.
          The first one should be the one belonging to the private key,
          the others the chain (in correct order).
        :param str key: A byte string containing the private key in the
          format specified in the key_format parameter (default pkcs8).
        :param str key_format: The format of the provided private key.
          Valid options are pkcs8 or rsa_raw. Defaults to pkcs8.

        :returns: A loaded :class:`PrivateKeyEntry` instance, ready
          to be placed in a keystore.

        :raises UnsupportedKeyFormatException: If the key format is
          unsupported.
        """
        timestamp = int(time.time()) * 1000

        cert_chain = []
        for cert in certs:
            cert_chain.append(('X.509', cert))

        pke = cls(
            timestamp=timestamp,
            # Alias must be lower case or it will corrupt the keystore for Java Keytool and Keytool Explorer
            alias=alias.lower(),
            cert_chain=cert_chain)

        if key_format == 'pkcs8':
            private_key_info = decoder.decode(
                key, asn1Spec=rfc5208.PrivateKeyInfo())[0]

            pke._algorithm_oid = private_key_info['privateKeyAlgorithm'][
                'algorithm'].asTuple()
            pke.pkey = private_key_info['privateKey'].asOctets()
            pke.pkey_pkcs8 = key

        elif key_format == 'rsa_raw':
            pke._algorithm_oid = RSA_ENCRYPTION_OID

            # We must encode it to pkcs8
            private_key_info = rfc5208.PrivateKeyInfo()
            private_key_info.setComponentByName('version', 'v1')
            a = AlgorithmIdentifier()
            a.setComponentByName('algorithm', pke._algorithm_oid)
            a.setComponentByName('parameters', '\x05\x00')
            private_key_info.setComponentByName('privateKeyAlgorithm', a)
            private_key_info.setComponentByName('privateKey', key)

            pke.pkey_pkcs8 = encoder.encode(private_key_info, ifNotEmpty=True)
            pke.pkey = key

        else:
            raise UnsupportedKeyFormatException(
                "Key Format '%s' is not supported" % key_format)

        return pke
Esempio n. 2
0
    def decrypt(self, key_password):
        """
        Decrypts the entry using the given password. Has no effect if the entry has already been decrypted.

        :param str key_password: The password to decrypt the entry with. If the entry was loaded from a JCEKS keystore,
                                 the password must not contain any characters outside of the ASCII character set.
        :raises DecryptionFailureException: If the entry could not be decrypted using the given password.
        :raises UnexpectedAlgorithmException: If the entry was encrypted with an unknown or unexpected algorithm
        :raise ValueError: If the entry was loaded from a JCEKS keystore and the password contains non-ASCII characters.
        """
        if self.is_decrypted():
            return

        encrypted_info = decoder.decode(
            self._encrypted, asn1Spec=rfc5208.EncryptedPrivateKeyInfo())[0]
        algo_id = encrypted_info['encryptionAlgorithm']['algorithm'].asTuple()
        algo_params = encrypted_info['encryptionAlgorithm'][
            'parameters'].asOctets()
        encrypted_private_key = encrypted_info['encryptedData'].asOctets()

        plaintext = None
        try:
            if algo_id == sun_crypto.SUN_JKS_ALGO_ID:
                plaintext = sun_crypto.jks_pkey_decrypt(
                    encrypted_private_key, key_password)

            elif algo_id == sun_crypto.SUN_JCE_ALGO_ID:
                if self.store_type != "jceks":
                    raise UnexpectedAlgorithmException(
                        "Encountered JCEKS private key protection algorithm in JKS keystore"
                    )
                # see RFC 2898, section A.3: PBES1 and definitions of AlgorithmIdentifier and PBEParameter
                params = decoder.decode(algo_params,
                                        asn1Spec=rfc2898.PBEParameter())[0]
                salt = params['salt'].asOctets()
                iteration_count = int(params['iterationCount'])
                plaintext = sun_crypto.jce_pbe_decrypt(encrypted_private_key,
                                                       key_password, salt,
                                                       iteration_count)
            else:
                raise UnexpectedAlgorithmException(
                    "Unknown %s private key protection algorithm: %s" %
                    (self.store_type.upper(), algo_id))

        except (BadHashCheckException, BadPaddingException):
            raise DecryptionFailureException(
                "Failed to decrypt data for private key '%s'; wrong password?"
                % self.alias)

        # at this point, 'plaintext' is a PKCS#8 PrivateKeyInfo (see RFC 5208)
        private_key_info = decoder.decode(plaintext,
                                          asn1Spec=rfc5208.PrivateKeyInfo())[0]
        key = private_key_info['privateKey'].asOctets()
        algorithm_oid = private_key_info['privateKeyAlgorithm'][
            'algorithm'].asTuple()

        self._encrypted = None
        self._pkey = key
        self._pkey_pkcs8 = plaintext
        self._algorithm_oid = algorithm_oid
Esempio n. 3
0
    def test_asn1_from_ed25519_private_key(self):
        priv = xtt.ED25519PrivateKey(
            b"""\xd1%\xce\xec\xfb\xdf\x82\xb1w~\xb5AL*\x10'\x9aX\x8f\xae\x05\tTm5\xafC\x14\x06]\xb3X^\x970Y=\\\x92\xbdsK2\x0cD%\x96\xf8\x1dh\xc4\x1d&k'+\x1a\xca\xd6\x16\x12\x90\x03="""
        )
        asn1 = xtt.asn1_from_ed25519_private_key(priv)

        decoded = der_decode(asn1,
                             asn1Spec=rfc5208.PrivateKeyInfo(),
                             decodeOpenTypes=True)[0]
        decoded_private_key = der_decode(decoded['privateKey'])[0].asOctets(
        )  # privateKey is itself another octet string
        self.assertEqual(decoded_private_key, priv.data[:32])
Esempio n. 4
0
File: bks.py Progetto: tomyy/pyjks
    def __init__(self, type, format, algorithm, encoded, **kwargs):
        super(BksKeyEntry, self).__init__(**kwargs)
        self.type = type
        """An integer indicating the type of key: one of :const:`KEY_TYPE_PRIVATE`, :const:`KEY_TYPE_PUBLIC`, :const:`KEY_TYPE_SECRET`."""
        self.format = format
        """A string indicating the format or encoding in which the key is stored. One of: ``PKCS8``, ``PKCS#8``, ``X.509``, ``X509``, ``RAW``."""
        self.algorithm = algorithm
        """A string indicating the algorithm for which the key is valid."""
        self.encoded = encoded
        """A byte string containing the key, formatted as indicated by the :attr:`format` attribute."""

        if self.type == KEY_TYPE_PRIVATE:
            if self.format not in ["PKCS8", "PKCS#8"]:
                raise UnexpectedKeyEncodingException(
                    "Unexpected encoding for private key entry: '%s'" %
                    self.format)
            # self.encoded is a PKCS#8 PrivateKeyInfo
            private_key_info = decoder.decode(
                self.encoded, asn1Spec=rfc5208.PrivateKeyInfo())[0]
            self.pkey_pkcs8 = self.encoded
            self.pkey = private_key_info['privateKey'].asOctets()
            self.algorithm_oid = private_key_info['privateKeyAlgorithm'][
                'algorithm'].asTuple()

        elif self.type == KEY_TYPE_PUBLIC:
            if self.format not in ["X.509", "X509"]:
                raise UnexpectedKeyEncodingException(
                    "Unexpected encoding for public key entry: '%s'" %
                    self.format)
            # self.encoded is an X.509 SubjectPublicKeyInfo
            spki = decoder.decode(self.encoded,
                                  asn1Spec=rfc2459.SubjectPublicKeyInfo())[0]
            self.public_key_info = self.encoded
            self.public_key = bitstring_to_bytes(spki['subjectPublicKey'])
            self.algorithm_oid = spki['algorithm']['algorithm'].asTuple()

        elif self.type == KEY_TYPE_SECRET:
            if self.format != "RAW":
                raise UnexpectedKeyEncodingException(
                    "Unexpected encoding for raw key entry: '%s'" %
                    self.format)
            # self.encoded is an unwrapped/raw cryptographic key
            self.key = encoded
            self.key_size = len(encoded) * 8

        else:
            raise UnexpectedKeyEncodingException(
                "Key format '%s' not recognized" % self.format)
Esempio n. 5
0
    def from_string(cls, key, password='******'):
        """Construct an RsaSigner instance from a string.

        Args:
            key: string, private key in PEM format.
            password: string, password for private key file. Unused for PEM
                      files.

        Returns:
            RsaSigner instance.

        Raises:
            ValueError if the key cannot be parsed as PKCS#1 or PKCS#8 in
            PEM format.
        """
        global _PKCS8_SPEC
        key = _helpers._from_bytes(key)  # pem expects str in Py3
        marker_id, key_bytes = pem.readPemBlocksFromFile(
            six.StringIO(key), _PKCS1_MARKER, _PKCS8_MARKER)

        if marker_id == 0:
            pkey = rsa.key.PrivateKey.load_pkcs1(key_bytes, format='DER')
        elif marker_id == 1:
            from pyasn1.codec.der import decoder
            from pyasn1_modules import rfc5208

            if _PKCS8_SPEC is None:
                _PKCS8_SPEC = rfc5208.PrivateKeyInfo()
            key_info, remaining = decoder.decode(key_bytes,
                                                 asn1Spec=_PKCS8_SPEC)
            if remaining != b'':
                raise ValueError('Unused bytes', remaining)
            pkey_info = key_info.getComponentByName('privateKey')
            pkey = rsa.key.PrivateKey.load_pkcs1(pkey_info.asOctets(),
                                                 format='DER')
        else:
            raise ValueError('No key could be detected.')

        return cls(pkey)
Esempio n. 6
0
 def setUp(self):
     self.asn1Spec = rfc5208.PrivateKeyInfo()
Esempio n. 7
0
$ cat pkcs8key.pem | %s""" % sys.argv[0])
    sys.exit(-1)

cnt = 0

while 1:
    idx, substrate = pem.readPemBlocksFromFile(
        sys.stdin,
        ('-----BEGIN PRIVATE KEY-----', '-----END PRIVATE KEY-----'),
        ('-----BEGIN ENCRYPTED PRIVATE KEY-----',
         '-----END ENCRYPTED PRIVATE KEY-----'))
    if not substrate:
        break

    if idx == 0:
        asn1Spec = rfc5208.PrivateKeyInfo()
    elif idx == 1:
        asn1Spec = rfc5208.EncryptedPrivateKeyInfo()
    else:
        break

    key, rest = decoder.decode(substrate, asn1Spec=asn1Spec)

    if rest: substrate = substrate[:-len(rest)]

    print(key.prettyPrint())

    assert encoder.encode(key) == substrate, 'pkcs8 recode fails'

    cnt = cnt + 1