1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
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
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
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
91 return 'ecdsa-sha2-nistp256'
92
95
97 return self.signing_key is not None
98
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
109 if msg.get_string() != 'ecdsa-sha2-nistp256':
110 return False
111 sig = msg.get_string()
112
113
114
115 hash_obj = SHA256.new(data).digest()
116 return self.verifying_key.verify_digest(sig, hash_obj,
117 sigdecode=self._sigdecode)
118
120 key = self.signing_key or self.verifying_key
121 self._write_private_key_file('EC', filename, key.to_der(), password)
122
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
147
148
150 data = self._read_private_key_file('EC', filename, password)
151 self._decode_key(data)
152
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']
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
176
182