示例#1
0
    def __init__(self, keyDer = None):
        # TODO: Implementation of managed properties?

        if keyDer == None:
            self._keyDer = Blob()
            self._keyType = None
            return

        self._keyDer = keyDer

        # Get the public key OID.
        oidString = ""
        try:
            parsedNode = DerNode.parse(keyDer.buf(), 0)
            rootChildren = parsedNode.getChildren()
            algorithmIdChildren = DerNode.getSequence(
              rootChildren, 0).getChildren()
            oidString = algorithmIdChildren[0].toVal()
        except DerDecodingException as ex:
          raise UnrecognizedKeyFormatException(
            "PublicKey.decodeKeyType: Error decoding the public key" + str(ex))

        # Verify that the we can decode.
        if oidString == self.RSA_ENCRYPTION_OID:
            self._keyType = KeyType.RSA
            RSA.importKey(keyDer.toRawStr())
        elif oidString == self.EC_ENCRYPTION_OID:
            self._keyType = KeyType.ECDSA
            # TODO: Check EC decoding.
        else:
            raise UnrecognizedKeyFormatException(
              "PublicKey.decodeKeyType: Unrecognized OID " + oidString)
示例#2
0
    def __init__(self, keyDer=None):
        # TODO: Implementation of managed properties?

        if keyDer == None:
            self._keyDer = Blob()
            self._keyType = None
            return

        self._keyDer = keyDer

        # Get the public key OID.
        oidString = ""
        try:
            parsedNode = DerNode.parse(keyDer.buf(), 0)
            rootChildren = parsedNode.getChildren()
            algorithmIdChildren = DerNode.getSequence(rootChildren,
                                                      0).getChildren()
            oidString = algorithmIdChildren[0].toVal()
        except DerDecodingException as ex:
            raise UnrecognizedKeyFormatException(
                "PublicKey.decodeKeyType: Error decoding the public key: " +
                str(ex))

        # Verify that the we can decode.
        if oidString == self.RSA_ENCRYPTION_OID:
            self._keyType = KeyType.RSA
            serialization.load_der_public_key(keyDer.toBytes(),
                                              backend=default_backend())
        elif oidString == self.EC_ENCRYPTION_OID:
            self._keyType = KeyType.ECDSA
            # TODO: Check EC decoding.
        else:
            raise UnrecognizedKeyFormatException(
                "PublicKey.decodeKeyType: Unrecognized OID " + oidString)
示例#3
0
    def sign(self, data, keyName, digestAlgorithm=DigestAlgorithm.SHA256):
        """
        Fetch the private key for keyName and sign the data, returning a
        signature Blob.

        :param data: Pointer the input byte buffer to sign.
        :type data: An array type with int elements
        :param Name keyName: The name of the signing key.
        :param digestAlgorithm: (optional) the digest algorithm. If omitted,
          use DigestAlgorithm.SHA256.
        :type digestAlgorithm: int from DigestAlgorithm
        :return: The signature Blob.
        :rtype: Blob
        """
        keyURI = keyName.toUri()

        if not self.doesKeyExist(keyName, KeyClass.PRIVATE):
            raise SecurityException(
                "FilePrivateKeyStorage.sign: private key doesn't exist")

        if digestAlgorithm != DigestAlgorithm.SHA256:
            raise SecurityException(
                "FilePrivateKeyStorage.sign: Unsupported digest algorithm")

        # Read the private key.
        base64Content = None
        with open(self.nameTransform(keyURI, ".pri")) as keyFile:
            base64Content = keyFile.read()
        der = Blob(base64.b64decode(base64Content), False)

        # Decode the PKCS #8 key to get the algorithm OID.
        parsedNode = DerNode.parse(der.buf(), 0)
        pkcs8Children = parsedNode.getChildren()
        algorithmIdChildren = DerNode.getSequence(pkcs8Children,
                                                  1).getChildren()
        oidString = algorithmIdChildren[0].toVal()

        privateKey = serialization.load_der_private_key(
            der.toBytes(), password=None, backend=default_backend())

        # Sign the data.
        data = Blob(data, False).toBytes()
        if (oidString == PublicKey.RSA_ENCRYPTION_OID
                or oidString == PublicKey.EC_ENCRYPTION_OID):
            if oidString == PublicKey.RSA_ENCRYPTION_OID:
                signer = privateKey.signer(padding.PKCS1v15(), hashes.SHA256())
            else:
                signer = privateKey.signer(ec.ECDSA(hashes.SHA256()))

            signer.update(data)
            signature = signer.finalize()
            return Blob(bytearray(signature), False)
        else:
            raise SecurityException(
                "FilePrivateKeyStorage.sign: Unrecognized private key type")
