4.1.3
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
const mongoose = require('mongoose')
|
||||
const crypto = require('crypto')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const DeviceLinkSessionModel = require('../../../models/DeviceLinkSessionModel')
|
||||
|
||||
@@ -152,11 +153,98 @@ const pollDeviceLink = async (req, res, next) => {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* رمزِ خودکارِ per-account برای رمزنگاری/بازگشاییِ خودکارِ بکآپِ کلیدِ E2EE — بهجای
|
||||
* PIN دستیِ کاربر. با یه درخواستِ احرازهویتشده به همین اکانت (از هر دستگاهی) قابل
|
||||
* دریافته، پس بازیابیِ هویت روی دستگاهِ جدید بدون هیچ دخالتِ کاربری انجام میشه.
|
||||
* اولینبار که خواسته بشه lazily ساخته میشه؛ با یه آپدیتِ شرطی (فقط اگه هنوز null
|
||||
* باشه) از race بینِ دو دستگاهی که همزمان اولینبار درخواستش میکنن جلوگیری میشه.
|
||||
*/
|
||||
const getOrCreateAutoBackupSecret = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.user._id
|
||||
const existing = await UserModel.findById(userId).select('e2ee_auto_backup_secret').lean()
|
||||
if (existing?.e2ee_auto_backup_secret) {
|
||||
return res.json({ secret: existing.e2ee_auto_backup_secret })
|
||||
}
|
||||
|
||||
const candidate = crypto.randomBytes(32).toString('base64')
|
||||
const updated = await UserModel.findOneAndUpdate(
|
||||
{ _id: userId, e2ee_auto_backup_secret: null },
|
||||
{ $set: { e2ee_auto_backup_secret: candidate } },
|
||||
{ new: true }
|
||||
).select('e2ee_auto_backup_secret').lean()
|
||||
|
||||
// اگه updated خالی برگشت یعنی یه درخواستِ همزمانِ دیگه (دستگاهِ دیگه) بین
|
||||
// خوندنِ بالا و همین آپدیت، خودش رمز رو ساخته بود — بخونش تا هر دو دستگاه دقیقاً
|
||||
// یه رمزِ یکسان بگیرن، نه دوتا رمزِ متفاوت
|
||||
const secret = updated?.e2ee_auto_backup_secret ||
|
||||
(await UserModel.findById(userId).select('e2ee_auto_backup_secret').lean())?.e2ee_auto_backup_secret
|
||||
|
||||
res.json({ secret })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ذخیرهی بکآپِ کلیدِ خصوصیِ رمزنگاریشده با PIN/رمزِ انتخابیِ کاربر. سرور فقط
|
||||
* ciphertext/salt/iv رو میبینه — نه خودِ PIN و نه کلیدِ خام. کاربر میتونه صدا بزنه
|
||||
* تا بکآپ رو بسازه یا (با یه ciphertext جدید) رمزش رو عوض کنه.
|
||||
*/
|
||||
const putKeyBackup = async (req, res, next) => {
|
||||
try {
|
||||
const { salt, iv, ciphertext, iterations } = req.body
|
||||
if (
|
||||
!salt || typeof salt !== 'string' ||
|
||||
!iv || typeof iv !== 'string' ||
|
||||
!ciphertext || typeof ciphertext !== 'string' ||
|
||||
typeof iterations !== 'number' || iterations < 100000
|
||||
) {
|
||||
return res.status(422).json({ error: 'invalid backup payload' })
|
||||
}
|
||||
if (ciphertext.length > 8192 || salt.length > 512 || iv.length > 512) {
|
||||
return res.status(422).json({ error: 'backup payload too large' })
|
||||
}
|
||||
|
||||
await UserModel.findByIdAndUpdate(req.user._id, {
|
||||
e2ee_key_backup: { salt, iv, ciphertext, iterations }
|
||||
})
|
||||
|
||||
res.json({ ok: true })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
/** فقط خودِ کاربر میتونه بکآپِ خودش رو بخونه — برای بازیابی روی یه دستگاه جدید. */
|
||||
const getKeyBackup = async (req, res, next) => {
|
||||
try {
|
||||
const user = await UserModel.findById(req.user._id).select('e2ee_key_backup').lean()
|
||||
res.json({ backup: user?.e2ee_key_backup || null })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const deleteKeyBackup = async (req, res, next) => {
|
||||
try {
|
||||
await UserModel.findByIdAndUpdate(req.user._id, { e2ee_key_backup: null })
|
||||
res.json({ ok: true })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
putMyPublicKey,
|
||||
getPublicKeyByUserId,
|
||||
startDeviceLink,
|
||||
getDeviceLinkSession,
|
||||
approveDeviceLink,
|
||||
pollDeviceLink
|
||||
pollDeviceLink,
|
||||
getOrCreateAutoBackupSecret,
|
||||
putKeyBackup,
|
||||
getKeyBackup,
|
||||
deleteKeyBackup
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user