test_e2e_keys.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. # Copyright 2016 OpenMarket Ltd
  2. # Copyright 2019 New Vector Ltd
  3. # Copyright 2019 The Matrix.org Foundation C.I.C.
  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. from unittest import mock
  17. from signedjson import key as key, sign as sign
  18. from synapse.api.constants import RoomEncryptionAlgorithms
  19. from synapse.api.errors import Codes, SynapseError
  20. from tests import unittest
  21. class E2eKeysHandlerTestCase(unittest.HomeserverTestCase):
  22. def make_homeserver(self, reactor, clock):
  23. return self.setup_test_homeserver(federation_client=mock.Mock())
  24. def prepare(self, reactor, clock, hs):
  25. self.handler = hs.get_e2e_keys_handler()
  26. self.store = self.hs.get_datastore()
  27. def test_query_local_devices_no_devices(self):
  28. """If the user has no devices, we expect an empty list."""
  29. local_user = "@boris:" + self.hs.hostname
  30. res = self.get_success(self.handler.query_local_devices({local_user: None}))
  31. self.assertDictEqual(res, {local_user: {}})
  32. def test_reupload_one_time_keys(self):
  33. """we should be able to re-upload the same keys"""
  34. local_user = "@boris:" + self.hs.hostname
  35. device_id = "xyz"
  36. keys = {
  37. "alg1:k1": "key1",
  38. "alg2:k2": {"key": "key2", "signatures": {"k1": "sig1"}},
  39. "alg2:k3": {"key": "key3"},
  40. }
  41. res = self.get_success(
  42. self.handler.upload_keys_for_user(
  43. local_user, device_id, {"one_time_keys": keys}
  44. )
  45. )
  46. self.assertDictEqual(res, {"one_time_key_counts": {"alg1": 1, "alg2": 2}})
  47. # we should be able to change the signature without a problem
  48. keys["alg2:k2"]["signatures"]["k1"] = "sig2"
  49. res = self.get_success(
  50. self.handler.upload_keys_for_user(
  51. local_user, device_id, {"one_time_keys": keys}
  52. )
  53. )
  54. self.assertDictEqual(res, {"one_time_key_counts": {"alg1": 1, "alg2": 2}})
  55. def test_change_one_time_keys(self):
  56. """attempts to change one-time-keys should be rejected"""
  57. local_user = "@boris:" + self.hs.hostname
  58. device_id = "xyz"
  59. keys = {
  60. "alg1:k1": "key1",
  61. "alg2:k2": {"key": "key2", "signatures": {"k1": "sig1"}},
  62. "alg2:k3": {"key": "key3"},
  63. }
  64. res = self.get_success(
  65. self.handler.upload_keys_for_user(
  66. local_user, device_id, {"one_time_keys": keys}
  67. )
  68. )
  69. self.assertDictEqual(res, {"one_time_key_counts": {"alg1": 1, "alg2": 2}})
  70. # Error when changing string key
  71. self.get_failure(
  72. self.handler.upload_keys_for_user(
  73. local_user, device_id, {"one_time_keys": {"alg1:k1": "key2"}}
  74. ),
  75. SynapseError,
  76. )
  77. # Error when replacing dict key with strin
  78. self.get_failure(
  79. self.handler.upload_keys_for_user(
  80. local_user, device_id, {"one_time_keys": {"alg2:k3": "key2"}}
  81. ),
  82. SynapseError,
  83. )
  84. # Error when replacing string key with dict
  85. self.get_failure(
  86. self.handler.upload_keys_for_user(
  87. local_user,
  88. device_id,
  89. {"one_time_keys": {"alg1:k1": {"key": "key"}}},
  90. ),
  91. SynapseError,
  92. )
  93. # Error when replacing dict key
  94. self.get_failure(
  95. self.handler.upload_keys_for_user(
  96. local_user,
  97. device_id,
  98. {
  99. "one_time_keys": {
  100. "alg2:k2": {"key": "key3", "signatures": {"k1": "sig1"}}
  101. }
  102. },
  103. ),
  104. SynapseError,
  105. )
  106. def test_claim_one_time_key(self):
  107. local_user = "@boris:" + self.hs.hostname
  108. device_id = "xyz"
  109. keys = {"alg1:k1": "key1"}
  110. res = self.get_success(
  111. self.handler.upload_keys_for_user(
  112. local_user, device_id, {"one_time_keys": keys}
  113. )
  114. )
  115. self.assertDictEqual(res, {"one_time_key_counts": {"alg1": 1}})
  116. res2 = self.get_success(
  117. self.handler.claim_one_time_keys(
  118. {"one_time_keys": {local_user: {device_id: "alg1"}}}, timeout=None
  119. )
  120. )
  121. self.assertEqual(
  122. res2,
  123. {
  124. "failures": {},
  125. "one_time_keys": {local_user: {device_id: {"alg1:k1": "key1"}}},
  126. },
  127. )
  128. def test_fallback_key(self):
  129. local_user = "@boris:" + self.hs.hostname
  130. device_id = "xyz"
  131. fallback_key = {"alg1:k1": "key1"}
  132. otk = {"alg1:k2": "key2"}
  133. # we shouldn't have any unused fallback keys yet
  134. res = self.get_success(
  135. self.store.get_e2e_unused_fallback_key_types(local_user, device_id)
  136. )
  137. self.assertEqual(res, [])
  138. self.get_success(
  139. self.handler.upload_keys_for_user(
  140. local_user,
  141. device_id,
  142. {"org.matrix.msc2732.fallback_keys": fallback_key},
  143. )
  144. )
  145. # we should now have an unused alg1 key
  146. res = self.get_success(
  147. self.store.get_e2e_unused_fallback_key_types(local_user, device_id)
  148. )
  149. self.assertEqual(res, ["alg1"])
  150. # claiming an OTK when no OTKs are available should return the fallback
  151. # key
  152. res = self.get_success(
  153. self.handler.claim_one_time_keys(
  154. {"one_time_keys": {local_user: {device_id: "alg1"}}}, timeout=None
  155. )
  156. )
  157. self.assertEqual(
  158. res,
  159. {"failures": {}, "one_time_keys": {local_user: {device_id: fallback_key}}},
  160. )
  161. # we shouldn't have any unused fallback keys again
  162. res = self.get_success(
  163. self.store.get_e2e_unused_fallback_key_types(local_user, device_id)
  164. )
  165. self.assertEqual(res, [])
  166. # claiming an OTK again should return the same fallback key
  167. res = self.get_success(
  168. self.handler.claim_one_time_keys(
  169. {"one_time_keys": {local_user: {device_id: "alg1"}}}, timeout=None
  170. )
  171. )
  172. self.assertEqual(
  173. res,
  174. {"failures": {}, "one_time_keys": {local_user: {device_id: fallback_key}}},
  175. )
  176. # if the user uploads a one-time key, the next claim should fetch the
  177. # one-time key, and then go back to the fallback
  178. self.get_success(
  179. self.handler.upload_keys_for_user(
  180. local_user, device_id, {"one_time_keys": otk}
  181. )
  182. )
  183. res = self.get_success(
  184. self.handler.claim_one_time_keys(
  185. {"one_time_keys": {local_user: {device_id: "alg1"}}}, timeout=None
  186. )
  187. )
  188. self.assertEqual(
  189. res,
  190. {"failures": {}, "one_time_keys": {local_user: {device_id: otk}}},
  191. )
  192. res = self.get_success(
  193. self.handler.claim_one_time_keys(
  194. {"one_time_keys": {local_user: {device_id: "alg1"}}}, timeout=None
  195. )
  196. )
  197. self.assertEqual(
  198. res,
  199. {"failures": {}, "one_time_keys": {local_user: {device_id: fallback_key}}},
  200. )
  201. def test_replace_master_key(self):
  202. """uploading a new signing key should make the old signing key unavailable"""
  203. local_user = "@boris:" + self.hs.hostname
  204. keys1 = {
  205. "master_key": {
  206. # private key: 2lonYOM6xYKdEsO+6KrC766xBcHnYnim1x/4LFGF8B0
  207. "user_id": local_user,
  208. "usage": ["master"],
  209. "keys": {
  210. "ed25519:nqOvzeuGWT/sRx3h7+MHoInYj3Uk2LD/unI9kDYcHwk": "nqOvzeuGWT/sRx3h7+MHoInYj3Uk2LD/unI9kDYcHwk"
  211. },
  212. }
  213. }
  214. self.get_success(self.handler.upload_signing_keys_for_user(local_user, keys1))
  215. keys2 = {
  216. "master_key": {
  217. # private key: 4TL4AjRYwDVwD3pqQzcor+ez/euOB1/q78aTJ+czDNs
  218. "user_id": local_user,
  219. "usage": ["master"],
  220. "keys": {
  221. "ed25519:Hq6gL+utB4ET+UvD5ci0kgAwsX6qP/zvf8v6OInU5iw": "Hq6gL+utB4ET+UvD5ci0kgAwsX6qP/zvf8v6OInU5iw"
  222. },
  223. }
  224. }
  225. self.get_success(self.handler.upload_signing_keys_for_user(local_user, keys2))
  226. devices = self.get_success(
  227. self.handler.query_devices({"device_keys": {local_user: []}}, 0, local_user)
  228. )
  229. self.assertDictEqual(devices["master_keys"], {local_user: keys2["master_key"]})
  230. def test_reupload_signatures(self):
  231. """re-uploading a signature should not fail"""
  232. local_user = "@boris:" + self.hs.hostname
  233. keys1 = {
  234. "master_key": {
  235. # private key: HvQBbU+hc2Zr+JP1sE0XwBe1pfZZEYtJNPJLZJtS+F8
  236. "user_id": local_user,
  237. "usage": ["master"],
  238. "keys": {
  239. "ed25519:EmkqvokUn8p+vQAGZitOk4PWjp7Ukp3txV2TbMPEiBQ": "EmkqvokUn8p+vQAGZitOk4PWjp7Ukp3txV2TbMPEiBQ"
  240. },
  241. },
  242. "self_signing_key": {
  243. # private key: 2lonYOM6xYKdEsO+6KrC766xBcHnYnim1x/4LFGF8B0
  244. "user_id": local_user,
  245. "usage": ["self_signing"],
  246. "keys": {
  247. "ed25519:nqOvzeuGWT/sRx3h7+MHoInYj3Uk2LD/unI9kDYcHwk": "nqOvzeuGWT/sRx3h7+MHoInYj3Uk2LD/unI9kDYcHwk"
  248. },
  249. },
  250. }
  251. master_signing_key = key.decode_signing_key_base64(
  252. "ed25519",
  253. "EmkqvokUn8p+vQAGZitOk4PWjp7Ukp3txV2TbMPEiBQ",
  254. "HvQBbU+hc2Zr+JP1sE0XwBe1pfZZEYtJNPJLZJtS+F8",
  255. )
  256. sign.sign_json(keys1["self_signing_key"], local_user, master_signing_key)
  257. signing_key = key.decode_signing_key_base64(
  258. "ed25519",
  259. "nqOvzeuGWT/sRx3h7+MHoInYj3Uk2LD/unI9kDYcHwk",
  260. "2lonYOM6xYKdEsO+6KrC766xBcHnYnim1x/4LFGF8B0",
  261. )
  262. self.get_success(self.handler.upload_signing_keys_for_user(local_user, keys1))
  263. # upload two device keys, which will be signed later by the self-signing key
  264. device_key_1 = {
  265. "user_id": local_user,
  266. "device_id": "abc",
  267. "algorithms": [
  268. "m.olm.curve25519-aes-sha2",
  269. RoomEncryptionAlgorithms.MEGOLM_V1_AES_SHA2,
  270. ],
  271. "keys": {
  272. "ed25519:abc": "base64+ed25519+key",
  273. "curve25519:abc": "base64+curve25519+key",
  274. },
  275. "signatures": {local_user: {"ed25519:abc": "base64+signature"}},
  276. }
  277. device_key_2 = {
  278. "user_id": local_user,
  279. "device_id": "def",
  280. "algorithms": [
  281. "m.olm.curve25519-aes-sha2",
  282. RoomEncryptionAlgorithms.MEGOLM_V1_AES_SHA2,
  283. ],
  284. "keys": {
  285. "ed25519:def": "base64+ed25519+key",
  286. "curve25519:def": "base64+curve25519+key",
  287. },
  288. "signatures": {local_user: {"ed25519:def": "base64+signature"}},
  289. }
  290. self.get_success(
  291. self.handler.upload_keys_for_user(
  292. local_user, "abc", {"device_keys": device_key_1}
  293. )
  294. )
  295. self.get_success(
  296. self.handler.upload_keys_for_user(
  297. local_user, "def", {"device_keys": device_key_2}
  298. )
  299. )
  300. # sign the first device key and upload it
  301. del device_key_1["signatures"]
  302. sign.sign_json(device_key_1, local_user, signing_key)
  303. self.get_success(
  304. self.handler.upload_signatures_for_device_keys(
  305. local_user, {local_user: {"abc": device_key_1}}
  306. )
  307. )
  308. # sign the second device key and upload both device keys. The server
  309. # should ignore the first device key since it already has a valid
  310. # signature for it
  311. del device_key_2["signatures"]
  312. sign.sign_json(device_key_2, local_user, signing_key)
  313. self.get_success(
  314. self.handler.upload_signatures_for_device_keys(
  315. local_user, {local_user: {"abc": device_key_1, "def": device_key_2}}
  316. )
  317. )
  318. device_key_1["signatures"][local_user]["ed25519:abc"] = "base64+signature"
  319. device_key_2["signatures"][local_user]["ed25519:def"] = "base64+signature"
  320. devices = self.get_success(
  321. self.handler.query_devices({"device_keys": {local_user: []}}, 0, local_user)
  322. )
  323. del devices["device_keys"][local_user]["abc"]["unsigned"]
  324. del devices["device_keys"][local_user]["def"]["unsigned"]
  325. self.assertDictEqual(devices["device_keys"][local_user]["abc"], device_key_1)
  326. self.assertDictEqual(devices["device_keys"][local_user]["def"], device_key_2)
  327. def test_self_signing_key_doesnt_show_up_as_device(self):
  328. """signing keys should be hidden when fetching a user's devices"""
  329. local_user = "@boris:" + self.hs.hostname
  330. keys1 = {
  331. "master_key": {
  332. # private key: 2lonYOM6xYKdEsO+6KrC766xBcHnYnim1x/4LFGF8B0
  333. "user_id": local_user,
  334. "usage": ["master"],
  335. "keys": {
  336. "ed25519:nqOvzeuGWT/sRx3h7+MHoInYj3Uk2LD/unI9kDYcHwk": "nqOvzeuGWT/sRx3h7+MHoInYj3Uk2LD/unI9kDYcHwk"
  337. },
  338. }
  339. }
  340. self.get_success(self.handler.upload_signing_keys_for_user(local_user, keys1))
  341. e = self.get_failure(
  342. self.hs.get_device_handler().check_device_registered(
  343. user_id=local_user,
  344. device_id="nqOvzeuGWT/sRx3h7+MHoInYj3Uk2LD/unI9kDYcHwk",
  345. initial_device_display_name="new display name",
  346. ),
  347. SynapseError,
  348. )
  349. res = e.value.code
  350. self.assertEqual(res, 400)
  351. res = self.get_success(self.handler.query_local_devices({local_user: None}))
  352. self.assertDictEqual(res, {local_user: {}})
  353. def test_upload_signatures(self):
  354. """should check signatures that are uploaded"""
  355. # set up a user with cross-signing keys and a device. This user will
  356. # try uploading signatures
  357. local_user = "@boris:" + self.hs.hostname
  358. device_id = "xyz"
  359. # private key: OMkooTr76ega06xNvXIGPbgvvxAOzmQncN8VObS7aBA
  360. device_pubkey = "NnHhnqiMFQkq969szYkooLaBAXW244ZOxgukCvm2ZeY"
  361. device_key = {
  362. "user_id": local_user,
  363. "device_id": device_id,
  364. "algorithms": [
  365. "m.olm.curve25519-aes-sha2",
  366. RoomEncryptionAlgorithms.MEGOLM_V1_AES_SHA2,
  367. ],
  368. "keys": {"curve25519:xyz": "curve25519+key", "ed25519:xyz": device_pubkey},
  369. "signatures": {local_user: {"ed25519:xyz": "something"}},
  370. }
  371. device_signing_key = key.decode_signing_key_base64(
  372. "ed25519", "xyz", "OMkooTr76ega06xNvXIGPbgvvxAOzmQncN8VObS7aBA"
  373. )
  374. self.get_success(
  375. self.handler.upload_keys_for_user(
  376. local_user, device_id, {"device_keys": device_key}
  377. )
  378. )
  379. # private key: 2lonYOM6xYKdEsO+6KrC766xBcHnYnim1x/4LFGF8B0
  380. master_pubkey = "nqOvzeuGWT/sRx3h7+MHoInYj3Uk2LD/unI9kDYcHwk"
  381. master_key = {
  382. "user_id": local_user,
  383. "usage": ["master"],
  384. "keys": {"ed25519:" + master_pubkey: master_pubkey},
  385. }
  386. master_signing_key = key.decode_signing_key_base64(
  387. "ed25519", master_pubkey, "2lonYOM6xYKdEsO+6KrC766xBcHnYnim1x/4LFGF8B0"
  388. )
  389. usersigning_pubkey = "Hq6gL+utB4ET+UvD5ci0kgAwsX6qP/zvf8v6OInU5iw"
  390. usersigning_key = {
  391. # private key: 4TL4AjRYwDVwD3pqQzcor+ez/euOB1/q78aTJ+czDNs
  392. "user_id": local_user,
  393. "usage": ["user_signing"],
  394. "keys": {"ed25519:" + usersigning_pubkey: usersigning_pubkey},
  395. }
  396. usersigning_signing_key = key.decode_signing_key_base64(
  397. "ed25519", usersigning_pubkey, "4TL4AjRYwDVwD3pqQzcor+ez/euOB1/q78aTJ+czDNs"
  398. )
  399. sign.sign_json(usersigning_key, local_user, master_signing_key)
  400. # private key: HvQBbU+hc2Zr+JP1sE0XwBe1pfZZEYtJNPJLZJtS+F8
  401. selfsigning_pubkey = "EmkqvokUn8p+vQAGZitOk4PWjp7Ukp3txV2TbMPEiBQ"
  402. selfsigning_key = {
  403. "user_id": local_user,
  404. "usage": ["self_signing"],
  405. "keys": {"ed25519:" + selfsigning_pubkey: selfsigning_pubkey},
  406. }
  407. selfsigning_signing_key = key.decode_signing_key_base64(
  408. "ed25519", selfsigning_pubkey, "HvQBbU+hc2Zr+JP1sE0XwBe1pfZZEYtJNPJLZJtS+F8"
  409. )
  410. sign.sign_json(selfsigning_key, local_user, master_signing_key)
  411. cross_signing_keys = {
  412. "master_key": master_key,
  413. "user_signing_key": usersigning_key,
  414. "self_signing_key": selfsigning_key,
  415. }
  416. self.get_success(
  417. self.handler.upload_signing_keys_for_user(local_user, cross_signing_keys)
  418. )
  419. # set up another user with a master key. This user will be signed by
  420. # the first user
  421. other_user = "@otherboris:" + self.hs.hostname
  422. other_master_pubkey = "fHZ3NPiKxoLQm5OoZbKa99SYxprOjNs4TwJUKP+twCM"
  423. other_master_key = {
  424. # private key: oyw2ZUx0O4GifbfFYM0nQvj9CL0b8B7cyN4FprtK8OI
  425. "user_id": other_user,
  426. "usage": ["master"],
  427. "keys": {"ed25519:" + other_master_pubkey: other_master_pubkey},
  428. }
  429. self.get_success(
  430. self.handler.upload_signing_keys_for_user(
  431. other_user, {"master_key": other_master_key}
  432. )
  433. )
  434. # test various signature failures (see below)
  435. ret = self.get_success(
  436. self.handler.upload_signatures_for_device_keys(
  437. local_user,
  438. {
  439. local_user: {
  440. # fails because the signature is invalid
  441. # should fail with INVALID_SIGNATURE
  442. device_id: {
  443. "user_id": local_user,
  444. "device_id": device_id,
  445. "algorithms": [
  446. "m.olm.curve25519-aes-sha2",
  447. RoomEncryptionAlgorithms.MEGOLM_V1_AES_SHA2,
  448. ],
  449. "keys": {
  450. "curve25519:xyz": "curve25519+key",
  451. # private key: OMkooTr76ega06xNvXIGPbgvvxAOzmQncN8VObS7aBA
  452. "ed25519:xyz": device_pubkey,
  453. },
  454. "signatures": {
  455. local_user: {
  456. "ed25519:" + selfsigning_pubkey: "something"
  457. }
  458. },
  459. },
  460. # fails because device is unknown
  461. # should fail with NOT_FOUND
  462. "unknown": {
  463. "user_id": local_user,
  464. "device_id": "unknown",
  465. "signatures": {
  466. local_user: {
  467. "ed25519:" + selfsigning_pubkey: "something"
  468. }
  469. },
  470. },
  471. # fails because the signature is invalid
  472. # should fail with INVALID_SIGNATURE
  473. master_pubkey: {
  474. "user_id": local_user,
  475. "usage": ["master"],
  476. "keys": {"ed25519:" + master_pubkey: master_pubkey},
  477. "signatures": {
  478. local_user: {"ed25519:" + device_pubkey: "something"}
  479. },
  480. },
  481. },
  482. other_user: {
  483. # fails because the device is not the user's master-signing key
  484. # should fail with NOT_FOUND
  485. "unknown": {
  486. "user_id": other_user,
  487. "device_id": "unknown",
  488. "signatures": {
  489. local_user: {
  490. "ed25519:" + usersigning_pubkey: "something"
  491. }
  492. },
  493. },
  494. other_master_pubkey: {
  495. # fails because the key doesn't match what the server has
  496. # should fail with UNKNOWN
  497. "user_id": other_user,
  498. "usage": ["master"],
  499. "keys": {
  500. "ed25519:" + other_master_pubkey: other_master_pubkey
  501. },
  502. "something": "random",
  503. "signatures": {
  504. local_user: {
  505. "ed25519:" + usersigning_pubkey: "something"
  506. }
  507. },
  508. },
  509. },
  510. },
  511. )
  512. )
  513. user_failures = ret["failures"][local_user]
  514. self.assertEqual(user_failures[device_id]["errcode"], Codes.INVALID_SIGNATURE)
  515. self.assertEqual(
  516. user_failures[master_pubkey]["errcode"], Codes.INVALID_SIGNATURE
  517. )
  518. self.assertEqual(user_failures["unknown"]["errcode"], Codes.NOT_FOUND)
  519. other_user_failures = ret["failures"][other_user]
  520. self.assertEqual(other_user_failures["unknown"]["errcode"], Codes.NOT_FOUND)
  521. self.assertEqual(
  522. other_user_failures[other_master_pubkey]["errcode"], Codes.UNKNOWN
  523. )
  524. # test successful signatures
  525. del device_key["signatures"]
  526. sign.sign_json(device_key, local_user, selfsigning_signing_key)
  527. sign.sign_json(master_key, local_user, device_signing_key)
  528. sign.sign_json(other_master_key, local_user, usersigning_signing_key)
  529. ret = self.get_success(
  530. self.handler.upload_signatures_for_device_keys(
  531. local_user,
  532. {
  533. local_user: {device_id: device_key, master_pubkey: master_key},
  534. other_user: {other_master_pubkey: other_master_key},
  535. },
  536. )
  537. )
  538. self.assertEqual(ret["failures"], {})
  539. # fetch the signed keys/devices and make sure that the signatures are there
  540. ret = self.get_success(
  541. self.handler.query_devices(
  542. {"device_keys": {local_user: [], other_user: []}}, 0, local_user
  543. )
  544. )
  545. self.assertEqual(
  546. ret["device_keys"][local_user]["xyz"]["signatures"][local_user][
  547. "ed25519:" + selfsigning_pubkey
  548. ],
  549. device_key["signatures"][local_user]["ed25519:" + selfsigning_pubkey],
  550. )
  551. self.assertEqual(
  552. ret["master_keys"][local_user]["signatures"][local_user][
  553. "ed25519:" + device_id
  554. ],
  555. master_key["signatures"][local_user]["ed25519:" + device_id],
  556. )
  557. self.assertEqual(
  558. ret["master_keys"][other_user]["signatures"][local_user][
  559. "ed25519:" + usersigning_pubkey
  560. ],
  561. other_master_key["signatures"][local_user]["ed25519:" + usersigning_pubkey],
  562. )