OLD | NEW |
| (Empty) |
1 # Copyright (c) 2001-2007 Twisted Matrix Laboratories. | |
2 # See LICENSE for details. | |
3 | |
4 # | |
5 # $Id: ckeygen.py,v 1.8 2003/05/10 14:03:40 spiv Exp $ | |
6 | |
7 #""" Implementation module for the `ckeygen` command. | |
8 #""" | |
9 | |
10 from twisted.conch.ssh import keys | |
11 from twisted.python import log, usage, randbytes | |
12 | |
13 import sys, os, getpass, md5, socket | |
14 if getpass.getpass == getpass.unix_getpass: | |
15 try: | |
16 import termios # hack around broken termios | |
17 termios.tcgetattr, termios.tcsetattr | |
18 except (ImportError, AttributeError): | |
19 sys.modules['termios'] = None | |
20 reload(getpass) | |
21 | |
22 class GeneralOptions(usage.Options): | |
23 synopsis = """Usage: ckeygen [options] | |
24 """ | |
25 | |
26 optParameters = [['bits', 'b', 1024, 'Number of bits in the key to create.']
, | |
27 ['filename', 'f', None, 'Filename of the key file.'], | |
28 ['type', 't', None, 'Specify type of key to create.'], | |
29 ['comment', 'C', None, 'Provide new comment.'], | |
30 ['newpass', 'N', None, 'Provide new passphrase.'], | |
31 ['pass', 'P', None, 'Provide old passphrase']] | |
32 | |
33 optFlags = [['fingerprint', 'l', 'Show fingerprint of key file.'], | |
34 ['changepass', 'p', 'Change passphrase of private key file.'], | |
35 ['quiet', 'q', 'Quiet.'], | |
36 ['showpub', 'y', 'Read private key file and print public key.']] | |
37 | |
38 #zsh_altArgDescr = {"bits":"Number of bits in the key (default: 1024)"} | |
39 #zsh_multiUse = ["foo", "bar"] | |
40 #zsh_mutuallyExclusive = [("foo", "bar"), ("bar", "baz")] | |
41 zsh_actions = {"type":"(rsa dsa)"} | |
42 #zsh_actionDescr = {"logfile":"log file name", "random":"random seed"} | |
43 | |
44 def run(): | |
45 options = GeneralOptions() | |
46 try: | |
47 options.parseOptions(sys.argv[1:]) | |
48 except usage.UsageError, u: | |
49 print 'ERROR: %s' % u | |
50 options.opt_help() | |
51 sys.exit(1) | |
52 log.discardLogs() | |
53 log.deferr = handleError # HACK | |
54 if options['type']: | |
55 if options['type'] == 'rsa': | |
56 generateRSAkey(options) | |
57 elif options['type'] == 'dsa': | |
58 generateDSAkey(options) | |
59 else: | |
60 sys.exit('Key type was %s, must be one of: rsa, dsa' % options['type
']) | |
61 elif options['fingerprint']: | |
62 printFingerprint(options) | |
63 elif options['changepass']: | |
64 changePassPhrase(options) | |
65 elif options['showpub']: | |
66 displayPublicKey(options) | |
67 else: | |
68 options.opt_help() | |
69 sys.exit(1) | |
70 | |
71 def handleError(): | |
72 from twisted.python import failure | |
73 global exitStatus | |
74 exitStatus = 2 | |
75 log.err(failure.Failure()) | |
76 reactor.stop() | |
77 raise | |
78 | |
79 def generateRSAkey(options): | |
80 from Crypto.PublicKey import RSA | |
81 print 'Generating public/private rsa key pair.' | |
82 key = RSA.generate(int(options['bits']), randbytes.secureRandom) | |
83 _saveKey(key, options) | |
84 | |
85 def generateDSAkey(options): | |
86 from Crypto.PublicKey import DSA | |
87 print 'Generating public/private dsa key pair.' | |
88 key = DSA.generate(int(options['bits']), randbytes.secureRandom) | |
89 _saveKey(key, options) | |
90 | |
91 def printFingerprint(options): | |
92 if not options['filename']: | |
93 filename = os.path.expanduser('~/.ssh/id_rsa') | |
94 options['filename'] = raw_input('Enter file in which the key is (%s): '
% filename) | |
95 if os.path.exists(options['filename']+'.pub'): | |
96 options['filename'] += '.pub' | |
97 try: | |
98 string = keys.getPublicKeyString(options['filename']) | |
99 obj = keys.getPublicKeyObject(string) | |
100 print '%s %s %s' % ( | |
101 obj.size()+1, | |
102 ':'.join(['%02x' % ord(x) for x in md5.new(string).digest()]), | |
103 os.path.basename(options['filename'])) | |
104 except: | |
105 sys.exit('bad key') | |
106 | |
107 def changePassPhrase(options): | |
108 if not options['filename']: | |
109 filename = os.path.expanduser('~/.ssh/id_rsa') | |
110 options['filename'] = raw_input('Enter file in which the key is (%s): '
% filename) | |
111 try: | |
112 key = keys.getPrivateKeyObject(options['filename']) | |
113 except keys.BadKeyError, e: | |
114 if e.args[0] != 'encrypted key with no passphrase': | |
115 raise | |
116 else: | |
117 if not options['pass']: | |
118 options['pass'] = getpass.getpass('Enter old passphrase: ') | |
119 key = keys.getPrivateKeyObject(options['filename'], passphrase = opt
ions['pass']) | |
120 if not options['newpass']: | |
121 while 1: | |
122 p1 = getpass.getpass('Enter new passphrase (empty for no passphrase)
: ') | |
123 p2 = getpass.getpass('Enter same passphrase again: ') | |
124 if p1 == p2: | |
125 break | |
126 print 'Passphrases do not match. Try again.' | |
127 options['newpass'] = p1 | |
128 open(options['filename'], 'w').write( | |
129 keys.makePrivateKeyString(key, passphrase=options['newpass'])) | |
130 print 'Your identification has been saved with the new passphrase.' | |
131 | |
132 def displayPublicKey(options): | |
133 if not options['filename']: | |
134 filename = os.path.expanduser('~/.ssh/id_rsa') | |
135 options['filename'] = raw_input('Enter file in which the key is (%s): '
% filename) | |
136 try: | |
137 key = keys.getPrivateKeyObject(options['filename']) | |
138 except keys.BadKeyError, e: | |
139 if e.args[0] != 'encrypted key with no passphrase': | |
140 raise | |
141 else: | |
142 if not options['pass']: | |
143 options['pass'] = getpass.getpass('Enter passphrase: ') | |
144 key = keys.getPrivateKeyObject(options['filename'], passphrase = opt
ions['pass']) | |
145 print keys.makePublicKeyString(key) | |
146 | |
147 def _saveKey(key, options): | |
148 if not options['filename']: | |
149 kind = keys.objectType(key) | |
150 kind = {'ssh-rsa':'rsa','ssh-dss':'dsa'}[kind] | |
151 filename = os.path.expanduser('~/.ssh/id_%s'%kind) | |
152 options['filename'] = raw_input('Enter file in which to save the key (%s
): '%filename).strip() or filename | |
153 if os.path.exists(options['filename']): | |
154 print '%s already exists.' % options['filename'] | |
155 yn = raw_input('Overwrite (y/n)? ') | |
156 if yn[0].lower() != 'y': | |
157 sys.exit() | |
158 if not options['pass']: | |
159 while 1: | |
160 p1 = getpass.getpass('Enter passphrase (empty for no passphrase): ') | |
161 p2 = getpass.getpass('Enter same passphrase again: ') | |
162 if p1 == p2: | |
163 break | |
164 print 'Passphrases do not match. Try again.' | |
165 options['pass'] = p1 | |
166 comment = '%s@%s' % (getpass.getuser(), socket.gethostname()) | |
167 open(options['filename'], 'w').write( | |
168 keys.makePrivateKeyString(key, passphrase=options['pass'])) | |
169 os.chmod(options['filename'], 33152) | |
170 open(options['filename']+'.pub', 'w').write( | |
171 keys.makePublicKeyString(key, comment = comment)) | |
172 pubKey = keys.getPublicKeyString(data=keys.makePublicKeyString(key, comment=
comment)) | |
173 print 'Your identification has been saved in %s' % options['filename'] | |
174 print 'Your public key has been saved in %s.pub' % options['filename'] | |
175 print 'The key fingerprint is:' | |
176 print ':'.join(['%02x' % ord(x) for x in md5.new(pubKey).digest()]) | |
177 | |
178 if __name__ == '__main__': | |
179 run() | |
180 | |
OLD | NEW |