mirror of
https://github.com/nodemailer/wildduck.git
synced 2025-09-29 08:24:48 +08:00
use encrypt totp seeds with a master password
This commit is contained in:
parent
1def9f1e5e
commit
c22612c869
2 changed files with 34 additions and 4 deletions
|
@ -52,6 +52,10 @@ maxForwards=2000
|
||||||
# used to push outbound emails to the sending queue
|
# used to push outbound emails to the sending queue
|
||||||
#sender="zone-mta"
|
#sender="zone-mta"
|
||||||
|
|
||||||
|
[totp]
|
||||||
|
cipher="aes192"
|
||||||
|
secret="a secret cat"
|
||||||
|
|
||||||
[attachments]
|
[attachments]
|
||||||
type="gridstore"
|
type="gridstore"
|
||||||
bucket="attachments"
|
bucket="attachments"
|
||||||
|
|
|
@ -622,11 +622,19 @@ class UserHandler {
|
||||||
|
|
||||||
if (!data.fresh && userData.seed) {
|
if (!data.fresh && userData.seed) {
|
||||||
if (userData.seed) {
|
if (userData.seed) {
|
||||||
|
let secret = userData.seed;
|
||||||
|
if (userData.seed.charAt(0) === '$') {
|
||||||
|
let decipher = crypto.createDecipher(config.totp.cipher, config.totp.secret);
|
||||||
|
secret = decipher.update(userData.seed.substr(1), 'hex', 'utf-8');
|
||||||
|
secret += decipher.final('utf8');
|
||||||
|
}
|
||||||
|
|
||||||
let otpauth_url = speakeasy.otpauthURL({
|
let otpauth_url = speakeasy.otpauthURL({
|
||||||
secret: base32.decode(userData.seed),
|
secret: base32.decode(secret),
|
||||||
label: userData.username,
|
label: userData.username,
|
||||||
issuer: data.issuer || 'Wild Duck'
|
issuer: data.issuer || 'Wild Duck'
|
||||||
});
|
});
|
||||||
|
|
||||||
return QRCode.toDataURL(otpauth_url, (err, data_url) => {
|
return QRCode.toDataURL(otpauth_url, (err, data_url) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
log.error('DB', 'QRFAIL username=%s error=%s', userData.username, err.message);
|
log.error('DB', 'QRFAIL username=%s error=%s', userData.username, err.message);
|
||||||
|
@ -642,12 +650,16 @@ class UserHandler {
|
||||||
name: userData.username
|
name: userData.username
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let cipher = crypto.createCipher(config.totp.cipher, config.totp.secret);
|
||||||
|
let seed = '$' + cipher.update(secret.base32, 'utf8', 'hex');
|
||||||
|
seed += cipher.final('hex');
|
||||||
|
|
||||||
return this.users.collection('users').findOneAndUpdate({
|
return this.users.collection('users').findOneAndUpdate({
|
||||||
_id: user,
|
_id: user,
|
||||||
enabled2fa: false
|
enabled2fa: false
|
||||||
}, {
|
}, {
|
||||||
$set: {
|
$set: {
|
||||||
seed: secret.base32
|
seed
|
||||||
}
|
}
|
||||||
}, {}, (err, result) => {
|
}, {}, (err, result) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -714,8 +726,15 @@ class UserHandler {
|
||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let secret = userData.seed;
|
||||||
|
if (userData.seed.charAt(0) === '$') {
|
||||||
|
let decipher = crypto.createDecipher(config.totp.cipher, config.totp.secret);
|
||||||
|
secret = decipher.update(userData.seed.substr(1), 'hex', 'utf-8');
|
||||||
|
secret += decipher.final('utf8');
|
||||||
|
}
|
||||||
|
|
||||||
let verified = speakeasy.totp.verify({
|
let verified = speakeasy.totp.verify({
|
||||||
secret: userData.seed,
|
secret,
|
||||||
encoding: 'base32',
|
encoding: 'base32',
|
||||||
token: data.token,
|
token: data.token,
|
||||||
window: 6
|
window: 6
|
||||||
|
@ -819,8 +838,15 @@ class UserHandler {
|
||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let secret = userData.seed;
|
||||||
|
if (userData.seed.charAt(0) === '$') {
|
||||||
|
let decipher = crypto.createDecipher(config.totp.cipher, config.totp.secret);
|
||||||
|
secret = decipher.update(userData.seed.substr(1), 'hex', 'utf-8');
|
||||||
|
secret += decipher.final('utf8');
|
||||||
|
}
|
||||||
|
|
||||||
let verified = speakeasy.totp.verify({
|
let verified = speakeasy.totp.verify({
|
||||||
secret: userData.seed,
|
secret,
|
||||||
encoding: 'base32',
|
encoding: 'base32',
|
||||||
token: data.token,
|
token: data.token,
|
||||||
window: 6
|
window: 6
|
||||||
|
|
Loading…
Add table
Reference in a new issue