示例#4
0
    def sign(self, data, keyName, digestAlgorithm = DigestAlgorithm.SHA256):
        """
        Fetch the private key for keyName and sign the data, returning a
        signature Blob.

        :param data: Pointer the input byte buffer to sign.
        :type data: An array type with int elements
        :param Name keyName: The name of the signing key.
        :param digestAlgorithm: (optional) the digest algorithm. If omitted,
          use DigestAlgorithm.SHA256.
        :type digestAlgorithm: int from DigestAlgorithm
        :return: The signature Blob.
        :rtype: Blob
        """
        keyURI = keyName.toUri()

        if not self.doesKeyExist(keyName, KeyClass.PRIVATE):
            raise SecurityException(
              "FilePrivateKeyStorage.sign: private key doesn't exist")

        if digestAlgorithm != DigestAlgorithm.SHA256:
            raise SecurityException(
              "FilePrivateKeyStorage.sign: Unsupported digest algorithm")

        # Read the private key.
        base64Content = None
        with open(self.nameTransform(keyURI, ".pri")) as keyFile:
            base64Content = keyFile.read()
        der = Blob(base64.b64decode(base64Content), False)

        # Decode the PKCS #8 key to get the algorithm OID.
        parsedNode = DerNode.parse(der.buf(), 0)
        pkcs8Children = parsedNode.getChildren()
        algorithmIdChildren = DerNode.getSequence(pkcs8Children, 1).getChildren()
        oidString = algorithmIdChildren[0].toVal()

        privateKey = serialization.load_der_private_key(
          der.toBytes(), password = None, backend = default_backend())

        # Sign the data.
        data = Blob(data, False).toBytes()
        if (oidString == PublicKey.RSA_ENCRYPTION_OID or
            oidString == PublicKey.EC_ENCRYPTION_OID):
            if oidString == PublicKey.RSA_ENCRYPTION_OID:
                signer = privateKey.signer(padding.PKCS1v15(), hashes.SHA256())
            else:
                signer = privateKey.signer(ec.ECDSA(hashes.SHA256()))

            signer.update(data)
            signature = signer.finalize()
            return Blob(bytearray(signature), False)
        else:
            raise SecurityException(
              "FilePrivateKeyStorage.sign: Unrecognized private key type")
示例#5
0
    def toDer(self):
        """
        Encode the public key into DER.

        :return: The encoded DER syntax tree.
        :rtype: DerNode
        """
        return DerNode.parse(self._keyDer)
示例#6
0
    def toDer(self):
        """
        Encode the public key into DER.

        :return: The encoded DER syntax tree.
        :rtype: DerNode
        """
        return DerNode.parse(self._keyDer)
