1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 """
18 Keyczart(ool) is a utility for creating and managing Keyczar keysets.
19
20 @author: arkajit.dey@gmail.com (Arkajit Dey)
21 """
22
23 import os
24 import sys
25
26 import errors
27 import keyczar
28 import keydata
29 import keyinfo
30 import readers
31 import util
32
33 KEYSETS = [('aes', keyinfo.DECRYPT_AND_ENCRYPT, None, None),
34 ('aes-crypted', keyinfo.DECRYPT_AND_ENCRYPT, None, 'aes'),
35 ('hmac', keyinfo.SIGN_AND_VERIFY, None, None),
36 ('rsa', keyinfo.DECRYPT_AND_ENCRYPT, 'rsa', None),
37 ('rsa-sign', keyinfo.SIGN_AND_VERIFY, 'rsa', None),
38 ('dsa', keyinfo.SIGN_AND_VERIFY, 'dsa', None)]
39
47
49 """Enum representing keyczart commands."""
50
51 CREATE = Command("create")
52 ADDKEY = Command("addkey")
53 PUBKEY = Command("pubkey")
54 PROMOTE = Command("promote")
55 DEMOTE = Command("demote")
56 REVOKE = Command("revoke")
57 GENKEY = Command("genkey")
58 commands = {"create": CREATE, "addkey": ADDKEY, "pubkey": PUBKEY,
59 "promote": PROMOTE, "demote": DEMOTE, "revoke": REVOKE,
60 "genkey": GENKEY}
61
67
69 """Enum representing keyczart flags."""
70
71 LOCATION = Flag("location")
72 NAME = Flag("name")
73 SIZE = Flag("size")
74 STATUS = Flag("status")
75 PURPOSE = Flag("purpose")
76 DESTINATION = Flag("destination")
77 VERSION = Flag("version")
78 ASYMMETRIC = Flag("asymmetric")
79 CRYPTER = Flag("crypter")
80 flags = {"location": LOCATION, "name": NAME, "size": SIZE, "status": STATUS,
81 "purpose": PURPOSE, "destination": DESTINATION, "version": VERSION,
82 "asymmetric": ASYMMETRIC, "crypter": CRYPTER}
83
89
90 -def Create(loc, name, purpose, asymmetric=None):
91 if loc is None:
92 raise errors.KeyczarError("Location missing")
93 kmd = None
94 if purpose == keyinfo.SIGN_AND_VERIFY:
95 if asymmetric is None:
96 kmd = keydata.KeyMetadata(name, purpose, keyinfo.HMAC_SHA1)
97 elif asymmetric.lower() == "rsa":
98 kmd = keydata.KeyMetadata(name, purpose, keyinfo.RSA_PRIV)
99 else:
100 kmd = keydata.KeyMetadata(name, purpose, keyinfo.DSA_PRIV)
101 elif purpose == keyinfo.DECRYPT_AND_ENCRYPT:
102 if asymmetric is None:
103 kmd = keydata.KeyMetadata(name, purpose, keyinfo.AES)
104 else:
105 kmd = keydata.KeyMetadata(name, purpose, keyinfo.RSA_PRIV)
106 else:
107 raise errors.KeyczarError("Missing or unsupported purpose")
108 name = os.path.join(loc, "meta")
109 if os.path.exists(name):
110 raise errors.KeyczarError("File already exists")
111 util.WriteFile(str(kmd), name)
112
113 -def AddKey(loc, status, crypter=None, size=None):
119
125
132
139
147
149 print "Generating private key sets..."
150 for (name, purpose, asymmetric, crypter) in KEYSETS:
151 print "."
152 dir = os.path.join(loc, name)
153 if crypter:
154 crypter = keyczar.Crypter.Read(os.path.join(loc, crypter))
155 Clean(dir)
156 Create(dir, "Test", purpose, asymmetric)
157 AddKey(dir, keyinfo.PRIMARY, crypter)
158 UseKey(purpose, dir, os.path.join(dir, "1.out"), crypter)
159 AddKey(dir, keyinfo.PRIMARY, crypter)
160 UseKey(purpose, dir, os.path.join(dir, "2.out"), crypter)
161
162 print "Exporting public key sets..."
163 for name in ('dsa', 'rsa-sign'):
164 print "."
165 dir = os.path.join(loc, name)
166 dest = os.path.join(loc, name + '.public')
167 PubKey(dir, dest)
168 print "Done!"
169
171 for file in os.listdir(directory):
172 path = os.path.join(directory, file)
173 if not os.path.isdir(path):
174 os.remove(path)
175
176 -def UseKey(purpose, loc, dest, crypter=None, msg="This is some test data"):
186
188 print '''Usage: "Keyczart command flags"
189 Commands: create addkey pubkey promote demote revoke
190 Flags: location name size status purpose destination version asymmetric crypter
191 Command Usage:
192 create --location=/path/to/keys --purpose=(crypt|sign) [--name="A name"] [--asymmetric=(dsa|rsa)]
193 Creates a new, empty key set in the given location.
194 This key set must have a purpose of either "crypt" or "sign"
195 and may optionally be given a name. The optional asymmetric
196 flag will generate a public key set of the given algorithm.
197 The "dsa" asymmetric value is valid only for sets with "sign" purpose.
198 with the given purpose.
199 addkey --location=/path/to/keys [--status=(active|primary)] [--size=size] [--crypter=crypterLocation]
200 Adds a new key to an existing key set. Optionally
201 specify a purpose, which is active by default. Optionally
202 specify a key size in bits. Also optionally specify the
203 location of a set of crypting keys, which will be used to
204 encrypt this key set.
205 pubkey --location=/path/to/keys --destination=/destination
206 Extracts public keys from a given key set and writes them
207 to the destination. The "pubkey" command Only works for
208 key sets that were created with the "--asymmetric" flag.
209 promote --location=/path/to/keys --version=versionNumber
210 Promotes the status of the given key version in the given
211 location. Active keys are promoted to primary (which demotes
212 any existing primary key to active). Keys scheduled for
213 revocation are promoted to be active.
214 demote --location=/path/to/keys --version=versionNumber
215 Demotes the status of the given key version in the given
216 location. Primary keys are demoted to active. Active keys
217 are scheduled for revocation.
218 revoke --location=/path/to/keys --version=versionNumber
219 Revokes the key of the given version number.
220 This key must have been scheduled for revocation by the
221 promote command. WARNING: The key will be destroyed.
222
223 Optional flags are in [brackets]. The notation (a|b|c) means "a", "b", and "c"
224 are the valid choices'''
225
234
236 czar.Write(loc, encrypter)
237
239 if len(argv) == 0:
240 Usage()
241 else:
242 cmd = GetCommand(argv[0])
243 flags = {}
244 for arg in argv:
245 if arg.startswith("--"):
246 arg = arg[2:]
247 try:
248 [flag, val] = arg.split("=")
249 flags[GetFlag(flag)] = val
250 except ValueError:
251 Usage()
252 if cmd == CREATE:
253 purpose = {'crypt': keyinfo.DECRYPT_AND_ENCRYPT,
254 'sign': keyinfo.SIGN_AND_VERIFY}.get(flags.get(PURPOSE))
255 Create(flags.get(LOCATION), flags.get(NAME, 'Test'), purpose,
256 flags.get(ASYMMETRIC))
257 elif cmd == ADDKEY:
258 if flags.has_key(CRYPTER):
259 crypter = keyczar.Encrypter.Read(flags[CRYPTER])
260 else:
261 crypter = None
262 AddKey(flags.get(LOCATION),
263 keyinfo.GetStatus(flags.get(STATUS, 'ACTIVE')),
264 int(flags.get(SIZE, -1)), crypter)
265 elif cmd == PUBKEY:
266 PubKey(flags.get(LOCATION), flags.get(DESTINATION))
267 elif cmd == PROMOTE:
268 Promote(flags.get(LOCATION), int(flags.get(VERSION, -1)))
269 elif cmd == DEMOTE:
270 Demote(flags.get(LOCATION), int(flags.get(VERSION, -1)))
271 elif cmd == REVOKE:
272 Revoke(flags.get(LOCATION), int(flags.get(VERSION, -1)))
273 elif cmd == GENKEY:
274 GenKeySet(flags.get(LOCATION))
275 else:
276 Usage()
277
278 if __name__ == '__main__':
279 sys.exit(main(sys.argv[1:]))
280