1
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
2
# See LICENSE for details.
5
# $Id: ckeygen.py,v 1.8 2003/05/10 14:03:40 spiv Exp $
7
#""" Implementation module for the `ckeygen` command.
10
from twisted.conch.ssh import keys, common
11
from twisted.python import log, usage
13
import sys, os, getpass, md5, socket
14
if getpass.getpass == getpass.unix_getpass:
16
import termios # hack around broken termios
17
termios.tcgetattr, termios.tcsetattr
18
except (ImportError, AttributeError):
19
sys.modules['termios'] = None
22
class GeneralOptions(usage.Options):
23
synopsis = """Usage: ckeygen [options]
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']]
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.']]
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"}
45
options = GeneralOptions()
47
options.parseOptions(sys.argv[1:])
48
except usage.UsageError, u:
53
log.deferr = handleError # HACK
55
if options['type'] == 'rsa':
56
generateRSAkey(options)
57
elif options['type'] == 'dsa':
58
generateDSAkey(options)
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)
72
from twisted.python import failure
75
log.err(failure.Failure())
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']), common.entropy.get_bytes)
83
_saveKey(key, options)
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']), common.entropy.get_bytes)
89
_saveKey(key, options)
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'
98
string = keys.getPublicKeyString(options['filename'])
99
obj = keys.getPublicKeyObject(string)
102
':'.join(['%02x' % ord(x) for x in md5.new(string).digest()]),
103
os.path.basename(options['filename']))
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)
112
key = keys.getPrivateKeyObject(options['filename'])
113
except keys.BadKeyError, e:
114
if e.args[0] != 'encrypted key with no passphrase':
117
if not options['pass']:
118
options['pass'] = getpass.getpass('Enter old passphrase: ')
119
key = keys.getPrivateKeyObject(options['filename'], passphrase = options['pass'])
120
if not options['newpass']:
122
p1 = getpass.getpass('Enter new passphrase (empty for no passphrase): ')
123
p2 = getpass.getpass('Enter same passphrase again: ')
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.'
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)
137
key = keys.getPrivateKeyObject(options['filename'])
138
except keys.BadKeyError, e:
139
if e.args[0] != 'encrypted key with no passphrase':
142
if not options['pass']:
143
options['pass'] = getpass.getpass('Enter passphrase: ')
144
key = keys.getPrivateKeyObject(options['filename'], passphrase = options['pass'])
145
print keys.makePublicKeyString(key)
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':
158
if not options['pass']:
160
p1 = getpass.getpass('Enter passphrase (empty for no passphrase): ')
161
p2 = getpass.getpass('Enter same passphrase again: ')
164
print 'Passphrases do not match. Try again.'
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()])
178
if __name__ == '__main__':