示例#7
0
    def loadPkcs8(self, encoding, keyType=None):
        """
        Load the unencrypted private key from a buffer with the PKCS #8 encoding.
        This replaces any existing private key in this object.

        :param encoding: The byte buffer with the private key encoding.
        :type encoding: str, or an array type with int elements which is
          converted to str
        :param KeyType keyType: (optional) The KeyType, such as KeyType.RSA.
          If omitted or None, then partially decode the private key to determine
          the key type.
        :raises TpmPrivateKey.Error: For errors decoding the key.
        """
        if keyType == None:
            # Decode the PKCS #8 DER to find the algorithm OID.
            oidString = None
            try:
                parsedNode = DerNode.parse(Blob(encoding, False).buf())
                pkcs8Children = parsedNode.getChildren()
                algorithmIdChildren = DerNode.getSequence(pkcs8Children,
                                                          1).getChildren()
                oidString = "" + algorithmIdChildren[0].toVal()
            except Exception as ex:
                raise TpmPrivateKey.Error(
                    "Cannot decode the PKCS #8 private key: " + str(ex))

            if oidString == TpmPrivateKey.EC_ENCRYPTION_OID:
                keyType = KeyType.ECDSA
            elif oidString == TpmPrivateKey.RSA_ENCRYPTION_OID:
                keyType = KeyType.RSA
            else:
                raise TpmPrivateKey.Error(
                    "loadPkcs8: Unrecognized private key OID: " + oidString)

        if keyType == KeyType.ECDSA or keyType == KeyType.RSA:
            self._privateKey = serialization.load_der_private_key(
                Blob(encoding, False).toBytes(),
                password=None,
                backend=default_backend())
        else:
            raise TpmPrivateKey.Error("loadPkcs8: Unrecognized keyType: " +
                                      str(keyType))

        self._keyType = keyType
示例#8
0
    def loadPkcs8(self, encoding, keyType = None):
        """
        Load the unencrypted private key from a buffer with the PKCS #8 encoding.
        This replaces any existing private key in this object.

        :param encoding: The byte buffer with the private key encoding.
        :type encoding: str, or an array type with int elements which is
          converted to str
        :param KeyType keyType: (optional) The KeyType, such as KeyType.RSA.
          If omitted or None, then partially decode the private key to determine
          the key type.
        :raises TpmPrivateKey.Error: For errors decoding the key.
        """
        if keyType == None:
            # Decode the PKCS #8 DER to find the algorithm OID.
            oidString = None
            try:
                parsedNode = DerNode.parse(Blob(encoding, False).buf())
                pkcs8Children = parsedNode.getChildren()
                algorithmIdChildren = DerNode.getSequence(
                  pkcs8Children, 1).getChildren()
                oidString = "" + algorithmIdChildren[0].toVal()
            except Exception as ex:
                raise TpmPrivateKey.Error(
                  "Cannot decode the PKCS #8 private key: " + str(ex))

            if oidString == TpmPrivateKey.EC_ENCRYPTION_OID:
                keyType = KeyType.EC
            elif oidString == TpmPrivateKey.RSA_ENCRYPTION_OID:
                keyType = KeyType.RSA
            else:
                raise TpmPrivateKey.Error(
                  "loadPkcs8: Unrecognized private key OID: " + oidString)

        if keyType == KeyType.EC or keyType == KeyType.RSA:
            self._privateKey = serialization.load_der_private_key(
              Blob(encoding, False).toBytes(), password = None, backend = default_backend())
        else:
            raise TpmPrivateKey.Error(
              "loadPkcs8: Unrecognized keyType: " + str(keyType))

        self._keyType = keyType
