diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/login.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/login.js index 8ef5c40e4db636ab3d991c9b8cbcc29328e2562f..e0ec38f6a25c5b2ce2f4027c23dfd9fbb1bc372b 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/login.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/login.js @@ -78,16 +78,16 @@ async function preLoginWithPassword (params = {}) { } } const passwordUtils = new PasswordUtils({ - passwordSecret: this.config.passwordSecret + passwordHash: userRecord.password, + passwordSecret: this.config.passwordSecret, + passwordSecretVersion: userRecord.password_secret_version }) const { success: checkPasswordSuccess, refreshPasswordInfo } = passwordUtils.checkUserPassword({ - password, - passwordHash: userRecord.password, - passwordSecretVersion: userRecord.password_secret_version + password }) if (!checkPasswordSuccess) { // 更新用户ip对应的密码错误记录 diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/password.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/password.js index 19ee9205249380741fcd780634d440327ae06056..0d6e7857f9b0ad9cf10c2de9b1a205207a48697b 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/password.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/password.js @@ -3,27 +3,62 @@ const { } = require('../../common/utils') const crypto = require('crypto') +const PasswordMethodMaps = { + A: 'hmac-sha1', + B: 'hmac-sha256' +} +const PasswordMethodFlagMaps = Object.keys(PasswordMethodMaps).reduce((res, item) => { + res[PasswordMethodMaps[item]] = item + return res +}, {}) + const PasswordHashMethod = { 'hmac-sha1': function (content, secret) { const hmac = crypto.createHmac('sha1', secret.toString('ascii')) hmac.update(content) return hmac.digest('hex') + }, + 'hmac-sha256': function (content, secret) { + const hmac = crypto.createHmac('sha256', secret) + hmac.update(content) + return hmac.digest('hex') } } class PasswordUtils { constructor ({ - passwordSecret + passwordHash = '', + passwordSecret = '', + passwordSecretVersion } = {}) { - const passwordSecretType = getType(passwordSecret) - if (passwordSecretType === 'array') { - this.passwordSecret = passwordSecret.sort((a, b) => { - return a.version - b.version - }) - } else if (passwordSecretType === 'string') { - this.passwordSecret = [{ value: passwordSecret }] - } else { - throw new Error('Invalid password secret') + this.passwordHash = passwordHash + this.passwordSecretVersion = passwordSecretVersion + + this.password = this.parsePassword() + + // 老版本会存在 passwordSecret + if (passwordSecret) { + const passwordSecretType = getType(passwordSecret) + if (passwordSecretType === 'array') { + this.passwordSecret = passwordSecret.sort((a, b) => { + return a.version - b.version + }) + } else if (passwordSecretType === 'string') { + this.passwordSecret = [{ value: passwordSecret }] + } + } + } + + parsePassword () { + const [algorithmKey = '', cost = 0, hashStr = ''] = this.passwordHash.split('$').filter(key => key) + const algorithm = PasswordMethodMaps[algorithmKey] || null + const salt = hashStr.substring(0, Number(cost)) + const hash = hashStr.substring(Number(cost)) + + return { + algorithm, + salt, + hash } } @@ -51,37 +86,34 @@ class PasswordUtils { checkUserPassword (params = {}) { const { password, - passwordHash: passwordHashToCheck, - passwordSecretVersion, autoRefresh = true } = params - const currentPasswordSecret = this.getSecretByVersion({ - version: passwordSecretVersion - }) - if (!currentPasswordSecret) { - throw new Error('Invalid password version') + + let passwordHash + + if (this.password.algorithm) { + passwordHash = PasswordHashMethod[this.password.algorithm](password, this.password.salt) + } else { + const hash = this.generatePasswordHash({ + password + }) + + passwordHash = hash.passwordHash } - const { - value: passwordSecret - } = currentPasswordSecret - const { - passwordHash - } = this.generatePasswordHash({ - password, - passwordSecret, - passwordSecretVersion - }) - if (passwordHashToCheck !== passwordHash) { + + if (passwordHash !== this.password.hash && passwordHash !== this.passwordHash) { return { success: false } } let refreshPasswordInfo - if (autoRefresh && passwordSecretVersion !== this.getLastestSecret().version) { + if (autoRefresh) { refreshPasswordInfo = this.generatePasswordHash({ - password + password, + forceUseInternal: true }) } + return { success: true, refreshPasswordInfo @@ -91,8 +123,7 @@ class PasswordUtils { generatePasswordHash (params = {}) { let { password, - passwordSecret, - passwordSecretVersion + forceUseInternal = false } = params if (getType(password) !== 'string') { throw new Error('Invalid password') @@ -101,14 +132,35 @@ class PasswordUtils { if (!password) { throw new Error('Invalid password') } - if (!passwordSecret) { - const lastestSecret = this.getLastestSecret() - passwordSecret = lastestSecret.value - passwordSecretVersion = lastestSecret.version + + // 没有 passwordSecret,使用内置算法(新版) + if (forceUseInternal || !this.passwordSecret) { + // 默认使用 sha256 加密算法 + const salt = crypto.randomBytes(10).toString('hex') + const sha256Hash = PasswordHashMethod['hmac-sha256'](password, salt) + const algorithm = PasswordMethodFlagMaps['hmac-sha256'] + // B 为固定值,对应 PasswordMethodMaps 中的 sha256算法 + // hash 格式 $[PasswordMethodFlagMapsKey]$[salt size]$[salt][Hash] + const hashStr = `$${algorithm}$${salt.length}$${salt}${sha256Hash}` + + return { + passwordHash: hashStr + } + } + + // 旧版本兼容 + let secret + if (this.passwordSecretVersion) { + secret = this.getSecretByVersion({ + version: this.passwordSecretVersion + }) + } else { + secret = this.getLastestSecret() } + return { - passwordHash: PasswordHashMethod['hmac-sha1'](password, passwordSecret), - version: passwordSecretVersion + passwordHash: PasswordHashMethod['hmac-sha1'](password, secret.value), + version: secret.version } } } diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/register.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/register.js index 2ecd186e32133dc40cf09fab4d777bea6ec0f440..1683477a3a545ad97f4089ce54b31b5458503f8d 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/register.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/lib/utils/register.js @@ -53,18 +53,14 @@ async function preRegisterWithPassword(params = {}) { await preRegister.call(this, { user }) - const passwordUtils = new PasswordUtils({ - passwordSecret: this.config.passwordSecret - }) + const passwordUtils = new PasswordUtils() const { - passwordHash, - version + passwordHash } = passwordUtils.generatePasswordHash({ password }) const extraData = { - password: passwordHash, - password_secret_version: version + password: passwordHash } return { user, diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/reset-pwd-by-email.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/reset-pwd-by-email.js index 914a05eed7c79ee3bbf249a473d146cc4f8ed0e7..42d1f127c039113d3be8e2cac7ac51fb3f3fefdd 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/reset-pwd-by-email.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/reset-pwd-by-email.js @@ -12,7 +12,7 @@ const { userCollection, EMAIL_SCENE, CAPTCHA_SCENE, - LOG_TYPE + LOG_TYPE, dbCmd } = require('../../common/constants') const { findUser @@ -92,17 +92,14 @@ module.exports = async function (params = {}) { } const { _id: uid } = userMatched[0] const { - passwordHash, - version - } = new PasswordUtils({ - passwordSecret: this.config.passwordSecret - }).generatePasswordHash({ + passwordHash + } = new PasswordUtils().generatePasswordHash({ password }) // 更新用户密码 await userCollection.doc(uid).update({ password: passwordHash, - password_secret_version: version, + password_secret_version: dbCmd.remove(), valid_token_date: Date.now() }) diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/reset-pwd-by-sms.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/reset-pwd-by-sms.js index 646834f321004dcd5bfa40d61db364bee7503c1a..20522772f52ba634e02c7b5536b76b35725ef8fb 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/reset-pwd-by-sms.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/reset-pwd-by-sms.js @@ -12,7 +12,7 @@ const { userCollection, SMS_SCENE, CAPTCHA_SCENE, - LOG_TYPE + LOG_TYPE, dbCmd } = require('../../common/constants') const { findUser @@ -92,17 +92,14 @@ module.exports = async function (params = {}) { } const { _id: uid } = userMatched[0] const { - passwordHash, - version - } = new PasswordUtils({ - passwordSecret: this.config.passwordSecret - }).generatePasswordHash({ + passwordHash + } = new PasswordUtils().generatePasswordHash({ password }) // 更新用户密码 await userCollection.doc(uid).update({ password: passwordHash, - password_secret_version: version, + password_secret_version: dbCmd.remove(), valid_token_date: Date.now() }) diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/update-pwd.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/update-pwd.js index 7329b736445393accaf754f20aef82e11b24c298..fa4b5cd7070a0a506834cfa73c896d40181b09a8 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/update-pwd.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/account/update-pwd.js @@ -1,5 +1,5 @@ const { - userCollection + userCollection, dbCmd } = require('../../common/constants') const { ERROR @@ -32,16 +32,18 @@ module.exports = async function (params = {}) { newPassword } = params const passwordUtils = new PasswordUtils({ - passwordSecret: this.config.passwordSecret + passwordHash: userRecord.password, + passwordSecret: this.config.passwordSecret, + passwordSecretVersion: userRecord.password_secret_version }) + const { success: checkPasswordSuccess } = passwordUtils.checkUserPassword({ password: oldPassword, - passwordHash: userRecord.password, - passwordSecretVersion: userRecord.password_secret_version, autoRefresh: false }) + if (!checkPasswordSuccess) { throw { errCode: ERROR.PASSWORD_ERROR @@ -49,15 +51,14 @@ module.exports = async function (params = {}) { } const { - passwordHash, - version + passwordHash } = passwordUtils.generatePasswordHash({ password: newPassword }) await userCollection.doc(uid).update({ password: passwordHash, - password_secret_version: version, + password_secret_version: dbCmd.remove(), valid_token_date: Date.now() // refreshToken时会校验,如果创建token时间在此时间点之前,则拒绝下发新token,返回token失效错误码 }) // 执行更新密码操作后客户端应将用户退出重新登录 diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/admin/add-user.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/admin/add-user.js index 6baa5752c017281a02a7250da8d39e0dbf54f55f..90b32934868a1e6b2eb2a0ee2af57a1794af3bdb 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/admin/add-user.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/admin/add-user.js @@ -82,19 +82,15 @@ module.exports = async function (params = {}) { errCode: ERROR.ACCOUNT_EXISTS } } - const passwordUtils = new PasswordUtils({ - passwordSecret: this.config.passwordSecret - }) + const passwordUtils = new PasswordUtils() const { - passwordHash, - version + passwordHash } = passwordUtils.generatePasswordHash({ password }) const data = { username, password: passwordHash, - password_secret_version: version, dcloud_appid: authorizedApp || [], nickname, role: role || [], diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/admin/update-user.js b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/admin/update-user.js index 5dc1b294fdd172071d2132b642f364f2d411c7df..2126466bc2edb24f178f785f0584a4462d5636cf 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/admin/update-user.js +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/admin/update-user.js @@ -5,7 +5,7 @@ const { ERROR } = require('../../common/error') const { - userCollection + userCollection, dbCmd } = require('../../common/constants') const PasswordUtils = require('../../lib/utils/password') @@ -106,18 +106,15 @@ module.exports = async function (params = {}) { } if (password) { - const passwordUtils = new PasswordUtils({ - passwordSecret: this.config.passwordSecret - }) + const passwordUtils = new PasswordUtils() const { - passwordHash, - version + passwordHash } = passwordUtils.generatePasswordHash({ password }) data.password = passwordHash - data.password_secret_version = version + data.password_secret_version = dbCmd.remove() } await userCollection.doc(uid).update(data)