101 |
101 |
return simplejson.loads(txt)
|
102 |
102 |
|
103 |
103 |
|
104 |
|
def DumpSignedJson(data, key, salt=None):
|
|
104 |
def DumpSignedJson(data, key, salt=None, key_selector=None):
|
105 |
105 |
"""Serialize a given object and authenticate it.
|
106 |
106 |
|
107 |
107 |
@param data: the data to serialize
|
108 |
108 |
@param key: shared hmac key
|
|
109 |
@param key_selector: name/id that identifies the key (in case there are
|
|
110 |
multiple keys in use, e.g. in a multi-cluster environment)
|
109 |
111 |
@return: the string representation of data signed by the hmac key
|
110 |
112 |
|
111 |
113 |
"""
|
... | ... | |
115 |
117 |
signed_dict = {
|
116 |
118 |
'msg': txt,
|
117 |
119 |
'salt': salt,
|
118 |
|
'hmac': hmac.new(key, salt + txt, sha1).hexdigest(),
|
119 |
120 |
}
|
|
121 |
if key_selector:
|
|
122 |
signed_dict["key_selector"] = key_selector
|
|
123 |
message = salt + key_selector + txt
|
|
124 |
else:
|
|
125 |
message = salt + txt
|
|
126 |
signed_dict["hmac"] = hmac.new(key, message,
|
|
127 |
sha1).hexdigest()
|
|
128 |
|
120 |
129 |
return DumpJson(signed_dict, indent=False)
|
121 |
130 |
|
122 |
131 |
|
... | ... | |
124 |
133 |
"""Verify that a given message was signed with the given key, and load it.
|
125 |
134 |
|
126 |
135 |
@param txt: json-encoded hmac-signed message
|
127 |
|
@param key: shared hmac key
|
|
136 |
@param key: the shared hmac key or a callable taking one argument (the key
|
|
137 |
selector), which returns the hmac key belonging to the key selector.
|
|
138 |
Typical usage is to pass a reference to the get method of a dict.
|
128 |
139 |
@rtype: tuple of original data, string
|
129 |
140 |
@return: original data, salt
|
130 |
141 |
@raises errors.SignatureError: if the message signature doesn't verify
|
... | ... | |
140 |
151 |
except KeyError:
|
141 |
152 |
raise errors.SignatureError('Invalid external message')
|
142 |
153 |
|
143 |
|
if hmac.new(key, salt + msg, sha1).hexdigest() != hmac_sign:
|
|
154 |
if callable(key):
|
|
155 |
key_selector = signed_dict.get("key_selector", None)
|
|
156 |
hmac_key = key(key_selector)
|
|
157 |
if not hmac_key:
|
|
158 |
raise errors.SignatureError("No key with key selector '%s' found" %
|
|
159 |
key_selector)
|
|
160 |
else:
|
|
161 |
key_selector = ""
|
|
162 |
hmac_key = key
|
|
163 |
|
|
164 |
if hmac.new(hmac_key, salt + key_selector + msg,
|
|
165 |
sha1).hexdigest() != hmac_sign:
|
144 |
166 |
raise errors.SignatureError('Invalid Signature')
|
145 |
167 |
|
146 |
168 |
return LoadJson(msg), salt
|