示例#9
0
    def loadPkcs1(self, encoding, keyType=None):
        """
        Load the unencrypted private key from a buffer with the PKCS #1 encoding.
        This replaces any existing private key in this object.

        :param encoding: The byte buffer with the private key encoding.
        :type encoding: str, or an array type with int elements which is
          converted to str
        :param KeyType keyType: (optional) The KeyType, such as KeyType.RSA.
          If omitted or None, then partially decode the private key to determine
          the key type.
        :raises TpmPrivateKey.Error: For errors decoding the key.
        """
        if keyType == None:
            # Try to determine the key type.
            try:
                parsedNode = DerNode.parse(Blob(encoding, False).buf())
                children = parsedNode.getChildren()

                # An RsaPrivateKey has integer version 0 and 8 integers.
                if (len(children) == 9 and isinstance(children[0], DerInteger)
                        and children[0].toVal() == 0
                        and isinstance(children[1], DerInteger)
                        and isinstance(children[2], DerInteger)
                        and isinstance(children[3], DerInteger)
                        and isinstance(children[4], DerInteger)
                        and isinstance(children[5], DerInteger)
                        and isinstance(children[6], DerInteger)
                        and isinstance(children[7], DerInteger)
                        and isinstance(children[8], DerInteger)):
                    keyType = KeyType.RSA
                else:
                    # Assume it is an EC key. Try decoding it below.
                    keyType = KeyType.ECDSA
            except DerDecodingException:
                # Assume it is an EC key. Try decoding it below.
                keyType = KeyType.ECDSA

        if keyType == KeyType.ECDSA or keyType == KeyType.RSA:
            # serialization can load PKCS #1 directly.
            self._privateKey = serialization.load_der_private_key(
                Blob(encoding, False).toBytes(),
                password=None,
                backend=default_backend())
        else:
            raise TpmPrivateKey.Error("loadPkcs1: Unrecognized keyType: " +
                                      str(keyType))

        self._keyType = keyType
示例#10
0
    def loadPkcs1(self, encoding, keyType = None):
        """
        Load the unencrypted private key from a buffer with the PKCS #1 encoding.
        This replaces any existing private key in this object.

        :param encoding: The byte buffer with the private key encoding.
        :type encoding: str, or an array type with int elements which is
          converted to str
        :param KeyType keyType: (optional) The KeyType, such as KeyType.RSA.
          If omitted or None, then partially decode the private key to determine
          the key type.
        :raises TpmPrivateKey.Error: For errors decoding the key.
        """
        if keyType == None:
            # Try to determine the key type.
            try:
                parsedNode = DerNode.parse(Blob(encoding, False).buf())
                children = parsedNode.getChildren()

                # An RsaPrivateKey has integer version 0 and 8 integers.
                if (len(children) == 9 and
                    isinstance(children[0], DerInteger) and
                    children[0].toVal() == 0 and
                    isinstance(children[1], DerInteger) and
                    isinstance(children[2], DerInteger) and
                    isinstance(children[3], DerInteger) and
                    isinstance(children[4], DerInteger) and
                    isinstance(children[5], DerInteger) and
                    isinstance(children[6], DerInteger) and
                    isinstance(children[7], DerInteger) and
                    isinstance( children[8], DerInteger)):
                    keyType = KeyType.RSA
                else:
                    # Assume it is an EC key. Try decoding it below.
                    keyType = KeyType.EC
            except DerDecodingException:
                # Assume it is an EC key. Try decoding it below.
                keyType =  KeyType.EC

        if keyType == KeyType.EC or keyType == KeyType.RSA:
            # serialization can load PKCS #1 directly.
            self._privateKey = serialization.load_der_private_key(
              Blob(encoding, False).toBytes(), password = None, backend = default_backend())
        else:
            raise TpmPrivateKey.Error(
              "loadPkcs1: Unrecognized keyType: " + str(keyType))

        self._keyType = keyType
示例#11
0
    def toPkcs1(self):
        """
        Get the encoded unencrypted private key in PKCS #1.

        :return: The private key encoding Blob.
        :rtype: Blob
        :raises TpmPrivateKey.Error: If no private key is loaded, or error
          encoding.
        """
        if self._keyType == None:
            raise TpmPrivateKey.Error("toPkcs1: The private key is not loaded")

        # Decode the PKCS #8 private key.
        try:
            parsedNode = DerNode.parse(self.toPkcs8().buf(), 0)
            pkcs8Children = parsedNode.getChildren()
            return pkcs8Children[2].getPayload()
        except Exception as ex:
            raise TpmPrivateKey.Error(
              "Error decoding PKCS #8 private key: " + str(ex))
