Package keyczar :: Module keyczart
[hide private]
[frames] | no frames]

Source Code for Module keyczar.keyczart

  1  #!/usr/bin/python2.4 
  2  # 
  3  # Copyright 2008 Google Inc. 
  4  # 
  5  # Licensed under the Apache License, Version 2.0 (the "License"); 
  6  # you may not use this file except in compliance with the License. 
  7  # You may obtain a copy of the License at 
  8  #  
  9  #      http://www.apache.org/licenses/LICENSE-2.0 
 10  #  
 11  # Unless required by applicable law or agreed to in writing, software 
 12  # distributed under the License is distributed on an "AS IS" BASIS, 
 13  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 14  # See the License for the specific language governing permissions and 
 15  # limitations under the License. 
 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   
40 -class _Name(object):
41
42 - def __init__(self, name):
43 self.name = name
44
45 - def __str__(self):
46 return self.name
47
48 -class Command(_Name):
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
62 -def GetCommand(cmd):
63 try: 64 return commands[cmd] 65 except KeyError: 66 raise errors.KeyczarError("Illegal command")
67
68 -class Flag(_Name):
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
84 -def GetFlag(flag):
85 try: 86 return flags[flag] 87 except KeyError: 88 raise errors.KeyczarError("Unknown flag")
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: # default to DSA 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: # default to RSA 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):
114 czar = CreateGenericKeyczar(loc, crypter) 115 if size == -1: 116 size = None 117 czar.AddVersion(status, size) 118 UpdateGenericKeyczar(czar, loc, crypter)
119
120 -def PubKey(loc, dest):
121 if dest is None: 122 raise errors.KeyczarError("Must define destination") 123 czar = CreateGenericKeyczar(loc) 124 czar.PublicKeyExport(dest)
125
126 -def Promote(loc, num):
127 czar = CreateGenericKeyczar(loc) 128 if num < 0: 129 raise errors.KeyczarError("Missing version") 130 czar.Promote(num) 131 UpdateGenericKeyczar(czar, loc)
132
133 -def Demote(loc, num):
134 czar = CreateGenericKeyczar(loc) 135 if num < 0: 136 raise errors.KeyczarError("Missing version") 137 czar.Demote(num) 138 UpdateGenericKeyczar(czar, loc)
139
140 -def Revoke(loc, num):
141 czar = CreateGenericKeyczar(loc) 142 if num < 0: 143 raise errors.KeyczarError("Missing version") 144 czar.Revoke(num) 145 UpdateGenericKeyczar(czar, loc) 146 os.remove(os.path.join(loc, str(num))) # remove key file
147
148 -def GenKeySet(loc):
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
170 -def Clean(directory):
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"):
177 reader = readers.FileReader(loc) 178 answer = "" 179 if crypter: 180 reader = readers.EncryptedReader(reader, crypter) 181 if purpose == keyinfo.DECRYPT_AND_ENCRYPT: 182 answer = keyczar.Crypter(reader).Encrypt(msg) 183 elif purpose == keyinfo.SIGN_AND_VERIFY: 184 answer = keyczar.Signer(reader).Sign(msg) 185 util.WriteFile(answer, dest)
186
187 -def Usage():
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
226 -def CreateGenericKeyczar(loc, crypter=None):
227 if loc is None: 228 raise errors.KeyczarError("Need location") 229 else: 230 reader = readers.FileReader(loc) 231 if crypter: 232 reader = readers.EncryptedReader(reader, crypter) 233 return keyczar.GenericKeyczar(reader)
234
235 -def UpdateGenericKeyczar(czar, loc, encrypter=None):
236 czar.Write(loc, encrypter)
237
238 -def main(argv):
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:] # trim leading dashes 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:])) # sys.argv[0] is name of program 280