From e282a9183fcecfcf2a969cc9fe47927b3ccc7a32 Mon Sep 17 00:00:00 2001 From: wukko Date: Tue, 5 Mar 2024 18:14:26 +0600 Subject: [PATCH 01/11] stream: encrypt cached stream data & clean up related modules also limited CORS methods to GET and POST --- src/core/api.js | 26 ++++++++++---- src/modules/stream/manage.js | 69 +++++++++++++++++++++++------------- src/modules/sub/crypto.js | 25 +++++++++++-- src/modules/sub/utils.js | 1 - 4 files changed, 88 insertions(+), 33 deletions(-) diff --git a/src/core/api.js b/src/core/api.js index 5f910315..8b3dec0e 100644 --- a/src/core/api.js +++ b/src/core/api.js @@ -51,7 +51,11 @@ export function runAPI(express, app, gitCommit, gitBranch, __dirname) { app.set('trust proxy', ['loopback', 'uniquelocal']); - app.use('/api/:type', cors(corsConfig)); + app.use('/api/:type', cors({ + methods: ['GET', 'POST'], + ...corsConfig + })); + app.use('/api/json', apiLimiter); app.use('/api/stream', apiLimiterStream); app.use('/api/onDemand', apiLimiter); @@ -60,6 +64,7 @@ export function runAPI(express, app, gitCommit, gitBranch, __dirname) { try { decodeURIComponent(req.path) } catch (e) { return res.redirect('/') } next(); }); + app.use('/api/json', express.json({ verify: (req, res, buf) => { let acceptCon = String(req.header('Accept')) === "application/json"; @@ -71,6 +76,7 @@ export function runAPI(express, app, gitCommit, gitBranch, __dirname) { } } })); + // handle express.json errors properly (https://github.com/expressjs/express/issues/4065) app.use('/api/json', (err, req, res, next) => { let errorText = "invalid json body"; @@ -86,6 +92,7 @@ export function runAPI(express, app, gitCommit, gitBranch, __dirname) { next(); } }); + app.post('/api/json', async (req, res) => { try { let lang = languageCode(req); @@ -118,13 +125,17 @@ export function runAPI(express, app, gitCommit, gitBranch, __dirname) { try { switch (req.params.type) { case 'stream': - if (req.query.t && req.query.h && req.query.e && req.query.t.toString().length === 21 - && req.query.h.toString().length === 64 && req.query.e.toString().length === 13) { - let streamInfo = verifyStream(req.query.t, req.query.h, req.query.e); + const q = req.query; + const checkQueries = q.t && q.e && q.h && q.s && q.i; + const checkBaseLength = q.t.length === 21 && q.e.length === 13; + const checkSafeLength = q.h.length === 44 && q.s.length === 344 && q.i.length === 24; + + if (checkQueries && checkBaseLength && checkSafeLength) { + let streamInfo = verifyStream(q.t, q.h, q.e, q.s, q.i); if (streamInfo.error) { return res.status(streamInfo.status).json(apiJSON(0, { t: streamInfo.error }).body); } - if (req.query.p) { + if (q.p) { return res.status(200).json({ status: "continue" }); @@ -132,7 +143,7 @@ export function runAPI(express, app, gitCommit, gitBranch, __dirname) { return stream(res, streamInfo); } else { let j = apiJSON(0, { - t: "stream token, hmac, or expiry timestamp is missing" + t: "bad request. stream link may be incomplete or corrupted." }) return res.status(j.status).json(j.body); } @@ -159,12 +170,15 @@ export function runAPI(express, app, gitCommit, gitBranch, __dirname) { }); } }); + app.get('/api/status', (req, res) => { res.status(200).end() }); + app.get('/favicon.ico', (req, res) => { res.sendFile(`${__dirname}/src/front/icons/favicon.ico`) }); + app.get('/*', (req, res) => { res.redirect('/api/json') }); diff --git a/src/modules/stream/manage.js b/src/modules/stream/manage.js index 459e5a6b..b034268f 100644 --- a/src/modules/stream/manage.js +++ b/src/modules/stream/manage.js @@ -2,7 +2,7 @@ import NodeCache from "node-cache"; import { randomBytes } from "crypto"; import { nanoid } from 'nanoid'; -import { sha256 } from "../sub/crypto.js"; +import { decryptStream, encryptStream, sha256 } from "../sub/crypto.js"; import { streamLifespan } from "../config.js"; const streamCache = new NodeCache({ @@ -15,48 +15,69 @@ streamCache.on("expired", (key) => { streamCache.del(key); }) -const streamSalt = randomBytes(64).toString('hex'); +const hmacSalt = randomBytes(64).toString('hex'); export function createStream(obj) { - let streamID = nanoid(), + const streamID = nanoid(), + iv = randomBytes(16).toString('base64'), + secret = randomBytes(256).toString('base64'), exp = Math.floor(new Date().getTime()) + streamLifespan, - ghmac = sha256(`${streamID},${obj.service},${exp}`, streamSalt); - - if (!streamCache.has(streamID)) { - streamCache.set(streamID, { - id: streamID, + hmac = sha256(`${streamID},${exp},${iv},${secret}`, hmacSalt), + streamData = { service: obj.service, type: obj.type, urls: obj.u, filename: obj.filename, - hmac: ghmac, exp: exp, - isAudioOnly: !!obj.isAudioOnly, audioFormat: obj.audioFormat, - time: obj.time ? obj.time : false, + isAudioOnly: !!obj.isAudioOnly, + time: obj.time || false, copy: !!obj.copy, mute: !!obj.mute, - metadata: obj.fileMetadata ? obj.fileMetadata : false - }); - } else { - let streamInfo = streamCache.get(streamID); - exp = streamInfo.exp; - ghmac = streamInfo.hmac; + metadata: obj.fileMetadata || false + }; + + streamCache.set( + streamID, + encryptStream(streamData, iv, secret) + ) + + let streamLink = new URL('/api/stream', process.env.apiURL); + + const params = { + 't': streamID, + 'e': exp, + 'h': hmac, + 's': secret, + 'i': iv } - return `${process.env.apiURL}api/stream?t=${streamID}&e=${exp}&h=${ghmac}`; + + for (const [key, value] of Object.entries(params)) { + streamLink.searchParams.append(key, value); + } + + return streamLink.toString(); } -export function verifyStream(id, hmac, exp) { +export function verifyStream(id, hmac, exp, secret, iv) { try { - let streamInfo = streamCache.get(id.toString()); + const ghmac = sha256(`${id},${exp},${iv},${secret}`, hmacSalt); + + if (ghmac !== String(hmac)) { + return { + error: "i couldn't verify if you have access to this stream. go back and try again!", + status: 401 + } + } + + const streamInfo = JSON.parse(decryptStream(streamCache.get(id.toString()), iv, secret)); + if (!streamInfo) return { error: "this download link has expired or doesn't exist. go back and try again!", status: 400 } - let ghmac = sha256(`${id},${streamInfo.service},${exp}`, streamSalt); - if (String(hmac) === ghmac && String(exp) === String(streamInfo.exp) && ghmac === String(streamInfo.hmac) - && Number(exp) > Math.floor(new Date().getTime())) { + if (String(exp) === String(streamInfo.exp) && Number(exp) > Math.floor(new Date().getTime())) { return streamInfo; } return { @@ -64,6 +85,6 @@ export function verifyStream(id, hmac, exp) { status: 401 } } catch (e) { - return { status: 500, body: { status: "error", text: "Internal Server Error" } }; + return { status: 500, body: { status: "error", text: "couldn't verify this stream. request a new one!" } }; } } diff --git a/src/modules/sub/crypto.js b/src/modules/sub/crypto.js index e8bf2f94..70484f4f 100644 --- a/src/modules/sub/crypto.js +++ b/src/modules/sub/crypto.js @@ -1,5 +1,26 @@ -import { createHmac } from "crypto"; +import { createHmac, createCipheriv, createDecipheriv, scryptSync } from "crypto"; + +const algorithm = "aes256" +const keyLength = 32; export function sha256(str, salt) { - return createHmac("sha256", salt).update(str).digest("hex"); + return createHmac("sha256", salt).update(str).digest("base64"); +} + +export function encryptStream(str, iv, secret) { + const buff = Buffer.from(JSON.stringify(str), "utf-8"); + + const key = scryptSync(Buffer.from(secret, "base64"), "salt", keyLength); + const cipher = createCipheriv(algorithm, key, Buffer.from(iv, "base64")); + + return Buffer.from(cipher.update(buff, "utf8", "binary") + cipher.final("binary"), "binary"); +} + +export function decryptStream(buf, iv, secret) { + const buff = Buffer.from(buf, "binary"); + + const key = scryptSync(Buffer.from(secret, "base64"), "salt", keyLength); + const decipher = createDecipheriv(algorithm, key, Buffer.from(iv, "base64")); + + return decipher.update(buff, "binary", "utf8") + decipher.final("utf8"); } diff --git a/src/modules/sub/utils.js b/src/modules/sub/utils.js index 8f8678d3..bb21bbb4 100644 --- a/src/modules/sub/utils.js +++ b/src/modules/sub/utils.js @@ -11,7 +11,6 @@ const apiVar = { }, booleanOnly: ["isAudioOnly", "isNoTTWatermark", "isTTFullAudio", "isAudioMuted", "dubLang", "vimeoDash", "disableMetadata", "twitterGif"] } -const forbiddenChars = ['}', '{', '(', ')', '\\', '>', '<', '^', '*', '!', '~', ';', ':', ',', '`', '[', ']', '#', '$', '"', "'", "@", '==']; const forbiddenCharsString = ['}', '{', '%', '>', '<', '^', ';', '`', '$', '"', "@", '=']; export function apiJSON(type, obj) { From dbe2a02152c8d298f7fd8e3ca9857a4b17812570 Mon Sep 17 00:00:00 2001 From: wukko Date: Tue, 5 Mar 2024 20:41:08 +0600 Subject: [PATCH 02/11] stream/manage: remove unnecessary Math.floor for timestamp from prehistoric times --- src/modules/stream/manage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/stream/manage.js b/src/modules/stream/manage.js index b034268f..842499f1 100644 --- a/src/modules/stream/manage.js +++ b/src/modules/stream/manage.js @@ -21,7 +21,7 @@ export function createStream(obj) { const streamID = nanoid(), iv = randomBytes(16).toString('base64'), secret = randomBytes(256).toString('base64'), - exp = Math.floor(new Date().getTime()) + streamLifespan, + exp = new Date().getTime() + streamLifespan, hmac = sha256(`${streamID},${exp},${iv},${secret}`, hmacSalt), streamData = { service: obj.service, @@ -77,7 +77,7 @@ export function verifyStream(id, hmac, exp, secret, iv) { status: 400 } - if (String(exp) === String(streamInfo.exp) && Number(exp) > Math.floor(new Date().getTime())) { + if (String(exp) === String(streamInfo.exp) && Number(exp) > new Date().getTime()) { return streamInfo; } return { From c22d76444b0067fbcd790d22b1a6b453214c0f85 Mon Sep 17 00:00:00 2001 From: wukko Date: Tue, 5 Mar 2024 20:41:33 +0600 Subject: [PATCH 03/11] core/api: remove unnecessary Math.floor for timestamp --- src/core/api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/api.js b/src/core/api.js index 8b3dec0e..05d20511 100644 --- a/src/core/api.js +++ b/src/core/api.js @@ -47,7 +47,7 @@ export function runAPI(express, app, gitCommit, gitBranch, __dirname) { }); const startTime = new Date(); - const startTimestamp = Math.floor(startTime.getTime()); + const startTimestamp = startTime.getTime(); app.set('trust proxy', ['loopback', 'uniquelocal']); From 9211b395887473ce530a66064273cacc3b043ebe Mon Sep 17 00:00:00 2001 From: wukko Date: Tue, 5 Mar 2024 20:45:54 +0600 Subject: [PATCH 04/11] createStream: removed an outdated variable --- src/modules/stream/manage.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/modules/stream/manage.js b/src/modules/stream/manage.js index 842499f1..b731c0b8 100644 --- a/src/modules/stream/manage.js +++ b/src/modules/stream/manage.js @@ -24,14 +24,13 @@ export function createStream(obj) { exp = new Date().getTime() + streamLifespan, hmac = sha256(`${streamID},${exp},${iv},${secret}`, hmacSalt), streamData = { - service: obj.service, + exp: exp, type: obj.type, urls: obj.u, + service: obj.service, filename: obj.filename, - exp: exp, audioFormat: obj.audioFormat, isAudioOnly: !!obj.isAudioOnly, - time: obj.time || false, copy: !!obj.copy, mute: !!obj.mute, metadata: obj.fileMetadata || false From 6ed03b003588182f6e5b40287c31cabae1e1d43e Mon Sep 17 00:00:00 2001 From: wukko Date: Tue, 5 Mar 2024 20:55:17 +0600 Subject: [PATCH 05/11] crypto: rename sha256 func to generateHmac it has always been actually hmac --- src/core/api.js | 6 +++--- src/modules/stream/manage.js | 6 +++--- src/modules/sub/crypto.js | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/core/api.js b/src/core/api.js index 05d20511..d78fd1d2 100644 --- a/src/core/api.js +++ b/src/core/api.js @@ -10,7 +10,7 @@ import { apiJSON, checkJSONPost, getIP, languageCode } from "../modules/sub/util import { Bright, Cyan } from "../modules/sub/consoleText.js"; import stream from "../modules/stream/stream.js"; import loc from "../localization/manager.js"; -import { sha256 } from "../modules/sub/crypto.js"; +import { generateHmac } from "../modules/sub/crypto.js"; import { verifyStream } from "../modules/stream/manage.js"; export function runAPI(express, app, gitCommit, gitBranch, __dirname) { @@ -24,7 +24,7 @@ export function runAPI(express, app, gitCommit, gitBranch, __dirname) { max: 20, standardHeaders: true, legacyHeaders: false, - keyGenerator: req => sha256(getIP(req), ipSalt), + keyGenerator: req => generateHmac(getIP(req), ipSalt), handler: (req, res, next, opt) => { return res.status(429).json({ "status": "rate-limit", @@ -37,7 +37,7 @@ export function runAPI(express, app, gitCommit, gitBranch, __dirname) { max: 25, standardHeaders: true, legacyHeaders: false, - keyGenerator: req => sha256(getIP(req), ipSalt), + keyGenerator: req => generateHmac(getIP(req), ipSalt), handler: (req, res, next, opt) => { return res.status(429).json({ "status": "rate-limit", diff --git a/src/modules/stream/manage.js b/src/modules/stream/manage.js index b731c0b8..32fa5fb5 100644 --- a/src/modules/stream/manage.js +++ b/src/modules/stream/manage.js @@ -2,7 +2,7 @@ import NodeCache from "node-cache"; import { randomBytes } from "crypto"; import { nanoid } from 'nanoid'; -import { decryptStream, encryptStream, sha256 } from "../sub/crypto.js"; +import { decryptStream, encryptStream, generateHmac } from "../sub/crypto.js"; import { streamLifespan } from "../config.js"; const streamCache = new NodeCache({ @@ -22,7 +22,7 @@ export function createStream(obj) { iv = randomBytes(16).toString('base64'), secret = randomBytes(256).toString('base64'), exp = new Date().getTime() + streamLifespan, - hmac = sha256(`${streamID},${exp},${iv},${secret}`, hmacSalt), + hmac = generateHmac(`${streamID},${exp},${iv},${secret}`, hmacSalt), streamData = { exp: exp, type: obj.type, @@ -60,7 +60,7 @@ export function createStream(obj) { export function verifyStream(id, hmac, exp, secret, iv) { try { - const ghmac = sha256(`${id},${exp},${iv},${secret}`, hmacSalt); + const ghmac = generateHmac(`${id},${exp},${iv},${secret}`, hmacSalt); if (ghmac !== String(hmac)) { return { diff --git a/src/modules/sub/crypto.js b/src/modules/sub/crypto.js index 70484f4f..7e312789 100644 --- a/src/modules/sub/crypto.js +++ b/src/modules/sub/crypto.js @@ -3,7 +3,7 @@ import { createHmac, createCipheriv, createDecipheriv, scryptSync } from "crypto const algorithm = "aes256" const keyLength = 32; -export function sha256(str, salt) { +export function generateHmac(str, salt) { return createHmac("sha256", salt).update(str).digest("base64"); } From 48ac75b135d5485bf8607841d16ce9382c004517 Mon Sep 17 00:00:00 2001 From: wukko Date: Tue, 5 Mar 2024 21:02:29 +0600 Subject: [PATCH 06/11] crypto: concat buffers in encryptStream and decryptStream --- src/modules/sub/crypto.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/sub/crypto.js b/src/modules/sub/crypto.js index 7e312789..3f02edc5 100644 --- a/src/modules/sub/crypto.js +++ b/src/modules/sub/crypto.js @@ -13,7 +13,7 @@ export function encryptStream(str, iv, secret) { const key = scryptSync(Buffer.from(secret, "base64"), "salt", keyLength); const cipher = createCipheriv(algorithm, key, Buffer.from(iv, "base64")); - return Buffer.from(cipher.update(buff, "utf8", "binary") + cipher.final("binary"), "binary"); + return Buffer.concat([ cipher.update(buff), cipher.final() ]) } export function decryptStream(buf, iv, secret) { @@ -22,5 +22,5 @@ export function decryptStream(buf, iv, secret) { const key = scryptSync(Buffer.from(secret, "base64"), "salt", keyLength); const decipher = createDecipheriv(algorithm, key, Buffer.from(iv, "base64")); - return decipher.update(buff, "binary", "utf8") + decipher.final("utf8"); + return Buffer.concat([ decipher.update(buff), decipher.final() ]) } From 73b63e5487caa555a4799f4c63afbd3216fa862f Mon Sep 17 00:00:00 2001 From: wukko Date: Tue, 5 Mar 2024 21:14:54 +0600 Subject: [PATCH 07/11] crypto: replace base64 with base64url --- src/modules/sub/crypto.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/modules/sub/crypto.js b/src/modules/sub/crypto.js index 3f02edc5..6a221e1a 100644 --- a/src/modules/sub/crypto.js +++ b/src/modules/sub/crypto.js @@ -4,14 +4,14 @@ const algorithm = "aes256" const keyLength = 32; export function generateHmac(str, salt) { - return createHmac("sha256", salt).update(str).digest("base64"); + return createHmac("sha256", salt).update(str).digest("base64url"); } export function encryptStream(str, iv, secret) { const buff = Buffer.from(JSON.stringify(str), "utf-8"); - const key = scryptSync(Buffer.from(secret, "base64"), "salt", keyLength); - const cipher = createCipheriv(algorithm, key, Buffer.from(iv, "base64")); + const key = scryptSync(Buffer.from(secret, "base64url"), "salt", keyLength); + const cipher = createCipheriv(algorithm, key, Buffer.from(iv, "base64url")); return Buffer.concat([ cipher.update(buff), cipher.final() ]) } @@ -19,8 +19,8 @@ export function encryptStream(str, iv, secret) { export function decryptStream(buf, iv, secret) { const buff = Buffer.from(buf, "binary"); - const key = scryptSync(Buffer.from(secret, "base64"), "salt", keyLength); - const decipher = createDecipheriv(algorithm, key, Buffer.from(iv, "base64")); + const key = scryptSync(Buffer.from(secret, "base64url"), "salt", keyLength); + const decipher = createDecipheriv(algorithm, key, Buffer.from(iv, "base64url")); return Buffer.concat([ decipher.update(buff), decipher.final() ]) } From f4acd2f14121d68be89b61aae06f54b8f3a0ae8c Mon Sep 17 00:00:00 2001 From: wukko Date: Tue, 5 Mar 2024 21:15:13 +0600 Subject: [PATCH 08/11] stream/manage: replace base64 with base64url --- src/modules/stream/manage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/stream/manage.js b/src/modules/stream/manage.js index 32fa5fb5..c8bcd979 100644 --- a/src/modules/stream/manage.js +++ b/src/modules/stream/manage.js @@ -19,8 +19,8 @@ const hmacSalt = randomBytes(64).toString('hex'); export function createStream(obj) { const streamID = nanoid(), - iv = randomBytes(16).toString('base64'), - secret = randomBytes(256).toString('base64'), + iv = randomBytes(16).toString('base64url'), + secret = randomBytes(256).toString('base64url'), exp = new Date().getTime() + streamLifespan, hmac = generateHmac(`${streamID},${exp},${iv},${secret}`, hmacSalt), streamData = { From 97f4528e92dc1245360266d13f5bc19029661a2d Mon Sep 17 00:00:00 2001 From: wukko Date: Tue, 5 Mar 2024 21:15:32 +0600 Subject: [PATCH 09/11] core/api: update checkSafeLength --- src/core/api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/api.js b/src/core/api.js index d78fd1d2..8f6060fe 100644 --- a/src/core/api.js +++ b/src/core/api.js @@ -128,7 +128,7 @@ export function runAPI(express, app, gitCommit, gitBranch, __dirname) { const q = req.query; const checkQueries = q.t && q.e && q.h && q.s && q.i; const checkBaseLength = q.t.length === 21 && q.e.length === 13; - const checkSafeLength = q.h.length === 44 && q.s.length === 344 && q.i.length === 24; + const checkSafeLength = q.h.length === 43 && q.s.length === 342 && q.i.length === 22; if (checkQueries && checkBaseLength && checkSafeLength) { let streamInfo = verifyStream(q.t, q.h, q.e, q.s, q.i); From fc39ac76b6471da4815efcb316bb59c5e28d18a8 Mon Sep 17 00:00:00 2001 From: wukko Date: Tue, 5 Mar 2024 21:18:20 +0600 Subject: [PATCH 10/11] crypto: change input var name in stream functions --- src/modules/sub/crypto.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modules/sub/crypto.js b/src/modules/sub/crypto.js index 6a221e1a..2fba1efc 100644 --- a/src/modules/sub/crypto.js +++ b/src/modules/sub/crypto.js @@ -7,8 +7,8 @@ export function generateHmac(str, salt) { return createHmac("sha256", salt).update(str).digest("base64url"); } -export function encryptStream(str, iv, secret) { - const buff = Buffer.from(JSON.stringify(str), "utf-8"); +export function encryptStream(plaintext, iv, secret) { + const buff = Buffer.from(JSON.stringify(plaintext), "utf-8"); const key = scryptSync(Buffer.from(secret, "base64url"), "salt", keyLength); const cipher = createCipheriv(algorithm, key, Buffer.from(iv, "base64url")); @@ -16,8 +16,8 @@ export function encryptStream(str, iv, secret) { return Buffer.concat([ cipher.update(buff), cipher.final() ]) } -export function decryptStream(buf, iv, secret) { - const buff = Buffer.from(buf, "binary"); +export function decryptStream(ciphertext, iv, secret) { + const buff = Buffer.from(ciphertext, "binary"); const key = scryptSync(Buffer.from(secret, "base64url"), "salt", keyLength); const decipher = createDecipheriv(algorithm, key, Buffer.from(iv, "base64url")); From 7fab5a37fffce5dd4d076bc3d6ffe8904033b96b Mon Sep 17 00:00:00 2001 From: dumbmoron Date: Tue, 5 Mar 2024 16:49:00 +0000 Subject: [PATCH 11/11] crypto: use secret directly instead of deriving key --- src/core/api.js | 2 +- src/modules/stream/manage.js | 2 +- src/modules/sub/crypto.js | 11 ++++------- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/core/api.js b/src/core/api.js index 8f6060fe..a439cddf 100644 --- a/src/core/api.js +++ b/src/core/api.js @@ -128,7 +128,7 @@ export function runAPI(express, app, gitCommit, gitBranch, __dirname) { const q = req.query; const checkQueries = q.t && q.e && q.h && q.s && q.i; const checkBaseLength = q.t.length === 21 && q.e.length === 13; - const checkSafeLength = q.h.length === 43 && q.s.length === 342 && q.i.length === 22; + const checkSafeLength = q.h.length === 43 && q.s.length === 43 && q.i.length === 22; if (checkQueries && checkBaseLength && checkSafeLength) { let streamInfo = verifyStream(q.t, q.h, q.e, q.s, q.i); diff --git a/src/modules/stream/manage.js b/src/modules/stream/manage.js index c8bcd979..120b6f00 100644 --- a/src/modules/stream/manage.js +++ b/src/modules/stream/manage.js @@ -20,7 +20,7 @@ const hmacSalt = randomBytes(64).toString('hex'); export function createStream(obj) { const streamID = nanoid(), iv = randomBytes(16).toString('base64url'), - secret = randomBytes(256).toString('base64url'), + secret = randomBytes(32).toString('base64url'), exp = new Date().getTime() + streamLifespan, hmac = generateHmac(`${streamID},${exp},${iv},${secret}`, hmacSalt), streamData = { diff --git a/src/modules/sub/crypto.js b/src/modules/sub/crypto.js index 2fba1efc..b3a0539b 100644 --- a/src/modules/sub/crypto.js +++ b/src/modules/sub/crypto.js @@ -1,25 +1,22 @@ import { createHmac, createCipheriv, createDecipheriv, scryptSync } from "crypto"; const algorithm = "aes256" -const keyLength = 32; export function generateHmac(str, salt) { return createHmac("sha256", salt).update(str).digest("base64url"); } export function encryptStream(plaintext, iv, secret) { - const buff = Buffer.from(JSON.stringify(plaintext), "utf-8"); - - const key = scryptSync(Buffer.from(secret, "base64url"), "salt", keyLength); + const buff = Buffer.from(JSON.stringify(plaintext)); + const key = Buffer.from(secret, "base64url"); const cipher = createCipheriv(algorithm, key, Buffer.from(iv, "base64url")); return Buffer.concat([ cipher.update(buff), cipher.final() ]) } export function decryptStream(ciphertext, iv, secret) { - const buff = Buffer.from(ciphertext, "binary"); - - const key = scryptSync(Buffer.from(secret, "base64url"), "salt", keyLength); + const buff = Buffer.from(ciphertext); + const key = Buffer.from(secret, "base64url"); const decipher = createDecipheriv(algorithm, key, Buffer.from(iv, "base64url")); return Buffer.concat([ decipher.update(buff), decipher.final() ])