Functional Weave
Code in Rust

auth.password-policy@1.0.1

vectors.json

10,622 bytes · view raw

[
  {"fn": "passwordPolicy", "name": "NIST SP 800-63B-4: a password that is the only factor needs 15 characters", "args": ["nist-800-63b-4-single-factor"], "expect": {"name": "nist-800-63b-4-single-factor", "minLength": 15, "maxLength": 128, "minCharacterClasses": 0, "blockCommon": true, "blockPersonal": true}},
  {"fn": "passwordPolicy", "name": "NIST SP 800-63B-4: a password used with a second factor needs 8", "args": ["nist-800-63b-4-multi-factor"], "expect": {"name": "nist-800-63b-4-multi-factor", "minLength": 8, "maxLength": 128, "minCharacterClasses": 0, "blockCommon": true, "blockPersonal": true}},
  {"fn": "passwordPolicy", "name": "composition rules for organisations that still require them", "args": ["composition-12-3"], "expect": {"name": "composition-12-3", "minLength": 12, "maxLength": 128, "minCharacterClasses": 3, "blockCommon": true, "blockPersonal": true}},
  {"fn": "passwordPolicy", "name": "an unknown name", "args": ["strong"], "expectError": "unknown password policy \"strong\"; known policies: nist-800-63b-4-single-factor, nist-800-63b-4-multi-factor, composition-12-3"},
  {"fn": "passwordPolicy", "name": "names are exact: case matters", "args": ["NIST-800-63B-4-SINGLE-FACTOR"], "expectError": "unknown password policy"},
  {"fn": "passwordPolicy", "name": "names are exact: no trimming", "args": ["nist-800-63b-4-multi-factor "], "expectError": "unknown password policy"},
  {"fn": "passwordPolicy", "name": "the empty name", "args": [""], "expectError": "unknown password policy"},
  {"fn": "passwordPolicy", "name": "an older revision's name is not silently mapped to the new one", "args": ["nist-800-63b"], "expectError": "unknown password policy"},
  {"fn": "checkPassword", "name": "a long passphrase with nothing personal in it", "args": ["correct horse battery staple", "ada@example.com", "Ada Lovelace", {"name": "nist-800-63b-4-single-factor", "minLength": 15, "maxLength": 128, "minCharacterClasses": 0, "blockCommon": true, "blockPersonal": true}], "expect": {"valid": true, "failures": []}},
  {"fn": "checkPassword", "name": "password is on the common list", "args": ["password", null, null, {"name": "nist-800-63b-4-multi-factor", "minLength": 8, "maxLength": 128, "minCharacterClasses": 0, "blockCommon": true, "blockPersonal": true}], "expect": {"valid": false, "failures": [{"code": "too_common", "message": "This password is too common. Choose something harder to guess."}]}},
  {"fn": "checkPassword", "name": "the common list is matched without regard to case", "args": ["PassWord", null, null, {"name": "nist-800-63b-4-multi-factor", "minLength": 8, "maxLength": 128, "minCharacterClasses": 0, "blockCommon": true, "blockPersonal": true}], "expect": {"valid": false, "failures": [{"code": "too_common", "message": "This password is too common. Choose something harder to guess."}]}},
  {"fn": "checkPassword", "name": "too short and too common, both reported", "args": ["password", null, null, {"name": "nist-800-63b-4-single-factor", "minLength": 15, "maxLength": 128, "minCharacterClasses": 0, "blockCommon": true, "blockPersonal": true}], "expect": {"valid": false, "failures": [{"code": "too_short", "message": "Use at least 15 characters."}, {"code": "too_common", "message": "This password is too common. Choose something harder to guess."}]}},
  {"fn": "checkPassword", "name": "too short, with no email or name to compare", "args": ["short", null, null, {"name": "nist-800-63b-4-single-factor", "minLength": 15, "maxLength": 128, "minCharacterClasses": 0, "blockCommon": true, "blockPersonal": true}], "expect": {"valid": false, "failures": [{"code": "too_short", "message": "Use at least 15 characters."}]}},
  {"fn": "checkPassword", "name": "the empty password", "args": ["", null, null, {"name": "nist-800-63b-4-multi-factor", "minLength": 8, "maxLength": 128, "minCharacterClasses": 0, "blockCommon": true, "blockPersonal": true}], "expect": {"valid": false, "failures": [{"code": "too_short", "message": "Use at least 8 characters."}]}},
  {"fn": "checkPassword", "name": "130 characters is over the maximum of 128", "args": ["ababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababab", null, null, {"name": "nist-800-63b-4-multi-factor", "minLength": 8, "maxLength": 128, "minCharacterClasses": 0, "blockCommon": true, "blockPersonal": true}], "expect": {"valid": false, "failures": [{"code": "too_long", "message": "Use no more than 128 characters."}]}},
  {"fn": "checkPassword", "name": "exactly 128 characters is allowed", "args": ["abababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababab", null, null, {"name": "nist-800-63b-4-multi-factor", "minLength": 8, "maxLength": 128, "minCharacterClasses": 0, "blockCommon": true, "blockPersonal": true}], "expect": {"valid": true, "failures": []}},
  {"fn": "checkPassword", "name": "the email's local part and the name, each reported", "args": ["adalovelace2026!!", "ada.lovelace@example.com", "Ada Lovelace", {"name": "nist-800-63b-4-single-factor", "minLength": 15, "maxLength": 128, "minCharacterClasses": 0, "blockCommon": true, "blockPersonal": true}], "expect": {"valid": false, "failures": [{"code": "contains_email", "message": "Do not include your email address in your password."}, {"code": "contains_name", "message": "Do not include your name in your password."}]}},
  {"fn": "checkPassword", "name": "a three-letter local part is refused inside the password", "args": ["my-bob-passphrase-is-long", "bob@example.com", null, {"name": "nist-800-63b-4-single-factor", "minLength": 15, "maxLength": 128, "minCharacterClasses": 0, "blockCommon": true, "blockPersonal": true}], "expect": {"valid": false, "failures": [{"code": "contains_email", "message": "Do not include your email address in your password."}]}},
  {"fn": "checkPassword", "name": "name words under three letters are not refused", "args": ["aljo-is-a-long-passphrase", null, "Al Jo", {"name": "nist-800-63b-4-single-factor", "minLength": 15, "maxLength": 128, "minCharacterClasses": 0, "blockCommon": true, "blockPersonal": true}], "expect": {"valid": true, "failures": []}},
  {"fn": "checkPassword", "name": "eight emoji are 8 characters, not 16 UTF-16 units: too short for 15", "args": ["🔑🔑🔑🔑🔑🔑🔑🔑", null, null, {"name": "nist-800-63b-4-single-factor", "minLength": 15, "maxLength": 128, "minCharacterClasses": 0, "blockCommon": true, "blockPersonal": true}], "expect": {"valid": false, "failures": [{"code": "too_short", "message": "Use at least 15 characters."}]}},
  {"fn": "checkPassword", "name": "eight emoji meet a minimum of 8", "args": ["🔑🔑🔑🔑🔑🔑🔑🔑", null, null, {"name": "nist-800-63b-4-multi-factor", "minLength": 8, "maxLength": 128, "minCharacterClasses": 0, "blockCommon": true, "blockPersonal": true}], "expect": {"valid": true, "failures": []}},
  {"fn": "checkPassword", "name": "one character class when three are required", "args": ["alllowercaseletters", null, null, {"name": "composition-12-3", "minLength": 12, "maxLength": 128, "minCharacterClasses": 3, "blockCommon": true, "blockPersonal": true}], "expect": {"valid": false, "failures": [{"code": "too_few_character_classes", "message": "Use at least 3 of these: lower-case letters, capital letters, digits, symbols."}]}},
  {"fn": "checkPassword", "name": "lower-case, capitals and digits make three classes", "args": ["Lower1234567", null, null, {"name": "composition-12-3", "minLength": 12, "maxLength": 128, "minCharacterClasses": 3, "blockCommon": true, "blockPersonal": true}], "expect": {"valid": true, "failures": []}},
  {"fn": "checkPassword", "name": "a non-ASCII letter counts in the fourth class, with symbols: lower-case, digit and ö make three", "args": ["passwördlong1", null, null, {"name": "composition-12-3", "minLength": 12, "maxLength": 128, "minCharacterClasses": 3, "blockCommon": true, "blockPersonal": true}], "expect": {"valid": true, "failures": []}},
  {"fn": "checkPassword", "name": "every rule broken at once, in the fixed order", "args": ["password1", "password@example.com", "Word Smith", {"name": "composition-12-3", "minLength": 12, "maxLength": 128, "minCharacterClasses": 3, "blockCommon": true, "blockPersonal": true}], "expect": {"valid": false, "failures": [{"code": "too_short", "message": "Use at least 12 characters."}, {"code": "too_few_character_classes", "message": "Use at least 3 of these: lower-case letters, capital letters, digits, symbols."}, {"code": "too_common", "message": "This password is too common. Choose something harder to guess."}, {"code": "contains_email", "message": "Do not include your email address in your password."}, {"code": "contains_name", "message": "Do not include your name in your password."}]}},
  {"fn": "checkPassword", "name": "a policy that blocks neither common nor personal passwords", "args": ["password", "password@example.com", "Pass Word", {"name": "custom", "minLength": 8, "maxLength": 64, "minCharacterClasses": 0, "blockCommon": false, "blockPersonal": false}], "expect": {"valid": true, "failures": []}},
  {"fn": "checkPassword", "name": "a minimum length of 0", "args": ["x", null, null, {"name": "custom", "minLength": 0, "maxLength": 64, "minCharacterClasses": 0, "blockCommon": false, "blockPersonal": false}], "expectError": "policy minLength must be a whole number of at least 1"},
  {"fn": "checkPassword", "name": "a maximum below the minimum", "args": ["x", null, null, {"name": "custom", "minLength": 8, "maxLength": 7, "minCharacterClasses": 0, "blockCommon": false, "blockPersonal": false}], "expectError": "policy maxLength must be a whole number no smaller than minLength"},
  {"fn": "checkPassword", "name": "five character classes do not exist", "args": ["x", null, null, {"name": "custom", "minLength": 8, "maxLength": 64, "minCharacterClasses": 5, "blockCommon": false, "blockPersonal": false}], "expectError": "policy minCharacterClasses must be a whole number from 0 to 4"},
  {"fn": "checkPassword", "name": "a fractional minimum length", "args": ["x", null, null, {"name": "custom", "minLength": 8.5, "maxLength": 64, "minCharacterClasses": 0, "blockCommon": false, "blockPersonal": false}], "expectError": "policy minLength must be a whole number of at least 1"},
  {"fn": "checkPassword", "name": "a password that is not text", "args": [12345678, null, null, {"name": "custom", "minLength": 8, "maxLength": 64, "minCharacterClasses": 0, "blockCommon": false, "blockPersonal": false}], "expectError": "password must be a string"}
]