示例#12
0
    def toPkcs1(self):
        """
        Get the encoded unencrypted private key in PKCS #1.

        :return: The private key encoding Blob.
        :rtype: Blob
        :raises TpmPrivateKey.Error: If no private key is loaded, or error
          encoding.
        """
        if self._keyType == None:
            raise TpmPrivateKey.Error("toPkcs1: The private key is not loaded")

        # Decode the PKCS #8 private key.
        try:
            parsedNode = DerNode.parse(self.toPkcs8().buf(), 0)
            pkcs8Children = parsedNode.getChildren()
            return pkcs8Children[2].getPayload()
        except Exception as ex:
            raise TpmPrivateKey.Error("Error decoding PKCS #8 private key: " +
                                      str(ex))
示例#13
0
    def loadEncryptedPkcs8(self, encoding, password):
        """
        Load the encrypted private key from a buffer with the PKCS #8 encoding
        of the EncryptedPrivateKeyInfo. This replaces any existing private key
        in this object. This partially decodes the private key to determine the
        key type.

        :param encoding: The byte buffer with the private key encoding.
        :type encoding: str, or an array type with int elements which is
          converted to str
        :param password: The password for decrypting the private key, which
          should have characters in the range of 1 to 127..
        :type password: an array which implements the buffer protocol
        :raises TpmPrivateKey.Error: For errors decoding the key.
        """
        # Decode the PKCS #8 EncryptedPrivateKeyInfo.
        # See https://tools.ietf.org/html/rfc5208.
        oidString = None
        parameters = None
        encryptedKey = None
        try:
            parsedNode = DerNode.parse(Blob(encoding, False).buf())
            encryptedPkcs8Children = parsedNode.getChildren()
            algorithmIdChildren = DerNode.getSequence(
              encryptedPkcs8Children, 0).getChildren()
            oidString = algorithmIdChildren[0].toVal()
            parameters = algorithmIdChildren[1]

            encryptedKey = encryptedPkcs8Children[1].toVal()
        except Exception as ex:
            raise TpmPrivateKey.Error(
              "Cannot decode the PKCS #8 EncryptedPrivateKeyInfo: " + str(ex))

        if oidString == TpmPrivateKey.PBES2_OID:
            # Decode the PBES2 parameters. See https://www.ietf.org/rfc/rfc2898.txt .
            keyDerivationOidString = None
            keyDerivationParameters = None
            encryptionSchemeOidString = None
            encryptionSchemeParameters = None
            try:
                parametersChildren = parameters.getChildren()

                keyDerivationAlgorithmIdChildren = DerNode.getSequence(
                  parametersChildren, 0).getChildren()
                keyDerivationOidString = keyDerivationAlgorithmIdChildren[0].toVal()
                keyDerivationParameters = keyDerivationAlgorithmIdChildren[1]

                encryptionSchemeAlgorithmIdChildren = DerNode.getSequence(
                  parametersChildren, 1).getChildren()
                encryptionSchemeOidString = encryptionSchemeAlgorithmIdChildren[0].toVal()
                encryptionSchemeParameters = encryptionSchemeAlgorithmIdChildren[1]
            except Exception as ex:
                raise TpmPrivateKey.Error(
                  "Cannot decode the PBES2 parameters: " + str(ex))

            # Get the derived key from the password.
            derivedKey = None
            if keyDerivationOidString == TpmPrivateKey.PBKDF2_OID:
                # Decode the PBKDF2 parameters.
                salt = None
                nIterations = None
                try:
                  pbkdf2ParametersChildren = keyDerivationParameters.getChildren()
                  salt = pbkdf2ParametersChildren[0].toVal()
                  nIterations = pbkdf2ParametersChildren[1].toVal()
                except Exception as ex:
                    raise TpmPrivateKey.Error(
                      "Cannot decode the PBES2 parameters: " + str(ex))

                # Check the encryption scheme here to get the needed result length.
                resultLength = None
                if encryptionSchemeOidString == TpmPrivateKey.DES_EDE3_CBC_OID:
                  resultLength = TpmPrivateKey.DES_EDE3_KEY_LENGTH
                else:
                    raise TpmPrivateKey.Error(
                      "Unrecognized PBES2 encryption scheme OID: " +
                      encryptionSchemeOidString)

            else:
                raise TpmPrivateKey.Error(
                  "Unrecognized PBES2 key derivation OID: " + keyDerivationOidString)

            pbkdf2 = PBKDF2HMAC(algorithm = hashes.SHA1(), length = resultLength,
              salt = Blob(salt, False).toBytes(), iterations = nIterations,
              backend = default_backend())
            derivedKey = pbkdf2.derive(Blob(password, False).toBytes())

            # Use the derived key to get the unencrypted pkcs8Encoding.
            if encryptionSchemeOidString == TpmPrivateKey.DES_EDE3_CBC_OID:
                # Decode the DES-EDE3-CBC parameters.
                initialVector = None
                try:
                    initialVector = encryptionSchemeParameters.toVal()
                except Exception as ex:
                    raise TpmPrivateKey.Error(
                      "Cannot decode the DES-EDE3-CBC parameters: " + str(ex))

                try:
                    cipher = Cipher(algorithms.TripleDES(
                      Blob(derivedKey, False).toBytes()),
                      modes.CBC(Blob(initialVector, False).toBytes()),
                      backend = default_backend())

                    # For the cryptography package, we have to remove the padding.
                    decryptor = cipher.decryptor()
                    resultWithPad = decryptor.update(
                      Blob(encryptedKey, False).toBytes()) + decryptor.finalize()
                    if sys.version_info[0] <= 2:
                        padLength = ord(resultWithPad[-1])
                    else:
                        padLength = resultWithPad[-1]

                    pkcs8Encoding = resultWithPad[:-padLength]
                except Exception as ex:
                    raise TpmPrivateKey.Error(
                      "Error decrypting the PKCS #8 key with DES-EDE3-CBC: " + str(ex))
            else:
                raise TpmPrivateKey.Error(
                  "Unrecognized PBES2 encryption scheme OID: " +
                  encryptionSchemeOidString)

        else:
            raise TpmPrivateKey.Error(
              "Unrecognized PKCS #8 EncryptedPrivateKeyInfo OID: " + oidString)

        self.loadPkcs8(pkcs8Encoding)
