From ed280d5ac360e2af796e9bd973d7b4df89f0c449 Mon Sep 17 00:00:00 2001 From: "Jeremy T. Bouse" Date: Fri, 27 Nov 2009 16:20:12 -0500 Subject: Imported Upstream version 1.7.4 --- docs/paramiko.pkey-pysrc.html | 540 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 540 insertions(+) create mode 100644 docs/paramiko.pkey-pysrc.html (limited to 'docs/paramiko.pkey-pysrc.html') diff --git a/docs/paramiko.pkey-pysrc.html b/docs/paramiko.pkey-pysrc.html new file mode 100644 index 0000000..8a9e368 --- /dev/null +++ b/docs/paramiko.pkey-pysrc.html @@ -0,0 +1,540 @@ + + + + + paramiko.pkey + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + Package paramiko :: + Module pkey + + + + + +
[frames] | no frames]
+
+

Source Code for Module paramiko.pkey

+
+  1  # Copyright (C) 2003-2007  Robey Pointer <robey@lag.net> 
+  2  # 
+  3  # This file is part of paramiko. 
+  4  # 
+  5  # Paramiko is free software; you can redistribute it and/or modify it under the 
+  6  # terms of the GNU Lesser General Public License as published by the Free 
+  7  # Software Foundation; either version 2.1 of the License, or (at your option) 
+  8  # any later version. 
+  9  # 
+ 10  # Paramiko is distrubuted in the hope that it will be useful, but WITHOUT ANY 
+ 11  # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 
+ 12  # A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more 
+ 13  # details. 
+ 14  # 
+ 15  # You should have received a copy of the GNU Lesser General Public License 
+ 16  # along with Paramiko; if not, write to the Free Software Foundation, Inc., 
+ 17  # 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. 
+ 18   
+ 19  """ 
+ 20  Common API for all public keys. 
+ 21  """ 
+ 22   
+ 23  import base64 
+ 24  from binascii import hexlify, unhexlify 
+ 25  import os 
+ 26   
+ 27  from Crypto.Hash import MD5 
+ 28  from Crypto.Cipher import DES3 
+ 29   
+ 30  from paramiko.common import * 
+ 31  from paramiko import util 
+ 32  from paramiko.message import Message 
+ 33  from paramiko.ssh_exception import SSHException, PasswordRequiredException 
+ 34   
+ 35   
+
36 -class PKey (object): +
37 """ + 38 Base class for public keys. + 39 """ + 40 + 41 # known encryption types for private key files: + 42 _CIPHER_TABLE = { + 43 'DES-EDE3-CBC': { 'cipher': DES3, 'keysize': 24, 'blocksize': 8, 'mode': DES3.MODE_CBC } + 44 } + 45 + 46 +
47 - def __init__(self, msg=None, data=None): +
48 """ + 49 Create a new instance of this public key type. If C{msg} is given, + 50 the key's public part(s) will be filled in from the message. If + 51 C{data} is given, the key's public part(s) will be filled in from + 52 the string. + 53 + 54 @param msg: an optional SSH L{Message} containing a public key of this + 55 type. + 56 @type msg: L{Message} + 57 @param data: an optional string containing a public key of this type + 58 @type data: str + 59 + 60 @raise SSHException: if a key cannot be created from the C{data} or + 61 C{msg} given, or no key was passed in. + 62 """ + 63 pass +
64 +
65 - def __str__(self): +
66 """ + 67 Return a string of an SSH L{Message} made up of the public part(s) of + 68 this key. This string is suitable for passing to L{__init__} to + 69 re-create the key object later. + 70 + 71 @return: string representation of an SSH key message. + 72 @rtype: str + 73 """ + 74 return '' +
75 +
76 - def __cmp__(self, other): +
77 """ + 78 Compare this key to another. Returns 0 if this key is equivalent to + 79 the given key, or non-0 if they are different. Only the public parts + 80 of the key are compared, so a public key will compare equal to its + 81 corresponding private key. + 82 + 83 @param other: key to compare to. + 84 @type other: L{PKey} + 85 @return: 0 if the two keys are equivalent, non-0 otherwise. + 86 @rtype: int + 87 """ + 88 hs = hash(self) + 89 ho = hash(other) + 90 if hs != ho: + 91 return cmp(hs, ho) + 92 return cmp(str(self), str(other)) +
93 +
94 - def get_name(self): +
95 """ + 96 Return the name of this private key implementation. + 97 + 98 @return: name of this private key type, in SSH terminology (for + 99 example, C{"ssh-rsa"}). +100 @rtype: str +101 """ +102 return '' +
103 +
104 - def get_bits(self): +
105 """ +106 Return the number of significant bits in this key. This is useful +107 for judging the relative security of a key. +108 +109 @return: bits in the key. +110 @rtype: int +111 """ +112 return 0 +
113 +
114 - def can_sign(self): +
115 """ +116 Return C{True} if this key has the private part necessary for signing +117 data. +118 +119 @return: C{True} if this is a private key. +120 @rtype: bool +121 """ +122 return False +
123 +
124 - def get_fingerprint(self): +
125 """ +126 Return an MD5 fingerprint of the public part of this key. Nothing +127 secret is revealed. +128 +129 @return: a 16-byte string (binary) of the MD5 fingerprint, in SSH +130 format. +131 @rtype: str +132 """ +133 return MD5.new(str(self)).digest() +
134 +
135 - def get_base64(self): +
136 """ +137 Return a base64 string containing the public part of this key. Nothing +138 secret is revealed. This format is compatible with that used to store +139 public key files or recognized host keys. +140 +141 @return: a base64 string containing the public part of the key. +142 @rtype: str +143 """ +144 return base64.encodestring(str(self)).replace('\n', '') +
145 +
146 - def sign_ssh_data(self, randpool, data): +
147 """ +148 Sign a blob of data with this private key, and return a L{Message} +149 representing an SSH signature message. +150 +151 @param randpool: a secure random number generator. +152 @type randpool: L{Crypto.Util.randpool.RandomPool} +153 @param data: the data to sign. +154 @type data: str +155 @return: an SSH signature message. +156 @rtype: L{Message} +157 """ +158 return '' +
159 +
160 - def verify_ssh_sig(self, data, msg): +
161 """ +162 Given a blob of data, and an SSH message representing a signature of +163 that data, verify that it was signed with this key. +164 +165 @param data: the data that was signed. +166 @type data: str +167 @param msg: an SSH signature message +168 @type msg: L{Message} +169 @return: C{True} if the signature verifies correctly; C{False} +170 otherwise. +171 @rtype: boolean +172 """ +173 return False +
174 +
175 - def from_private_key_file(cls, filename, password=None): +
176 """ +177 Create a key object by reading a private key file. If the private +178 key is encrypted and C{password} is not C{None}, the given password +179 will be used to decrypt the key (otherwise L{PasswordRequiredException} +180 is thrown). Through the magic of python, this factory method will +181 exist in all subclasses of PKey (such as L{RSAKey} or L{DSSKey}), but +182 is useless on the abstract PKey class. +183 +184 @param filename: name of the file to read +185 @type filename: str +186 @param password: an optional password to use to decrypt the key file, +187 if it's encrypted +188 @type password: str +189 @return: a new key object based on the given private key +190 @rtype: L{PKey} +191 +192 @raise IOError: if there was an error reading the file +193 @raise PasswordRequiredException: if the private key file is +194 encrypted, and C{password} is C{None} +195 @raise SSHException: if the key file is invalid +196 """ +197 key = cls(filename=filename, password=password) +198 return key +
199 from_private_key_file = classmethod(from_private_key_file) +200 +
201 - def from_private_key(cls, file_obj, password=None): +
202 """ +203 Create a key object by reading a private key from a file (or file-like) +204 object. If the private key is encrypted and C{password} is not C{None}, +205 the given password will be used to decrypt the key (otherwise +206 L{PasswordRequiredException} is thrown). +207 +208 @param file_obj: the file to read from +209 @type file_obj: file +210 @param password: an optional password to use to decrypt the key, if it's +211 encrypted +212 @type password: str +213 @return: a new key object based on the given private key +214 @rtype: L{PKey} +215 +216 @raise IOError: if there was an error reading the key +217 @raise PasswordRequiredException: if the private key file is encrypted, +218 and C{password} is C{None} +219 @raise SSHException: if the key file is invalid +220 """ +221 key = cls(file_obj=file_obj, password=password) +222 return key +
223 from_private_key = classmethod(from_private_key) +224 +
225 - def write_private_key_file(self, filename, password=None): +
226 """ +227 Write private key contents into a file. If the password is not +228 C{None}, the key is encrypted before writing. +229 +230 @param filename: name of the file to write +231 @type filename: str +232 @param password: an optional password to use to encrypt the key file +233 @type password: str +234 +235 @raise IOError: if there was an error writing the file +236 @raise SSHException: if the key is invalid +237 """ +238 raise Exception('Not implemented in PKey') +
239 +
240 - def write_private_key(self, file_obj, password=None): +
241 """ +242 Write private key contents into a file (or file-like) object. If the +243 password is not C{None}, the key is encrypted before writing. +244 +245 @param file_obj: the file object to write into +246 @type file_obj: file +247 @param password: an optional password to use to encrypt the key +248 @type password: str +249 +250 @raise IOError: if there was an error writing to the file +251 @raise SSHException: if the key is invalid +252 """ +253 raise Exception('Not implemented in PKey') +
254 +
255 - def _read_private_key_file(self, tag, filename, password=None): +
256 """ +257 Read an SSH2-format private key file, looking for a string of the type +258 C{"BEGIN xxx PRIVATE KEY"} for some C{xxx}, base64-decode the text we +259 find, and return it as a string. If the private key is encrypted and +260 C{password} is not C{None}, the given password will be used to decrypt +261 the key (otherwise L{PasswordRequiredException} is thrown). +262 +263 @param tag: C{"RSA"} or C{"DSA"}, the tag used to mark the data block. +264 @type tag: str +265 @param filename: name of the file to read. +266 @type filename: str +267 @param password: an optional password to use to decrypt the key file, +268 if it's encrypted. +269 @type password: str +270 @return: data blob that makes up the private key. +271 @rtype: str +272 +273 @raise IOError: if there was an error reading the file. +274 @raise PasswordRequiredException: if the private key file is +275 encrypted, and C{password} is C{None}. +276 @raise SSHException: if the key file is invalid. +277 """ +278 f = open(filename, 'r') +279 data = self._read_private_key(tag, f, password) +280 f.close() +281 return data +
282 +
283 - def _read_private_key(self, tag, f, password=None): +
284 lines = f.readlines() +285 start = 0 +286 while (start < len(lines)) and (lines[start].strip() != '-----BEGIN ' + tag + ' PRIVATE KEY-----'): +287 start += 1 +288 if start >= len(lines): +289 raise SSHException('not a valid ' + tag + ' private key file') +290 # parse any headers first +291 headers = {} +292 start += 1 +293 while start < len(lines): +294 l = lines[start].split(': ') +295 if len(l) == 1: +296 break +297 headers[l[0].lower()] = l[1].strip() +298 start += 1 +299 # find end +300 end = start +301 while (lines[end].strip() != '-----END ' + tag + ' PRIVATE KEY-----') and (end < len(lines)): +302 end += 1 +303 # if we trudged to the end of the file, just try to cope. +304 try: +305 data = base64.decodestring(''.join(lines[start:end])) +306 except base64.binascii.Error, e: +307 raise SSHException('base64 decoding error: ' + str(e)) +308 if 'proc-type' not in headers: +309 # unencryped: done +310 return data +311 # encrypted keyfile: will need a password +312 if headers['proc-type'] != '4,ENCRYPTED': +313 raise SSHException('Unknown private key structure "%s"' % headers['proc-type']) +314 try: +315 encryption_type, saltstr = headers['dek-info'].split(',') +316 except: +317 raise SSHException('Can\'t parse DEK-info in private key file') +318 if encryption_type not in self._CIPHER_TABLE: +319 raise SSHException('Unknown private key cipher "%s"' % encryption_type) +320 # if no password was passed in, raise an exception pointing out that we need one +321 if password is None: +322 raise PasswordRequiredException('Private key file is encrypted') +323 cipher = self._CIPHER_TABLE[encryption_type]['cipher'] +324 keysize = self._CIPHER_TABLE[encryption_type]['keysize'] +325 mode = self._CIPHER_TABLE[encryption_type]['mode'] +326 salt = unhexlify(saltstr) +327 key = util.generate_key_bytes(MD5, salt, password, keysize) +328 return cipher.new(key, mode, salt).decrypt(data) +
329 +
330 - def _write_private_key_file(self, tag, filename, data, password=None): +
331 """ +332 Write an SSH2-format private key file in a form that can be read by +333 paramiko or openssh. If no password is given, the key is written in +334 a trivially-encoded format (base64) which is completely insecure. If +335 a password is given, DES-EDE3-CBC is used. +336 +337 @param tag: C{"RSA"} or C{"DSA"}, the tag used to mark the data block. +338 @type tag: str +339 @param filename: name of the file to write. +340 @type filename: str +341 @param data: data blob that makes up the private key. +342 @type data: str +343 @param password: an optional password to use to encrypt the file. +344 @type password: str +345 +346 @raise IOError: if there was an error writing the file. +347 """ +348 f = open(filename, 'w', 0600) +349 # grrr... the mode doesn't always take hold +350 os.chmod(filename, 0600) +351 self._write_private_key(tag, f, data, password) +352 f.close() +
353 +
354 - def _write_private_key(self, tag, f, data, password=None): +
355 f.write('-----BEGIN %s PRIVATE KEY-----\n' % tag) +356 if password is not None: +357 # since we only support one cipher here, use it +358 cipher_name = self._CIPHER_TABLE.keys()[0] +359 cipher = self._CIPHER_TABLE[cipher_name]['cipher'] +360 keysize = self._CIPHER_TABLE[cipher_name]['keysize'] +361 blocksize = self._CIPHER_TABLE[cipher_name]['blocksize'] +362 mode = self._CIPHER_TABLE[cipher_name]['mode'] +363 salt = randpool.get_bytes(8) +364 key = util.generate_key_bytes(MD5, salt, password, keysize) +365 if len(data) % blocksize != 0: +366 n = blocksize - len(data) % blocksize +367 #data += randpool.get_bytes(n) +368 # that would make more sense ^, but it confuses openssh. +369 data += '\0' * n +370 data = cipher.new(key, mode, salt).encrypt(data) +371 f.write('Proc-Type: 4,ENCRYPTED\n') +372 f.write('DEK-Info: %s,%s\n' % (cipher_name, hexlify(salt).upper())) +373 f.write('\n') +374 s = base64.encodestring(data) +375 # re-wrap to 64-char lines +376 s = ''.join(s.split('\n')) +377 s = '\n'.join([s[i : i+64] for i in range(0, len(s), 64)]) +378 f.write(s) +379 f.write('\n') +380 f.write('-----END %s PRIVATE KEY-----\n' % tag) +
381 +
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + -- cgit v1.2.3