Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cc605e0e authored by Akhil's avatar Akhil 🙂
Browse files

feat: set accepted password length to 8-32 characters in passwords client

parent f39b3356
Loading
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -183,7 +183,7 @@ class AccountController extends Controller {
		$inputData = [
			'username' => ['value' => $username, 'maxLength' => 30],
			'display name' => ['value' => $displayname, 'maxLength' => 30],
			'password' => ['value' => $password, 'maxLength' => 1024],
			'password' => ['value' => $password, 'maxLength' => 32],
		];
		
		foreach ($inputData as $inputName => $inputInfo) {
+3 −0
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@ import EnhancedClassLoader from 'passwords-client/enhanced-class-loader'
import PasswordsClient from 'passwords-client'
import LegacyPasswordsApi from './LegacyPasswordsApi.js'
import ApiRequest from './ApiRequest.js'
import PWDv1Challenge from './PWDv1Challenge.js'

export default new class ClientService {
	constructor() {
@@ -21,6 +22,8 @@ export default new class ClientService {
				client.initialize(this.getClient(), legacyConfig)
				return client
			},
			// Need to over-ride the challenge class to set accepted password length to 8-32 characters
			'challenge.pwdv1': PWDv1Challenge,
			'network.request': ApiRequest,
		}

+72 −0
Original line number Diff line number Diff line
import sodium from 'libsodium-wrappers'
import DefaultClassLoader from 'passwords-client/default-class-loader'

const classLoader = new DefaultClassLoader()
const BasePWDv1Challenge = classLoader._classes['challenge.pwdv1']

export default class PWDv1Challenge extends BasePWDv1Challenge {
	constructor(data = {}) {
		super(data)
	}

	_validatePasswordLength() {
		if (this._password.length < 8) throw new Error('Password is too short')
		if (this._password.length > 128) throw new Error('Password is too long')
	}

	solve() {
		this._validatePasswordLength()
		const salts = this._salts

		const passwordSalt = sodium.from_hex(salts[0])
		const genericHashKey = sodium.from_hex(salts[1])
		const passwordHashSalt = sodium.from_hex(salts[2])
		const genericHash = sodium.crypto_generichash(
			sodium.crypto_generichash_BYTES_MAX,
			new Uint8Array([...sodium.from_string(this._password), ...passwordSalt]),
			genericHashKey
		)

		const passwordHash = sodium.crypto_pwhash(
			sodium.crypto_box_SEEDBYTES,
			genericHash,
			passwordHashSalt,
			sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE,
			sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE,
			sodium.crypto_pwhash_ALG_DEFAULT
		)

		return sodium.to_hex(passwordHash)
	}

	create() {
		this._validatePasswordLength()

		const passwordSalt = sodium.randombytes_buf(256)
		const genericHashKey = sodium.randombytes_buf(sodium.crypto_generichash_KEYBYTES_MAX)
		const genericHash = sodium.crypto_generichash(
			sodium.crypto_generichash_BYTES_MAX,
			new Uint8Array([...sodium.from_string(this._password), ...passwordSalt]),
			genericHashKey
		)

		const passwordHashSalt = sodium.randombytes_buf(sodium.crypto_pwhash_SALTBYTES)
		const passwordHash = sodium.crypto_pwhash(
			sodium.crypto_box_SEEDBYTES,
			genericHash,
			passwordHashSalt,
			sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE,
			sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE,
			sodium.crypto_pwhash_ALG_DEFAULT
		)

		return {
			salts: [
				sodium.to_hex(passwordSalt),
				sodium.to_hex(genericHashKey),
				sodium.to_hex(passwordHashSalt),
			],
			secret: sodium.to_hex(passwordHash),
		}
	}
}