| 11 | # This class implements the packets encryption keychain. It loads and |
| 12 | # saves keys from/to disk, and implements encryption and decryption. |
| 13 | class Keychain: |
| 14 | def __init__(self,keychain_dir="keys"): |
| 15 | try: os.mkdir(keychain_dir) |
| 16 | except: pass |
| 17 | self.keychain_dir = keychain_dir |
| 18 | self.load_keys() |
| 19 | |
| 20 | # Load keys in memory. |
| 21 | def load_keys(self): |
| 22 | self.keys = {} # Map "key name" -> SHA256(key) |
| 23 | for key_name in os.listdir(self.keychain_dir): |
| 24 | try: |
| 25 | f = open(self.keychain_dir+"/"+key_name,'rb') |
| 26 | key = f.read() |
| 27 | f.close() |
| 28 | self.keys[key_name] = self.sha16(key) |
| 29 | except: pass |
| 30 | |
| 31 | # Return all the available key names |
| 32 | def list_keys(self): |
| 33 | return os.listdir(self.keychain_dir) |
| 34 | |
| 35 | # Delete the specified key |
| 36 | def del_key(self,key_name): |
| 37 | try: os.unlink(self.keychain_dir+"/"+key_name) |
| 38 | except: pass |
| 39 | del self.keys[key_name] |
| 40 | |
| 41 | # Add a new key into the keychain, overwriting an old one |
| 42 | # with the same name if any. |
| 43 | def add_key(self,key_name,key): |
| 44 | f = open(self.keychain_dir+"/"+key_name,'wb') |
| 45 | f.write(key) |
| 46 | f.close() |
| 47 | self.load_keys() |
| 48 | |
| 49 | # Return True if the key exists. |
| 50 | def has_key(self,key_name): |
| 51 | return self.keys.get(key_name) != None |
| 52 | |
| 53 | # Given a key, derive two keys, one for AES and the other |
| 54 | # for the HMAC. |
| 55 | def derive_keys(self,key): |
| 56 | return HMAC_SHA256(key,"AES14159265358979323846")[:16], \ |
| 57 | HMAC_SHA256(key,"MAC26433832795028841971") |
| 58 | |
| 59 | # Return the SHA256 digest truncated to 16 bytes |
| 60 | def sha16(self,data): |
| 61 | return hashlib.sha256(data).digest()[:16] |
| 62 | |
| 63 | # This function expects an already encoded data packet, and |
| 64 | # return its encrypted version. |
| 65 | def encrypt(self,packet,key_name): |
| 66 | key = self.keys.get(key_name) |
| 67 | if key == None: |
| 68 | raise Exception("No key with the specified name: "+str(key_name)) |
| 69 | |
| 70 | # Derive the encryption and HMAC keys. |
no outgoing calls
no test coverage detected