Skip to content

Commit 23f9909

Browse files
committed
lib.binary refactor, updateProfile() work
1 parent 2f111d2 commit 23f9909

File tree

1 file changed

+44
-111
lines changed

1 file changed

+44
-111
lines changed

lib/open_group_v3.js

Lines changed: 44 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -5,72 +5,7 @@ const protobuf = require('./protobuf.js')
55
//const _sodium = require('libsodium-wrappers')
66
const _sodium = require('libsodium-wrappers-sumo') // maybe put in session-client?
77
//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')
749

7510
// OnionSending in https://github.com/oxen-io/session-desktop/blob/0794edeb69aac582187da35771dc29ae3e68279c/ts/session/onions/onionSend.ts#L36
7611
// NOTE some endpoints require decoded strings
@@ -94,7 +29,7 @@ async function getOurOGHeaders(serverPubKeyHex, endpoint, method, blinded, body,
9429
const timestamp = Math.floor(Date.now() / 1000)
9530
//const nonce = new Uint8Array(16)
9631
const nonce = await sodium.randombytes_buf(16)
97-
const srvU8A = loki_crypto.hexStringToUint8Array(serverPubKeyHex)
32+
const srvU8A = binary.hexStringToUint8Array(serverPubKeyHex)
9833

9934
let pubkey, ka, kA
10035
// 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,
11651
// requires front /
11752
//console.log('endpoint', endpoint)
11853
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
12055

12156
//const srvPubKeyBuf = Buffer.from(serverPubKeyHex, 16)
12257
//console.log('srvPubKeyBuf', srvPubKeyBuf)
@@ -130,8 +65,8 @@ async function getOurOGHeaders(serverPubKeyHex, endpoint, method, blinded, body,
13065
}
13166
*/
13267
//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)
13570
if (0) {
13671
console.log('srvU8A', srvU8A)
13772
console.log('nonce', nonce)
@@ -140,7 +75,7 @@ async function getOurOGHeaders(serverPubKeyHex, endpoint, method, blinded, body,
14075
console.log('encodedPath', encodedPath)
14176
}
14277

143-
let toSign = concatUInt8Array(
78+
let toSign = binary.concatUInt8Array(
14479
srvU8A,
14580
nonce,
14681
tsU8a,
@@ -150,16 +85,16 @@ async function getOurOGHeaders(serverPubKeyHex, endpoint, method, blinded, body,
15085

15186
if (body) {
15287
// body hash to signature
153-
toSign = concatUInt8Array(toSign, sodium.crypto_generichash(64, body))
88+
toSign = binary.concatUInt8Array(toSign, sodium.crypto_generichash(64, body))
15489
}
15590

15691
const signature = await loki_crypto.getSogsSignature(blinded, ka, kA, signingKeys, toSign)
15792

15893
return {
15994
'X-SOGS-Pubkey': pubkey, // user pubkey
16095
'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),
16398
};
16499
}
165100

@@ -191,47 +126,18 @@ async function sogs_rpcv3(method, endpoint, querystring, body, baseUrl, serverPu
191126
return result
192127
}
193128

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-
229129
// for multiple keypairs, servers and rooms
230130
class SessionOpenGroupV3Manager {
231131
constructor(options = {}) {
232132
this.servers = {}
233133
}
234134

135+
updateProfile(keypair, displayName, profileInfo) {
136+
for(const url in this.servers) {
137+
this.servers[url].updateProfile(keypair, displayName, profileInfo)
138+
}
139+
}
140+
235141
joinServer(baseURL, serverPubkeyHex, options) {
236142
if (this.servers[baseURL]) {
237143
console.log('SessionOpenGroupV3Manager::joinServer - already joined', baseURL)
@@ -285,6 +191,17 @@ class SessionOpenGroupV3Server {
285191
return keypair.publicKeyHex + '_' + room
286192
}
287193

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+
288205
// header support?
289206
// keypair, endpoint, body, querystring, method
290207
async rpc(method, endpoint, querystring, body, keypair) {
@@ -721,6 +638,8 @@ class SessionOpenGroupV3Room {
721638
// active_users, active_users_cutoff, admins, created, image_id, info_updates,
722639
// message_sequence, moderators, name, read, token, upload, write
723640
this.roomData = {}
641+
this.displayName = undefined
642+
this.profileInfo = undefined
724643
}
725644

726645
async ensureToken() {
@@ -742,7 +661,7 @@ class SessionOpenGroupV3Room {
742661
}
743662
if (this.server.blinded) {
744663
// srvkey + ourkey => blindedkey
745-
const srvU8A = loki_crypto.hexStringToUint8Array(this.server.serverPubkeyHex)
664+
const srvU8A = binary.hexStringToUint8Array(this.server.serverPubkeyHex)
746665
const blindingValues = await loki_crypto.getBlindingValues(srvU8A, this.keypair.ed25519KeyPair)
747666
//console.log('blindingValues', blindingValues)
748667
const ka = blindingValues.secretKey
@@ -760,6 +679,11 @@ class SessionOpenGroupV3Room {
760679
// DELETE token
761680
}
762681

682+
updateProfile(keypair, displayName, profileInfo) {
683+
if (displayName !== undefined) this.displayName = displayName
684+
if (profileInfo !== undefined) this.profileInfo = profileInfo
685+
}
686+
763687
async send(text, options = {}) {
764688
await this.ensureToken()
765689
try {
@@ -768,6 +692,15 @@ class SessionOpenGroupV3Room {
768692

769693
// padPlainTextBuffer returns uint8 array
770694
// 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+
771704
const plaintextBuf = Buffer.from(protobuf.encodeContentMessage(text, ts, options))
772705

773706
// maybe we should sign it with our pubkey, not the server's pubkey
@@ -778,7 +711,7 @@ class SessionOpenGroupV3Room {
778711
//console.log('signature', signature, signature.byteLength)
779712

780713
// srvkey + ourkey => blindedkey
781-
const srvU8A = loki_crypto.hexStringToUint8Array(this.server.serverPubkeyHex)
714+
const srvU8A = binary.hexStringToUint8Array(this.server.serverPubkeyHex)
782715
const blindingValues = await loki_crypto.getBlindingValues(srvU8A, this.keypair.ed25519KeyPair)
783716
//console.log('blindingValues', blindingValues)
784717
const ka = blindingValues.secretKey

0 commit comments

Comments
 (0)