示例#14
0
    def loadEncryptedPkcs8(self, encoding, password):
        """
        Load the encrypted private key from a buffer with the PKCS #8 encoding
        of the EncryptedPrivateKeyInfo. This replaces any existing private key
        in this object. This partially decodes the private key to determine the
        key type.

        :param encoding: The byte buffer with the private key encoding.
        :type encoding: str, or an array type with int elements which is
          converted to str
        :param password: The password for decrypting the private key, which
          should have characters in the range of 1 to 127..
        :type password: an array which implements the buffer protocol
        :raises TpmPrivateKey.Error: For errors decoding the key.
        """
        # Decode the PKCS #8 EncryptedPrivateKeyInfo.
        # See https://tools.ietf.org/html/rfc5208.
        oidString = None
        parameters = None
        encryptedKey = None
        try:
            parsedNode = DerNode.parse(Blob(encoding, False).buf())
            encryptedPkcs8Children = parsedNode.getChildren()
            algorithmIdChildren = DerNode.getSequence(encryptedPkcs8Children,
                                                      0).getChildren()
            oidString = algorithmIdChildren[0].toVal()
            parameters = algorithmIdChildren[1]

            encryptedKey = encryptedPkcs8Children[1].toVal()
        except Exception as ex:
            raise TpmPrivateKey.Error(
                "Cannot decode the PKCS #8 EncryptedPrivateKeyInfo: " +
                str(ex))

        if oidString == TpmPrivateKey.PBES2_OID:
            # Decode the PBES2 parameters. See https://www.ietf.org/rfc/rfc2898.txt .
            keyDerivationOidString = None
            keyDerivationParameters = None
            encryptionSchemeOidString = None
            encryptionSchemeParameters = None
            try:
                parametersChildren = parameters.getChildren()

                keyDerivationAlgorithmIdChildren = DerNode.getSequence(
                    parametersChildren, 0).getChildren()
                keyDerivationOidString = keyDerivationAlgorithmIdChildren[
                    0].toVal()
                keyDerivationParameters = keyDerivationAlgorithmIdChildren[1]

                encryptionSchemeAlgorithmIdChildren = DerNode.getSequence(
                    parametersChildren, 1).getChildren()
                encryptionSchemeOidString = encryptionSchemeAlgorithmIdChildren[
                    0].toVal()
                encryptionSchemeParameters = encryptionSchemeAlgorithmIdChildren[
                    1]
            except Exception as ex:
                raise TpmPrivateKey.Error(
                    "Cannot decode the PBES2 parameters: " + str(ex))

            # Get the derived key from the password.
            derivedKey = None
            if keyDerivationOidString == TpmPrivateKey.PBKDF2_OID:
                # Decode the PBKDF2 parameters.
                salt = None
                nIterations = None
                try:
                    pbkdf2ParametersChildren = keyDerivationParameters.getChildren(
                    )
                    salt = pbkdf2ParametersChildren[0].toVal()
                    nIterations = pbkdf2ParametersChildren[1].toVal()
                except Exception as ex:
                    raise TpmPrivateKey.Error(
                        "Cannot decode the PBES2 parameters: " + str(ex))

                # Check the encryption scheme here to get the needed result length.
                resultLength = None
                if encryptionSchemeOidString == TpmPrivateKey.DES_EDE3_CBC_OID:
                    resultLength = TpmPrivateKey.DES_EDE3_KEY_LENGTH
                else:
                    raise TpmPrivateKey.Error(
                        "Unrecognized PBES2 encryption scheme OID: " +
                        encryptionSchemeOidString)

            else:
                raise TpmPrivateKey.Error(
                    "Unrecognized PBES2 key derivation OID: " +
                    keyDerivationOidString)

            pbkdf2 = PBKDF2HMAC(algorithm=hashes.SHA1(),
                                length=resultLength,
                                salt=Blob(salt, False).toBytes(),
                                iterations=nIterations,
                                backend=default_backend())
            derivedKey = pbkdf2.derive(Blob(password, False).toBytes())

            # Use the derived key to get the unencrypted pkcs8Encoding.
            if encryptionSchemeOidString == TpmPrivateKey.DES_EDE3_CBC_OID:
                # Decode the DES-EDE3-CBC parameters.
                initialVector = None
                try:
                    initialVector = encryptionSchemeParameters.toVal()
                except Exception as ex:
                    raise TpmPrivateKey.Error(
                        "Cannot decode the DES-EDE3-CBC parameters: " +
                        str(ex))

                try:
                    cipher = Cipher(algorithms.TripleDES(
                        Blob(derivedKey, False).toBytes()),
                                    modes.CBC(
                                        Blob(initialVector, False).toBytes()),
                                    backend=default_backend())

                    # For the cryptography package, we have to remove the padding.
                    decryptor = cipher.decryptor()
                    resultWithPad = decryptor.update(
                        Blob(encryptedKey,
                             False).toBytes()) + decryptor.finalize()
                    if sys.version_info[0] <= 2:
                        padLength = ord(resultWithPad[-1])
                    else:
                        padLength = resultWithPad[-1]

                    pkcs8Encoding = resultWithPad[:-padLength]
                except Exception as ex:
                    raise TpmPrivateKey.Error(
                        "Error decrypting the PKCS #8 key with DES-EDE3-CBC: "
                        + str(ex))
            else:
                raise TpmPrivateKey.Error(
                    "Unrecognized PBES2 encryption scheme OID: " +
                    encryptionSchemeOidString)

        else:
            raise TpmPrivateKey.Error(
                "Unrecognized PKCS #8 EncryptedPrivateKeyInfo OID: " +
                oidString)

        self.loadPkcs8(pkcs8Encoding)