1# 2# Copyright (C) 2010-2017 Samuel Abels 3# The MIT License (MIT) 4# 5# Permission is hereby granted, free of charge, to any person obtaining 6# a copy of this software and associated documentation files 7# (the "Software"), to deal in the Software without restriction, 8# including without limitation the rights to use, copy, modify, merge, 9# publish, distribute, sublicense, and/or sell copies of the Software, 10# and to permit persons to whom the Software is furnished to do so, 11# subject to the following conditions: 12# 13# The above copyright notice and this permission notice shall be 14# included in all copies or substantial portions of the Software. 15# 16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23""" 24Represents a private key. 25""" 26from builtins import object 27from paramiko import RSAKey, DSSKey 28from paramiko.ssh_exception import SSHException 29 30 31class PrivateKey(object): 32 33 """ 34 Represents a cryptographic key, and may be used to authenticate 35 useing :class:`Exscript.protocols`. 36 """ 37 keytypes = set() 38 39 def __init__(self, keytype='rsa'): 40 """ 41 Constructor. Supported key types are provided by their respective 42 protocol adapters and can be retrieved from the PrivateKey.keytypes 43 class attribute. 44 45 :type keytype: string 46 :param keytype: The key type. 47 """ 48 if keytype not in self.keytypes: 49 raise TypeError('unsupported key type: ' + repr(keytype)) 50 self.keytype = keytype 51 self.filename = None 52 self.password = None 53 54 @staticmethod 55 def from_file(filename, password='', keytype=None): 56 """ 57 Returns a new PrivateKey instance with the given attributes. 58 If keytype is None, we attempt to automatically detect the type. 59 60 :type filename: string 61 :param filename: The key file name. 62 :type password: string 63 :param password: The key password. 64 :type keytype: string 65 :param keytype: The key type. 66 :rtype: PrivateKey 67 :return: The new key. 68 """ 69 if keytype is None: 70 try: 71 key = RSAKey.from_private_key_file(filename) 72 keytype = 'rsa' 73 except SSHException as e: 74 try: 75 key = DSSKey.from_private_key_file(filename) 76 keytype = 'dss' 77 except SSHException as e: 78 msg = 'not a recognized private key: ' + repr(filename) 79 raise ValueError(msg) 80 key = PrivateKey(keytype) 81 key.filename = filename 82 key.password = password 83 return key 84 85 def get_type(self): 86 """ 87 Returns the type of the key, e.g. RSA or DSA. 88 89 :rtype: string 90 :return: The key type 91 """ 92 return self.keytype 93 94 def set_filename(self, filename): 95 """ 96 Sets the name of the key file to use. 97 98 :type filename: string 99 :param filename: The key filename. 100 """ 101 self.filename = filename 102 103 def get_filename(self): 104 """ 105 Returns the name of the key file. 106 107 :rtype: string 108 :return: The key password. 109 """ 110 return self.filename 111 112 def set_password(self, password): 113 """ 114 Defines the password used for decrypting the key. 115 116 :type password: string 117 :param password: The key password. 118 """ 119 self.password = password 120 121 def get_password(self): 122 """ 123 Returns the password for the key. 124 125 :rtype: string 126 :return: The key password. 127 """ 128 return self.password 129