Add basic openpgp key handling to Key Manager
[leap_pycommon.git] / src / leap / common / keymanager / __init__.py
1 # -*- coding: utf-8 -*-
2 # __init__.py
3 # Copyright (C) 2013 LEAP
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18
19 """
20 Key Manager is a Nicknym agent for LEAP client.
21 """
22
23
24 try:
25     import simplejson as json
26 except ImportError:
27     import json  # noqa
28
29
30 from u1db.errors import HTTPError
31
32
33 from leap.common.keymanager.errors import (
34     KeyNotFound,
35     KeyAlreadyExists,
36 )
37 from leap.common.keymanager.openpgp import (
38     OpenPGPKey,
39     OpenPGPWrapper,
40 )
41
42
43 wrapper_map = {
44     OpenPGPKey: OpenPGPWrapper(),
45 }
46
47
48 class KeyManager(object):
49
50     def __init__(self, address, url):
51         """
52         Initialize a Key Manager for user's C{address} with provider's
53         nickserver reachable in C{url}.
54
55         @param address: The address of the user of this Key Manager.
56         @type address: str
57         @param url: The URL of the key manager.
58         @type url: str
59         """
60         self.address = address
61         self.url = url
62
63     def send_key(self, ktype, send_private=False, password=None):
64         """
65         Send user's key of type C{ktype} to provider.
66
67         Public key bound to user's is sent to provider, which will sign it and
68         replace any prior keys for the same address in its database.
69
70         If C{send_private} is True, then the private key is encrypted with
71         C{password} and sent to server in the same request, together with a
72         hash string of user's address and password. The encrypted private key
73         will be saved in the server in a way it is publicly retrievable
74         through the hash string.
75
76         @param address: The address bound to the key.
77         @type address: str
78         @param ktype: The type of the key.
79         @type ktype: KeyType
80
81         @raise httplib.HTTPException:
82         """
83
84     def get_key(self, address, ktype):
85         """
86         Return a key of type C{ktype} bound to C{address}.
87
88         First, search for the key in local storage. If it is not available,
89         then try to fetch from nickserver.
90
91         @param address: The address bound to the key.
92         @type address: str
93         @param ktype: The type of the key.
94         @type ktype: KeyType
95
96         @return: A key of type C{ktype} bound to C{address}.
97         @rtype: EncryptionKey
98         @raise KeyNotFound: If the key was not found both locally and in
99             keyserver.
100         """
101         try:
102             return wrapper_map[ktype].get_key(address)
103         except KeyNotFound:
104             key = filter(lambda k: isinstance(k, ktype),
105                          self._fetch_keys(address))
106             if key is None:
107                 raise KeyNotFound()
108             wrapper_map[ktype].put_key(key)
109             return key
110
111
112     def _fetch_keys(self, address):
113         """
114         Fetch keys bound to C{address} from nickserver.
115
116         @param address: The address bound to the keys.
117         @type address: str
118
119         @return: A list of keys bound to C{address}.
120         @rtype: list of EncryptionKey
121         @raise KeyNotFound: If the key was not found on nickserver.
122         @raise httplib.HTTPException:
123         """
124
125     def refresh_keys(self):
126         """
127         Update the user's db of validated keys to see if there are changes.
128         """
129
130     def gen_key(self, ktype):
131         """
132         Generate a key of type C{ktype} bound to the user's address.
133
134         @param ktype: The type of the key.
135         @type ktype: KeyType
136
137         @return: The generated key.
138         @rtype: EncryptionKey
139         """
140         return wrapper_map[ktype].gen_key(self.address)