/**
* @file MFKDF Policy Evaluation
* @copyright Multifactor 2022 All Rights Reserved
*
* @description
* Determine whether key can be derived from given factors
*
* @author Vivek Nair (https://nair.me) <[email protected]>
*/
/**
* Evaluate a policy-based multi-factor derived key
*
* @example
* // setup key that can be derived from passwordA AND (passwordB OR passwordC)
* const setup = await mfkdf.policy.setup(
* await mfkdf.policy.and(
* await mfkdf.setup.factors.password('passwordA', { id: 'passwordA' }),
* await mfkdf.policy.or(
* await mfkdf.setup.factors.password('passwordB', { id: 'passwordB' }),
* await mfkdf.setup.factors.password('passwordC', { id: 'passwordC' })
* )
* )
* )
*
* // check if key can be derived with passwordA and passwordC
* const valid1 = await mfkdf.policy.evaluate(setup.policy, ['passwordA', 'passwordC']) // -> true
*
* // check if key can be derived with passwordB and passwordC
* const valid2 = await mfkdf.policy.evaluate(setup.policy, ['passwordB', 'passwordC']) // -> false
*
* @param {Object} policy - The key policy for the key being derived
* @param {Array.<string>} factors - Array of factor ids used to derive this key
* @returns {boolean} Whether the key can be derived with given factor ids
* @author Vivek Nair (https://nair.me) <[email protected]>
* @since 0.16.0
* @memberOf policy
*/
function evaluate (policy, factors) {
const threshold = policy.threshold
let actual = 0
for (const factor of policy.factors) {
if (factor.type === 'stack') {
if (evaluate(factor.params, factors)) actual++
} else {
if (factors.includes(factor.id)) actual++
}
}
return (actual >= threshold)
}
module.exports.evaluate = evaluate