Skip to content

Commit 0f8f809

Browse files
authored
security(2820): More secure frontend<->backend socket secret generation/verification (#2928)
* Use libsodium for generating and verifying socketiosecrets - updates verification for all environments - updates secret gen on desktop - mobile still in progress * Add libsodium to android and properly generate socket IO secret * Fix mobile issues and use hex vs base64 for compatibility with android library * Make secrets on ios hex strings * Update changelog * Accidental commit * Remove debug log * Another
1 parent 99f121c commit 0f8f809

19 files changed

Lines changed: 199 additions & 96 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Changelog
22

3+
## [Unreleased]
4+
5+
### Security
6+
7+
* Use libsodium for socketIOSecret comparison and migrate logic from common to backend [#2820](https://github.com/TryQuiet/quiet/issues/2820)
8+
* Use libsodium for socketIOSecret generation in desktop and android [#2820](https://github.com/TryQuiet/quiet/issues/2820)
9+
* Simplify/standardize socketIOSecret generation on IOS (no libsodium) [#2820](https://github.com/TryQuiet/quiet/issues/2820)
10+
311
## [6.0.0]
412

513
### Features

packages/backend/package-lock.json

Lines changed: 27 additions & 30 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/backend/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@
7171
"@types/express": "^4.17.9",
7272
"@types/get-port": "4.2.0",
7373
"@types/jest": "28.1.8",
74-
"@types/libsodium-wrappers-sumo": "^0.7.8",
7574
"@types/luxon": "^3.4.2",
7675
"@types/mock-fs": "^4.13.1",
7776
"@types/node": "18.11.9",
@@ -124,6 +123,7 @@
124123
"@libp2p/websockets": "^9.1.0",
125124
"@localfirst/auth": "file:../../3rd-party/auth/packages/auth/dist",
126125
"@localfirst/crdx": "file:../../3rd-party/auth/packages/crdx/dist",
126+
"@localfirst/crypto": "file:../../3rd-party/auth/packages/crypto/dist",
127127
"@multiformats/multiaddr": "^12.3.0",
128128
"@multiformats/multiaddr-matcher": "^1.6.0",
129129
"@multiformats/multiaddr-to-uri": "^10.1.0",
@@ -176,7 +176,6 @@
176176
"joi": "^17.13.3",
177177
"level": "8.0.1",
178178
"libp2p": "2.4.2",
179-
"libsodium-wrappers-sumo": "0.7.15",
180179
"luxon": "^3.4.4",
181180
"multiformats": "13.3.1",
182181
"node-fetch": "^3.3.0",

packages/backend/src/nest/app.module.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ import { Server as SocketIO } from 'socket.io'
3636
import { StorageModule } from './storage/storage.module'
3737
import { IpfsModule } from './ipfs/ipfs.module'
3838
import { Level } from 'level'
39-
import { verifyToken } from '@quiet/common'
4039
import { createLogger } from './common/logger'
4140
import { SocketActionsMap, SocketEventsMap } from '@quiet/types'
4241
import { QSSModule } from './qss/qss.module'
42+
import { verifyToken } from './common/token'
4343

4444
const logger = createLogger('appModule')
4545

@@ -115,7 +115,7 @@ export class AppModule {
115115
pingTimeout: 30_000,
116116
})
117117
// @ts-ignore
118-
io.engine.use((req, res, next) => {
118+
io.engine.use(async (req, res, next) => {
119119
const authHeader = req.headers['authorization']
120120
if (!authHeader) {
121121
_ioLogger.error('Backend server: No authorization header')
@@ -132,7 +132,7 @@ export class AppModule {
132132
return
133133
}
134134

135-
if (verifyToken(options.socketIOSecret, token)) {
135+
if (await verifyToken(options.socketIOSecret, token)) {
136136
next()
137137
} else {
138138
_ioLogger.error('Backend server: Unauthorized')
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { to_hex, to_base64, randomBytes, base64_variants } from '@localfirst/crypto'
2+
3+
import { verifyToken } from './token'
4+
import { createLogger } from './logger'
5+
6+
const logger = createLogger('token:test')
7+
8+
describe('token', () => {
9+
describe('verifyToken', () => {
10+
it('returns true for matching tokens', async () => {
11+
const token = to_hex(randomBytes(32))
12+
expect(await verifyToken(token, token)).toBeTruthy()
13+
})
14+
15+
it('returns false for non-matching tokens', async () => {
16+
const token1 = to_hex(randomBytes(32))
17+
const token2 = to_hex(randomBytes(32))
18+
expect(await verifyToken(token1, token2)).toBeFalsy()
19+
})
20+
21+
it('returns false for tokens in different encodings', async () => {
22+
const bytes = randomBytes(32)
23+
const token1 = to_base64(bytes, base64_variants.ORIGINAL)
24+
const token2 = to_hex(bytes)
25+
expect(await verifyToken(token1, token2)).toBeFalsy()
26+
})
27+
28+
it('returns false for tokens of different lengths', async () => {
29+
const token1 = to_hex(randomBytes(32))
30+
const token2 = to_hex(randomBytes(8))
31+
expect(await verifyToken(token1, token2)).toBeFalsy()
32+
})
33+
})
34+
})
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { from_hex, compare } from '@localfirst/crypto'
2+
import { createLogger } from './logger'
3+
4+
const logger = createLogger('token')
5+
6+
export const verifyToken = async (secret: string, token: string): Promise<boolean> => {
7+
try {
8+
const secretBytes = from_hex(secret)
9+
const tokenBytes = from_hex(token)
10+
const result = compare(secretBytes, tokenBytes)
11+
return result === 0
12+
} catch (e) {
13+
console.error('Error while comparing tokens', e)
14+
return false
15+
}
16+
}

packages/common/src/auth.test.ts

Lines changed: 0 additions & 19 deletions
This file was deleted.

packages/common/src/auth.ts

Lines changed: 0 additions & 6 deletions
This file was deleted.

packages/common/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ export * from './naming'
1010
export * from './fileData'
1111
export * from './libp2p'
1212
export * from './tests'
13-
export * from './auth'
1413
export * from './messages'
1514
export * from './compare'
1615
export * from './dir'

0 commit comments

Comments
 (0)