@@ -52,7 +52,7 @@ const ENCRYPTED_EVENT = new MatrixEvent({
5252 origin_server_ts : 1507753886000 ,
5353} ) ;
5454
55- const KEY_BACKUP_DATA = {
55+ const CURVE25519_KEY_BACKUP_DATA = {
5656 first_message_index : 0 ,
5757 forwarded_count : 0 ,
5858 is_verified : false ,
@@ -73,14 +73,41 @@ const KEY_BACKUP_DATA = {
7373 } ,
7474} ;
7575
76- const BACKUP_INFO = {
76+ const AES256_KEY_BACKUP_DATA = {
77+ first_message_index : 0 ,
78+ forwarded_count : 0 ,
79+ is_verified : false ,
80+ session_data : {
81+ iv : 'b3Jqqvm5S9QdmXrzssspLQ' ,
82+ ciphertext : 'GOOASO3E9ThogkG0zMjEduGLM3u9jHZTkS7AvNNbNj3q1znwk4OlaVKXce'
83+ + '7ynofiiYIiS865VlOqrKEEXv96XzRyUpgn68e3WsicwYl96EtjIEh/iY003PG2Qd'
84+ + 'EluT899Ax7PydpUHxEktbWckMppYomUR5q8x1KI1SsOQIiJaIGThmIMPANRCFiK0'
85+ + 'WQj+q+dnhzx4lt9AFqU5bKov8qKnw2qGYP7/+6RmJ0Kpvs8tG6lrcNDEHtFc2r0r'
86+ + 'KKubDypo0Vc8EWSwsAHdKa36ewRavpreOuE8Z9RLfY0QIR1ecXrMqW0CdGFr7H3P'
87+ + 'vcjF8sjwvQAavzxEKT1WMGizSMLeKWo2mgZ5cKnwV5HGUAw596JQvKs9laG2U89K'
88+ + 'YrT0sH30vi62HKzcBLcDkWkUSNYPz7UiZ1MM0L380UA+1ZOXSOmtBA9xxzzbc8Xd'
89+ + 'fRimVgklGdxrxjzuNLYhL2BvVH4oPWonD9j0bvRwE6XkimdbGQA8HB7UmXXjE8WA'
90+ + 'RgaDHkfzoA3g3aeQ' ,
91+ mac : 'uR988UYgGL99jrvLLPX3V1ows+UYbktTmMxPAo2kxnU' ,
92+ } ,
93+ } ;
94+
95+ const CURVE25519_BACKUP_INFO = {
7796 algorithm : "m.megolm_backup.v1.curve25519-aes-sha2" ,
7897 version : 1 ,
7998 auth_data : {
8099 public_key : "hSDwCYkwp1R0i33ctD73Wg2/Og0mOBr066SpjqqbTmo" ,
81100 } ,
82101} ;
83102
103+ const AES256_BACKUP_INFO = {
104+ algorithm : "org.matrix.msc3270.v1.aes-hmac-sha2" ,
105+ version : 1 ,
106+ auth_data : {
107+ // FIXME: add iv and mac
108+ } ,
109+ } ;
110+
84111const keys = { } ;
85112
86113function getCrossSigningKey ( type ) {
@@ -144,7 +171,7 @@ describe("MegolmBackup", function() {
144171 mockCrypto . backupKey . set_recipient_key (
145172 "hSDwCYkwp1R0i33ctD73Wg2/Og0mOBr066SpjqqbTmo" ,
146173 ) ;
147- mockCrypto . backupInfo = BACKUP_INFO ;
174+ mockCrypto . backupInfo = CURVE25519_BACKUP_INFO ;
148175
149176 mockStorage = new MockStorageApi ( ) ;
150177 sessionStore = new WebStorageSessionStore ( mockStorage ) ;
@@ -228,7 +255,7 @@ describe("MegolmBackup", function() {
228255 } ) ;
229256 } ) ;
230257
231- it ( 'sends backups to the server' , function ( ) {
258+ it ( 'sends backups to the server (Curve25519 version) ' , function ( ) {
232259 const groupSession = new Olm . OutboundGroupSession ( ) ;
233260 groupSession . create ( ) ;
234261 const ibGroupSession = new Olm . InboundGroupSession ( ) ;
@@ -306,6 +333,88 @@ describe("MegolmBackup", function() {
306333 } ) ;
307334 } ) ;
308335
336+ it ( 'sends backups to the server (AES-256 version)' , function ( ) {
337+ const groupSession = new Olm . OutboundGroupSession ( ) ;
338+ groupSession . create ( ) ;
339+ const ibGroupSession = new Olm . InboundGroupSession ( ) ;
340+ ibGroupSession . create ( groupSession . session_key ( ) ) ;
341+
342+ const client = makeTestClient ( sessionStore , cryptoStore ) ;
343+
344+ megolmDecryption = new MegolmDecryption ( {
345+ userId : '@user:id' ,
346+ crypto : mockCrypto ,
347+ olmDevice : olmDevice ,
348+ baseApis : client ,
349+ roomId : ROOM_ID ,
350+ } ) ;
351+
352+ megolmDecryption . olmlib = mockOlmLib ;
353+
354+ return client . initCrypto ( )
355+ . then ( ( ) => {
356+ return client . crypto . storeSessionBackupPrivateKey ( new Uint8Array ( 32 ) ) ;
357+ } )
358+ . then ( ( ) => {
359+ return cryptoStore . doTxn (
360+ "readwrite" ,
361+ [ cryptoStore . STORE_SESSION ] ,
362+ ( txn ) => {
363+ cryptoStore . addEndToEndInboundGroupSession (
364+ "F0Q2NmyJNgUVj9DGsb4ZQt3aVxhVcUQhg7+gvW0oyKI" ,
365+ groupSession . session_id ( ) ,
366+ {
367+ forwardingCurve25519KeyChain : undefined ,
368+ keysClaimed : {
369+ ed25519 : "SENDER_ED25519" ,
370+ } ,
371+ room_id : ROOM_ID ,
372+ session : ibGroupSession . pickle ( olmDevice . _pickleKey ) ,
373+ } ,
374+ txn ) ;
375+ } ) ;
376+ } )
377+ . then ( ( ) => {
378+ client . enableKeyBackup ( {
379+ algorithm : "org.matrix.msc3270.v1.aes-hmac-sha2" ,
380+ version : 1 ,
381+ auth_data : {
382+ iv : "PsCAtR7gMc4xBd9YS3A9Ow" ,
383+ mac : "ZSDsTFEZK7QzlauCLMleUcX96GQZZM7UNtk4sripSqQ" ,
384+ } ,
385+ } ) ;
386+ let numCalls = 0 ;
387+ return new Promise ( ( resolve , reject ) => {
388+ client . http . authedRequest = function (
389+ callback , method , path , queryParams , data , opts ,
390+ ) {
391+ ++ numCalls ;
392+ expect ( numCalls ) . toBeLessThanOrEqual ( 1 ) ;
393+ if ( numCalls >= 2 ) {
394+ // exit out of retry loop if there's something wrong
395+ reject ( new Error ( "authedRequest called too many timmes" ) ) ;
396+ return Promise . resolve ( { } ) ;
397+ }
398+ expect ( method ) . toBe ( "PUT" ) ;
399+ expect ( path ) . toBe ( "/room_keys/keys" ) ;
400+ expect ( queryParams . version ) . toBe ( 1 ) ;
401+ expect ( data . rooms [ ROOM_ID ] . sessions ) . toBeDefined ( ) ;
402+ expect ( data . rooms [ ROOM_ID ] . sessions ) . toHaveProperty (
403+ groupSession . session_id ( ) ,
404+ ) ;
405+ resolve ( ) ;
406+ return Promise . resolve ( { } ) ;
407+ } ;
408+ client . crypto . backupManager . backupGroupSession (
409+ "F0Q2NmyJNgUVj9DGsb4ZQt3aVxhVcUQhg7+gvW0oyKI" ,
410+ groupSession . session_id ( ) ,
411+ ) ;
412+ } ) . then ( ( ) => {
413+ expect ( numCalls ) . toBe ( 1 ) ;
414+ } ) ;
415+ } ) ;
416+ } ) ;
417+
309418 it ( 'signs backups with the cross-signing master key' , async function ( ) {
310419 const groupSession = new Olm . OutboundGroupSession ( ) ;
311420 groupSession . create ( ) ;
@@ -512,38 +621,55 @@ describe("MegolmBackup", function() {
512621 client . stopClient ( ) ;
513622 } ) ;
514623
515- it ( 'can restore from backup' , function ( ) {
624+ it ( 'can restore from backup (Curve25519 version)' , function ( ) {
625+ client . http . authedRequest = function ( ) {
626+ return Promise . resolve ( CURVE25519_KEY_BACKUP_DATA ) ;
627+ } ;
628+ return client . restoreKeyBackupWithRecoveryKey (
629+ "EsTc LW2K PGiF wKEA 3As5 g5c4 BXwk qeeJ ZJV8 Q9fu gUMN UE4d" ,
630+ ROOM_ID ,
631+ SESSION_ID ,
632+ CURVE25519_BACKUP_INFO ,
633+ ) . then ( ( ) => {
634+ return megolmDecryption . decryptEvent ( ENCRYPTED_EVENT ) ;
635+ } ) . then ( ( res ) => {
636+ expect ( res . clearEvent . content ) . toEqual ( 'testytest' ) ;
637+ expect ( res . untrusted ) . toBeTruthy ( ) ; // keys from Curve25519 backup are untrusted
638+ } ) ;
639+ } ) ;
640+
641+ it ( 'can restore from backup (AES-256 version)' , function ( ) {
516642 client . http . authedRequest = function ( ) {
517- return Promise . resolve ( KEY_BACKUP_DATA ) ;
643+ return Promise . resolve ( AES256_KEY_BACKUP_DATA ) ;
518644 } ;
519645 return client . restoreKeyBackupWithRecoveryKey (
520646 "EsTc LW2K PGiF wKEA 3As5 g5c4 BXwk qeeJ ZJV8 Q9fu gUMN UE4d" ,
521647 ROOM_ID ,
522648 SESSION_ID ,
523- BACKUP_INFO ,
649+ AES256_BACKUP_INFO ,
524650 ) . then ( ( ) => {
525651 return megolmDecryption . decryptEvent ( ENCRYPTED_EVENT ) ;
526652 } ) . then ( ( res ) => {
527653 expect ( res . clearEvent . content ) . toEqual ( 'testytest' ) ;
528- expect ( res . untrusted ) . toBeTruthy ( ) ; // keys from backup are untrusted
654+ expect ( res . untrusted ) . toBeFalsy ( ) ; // keys from AES backup are trusted
529655 } ) ;
530656 } ) ;
531657
532- it ( 'can restore backup by room' , function ( ) {
658+ it ( 'can restore backup by room (Curve25519 version) ' , function ( ) {
533659 client . http . authedRequest = function ( ) {
534660 return Promise . resolve ( {
535661 rooms : {
536662 [ ROOM_ID ] : {
537663 sessions : {
538- [ SESSION_ID ] : KEY_BACKUP_DATA ,
664+ [ SESSION_ID ] : CURVE25519_KEY_BACKUP_DATA ,
539665 } ,
540666 } ,
541667 } ,
542668 } ) ;
543669 } ;
544670 return client . restoreKeyBackupWithRecoveryKey (
545671 "EsTc LW2K PGiF wKEA 3As5 g5c4 BXwk qeeJ ZJV8 Q9fu gUMN UE4d" ,
546- null , null , BACKUP_INFO ,
672+ null , null , CURVE25519_BACKUP_INFO ,
547673 ) . then ( ( ) => {
548674 return megolmDecryption . decryptEvent ( ENCRYPTED_EVENT ) ;
549675 } ) . then ( ( res ) => {
@@ -562,14 +688,14 @@ describe("MegolmBackup", function() {
562688 const cachedNull = await client . crypto . getSessionBackupPrivateKey ( ) ;
563689 expect ( cachedNull ) . toBeNull ( ) ;
564690 client . http . authedRequest = function ( ) {
565- return Promise . resolve ( KEY_BACKUP_DATA ) ;
691+ return Promise . resolve ( CURVE25519_KEY_BACKUP_DATA ) ;
566692 } ;
567693 await new Promise ( ( resolve ) => {
568694 client . restoreKeyBackupWithRecoveryKey (
569695 "EsTc LW2K PGiF wKEA 3As5 g5c4 BXwk qeeJ ZJV8 Q9fu gUMN UE4d" ,
570696 ROOM_ID ,
571697 SESSION_ID ,
572- BACKUP_INFO ,
698+ CURVE25519_BACKUP_INFO ,
573699 { cacheCompleteCallback : resolve } ,
574700 ) ;
575701 } ) ;
@@ -578,11 +704,11 @@ describe("MegolmBackup", function() {
578704 } ) ;
579705
580706 it ( "fails if an known algorithm is used" , async function ( ) {
581- const BAD_BACKUP_INFO = Object . assign ( { } , BACKUP_INFO , {
707+ const BAD_BACKUP_INFO = Object . assign ( { } , CURVE25519_BACKUP_INFO , {
582708 algorithm : "this.algorithm.does.not.exist" ,
583709 } ) ;
584710 client . http . authedRequest = function ( ) {
585- return Promise . resolve ( KEY_BACKUP_DATA ) ;
711+ return Promise . resolve ( CURVE25519_KEY_BACKUP_DATA ) ;
586712 } ;
587713
588714 await expect ( client . restoreKeyBackupWithRecoveryKey (
0 commit comments