@@ -5,72 +5,7 @@ const protobuf = require('./protobuf.js')
5
5
//const _sodium = require('libsodium-wrappers')
6
6
const _sodium = require ( 'libsodium-wrappers-sumo' ) // maybe put in session-client?
7
7
//const crypto = require('crypto')
8
-
9
- // move to a binary utility lib
10
- const concatUInt8Array = ( ...args ) => {
11
- const totalLength = args . reduce ( ( acc , current ) => acc + current . length , 0 )
12
-
13
- const concatted = new Uint8Array ( totalLength )
14
- let currentIndex = 0
15
- args . forEach ( arr => {
16
- concatted . set ( arr , currentIndex )
17
- currentIndex += arr . length
18
- } )
19
-
20
- return concatted
21
- }
22
-
23
- /**
24
- * Take a string value with the given encoding and converts it to an `ArrayBuffer`.
25
- * @param value The string value.
26
- * @param encoding The encoding of the string value.
27
- */
28
- function encode ( value , encoding ) {
29
- //return ByteBuffer.wrap(value, encoding).toArrayBuffer();
30
- const buf = Buffer . from ( value , encoding )
31
- const ab = new ArrayBuffer ( buf . length )
32
- const view = new Uint8Array ( ab )
33
- for ( let i = 0 ; i < buf . length ; ++ i ) {
34
- view [ i ] = buf [ i ]
35
- }
36
- return ab
37
- }
38
-
39
- /**
40
- * Take a buffer and convert it to a string with the given encoding.
41
- * @param buffer The buffer.
42
- * @param stringEncoding The encoding of the converted string value.
43
- */
44
- function decode ( buffer , stringEncoding ) {
45
- const buf = Buffer . from ( buffer . buffer , buffer . byteOffset , buffer . byteLength )
46
- return buf . toString ( stringEncoding )
47
- // [] or Uint8Array
48
- //console.log('typeof', typeof(buffer), buffer)
49
- //return ByteBuffer.wrap(buffer).toString(stringEncoding);
50
- }
51
-
52
- const fromUInt8ArrayToBase64 = d => decode ( d , 'base64' )
53
-
54
- function fromBase64ToUint8Array ( base64Str ) {
55
- const buf = Buffer . from ( base64Str , 'base64' )
56
- return new Uint8Array ( buf . buffer )
57
- }
58
-
59
- const stringToArrayBuffer = str => {
60
- if ( typeof str !== 'string' ) {
61
- throw new TypeError ( "'string' must be a string" )
62
- }
63
-
64
- return encode ( str , 'binary' )
65
- }
66
-
67
- const stringToUint8Array = str => {
68
- if ( ! str ) {
69
- return new Uint8Array ( )
70
- }
71
-
72
- return new Uint8Array ( stringToArrayBuffer ( str ) )
73
- }
8
+ const binary = require ( './lib.binary.js' )
74
9
75
10
// OnionSending in https://github.com/oxen-io/session-desktop/blob/0794edeb69aac582187da35771dc29ae3e68279c/ts/session/onions/onionSend.ts#L36
76
11
// NOTE some endpoints require decoded strings
@@ -94,7 +29,7 @@ async function getOurOGHeaders(serverPubKeyHex, endpoint, method, blinded, body,
94
29
const timestamp = Math . floor ( Date . now ( ) / 1000 )
95
30
//const nonce = new Uint8Array(16)
96
31
const nonce = await sodium . randombytes_buf ( 16 )
97
- const srvU8A = loki_crypto . hexStringToUint8Array ( serverPubKeyHex )
32
+ const srvU8A = binary . hexStringToUint8Array ( serverPubKeyHex )
98
33
99
34
let pubkey , ka , kA
100
35
// https://github.com/oxen-io/session-desktop/blob/0794edeb69aac582187da35771dc29ae3e68279c/ts/session/types/PubKey.ts#L5
@@ -116,7 +51,7 @@ async function getOurOGHeaders(serverPubKeyHex, endpoint, method, blinded, body,
116
51
// requires front /
117
52
//console.log('endpoint', endpoint)
118
53
const rawPath = endpointRequiresDecoding ( endpoint ) // this gets a string of the path with potentially emojis in it
119
- const encodedPath = new Uint8Array ( encode ( rawPath , 'utf8' ) ) // this gets the binary content of that utf8 string
54
+ const encodedPath = new Uint8Array ( binary . encode ( rawPath , 'utf8' ) ) // this gets the binary content of that utf8 string
120
55
121
56
//const srvPubKeyBuf = Buffer.from(serverPubKeyHex, 16)
122
57
//console.log('srvPubKeyBuf', srvPubKeyBuf)
@@ -130,8 +65,8 @@ async function getOurOGHeaders(serverPubKeyHex, endpoint, method, blinded, body,
130
65
}
131
66
*/
132
67
//console.debug('serverPubKeyHex', serverPubKeyHex, 'timestamp', timestamp, 'method', method, 'path', endpoint, 'body', body)
133
- const tsU8a = stringToUint8Array ( timestamp . toString ( ) )
134
- const methU8a = stringToUint8Array ( method )
68
+ const tsU8a = binary . stringToUint8Array ( timestamp . toString ( ) )
69
+ const methU8a = binary . stringToUint8Array ( method )
135
70
if ( 0 ) {
136
71
console . log ( 'srvU8A' , srvU8A )
137
72
console . log ( 'nonce' , nonce )
@@ -140,7 +75,7 @@ async function getOurOGHeaders(serverPubKeyHex, endpoint, method, blinded, body,
140
75
console . log ( 'encodedPath' , encodedPath )
141
76
}
142
77
143
- let toSign = concatUInt8Array (
78
+ let toSign = binary . concatUInt8Array (
144
79
srvU8A ,
145
80
nonce ,
146
81
tsU8a ,
@@ -150,16 +85,16 @@ async function getOurOGHeaders(serverPubKeyHex, endpoint, method, blinded, body,
150
85
151
86
if ( body ) {
152
87
// body hash to signature
153
- toSign = concatUInt8Array ( toSign , sodium . crypto_generichash ( 64 , body ) )
88
+ toSign = binary . concatUInt8Array ( toSign , sodium . crypto_generichash ( 64 , body ) )
154
89
}
155
90
156
91
const signature = await loki_crypto . getSogsSignature ( blinded , ka , kA , signingKeys , toSign )
157
92
158
93
return {
159
94
'X-SOGS-Pubkey' : pubkey , // user pubkey
160
95
'X-SOGS-Timestamp' : '' + timestamp ,
161
- 'X-SOGS-Nonce' : fromUInt8ArrayToBase64 ( nonce ) ,
162
- 'X-SOGS-Signature' : fromUInt8ArrayToBase64 ( signature ) ,
96
+ 'X-SOGS-Nonce' : binary . fromUInt8ArrayToBase64 ( nonce ) ,
97
+ 'X-SOGS-Signature' : binary . fromUInt8ArrayToBase64 ( signature ) ,
163
98
} ;
164
99
}
165
100
@@ -191,47 +126,18 @@ async function sogs_rpcv3(method, endpoint, querystring, body, baseUrl, serverPu
191
126
return result
192
127
}
193
128
194
- /*
195
- async function getToken(baseUrl, room, serverPubKeyHex, privKey, pubkeyHex) {
196
- const result = await lib.lsrpc(baseUrl, 'public_key=' + pubkeyHex, serverPubKeyHex,
197
- 'auth_token_challenge', 'GET', '', { Room: room })
198
- //console.log('result', result)
199
- if (!result || !result.challenge || !result.challenge.ciphertext || !result.challenge.ephemeral_public_key) {
200
- console.error('open_group_v3::getToken - result', typeof (result), result)
201
- return
202
- }
203
- // decode everything into buffer format
204
- const ephermalPubBuf = Buffer.from(result.challenge.ephemeral_public_key, 'base64')
205
- const cipherTextBuf = Buffer.from(result.challenge.ciphertext, 'base64')
206
-
207
- const symmetricKey = loki_crypto.makeOnionSymKey(privKey, ephermalPubBuf)
208
- const tokenBuf = loki_crypto.decryptGCM(symmetricKey, cipherTextBuf)
209
-
210
- const tokenHex = tokenBuf.toString('hex') // fix up type
211
-
212
- const pkJSON = JSON.stringify({ public_key: pubkeyHex })
213
- try {
214
- const activateRes = await lib.lsrpc(baseUrl, '', serverPubKeyHex,
215
- 'claim_auth_token', 'POST', pkJSON, { Room: room, Authorization: tokenHex })
216
- //
217
- if (activateRes.status_code !== 200) {
218
- console.error('open_group_v3::getToken - claim_auth_token failure', activateRes)
219
- return
220
- }
221
- //console.log('activated', tokenHex)
222
- return tokenHex
223
- } catch (e) {
224
- console.error('open_group_v3::getToken - exception', e)
225
- }
226
- }
227
- */
228
-
229
129
// for multiple keypairs, servers and rooms
230
130
class SessionOpenGroupV3Manager {
231
131
constructor ( options = { } ) {
232
132
this . servers = { }
233
133
}
234
134
135
+ updateProfile ( keypair , displayName , profileInfo ) {
136
+ for ( const url in this . servers ) {
137
+ this . servers [ url ] . updateProfile ( keypair , displayName , profileInfo )
138
+ }
139
+ }
140
+
235
141
joinServer ( baseURL , serverPubkeyHex , options ) {
236
142
if ( this . servers [ baseURL ] ) {
237
143
console . log ( 'SessionOpenGroupV3Manager::joinServer - already joined' , baseURL )
@@ -285,6 +191,17 @@ class SessionOpenGroupV3Server {
285
191
return keypair . publicKeyHex + '_' + room
286
192
}
287
193
194
+ updateProfile ( keypair , displayName , profileInfo ) {
195
+ // search rooms for rooms with this keypair
196
+ for ( const kp_name in this . rooms ) {
197
+ const parts = kp_name . split ( '_' , 2 )
198
+ const pkHex = parts [ 0 ]
199
+ if ( pkHex === keypair . publicKeyHex ) {
200
+ this . rooms [ kp_name ] . updateProfile ( displayName , profileInfo )
201
+ }
202
+ }
203
+ }
204
+
288
205
// header support?
289
206
// keypair, endpoint, body, querystring, method
290
207
async rpc ( method , endpoint , querystring , body , keypair ) {
@@ -721,6 +638,8 @@ class SessionOpenGroupV3Room {
721
638
// active_users, active_users_cutoff, admins, created, image_id, info_updates,
722
639
// message_sequence, moderators, name, read, token, upload, write
723
640
this . roomData = { }
641
+ this . displayName = undefined
642
+ this . profileInfo = undefined
724
643
}
725
644
726
645
async ensureToken ( ) {
@@ -742,7 +661,7 @@ class SessionOpenGroupV3Room {
742
661
}
743
662
if ( this . server . blinded ) {
744
663
// srvkey + ourkey => blindedkey
745
- const srvU8A = loki_crypto . hexStringToUint8Array ( this . server . serverPubkeyHex )
664
+ const srvU8A = binary . hexStringToUint8Array ( this . server . serverPubkeyHex )
746
665
const blindingValues = await loki_crypto . getBlindingValues ( srvU8A , this . keypair . ed25519KeyPair )
747
666
//console.log('blindingValues', blindingValues)
748
667
const ka = blindingValues . secretKey
@@ -760,6 +679,11 @@ class SessionOpenGroupV3Room {
760
679
// DELETE token
761
680
}
762
681
682
+ updateProfile ( keypair , displayName , profileInfo ) {
683
+ if ( displayName !== undefined ) this . displayName = displayName
684
+ if ( profileInfo !== undefined ) this . profileInfo = profileInfo
685
+ }
686
+
763
687
async send ( text , options = { } ) {
764
688
await this . ensureToken ( )
765
689
try {
@@ -768,6 +692,15 @@ class SessionOpenGroupV3Room {
768
692
769
693
// padPlainTextBuffer returns uint8 array
770
694
// probably should be creating a OpenGroupMessageV2 message
695
+
696
+ // we need to inject profile stuff into options...
697
+ if ( options . profile === undefined ) {
698
+ options . profile = {
699
+ displayName : this . displayName ,
700
+ avatar : this . profileInfo ?. avatar_image ?. url ,
701
+ }
702
+ }
703
+
771
704
const plaintextBuf = Buffer . from ( protobuf . encodeContentMessage ( text , ts , options ) )
772
705
773
706
// maybe we should sign it with our pubkey, not the server's pubkey
@@ -778,7 +711,7 @@ class SessionOpenGroupV3Room {
778
711
//console.log('signature', signature, signature.byteLength)
779
712
780
713
// srvkey + ourkey => blindedkey
781
- const srvU8A = loki_crypto . hexStringToUint8Array ( this . server . serverPubkeyHex )
714
+ const srvU8A = binary . hexStringToUint8Array ( this . server . serverPubkeyHex )
782
715
const blindingValues = await loki_crypto . getBlindingValues ( srvU8A , this . keypair . ed25519KeyPair )
783
716
//console.log('blindingValues', blindingValues)
784
717
const ka = blindingValues . secretKey
0 commit comments