Package paramiko :: Module ecdsakey
[frames] | no frames]

Source Code for Module paramiko.ecdsakey

  1  # Copyright (C) 2003-2007  Robey Pointer <robeypointer@gmail.com> 
  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  L{ECDSAKey} 
 21  """ 
 22   
 23  import binascii 
 24  from ecdsa import SigningKey, VerifyingKey, der, curves 
 25  from ecdsa.util import number_to_string, sigencode_string, sigencode_strings, sigdecode_strings 
 26  from Crypto.Hash import SHA256, MD5 
 27  from Crypto.Cipher import DES3 
 28   
 29  from paramiko.common import * 
 30  from paramiko import util 
 31  from paramiko.message import Message 
 32  from paramiko.ber import BER, BERException 
 33  from paramiko.pkey import PKey 
 34  from paramiko.ssh_exception import SSHException 
 35   
 36   
37 -class ECDSAKey (PKey):
38 """ 39 Representation of an ECDSA key which can be used to sign and verify SSH2 40 data. 41 """ 42
43 - def __init__(self, msg=None, data=None, filename=None, password=None, vals=None, file_obj=None):
44 self.verifying_key = None 45 self.signing_key = None 46 if file_obj is not None: 47 self._from_private_key(file_obj, password) 48 return 49 if filename is not None: 50 self._from_private_key_file(filename, password) 51 return 52 if (msg is None) and (data is not None): 53 msg = Message(data) 54 if vals is not None: 55 self.verifying_key, self.signing_key = vals 56 else: 57 if msg is None: 58 raise SSHException('Key object may not be empty') 59 if msg.get_string() != 'ecdsa-sha2-nistp256': 60 raise SSHException('Invalid key') 61 curvename = msg.get_string() 62 if curvename != 'nistp256': 63 raise SSHException("Can't handle curve of type %s" % curvename) 64 65 pointinfo = msg.get_string() 66 if pointinfo[0] != "\x04": 67 raise SSHException('Point compression is being used: %s'% 68 binascii.hexlify(pointinfo)) 69 self.verifying_key = VerifyingKey.from_string(pointinfo[1:], 70 curve=curves.NIST256p) 71 self.size = 256
72
73 - def __str__(self):
74 key = self.verifying_key 75 m = Message() 76 m.add_string('ecdsa-sha2-nistp256') 77 m.add_string('nistp256') 78 79 point_str = "\x04" + key.to_string() 80 81 m.add_string(point_str) 82 return str(m)
83
84 - def __hash__(self):
85 h = hash(self.get_name()) 86 h = h * 37 + hash(self.verifying_key.pubkey.point.x()) 87 h = h * 37 + hash(self.verifying_key.pubkey.point.y()) 88 return hash(h)
89
90 - def get_name(self):
91 return 'ecdsa-sha2-nistp256'
92
93 - def get_bits(self):
94 return self.size
95
96 - def can_sign(self):
97 return self.signing_key is not None
98
99 - def sign_ssh_data(self, rpool, data):
100 digest = SHA256.new(data).digest() 101 sig = self.signing_key.sign_digest(digest, entropy=rpool.read, 102 sigencode=self._sigencode) 103 m = Message() 104 m.add_string('ecdsa-sha2-nistp256') 105 m.add_string(sig) 106 return m
107
108 - def verify_ssh_sig(self, data, msg):
109 if msg.get_string() != 'ecdsa-sha2-nistp256': 110 return False 111 sig = msg.get_string() 112 113 # verify the signature by SHA'ing the data and encrypting it 114 # using the public key. 115 hash_obj = SHA256.new(data).digest() 116 return self.verifying_key.verify_digest(sig, hash_obj, 117 sigdecode=self._sigdecode)
118
119 - def write_private_key_file(self, filename, password=None):
120 key = self.signing_key or self.verifying_key 121 self._write_private_key_file('EC', filename, key.to_der(), password)
122
123 - def write_private_key(self, file_obj, password=None):
124 key = self.signing_key or self.verifying_key 125 self._write_private_key('EC', file_obj, key.to_der(), password)
126
127 - def generate(bits, progress_func=None):
128 """ 129 Generate a new private RSA key. This factory function can be used to 130 generate a new host key or authentication key. 131 132 @param bits: number of bits the generated key should be. 133 @type bits: int 134 @param progress_func: an optional function to call at key points in 135 key generation (used by C{pyCrypto.PublicKey}). 136 @type progress_func: function 137 @return: new private key 138 @rtype: L{RSAKey} 139 """ 140 signing_key = ECDSA.generate() 141 key = ECDSAKey(vals=(signing_key, signing_key.get_verifying_key())) 142 return key
143 generate = staticmethod(generate) 144 145 146 ### internals... 147 148
149 - def _from_private_key_file(self, filename, password):
150 data = self._read_private_key_file('EC', filename, password) 151 self._decode_key(data)
152
153 - def _from_private_key(self, file_obj, password):
154 data = self._read_private_key('EC', file_obj, password) 155 self._decode_key(data)
156 157 ALLOWED_PADDINGS = ['\x01', '\x02\x02', '\x03\x03\x03', '\x04\x04\x04\x04', 158 '\x05\x05\x05\x05\x05', '\x06\x06\x06\x06\x06\x06', 159 '\x07\x07\x07\x07\x07\x07\x07']
160 - def _decode_key(self, data):
161 s, padding = der.remove_sequence(data) 162 if padding: 163 if padding not in self.ALLOWED_PADDINGS: 164 raise ValueError, "weird padding: %s" % (binascii.hexlify(empty)) 165 data = data[:-len(padding)] 166 key = SigningKey.from_der(data) 167 self.signing_key = key 168 self.verifying_key = key.get_verifying_key() 169 self.size = 256
170
171 - def _sigencode(self, r, s, order):
172 msg = Message() 173 msg.add_mpint(r) 174 msg.add_mpint(s) 175 return str(msg)
176
177 - def _sigdecode(self, sig, order):
178 msg = Message(sig) 179 r = msg.get_mpint() 180 s = msg.get_mpint() 181 return (r, s)
182