code: def protect(self, passphrase, enc_alg, hash_alg):
          
          ##TODO: specify strong defaults for enc_alg and hash_alg
          if self.is_public:
              # we can't protect public keys because only private key material is ever protected
              warnings.warn("Public keys cannot be passphrase-protected", stacklevel=2)
              return
  
          if self.is_protected and not self.is_unlocked:
              # we can't protect a key that is already protected unless it is unlocked first
              warnings.warn("This key is already protected with a passphrase - "
                            "please unlock it before attempting to specify a new passphrase", stacklevel=2)
              return
  
          for sk in itertools.chain([self], self.subkeys.values()):
              sk._key.protect(passphrase, enc_alg, hash_alg)
  
          del passphrase
docs: Add a passphrase to a private key. If the key is already passphrase protected, it should be unlocked before
          a new passphrase can be specified.
  
          Has no effect on public keys.
  
          :param passphrase: A passphrase to protect the key with
          :type passphrase: ``str``, ``unicode``
          :param enc_alg: Symmetric encryption algorithm to use to protect the key
          :type enc_alg: :py:obj:`~constants.SymmetricKeyAlgorithm`
          :param hash_alg: Hash algorithm to use in the String-to-Key specifier
          :type hash_alg: :py:obj:`~constants.HashAlgorithm`