@@ -181,6 +181,94 @@ def test_replace_master_key(self):
181181 devices = yield self .handler .query_devices ({"device_keys" : {local_user : []}}, 0 )
182182 self .assertDictEqual (devices ["master_keys" ], {local_user : keys2 ["master_key" ]})
183183
184+ @defer .inlineCallbacks
185+ def test_reupload_signatures (self ):
186+ """re-uploading a signature should not fail"""
187+ local_user = "@boris:" + self .hs .hostname
188+ keys1 = {
189+ "master_key" : {
190+ # private key: HvQBbU+hc2Zr+JP1sE0XwBe1pfZZEYtJNPJLZJtS+F8
191+ "user_id" : local_user ,
192+ "usage" : ["master" ],
193+ "keys" : {
194+ "ed25519:EmkqvokUn8p+vQAGZitOk4PWjp7Ukp3txV2TbMPEiBQ" : "EmkqvokUn8p+vQAGZitOk4PWjp7Ukp3txV2TbMPEiBQ"
195+ },
196+ },
197+ "self_signing_key" : {
198+ # private key: 2lonYOM6xYKdEsO+6KrC766xBcHnYnim1x/4LFGF8B0
199+ "user_id" : local_user ,
200+ "usage" : ["self_signing" ],
201+ "keys" : {
202+ "ed25519:nqOvzeuGWT/sRx3h7+MHoInYj3Uk2LD/unI9kDYcHwk" : "nqOvzeuGWT/sRx3h7+MHoInYj3Uk2LD/unI9kDYcHwk"
203+ },
204+ },
205+ }
206+ master_signing_key = key .decode_signing_key_base64 (
207+ "ed25519" ,
208+ "EmkqvokUn8p+vQAGZitOk4PWjp7Ukp3txV2TbMPEiBQ" ,
209+ "HvQBbU+hc2Zr+JP1sE0XwBe1pfZZEYtJNPJLZJtS+F8" ,
210+ )
211+ sign .sign_json (keys1 ["self_signing_key" ], local_user , master_signing_key )
212+ signing_key = key .decode_signing_key_base64 (
213+ "ed25519" ,
214+ "nqOvzeuGWT/sRx3h7+MHoInYj3Uk2LD/unI9kDYcHwk" ,
215+ "2lonYOM6xYKdEsO+6KrC766xBcHnYnim1x/4LFGF8B0" ,
216+ )
217+ yield self .handler .upload_signing_keys_for_user (local_user , keys1 )
218+
219+ # upload two device keys, which will be signed later by the self-signing key
220+ device_key_1 = {
221+ "user_id" : local_user ,
222+ "device_id" : "abc" ,
223+ "algorithms" : ["m.olm.curve25519-aes-sha256" , "m.megolm.v1.aes-sha" ],
224+ "keys" : {
225+ "ed25519:abc" : "base64+ed25519+key" ,
226+ "curve25519:abc" : "base64+curve25519+key" ,
227+ },
228+ "signatures" : {local_user : {"ed25519:abc" : "base64+signature" }},
229+ }
230+ device_key_2 = {
231+ "user_id" : local_user ,
232+ "device_id" : "def" ,
233+ "algorithms" : ["m.olm.curve25519-aes-sha256" , "m.megolm.v1.aes-sha" ],
234+ "keys" : {
235+ "ed25519:def" : "base64+ed25519+key" ,
236+ "curve25519:def" : "base64+curve25519+key" ,
237+ },
238+ "signatures" : {local_user : {"ed25519:def" : "base64+signature" }},
239+ }
240+
241+ yield self .handler .upload_keys_for_user (
242+ local_user , "abc" , {"device_keys" : device_key_1 }
243+ )
244+ yield self .handler .upload_keys_for_user (
245+ local_user , "def" , {"device_keys" : device_key_2 }
246+ )
247+
248+ # sign the first device key and upload it
249+ del device_key_1 ["signatures" ]
250+ sign .sign_json (device_key_1 , local_user , signing_key )
251+ yield self .handler .upload_signatures_for_device_keys (
252+ local_user , {local_user : {"abc" : device_key_1 }}
253+ )
254+
255+ # sign the second device key and upload both device keys. The server
256+ # should ignore the first device key since it already has a valid
257+ # signature for it
258+ del device_key_2 ["signatures" ]
259+ sign .sign_json (device_key_2 , local_user , signing_key )
260+ yield self .handler .upload_signatures_for_device_keys (
261+ local_user , {local_user : {"abc" : device_key_1 , "def" : device_key_2 }}
262+ )
263+
264+ device_key_1 ["signatures" ][local_user ]["ed25519:abc" ] = "base64+signature"
265+ device_key_2 ["signatures" ][local_user ]["ed25519:def" ] = "base64+signature"
266+ devices = yield self .handler .query_devices ({"device_keys" : {local_user : []}}, 0 )
267+ del devices ["device_keys" ][local_user ]["abc" ]["unsigned" ]
268+ del devices ["device_keys" ][local_user ]["def" ]["unsigned" ]
269+ self .assertDictEqual (devices ["device_keys" ][local_user ]["abc" ], device_key_1 )
270+ self .assertDictEqual (devices ["device_keys" ][local_user ]["def" ], device_key_2 )
271+
184272 @defer .inlineCallbacks
185273 def test_self_signing_key_doesnt_show_up_as_device (self ):
186274 """signing keys should be hidden when fetching a user's devices"""
0 commit comments