RFC 7613

Preparation, Enforcement, and Comparison of Internationalized Strings Representing Usernames and Passwords

πŸ“… published August 2015, from ietf

Preparation, Enforcement, and Comparison of Internationalized Strings Representing Usernames and Passwords ✨

Okay bestie, let's start with the basics πŸŽ€. This is RFC 7613, written by P. Saint-Andre (from &yet) and A. Melnikov (from Isode Ltd), and it was published in August 2015. It's a Standards Track document, ISSN 2070-1721, and it obsoletes RFC 4013 πŸ’…. It doesn't list any RFCs that it updates.

Abstract

okay so this doc gives us updated ways to handle Unicode strings that hold usernames and passwords πŸ¦‹. The old approach was called SASLprep (RFC 4013), and it was built on stringprep (RFC 3454). The new methods are way more sustainable for internationalized usernames and passwords, lowkey iconic πŸ‘‘. The PRECIS framework (RFC 7564) obsoletes RFC 3454, and this document obsoletes RFC 4013 🫢.

Status of This Memo

this is an Internet Standards Track document 🌈.

it's a product of the Internet Engineering Task Force (IETF) and it represents the consensus of the IETF community πŸ’œ. It got public review and was approved for publication by the Internet Engineering Steering Group (IESG). If you want more info on Internet Standards, check Section 2 of RFC 5741 πŸ“.

For the current status of this document, any errata, and how to give feedback on it, go to http://www.rfc-editor.org/info/rfc7613 ✨.

Copyright (c) 2015 IETF Trust and the persons identified as the document authors. All rights reserved πŸ”₯.

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, because they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions, and they are provided without warranty as described in the Simplified BSD License πŸ’–.

Table of Contents

   1. Introduction ....................................................4
   2. Terminology .....................................................5
   3. Usernames .......................................................6
      3.1. Definition .................................................6
      3.2. UsernameCaseMapped Profile .................................7
           3.2.1. Preparation .........................................7
           3.2.2. Enforcement .........................................7
           3.2.3. Comparison ..........................................8
      3.3. UsernameCasePreserved Profile ..............................8
           3.3.1. Preparation .........................................8
           3.3.2. Enforcement .........................................8
           3.3.3. Comparison ..........................................9
      3.4. Case Mapping vs. Case Preservation .........................9
      3.5. Application-Layer Constructs ..............................10
      3.6. Examples ..................................................11
   4. Passwords ......................................................13
      4.1. Definition ................................................13
      4.2. OpaqueString Profile ......................................14
           4.2.1. Preparation ........................................14
           4.2.2. Enforcement ........................................14
           4.2.3. Comparison .........................................15
      4.3. Examples ..................................................15
   5. Use in Application Protocols ...................................16
   6. Migration ......................................................16
      6.1. Usernames .................................................17
      6.2. Passwords .................................................18
   7. IANA Considerations ............................................19
      7.1. UsernameCaseMapped Profile ................................19
      7.2. UsernameCasePreserved Profile .............................20
      7.3. OpaqueString Profile ......................................20
      7.4. Stringprep Profile ........................................21
   8. Security Considerations ........................................21
      8.1. Password/Passphrase Strength ..............................21
      8.2. Identifier Comparison .....................................21
      8.3. Reuse of PRECIS ...........................................21
      8.4. Reuse of Unicode ..........................................22
   9. References .....................................................22
      9.1. Normative References ......................................22
      9.2. Informative References ....................................23
   Appendix A. Differences from RFC 4013 .............................26
   Acknowledgements ..................................................27
   Authors' Addresses ................................................27

1. Introduction ✨

Usernames and passwords are everywhere for authentication and authorization on the Internet πŸ”. Sometimes they're sent in plaintext, like in the PLAIN Simple Authentication and Security Layer (SASL) mechanism [RFC4616] and the HTTP Basic scheme [HTTP-BASIC-AUTH]. Other times they're fed into a cryptographic algorithm like a hash function, like in the Salted Challenge Response Authentication Mechanism (SCRAM) SASL mechanism [RFC5802] and the HTTP Digest scheme [HTTP-DIGEST-AUTH] πŸ’œ.

So this document defines rules for preparing, enforcing, and comparing internationalized strings that represent usernames and passwords 🌸. The goal is that input and comparison work in ways that make sense for typical users all around the world. These strings are made of characters from the Unicode character set [Unicode], with special attention to characters outside the ASCII range [RFC20]. The rules are specified through profiles of the string classes in the preparation, enforcement, and comparison of internationalized strings (PRECIS) framework specification [RFC7564] πŸ¦‹.

PRECIS profiles let software handle non-ASCII Unicode characters automatically, so those characters get treated carefully and consistently across application protocols 🫧. Mostly, these profiles protect app developers from the risks of supporting the whole Unicode range. For example, in almost every application protocol it would be dangerous to treat SUPERSCRIPT ONE (U+00B9) as equal to DIGIT ONE (U+0031). That would cause false positives during comparison, authentication, and authorization. An attacker could easily spoof an account like "user1@example.com" πŸ™ˆ.

Basically, if you use Unicode naively, those attacks become trivially easy. The PRECIS profile for usernames protects apps from accidentally causing this stuff πŸ›‘οΈ. (Similar concerns apply to passwords, but there it's better to support a wider range of characters so you get more entropy for authentication πŸ”₯.)

The methods here might apply anywhere usernames or passwords are used. They are not meant for preparing strings that aren't usernames, like Lightweight Directory Access Protocol (LDAP) distinguished names. They also aren't for cases where identifiers or secrets aren't strings, like keys and certificates, or where they need specialized handling πŸ™…β€β™€οΈ.

This document obsoletes RFC 4013 (the SASLprep profile of stringprep [RFC3454]). It can still be used by technologies other than SASL [RFC4422], such as HTTP authentication as specified in [HTTP-BASIC-AUTH] and [HTTP-DIGEST-AUTH] 🧚.

This document does not change how existing application protocols that use SASLprep handle internationalized strings in usernames and passwords. If a community that uses one of those protocols wants to modernize and switch from stringprep to PRECIS, it needs to explicitly update that application protocol definition. One example is [XMPP-ADDR], which is intended to obsolete [RFC6122]. Non-coordinated updates to protocol implementations are discouraged, because they can seriously hurt interoperability and security πŸ’€.

2. Terminology ✨

A lot of the important terms in this doc are defined in [RFC5890], [RFC6365], [RFC7564], and [Unicode] πŸ“š. The term "non-ASCII space" means any Unicode code point with the Unicode general category "Zs", except for U+0020 (here called "ASCII space") 🌈.

Here, "password" isn't literally limited to one word. A password could be a passphrase made of several words, maybe separated by spaces, punctuation, or other non-alphanumeric characters πŸ“.

Some SASL mechanisms (like CRAM-MD5, DIGEST-MD5, and SCRAM) say that the authentication identity is a "simple user name" (see Section 2 of [RFC4422] and [RFC4013]). A lot of application technologies also assume a user's identity is a username, like HTTP authentication as specified in [HTTP-BASIC-AUTH] and [HTTP-DIGEST-AUTH], whether or not they use SASL πŸ’–. Just know that the exact form of a username in any given SASL mechanism or app technology is up to implementation and deployment. A username also doesn't have to map to any particular application identifier, like the localpart of an email address 🫢.

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119] πŸŽ€.

3. Usernames πŸ‘‘

3.1. Definition ✨

okay so bestie, here's the tea πŸ«– a username is a string of Unicode code points [Unicode], encoded in UTF-8 [RFC3629], and it's built as an ordered sequence of "userparts" 🧩 A userpart can only contain code points that are themselves allowed by the PRECIS IdentifierClass defined in Section 4.2 of [RFC7564], so it's basically letters and digits and nothing spicy πŸ’… A username can be one userpart on its own, or a space-separated sequence of userparts 🌸

The syntax is defined like this, using the Augmented Backus-Naur Form (ABNF) [RFC5234] πŸŽ€

      username   = userpart *(1*SP userpart)
      userpart   = 1*(idbyte)
                   ;
                   ; an "idbyte" is a byte used to represent a
                   ; UTF-8 encoded Unicode code point that can be
                   ; contained in a string that conforms to the
                   ; PRECIS IdentifierClass
                   ;

Everything that isn't explicitly allowed in the PRECIS IdentifierClass is disallowed 🚫 That includes private use characters, surrogate code points, and the other code points and blocks that were defined as "Prohibited Output" in [RFC4013] πŸ’€ Also, common constructions like "user@example.com" (for example, the Network Access Identifier from [RFC7542]) are still allowed as usernames under this spec, same as they were under [RFC4013] πŸ¦‹

Implementation Note: The username construct defined in this document does not necessarily match what all deployed applications might refer to as a "username" or "userid" but instead provides a relatively safe subset of Unicode characters that can be used in existing SASL mechanisms and in application protocols that use SASL, and even in most application protocols that do not currently use SASL. 🧚

A username MUST NOT be zero bytes in length πŸ™…β€β™€οΈ This rule gets enforced after any normalization and mapping of code points, so the empty-string sneak attack doesn't work 😀

In protocols that hand usernames to a cryptographic algorithm such as a hash function, the client will need to enforce the rules for the UsernameCaseMapped or UsernameCasePreserved profile before applying the algorithm πŸ”

This spec defines two profiles for usernames: one that does case mapping and one that does case preservation (more on that drama in Section 3.4) πŸ’œ


3.2. UsernameCaseMapped Profile πŸ“

The UsernameCaseMapped profile of the IdentifierClass is defined in the sections below, with all the details on preparation, enforcement, and comparison πŸ“ (if you're wondering how those three differ, check out [RFC7564] for the full breakdown πŸ€“)

3.2.1. Preparation

An entity that prepares a string according to this profile MUST first map fullwidth and halfwidth characters to their decomposition mappings (see Unicode Standard Annex #11 [UAX11]) πŸͺ„ This is needed because the PRECIS "HasCompat" category specified in Section 9.17 of [RFC7564] would otherwise forbid fullwidth and halfwidth characters πŸ™ƒ After applying this width-mapping rule, the entity then MUST ensure that the string consists only of Unicode code points that conform to the PRECIS IdentifierClass defined in Section 4.2 of [RFC7564] 🧼 And then the entity MUST encode the string as UTF-8 [RFC3629] ✨

3.2.2. Enforcement

An entity that enforces this profile MUST prepare a string as described in Section 3.2.1 and MUST also apply the rules below for the UsernameCaseMapped profile, and these rules MUST be applied in the order shown πŸ”₯

  1. Width-Mapping Rule: Applied as part of preparation (see above).
  2. Additional Mapping Rule: There is no additional mapping rule.
  3. Case-Mapping Rule: Uppercase and titlecase characters MUST be mapped to their lowercase equivalents, preferably using Unicode Default Case Folding as defined in the Unicode Standard [Unicode] (at the time of this writing, the algorithm is specified in Chapter 3 of [Unicode7.0], but the chapter number might change in a future version of the Unicode Standard); see further discussion in Section 3.4. πŸ”‘
  4. Normalization Rule: Unicode Normalization Form C (NFC) MUST be applied to all characters. 🧩
  5. Directionality Rule: Applications MUST apply the "Bidi Rule" defined in [RFC5893] to strings that contain right-to-left characters (i.e., each of the six conditions of the Bidi Rule must be satisfied). πŸ”„

3.2.3. Comparison

An entity that compares two strings according to this profile MUST prepare each string as specified in Section 3.2.1 and then enforce the rules specified in Section 3.2.2 πŸͺž The two strings are considered equivalent if they are an exact octet-for-octet match (sometimes called "bit-string identity") πŸ’–


3.3. UsernameCasePreserved Profile 🌈

The UsernameCasePreserved profile of the IdentifierClass is defined in the sections below, with detailed info on preparation, enforcement, and comparison πŸ’… (the difference between those actions is covered in [RFC7564] πŸ“š)

3.3.1. Preparation

An entity that prepares a string according to this profile MUST first map fullwidth and halfwidth characters to their decomposition mappings (see Unicode Standard Annex #11 [UAX11]) πŸͺ„ This is needed because the PRECIS "HasCompat" category specified in Section 9.17 of [RFC7564] would otherwise forbid fullwidth and halfwidth characters πŸ™ƒ After applying this width-mapping rule, the entity then MUST ensure that the string consists only of Unicode code points that conform to the PRECIS IdentifierClass defined in Section 4.2 of [RFC7564] 🧼 And then the entity MUST encode the string as UTF-8 [RFC3629] ✨

3.3.2. Enforcement

An entity that enforces this profile MUST prepare a string as described in Section 3.3.1 and MUST also apply the rules below for the UsernameCasePreserved profile (these rules MUST be applied in the order shown) πŸŽ€

  1. Width-Mapping Rule: Applied as part of preparation (see above).
  2. Additional Mapping Rule: There is no additional mapping rule.
  3. Case-Mapping Rule: Uppercase and titlecase characters MUST NOT be mapped to their lowercase equivalents; see further discussion in Section 3.4. πŸ™…β€β™€οΈ
  4. Normalization Rule: Unicode Normalization Form C (NFC) MUST be applied to all characters. 🧩
  5. Directionality Rule: Applications MUST apply the "Bidi Rule" defined in [RFC5893] to strings that contain right-to-left characters (i.e., each of the six conditions of the Bidi Rule must be satisfied). πŸ”„

3.3.3. Comparison

An entity that compares two strings according to this profile MUST prepare each string as specified in Section 3.3.1 and then enforce the rules specified in Section 3.3.2 πŸͺž The two strings are considered equivalent if they are an exact octet-for-octet match (sometimes called "bit-string identity") πŸ’–


3.4. Case Mapping vs. Case Preservation πŸ₯Ή

To cover the widest range of username setups in applications, this document defines two username profiles: UsernameCaseMapped and UsernameCasePreserved πŸ’œ They differ only in the Case-Mapping Rule and are otherwise identical πŸ‘―β€β™€οΈ

Case mapping is a matter for the application protocol, protocol implementation, or end deployment 🫢 In general, this document suggests that it is preferable to apply the UsernameCaseMapped profile (so, do case mapping) πŸ™Œ Not doing it can lead to false positives during authentication and authorization (as described in [RFC6943]) and can cause confusion for end users, given how common case mapping already is in many existing protocols and applications 😭 That said, there can be good reasons to apply the UsernameCasePreserved profile and skip case mapping, like backward compatibility with deployed infrastructure 🏚️

Here's the breakdown πŸ‘‡

  • SASL mechanisms that follow the recommendations in this document MUST specify whether and when case mapping is to be applied to authentication identifiers. SASL mechanisms SHOULD delay any case mapping to the last possible moment, such as when doing a lookup by username, performing username comparisons, or generating a cryptographic salt from a username (if the last possible moment happens on the server, then decisions about case mapping can be a matter of deployment policy). In keeping with [RFC4422], SASL mechanisms are not to apply this or any other profile to authorization identifiers, only to authentication identifiers. πŸ”‘
  • Application protocols that use SASL (such as IMAP [RFC3501] and the Extensible Messaging and Presence Protocol (XMPP) [RFC6120]) and that directly reuse this profile MUST specify whether or not case mapping is to be applied to authorization identifiers. Such "SASL application protocols" SHOULD delay any case-mapping of authorization identifiers to the last possible moment, which happens to necessarily be on the server side (this enables decisions about case mapping to be a matter of deployment policy). In keeping with [RFC4422], SASL application protocols are not to apply this or any other profile to authentication identifiers, only to authorization identifiers. πŸ“¬
  • Application protocols that do not use SASL (such as HTTP authentication with the HTTP Basic and Digest schemes as specified in [HTTP-BASIC-AUTH] and [HTTP-DIGEST-AUTH]) but that directly reuse this profile MUST specify whether and when case mapping is to be applied to authentication identifiers or authorization identifiers, or both. Such "non-SASL application protocols" SHOULD delay any case mapping to the last possible moment, such as when doing a lookup by username, performing username comparisons, or generating a cryptographic salt from a username (if the last possible moment happens on the server, then decisions about case mapping can be a matter of deployment policy). 🌐

If the specification for a SASL mechanism, SASL application protocol, or non-SASL application protocol uses the UsernameCaseMapped profile, it MUST clearly describe whether case mapping is to be applied at the level of the protocol itself, implementations thereof, or service deployments (each of these approaches can be legitimate, depending on the application in question) πŸ“‹


3.5. Application-Layer Constructs 🧁

Both the UsernameCaseMapped and UsernameCasePreserved profiles let an application protocol, implementation, or deployment create application-layer constructs, like a username that's a space-separated set of userparts such as "Firstname Middlename Lastname" πŸŽ‚ Technically that construct isn't a profile of the PRECIS IdentifierClass (because U+0020 SPACE isn't allowed in the IdentifierClass) πŸ™ˆ But it can still be created at the application layer, because U+0020 SPACE can be used as a separator between instances of the PRECIS IdentifierClass (for example, userparts as defined in this specification) 🌟

3.6. Examples πŸ–ΌοΈ

okay, this is the example gallery πŸ’… These are userparts (not full usernames, bestie!) that follow the format we just covered. The < and > are only there to show where each userpart starts and ends. They are NOT part of the string 🫢

      +--------------------------+---------------------------------+
      | # | Userpart             | Notes                           |
      +--------------------------+---------------------------------+
      | 1 | <juliet@example.com> | The at-sign is allowed in the   |
      |   |                      | PRECIS IdentifierClass          |
      +--------------------------+---------------------------------+
      | 2 | <fussball>           |                                 |
      +--------------------------+---------------------------------+
      | 3 | <fu&#xDF;ball>       | The third character is LATIN    |
      |   |                      | SMALL LETTER SHARP S (U+00DF)   |
      +--------------------------+---------------------------------+
      | 4 | <&#x3C0;>            | A userpart of GREEK SMALL       |
      |   |                      | LETTER PI (U+03C0)              |
      +--------------------------+---------------------------------+
      | 5 | <&#x3A3;>            | A userpart of GREEK CAPITAL     |
      |   |                      | LETTER SIGMA (U+03A3)           |
      +--------------------------+---------------------------------+
      | 6 | <&#x3C3;>            | A userpart of GREEK SMALL       |
      |   |                      | LETTER SIGMA (U+03C3)           |
      +--------------------------+---------------------------------+
      | 7 | <&#x3C2;>            | A userpart of GREEK SMALL       |
      |   |                      | LETTER FINAL SIGMA (U+03C2)     |
      +--------------------------+---------------------------------+

                   Table 1: A Sample of Legal Userparts

okay, a few things are worth noticing πŸ‘€ Examples 2 and 3 are the eszett situation πŸ‡©πŸ‡ͺ In German, the character eszett (LATIN SMALL LETTER SHARP S (U+00DF)) can mostly be swapped with the two characters "ss", BUT these userparts are different. So if you want, a server needs a registration policy that blocks one of them whenever the other is already registered πŸ”’

Examples 5, 6, and 7 are the sigma drama 😭 If comparison optionally case-maps GREEK CAPITAL LETTER SIGMA (U+03A3) to lowercase (that's GREEK SMALL LETTER SIGMA (U+03C3)), then examples 5 and 6 match ✨ Here's the tea though: the PRECIS mapping rules don't account for the special status of GREEK SMALL LETTER FINAL SIGMA (U+03C2), so example 7 doesn't match either one. That means 5 and 7, or 6 and 7, won't match during comparison πŸ’€

Now for the strings that are NOT valid userparts, because they break the format πŸ™…β€β™€οΈ

      +--------------------------+---------------------------------+
      | # | Non-Userpart String  | Notes                           |
      +--------------------------+---------------------------------+
      | 8 | <foo bar>            | Space (U+0020) is disallowed in |
      |   |                      | the userpart                    |
      +--------------------------+---------------------------------+
      | 9 | <>                   | Zero-length userpart            |
      +--------------------------+---------------------------------+
      | 10| <henry&#x2163;>      | The sixth character is ROMAN    |
      |   |                      | NUMERAL FOUR (U+2163)           |
      +--------------------------+---------------------------------+
      | 11| <&#x265A;>           | A localpart of BLACK CHESS KING |
      |   |                      | (U+265A)                        |
      +--------------------------+---------------------------------+

        Table 2: A Sample of Strings That Violate the Userpart Rule

and yes, a few more notes 🧐 Example 8 is not a valid userpart, BUT it IS a valid username, because it's a space-separated sequence of userparts. Main character plot twist πŸŽ€ Example 10: ROMAN NUMERAL FOUR (U+2163) has a compatibility equivalent of the string made from LATIN CAPITAL LETTER I (U+0049) and LATIN CAPITAL LETTER V (U+0056), but characters with compatibility equivalents are not allowed in the PRECIS IdentifierClass. Example 11: symbol characters like BLACK CHESS KING (U+265A) are also not allowed in the PRECIS IdentifierClass β™ŸοΈπŸš«


4. Passwords πŸ”

4.1. Definition πŸ—οΈ

okay so in this document, a password is a string of Unicode code points [Unicode], encoded using UTF-8 [RFC3629], and it has to be conformant to the OpaqueString profile (more on that below) of the PRECIS FreeformClass defined in Section 4.3 of [RFC7564] πŸ’–

The syntax for a password is defined using the Augmented Backus-Naur Form (ABNF) [RFC5234]:

   password   = 1*(freebyte)
                ;
                ; a "freebyte" is a byte used to represent a
                ; UTF-8 encoded Unicode code point that can be
                ; contained in a string that conforms to the
                ; PRECIS FreeformClass
                ;

Anything not explicitly allowed in the PRECIS FreeformClass is disallowed, no exceptions 🚫 That includes private use characters, surrogate code points, and the other code points and blocks defined as "Prohibited Output" in Section 2.3 of RFC 4013 (when corrected per [Err1812]).

A password MUST NOT be zero bytes in length. This rule is enforced after any normalization and mapping of code points. 🚨
Note: Some existing systems let an empty string sit where a password should be, like command-line tools called from an automated script, or servers that need a restart without a human around πŸ€– From the perspective of this document (and RFC 4013 before it), those empty strings aren't passwords. They're workarounds for the practical difficulty of using passwords in certain scenarios. The zero-length ban isn't a comment on password strength (a one-byte password is extremely insecure, obviously). It's there to stop apps from accidentally leaving the password out entirely. That can happen once internationalized characters are accepted, because a non-empty sequence of characters can end up as a zero-length password after canonicalization 😭

Protocols that give a password to a cryptographic algorithm, like a hash function, have a catch πŸ™ˆ The client will need to enforce the OpaqueString profile rules before applying the algorithm, because the server never gets the password in plaintext.

4.2. OpaqueString Profile 🌸

The OpaqueString profile is spelled out in the sections below, covering preparation, enforcement, and comparison. (If you're confused about how those three differ, refer to [RFC7564] πŸ“š)

4.2.1. Preparation ✨

An entity that prepares a string under this profile MUST make sure the string only has Unicode code points that conform to the FreeformClass base string class defined in [RFC7564]. On top of that, the entity MUST encode the string as UTF-8 [RFC3629] πŸ’œ

4.2.2. Enforcement πŸ’…

An entity that enforces this profile MUST prepare the string as described in Section 4.2.1 AND MUST apply the rules below for the OpaqueString profile (these rules MUST be applied in the order shown) πŸŽ€

  1. Width-Mapping Rule: Fullwidth and halfwidth characters MUST NOT be mapped to their decomposition mappings (see Unicode Standard Annex #11 [UAX11]) πŸ™…β€β™€οΈ
  2. Additional Mapping Rule: Any instance of non-ASCII space MUST be mapped to ASCII space (U+0020). A non-ASCII space is any Unicode code point with a Unicode general category of "Zs" (except U+0020) 🌈
  3. Case-Mapping Rule: Uppercase and titlecase characters MUST NOT be mapped to their lowercase equivalents πŸ” 
  4. Normalization Rule: Unicode Normalization Form C (NFC) MUST be applied to all characters 🧼
  5. Directionality Rule: There is no directionality rule here. The "Bidi Rule" (defined in [RFC5893]) and similar rules are unnecessary and inapplicable to passwords, because they can shrink the set of allowed characters and therefore shrink the entropy a password can have. Those rules exist so the same string looks the same on a right-to-left layout system and a left-to-right one. But passwords are usually not displayed at all, and they're rarely meant to be interoperable across layout systems the way non-secret strings like domain names and usernames are. Also, it's totally fine for opaque strings other than passwords to look different on different layout systems, as long as the look stays consistent on any given system 🌍

4.2.3. Comparison πŸ”

An entity that compares two strings under this profile MUST prepare each string as specified in Section 4.2.1, and then enforce the rules in Section 4.2.2. The two strings count as equivalent only if they're an exact octet-for-octet match (sometimes called "bit-string identity") 🫢

4.3. Examples πŸŽ€

Okay, so here are some passwords that totally pass the vibe check for the format we just defined πŸ’… (quick note: the "<" and ">" are only there to show where each password starts and ends. They're NOT part of the password itself πŸ™ˆ)

   +------------------------------------+------------------------------+
   | # | Password                       | Notes                        |
   +------------------------------------+------------------------------+
   | 12| <correct horse battery staple> | ASCII space is allowed       |
   +------------------------------------+------------------------------+
   | 13| <Correct Horse Battery Staple> | Differs by case from         |
   |   |                                | example 12                   |
   +------------------------------------+------------------------------+
   | 14| <&#x3C0;&#xDF;&#xE5;>          | Non-ASCII letters are OK     |
   |   |                                | (e.g., GREEK SMALL LETTER    |
   |   |                                | PI (U+03C0))                 |
   +------------------------------------+------------------------------+
   | 15| <Jack of &#x2666;s>            | Symbols are OK (e.g., BLACK  |
   |   |                                | DIAMOND SUIT (U+2666))       |
   +------------------------------------+------------------------------+
   | 16| <foo&#x1680;bar>               | OGHAM SPACE MARK (U+1680) is |
   |   |                                | mapped to U+0020, and thus   |
   |   |                                | the full string is mapped to |
   |   |                                | <foo bar>                    |
   +------------------------------------+------------------------------+

                   Table 3: A Sample of Legal Passwords

Next up, a string that is NOT a valid password, because it breaks the format rules we just talked about πŸ’€

   +------------------------------------+------------------------------+
   | # | Password                       | Notes                        |
   +------------------------------------+------------------------------+
   | 17| <my cat is a &#x9;by>          | Controls are disallowed      |
   +------------------------------------+------------------------------+

            Table 4: A String That Violates the Password Rules

5. Use in Application Protocols ✨

Bestie, this spec only defines the PRECIS-based rules for strings that follow the UsernameCaseMapped and UsernameCasePreserved profiles of the PRECIS IdentifierClass, plus strings that follow the OpaqueString profile of the PRECIS FreeformClass πŸ’œ It's the job of each application protocol to say which protocol slots these strings can show up in, who is supposed to enforce the rules, and at what points during protocol processing or interface handling the rules get enforced. If you want guidelines on using PRECIS profiles in applications, check out Section 6 of [RFC7564] πŸ”₯

Beyond the PRECIS-based rules here, application protocols can also add their own application-specific rules for these strings. That means things like minimum or maximum length, extra limits on which characters or character ranges are allowed, safeguards against visually similar characters, and so on πŸ¦‹ They can also define application-layer constructs (see Section 3.5), plus related matters.

Some PRECIS profile definitions encourage the enforcing entities to be liberal in what they accept. Lowkey though, for usernames and passwords that can be a problem, because it can lead to false positives 😭 There's a deeper dive on this in [RFC6943] 🌸


6. Migration 🧚

Okay, so the rules in this spec are a little different from the ones in the SASLprep specification [RFC4013]. The sections below walk through those differences and what they mean for migrating, in more detail 🫢

6.1. Usernames πŸ“

If a deployment is currently using SASLprep for usernames, it might need to scrub its existing data when it migrates to the rules in this spec. Here's what to watch for:

  • SASLprep specified the use of Unicode Normalization Form KC (NFKC), whereas the UsernameCaseMapped and UsernameCasePreserved profiles use Unicode Normalization Form C (NFC). In practice, this change is unlikely to cause big problems. NFKC maps Unicode code points with compatibility equivalents to those equivalents, whereas the PRECIS IdentifierClass completely disallows Unicode code points with compatibility equivalents. (So during comparison, NFKC is more "aggressive" about finding matches than NFC.) A few examples should show the idea:
    1. LATIN SMALL LETTER LONG S (U+017F) is compatibility equivalent to LATIN SMALL LETTER S (U+0073).
    2. ROMAN NUMERAL FOUR (U+2163) is compatibility equivalent to LATIN CAPITAL LETTER I (U+0049) and LATIN CAPITAL LETTER V (U+0056).
    3. LATIN SMALL LIGATURE FI (U+FB01) is compatibility equivalent to LATIN SMALL LETTER F (U+0066) and LATIN SMALL LETTER I (U+0069).

Under SASLprep, NFKC also handled the mapping of fullwidth and halfwidth code points to their decomposition mappings.

For migration, operators might want to search their database of usernames for names that contain Unicode code points with compatibility equivalents. Where there's no conflict, they can map those code points to their equivalents. Naturally, this process might turn up conflicting usernames. For example, "HENRYIV" with the last two characters being LATIN CAPITAL LETTER I (U+0049) and LATIN CAPITAL LETTER V (U+0056), versus "HENRYIV" with the last character being ROMAN NUMERAL FOUR (U+2163), which is compatibility equivalent to U+0049 and U+0056. In those cases, the operator will need to figure out how to proceed. One option is disabling the account whose name contains a Unicode code point with a compatibility equivalent. Cases like this are probably rare, but it's important for operators to be aware of them πŸ‘‘

  • SASLprep mapped the "characters commonly mapped to nothing" from Appendix B.1 of [RFC3454]) to nothing. The PRECIS IdentifierClass, on the other hand, completely disallows most of these characters. They correspond to the code points from the PRECIS "M" category defined under Section 9.13 of [RFC7564] (with the exception of MONGOLIAN TODO SOFT HYPHEN (U+1806), which was "commonly mapped to nothing" in Unicode 3.2 but, at the time of this writing, does not have a derived property of Default_Ignorable_Code_Point in Unicode 7.0). For migration, the operator might want to remove from usernames any code points contained in the PRECIS "M" category (e.g., SOFT HYPHEN (U+00AD)). Because these code points would have been "mapped to nothing" in stringprep, in practice a user wouldn't notice the difference if the code points are removed during the move to PRECIS πŸ™ˆ
  • SASLprep allowed uppercase and titlecase characters. The UsernameCaseMapped profile maps uppercase and titlecase characters to their lowercase equivalents (by contrast, the UsernameCasePreserved profile matches SASLprep on this). For migration, the operator can use either the UsernameCaseMapped profile (which loses the case information) or the UsernameCasePreserved profile (which ignores case differences when comparing usernames) ✨

6.2. Passwords 🌈

Depending on local service policy, migrating from RFC 4013 to this spec might not involve scrubbing any data, because passwords might not be stored in the clear anyway. Still, service providers need to be aware of possible issues that might pop up during migration. Here's the tea:

  • SASLprep specified the use of Unicode Normalization Form KC (NFKC), whereas the OpaqueString profile uses Unicode Normalization Form C (NFC). Because NFKC is more aggressive about finding matches than NFC, this change is unlikely to cause big problems in practice. It actually has the security benefit of probably resulting in fewer false positives when comparing passwords πŸ”₯ A few examples should show the idea:
    1. LATIN SMALL LETTER LONG S (U+017F) is compatibility equivalent to LATIN SMALL LETTER S (U+0073).
    2. ROMAN NUMERAL FOUR (U+2163) is compatibility equivalent to LATIN CAPITAL LETTER I (U+0049) and LATIN CAPITAL LETTER V (U+0056).
    3. LATIN SMALL LIGATURE FI (U+FB01) is compatibility equivalent to LATIN SMALL LETTER F (U+0066) and LATIN SMALL LETTER I (U+0069).

Under SASLprep, NFKC also handled the mapping of fullwidth and halfwidth code points to their decomposition mappings. It's expected that code points with compatibility equivalents are rare in existing passwords, but some passwords that matched when SASLprep was used might no longer work once the rules in this spec are applied πŸ’€

  • SASLprep mapped the "characters commonly mapped to nothing" from Appendix B.1 of [RFC3454]) to nothing. The PRECIS FreeformClass, on the other hand, completely disallows those characters, which correspond to the code points from the PRECIS "M" category defined under Section 9.13 of [RFC7564] (with the exception of MONGOLIAN TODO SOFT HYPHEN (U+1806), which was commonly mapped to nothing in Unicode 3.2 but, at the time of this writing, is allowed by Unicode 7.0). In practice, this change will probably have no effect on comparison. User-oriented software might reject such code points instead of ignoring them during password preparation, though 🫢

7. IANA Considerations πŸ’–

IANA has made the updates described below πŸŽ€

7.1. UsernameCaseMapped Profile πŸ’œ

IANA has added the following entry to the "PRECIS Profiles" registry 🧚

   Name:  UsernameCaseMapped.

   Base Class:  IdentifierClass.

   Applicability:  Usernames in security and application protocols.

   Replaces:  The SASLprep profile of stringprep.

   Width-Mapping Rule:  Map fullwidth and halfwidth characters to their
      decomposition mappings.

   Additional Mapping Rule:  None.

   Case-Mapping Rule:  Map uppercase and titlecase characters to
      lowercase.

   Normalization Rule:  NFC.

   Directionality Rule:  The "Bidi Rule" defined in RFC 5893 applies.

   Enforcement:  To be defined by security or application protocols that
      use this profile.

   Specification:  RFC 7613 (this document), Section 3.2.

7.2. UsernameCasePreserved Profile πŸ¦‹

IANA has added the following entry to the "PRECIS Profiles" registry ✨

   Name:  UsernameCasePreserved.

   Base Class:  IdentifierClass.

   Applicability:  Usernames in security and application protocols.

   Replaces:  The SASLprep profile of stringprep.

   Width-Mapping Rule:  Map fullwidth and halfwidth characters to their
      decomposition mappings.

   Additional Mapping Rule:  None.

   Case-Mapping Rule:  None.

   Normalization Rule:  NFC.

   Directionality Rule:  The "Bidi Rule" defined in RFC 5893 applies.

   Enforcement:  To be defined by security or application protocols that
      use this profile.

   Specification:  RFC 7613 (this document), Section 3.3.

7.3. OpaqueString Profile πŸ’–

IANA added this entry to the "PRECIS Profiles" registry πŸ’…

   Name:  OpaqueString.

   Base Class:  FreeformClass.

   Applicability:  Passwords and other opaque strings in security and
      application protocols.

   Replaces:  The SASLprep profile of stringprep.

   Width-Mapping Rule:  None.

   Additional Mapping Rule:  Map non-ASCII space characters to ASCII
      space.

   Case-Mapping Rule:  None.

   Normalization Rule:  NFC.

   Directionality Rule:  None.

   Enforcement:  To be defined by security or application protocols that
      use this profile.

   Specification:  RFC 7613 (this document), Section 4.2.

7.4. Stringprep Profile πŸŽ€

Okay so the stringprep spec [RFC3454] only let entries in the "Stringprep Profiles" registry be "Current" or "Not Current", with no in-between vibes πŸ™ˆ Because this document obsoletes RFC 4013 (the one that registered the SASLprep profile of stringprep), IANA marked that profile as "Not Current" and added this document as an extra reference. Bestie, that's a clean handoff ✨

8. Security Considerations πŸ”₯

This part is serious, so pay attention 🫢

8.1. Password/Passphrase Strength πŸ”

Being able to use a wide range of characters in passwords and passphrases can make it easier to build a strong password with high entropy πŸ’ͺ But in practice, that freedom ought to be weighed against the need to type or reproduce those characters on different devices using different input methods. Not every keyboard is giving the same vibes 😭

8.2. Identifier Comparison 🧐

Comparing identifiers (like SASL simple user names, authentication identifiers, and authorization identifiers) can lead to false negatives or false positives, and both of those have security implications πŸ’€ For a deeper dive, check out [RFC6943].

8.3. Reuse of PRECIS 🌈

The security considerations in [RFC7564] apply to the IdentifierClass and FreeformClass base string classes used in this document for usernames and passwords, respectively. So go read those too, iykyk πŸ‘‘

8.4. Reuse of Unicode 🌸

The security considerations in [UTS39] apply to the use of Unicode characters in usernames and passwords. Unicode is powerful but it's also a lot, so take this one seriously πŸ’œ

9. References πŸ“š

9.1. Normative References 🧚

   [RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119,
              DOI 10.17487/RFC2119, March 1997,
              <http://www.rfc-editor.org/info/rfc2119>.

   [RFC3629]  Yergeau, F., "UTF-8, a transformation format of
              ISO 10646", STD 63, RFC 3629, DOI 10.17487/RFC3629,
              November 2003, <http://www.rfc-editor.org/info/rfc3629>.

   [RFC5234]  Crocker, D., Ed., and P. Overell, "Augmented BNF for
              Syntax Specifications: ABNF", STD 68, RFC 5234,
              DOI 10.17487/RFC5234, January 2008,
              <http://www.rfc-editor.org/info/rfc5234>.

   [RFC5890]  Klensin, J., "Internationalized Domain Names for
              Applications (IDNA): Definitions and Document Framework",
              RFC 5890, DOI 10.17487/RFC5890, August 2010,
              <http://www.rfc-editor.org/info/rfc5890>.

   [RFC6365]  Hoffman, P. and J. Klensin, "Terminology Used in
              Internationalization in the IETF", BCP 166, RFC 6365,
              DOI 10.17487/RFC6365, September 2011,
              <http://www.rfc-editor.org/info/rfc6365>.

   [RFC7564]  Saint-Andre, P. and M. Blanchet, "PRECIS Framework:
              Preparation, Enforcement, and Comparison of
              Internationalized Strings in Application Protocols",
              RFC 7564, DOI 10.17487/RFC7564, May 2015,
              <http://www.rfc-editor.org/info/rfc7564>.

   [UAX11]    Unicode Standard Annex #11, "East Asian Width", edited by
              Ken Lunde.  An integral part of The Unicode Standard,
              <http://unicode.org/reports/tr11/>.

   [Unicode]  The Unicode Consortium, "The Unicode Standard",
              <http://www.unicode.org/versions/latest/>.

   [Unicode7.0]
              The Unicode Consortium, "The Unicode Standard,
              Version 7.0.0", (Mountain View, CA: The Unicode
              Consortium, 2014 ISBN 978-1-936213-09-2),
              <http://www.unicode.org/versions/Unicode7.0.0/>.

9.2. Informative References πŸ¦‹

   [Err1812]  RFC Errata, Erratum ID 1812, RFC 4013,
              <http://www.rfc-editor.org>.

   [HTTP-BASIC-AUTH]
              Reschke, J., "The 'Basic' HTTP Authentication Scheme",
              Work in Progress, draft-ietf-httpauth-basicauth-update-07,
              February 2015.

   [HTTP-DIGEST-AUTH]
              Shekh-Yusef, R., Ed., Ahrens, D., and S. Bremer, "HTTP
              Digest Access Authentication", Work in Progress,
              draft-ietf-httpauth-digest-19, April 2015.

   [RFC20]    Cerf, V., "ASCII format for network interchange", STD 80,
              RFC 20, DOI 10.17487/RFC0020, October 1969,
              <http://www.rfc-editor.org/info/rfc20>.

   [RFC3454]  Hoffman, P. and M. Blanchet, "Preparation of
              Internationalized Strings ("stringprep")", RFC 3454,
              DOI 10.17487/RFC3454, December 2002,
              <http://www.rfc-editor.org/info/rfc3454>.

   [RFC3501]  Crispin, M., "INTERNET MESSAGE ACCESS PROTOCOL -
              VERSION 4rev1", RFC 3501, DOI 10.17487/RFC3501,
              March 2003, <http://www.rfc-editor.org/info/rfc3501>.

   [RFC4013]  Zeilenga, K., "SASLprep: Stringprep Profile for User Names
              and Passwords", RFC 4013, DOI 10.17487/RFC4013,
              February 2005, <http://www.rfc-editor.org/info/rfc4013>.

   [RFC4422]  Melnikov, A., Ed., and K. Zeilenga, Ed., "Simple
              Authentication and Security Layer (SASL)", RFC 4422,
              DOI 10.17487/RFC4422, June 2006,
              <http://www.rfc-editor.org/info/rfc4422>.

   [RFC4616]  Zeilenga, K., Ed., "The PLAIN Simple Authentication and
              Security Layer (SASL) Mechanism", RFC 4616,
              DOI 10.17487/RFC4616, August 2006,
              <http://www.rfc-editor.org/info/rfc4616>.

   [RFC5802]  Newman, C., Menon-Sen, A., Melnikov, A., and N. Williams,
              "Salted Challenge Response Authentication Mechanism
              (SCRAM) SASL and GSS-API Mechanisms", RFC 5802,
              DOI 10.17487/RFC5802, July 2010,
              <http://www.rfc-editor.org/info/rfc5802>.

   [RFC5891]  Klensin, J., "Internationalized Domain Names in
              Applications (IDNA): Protocol", RFC 5891,
              DOI 10.17487/RFC5891, August 2010,
              <http://www.rfc-editor.org/info/rfc5891>.

   [RFC5893]  Alvestrand, H., Ed., and C. Karp, "Right-to-Left Scripts
              for Internationalized Domain Names for Applications
              (IDNA)", RFC 5893, DOI 10.17487/RFC5893, August 2010,
              <http://www.rfc-editor.org/info/rfc5893>.

   [RFC5894]  Klensin, J., "Internationalized Domain Names for
              Applications (IDNA): Background, Explanation, and
              Rationale", RFC 5894, DOI 10.17487/RFC5894, August 2010,
              <http://www.rfc-editor.org/info/rfc5894>.

   [RFC6120]  Saint-Andre, P., "Extensible Messaging and Presence
              Protocol (XMPP): Core", RFC 6120, DOI 10.17487/RFC6120,
              March 2011, <http://www.rfc-editor.org/info/rfc6120>.

   [RFC6122]  Saint-Andre, P., "Extensible Messaging and Presence
              Protocol (XMPP): Address Format", RFC 6122,
              DOI 10.17487/RFC6122, March 2011,
              <http://www.rfc-editor.org/info/rfc6122>.

   [RFC6943]  Thaler, D., Ed., "Issues in Identifier Comparison for
              Security Purposes", RFC 6943, DOI 10.17487/RFC6943,
              May 2013, <http://www.rfc-editor.org/info/rfc6943>.

   [RFC7542]  DeKok, A., "The Network Access Identifier", RFC 7542,
              DOI 10.17487/RFC7542, May 2015,
              <http://www.rfc-editor.org/info/rfc7542>.

   [UTS39]    Unicode Technical Standard #39, "Unicode Security
              Mechanisms", edited by Mark Davis and Michel Suignard,
              <http://unicode.org/reports/tr39/>.

   [XMPP-ADDR]
              Saint-Andre, P., "Extensible Messaging and Presence
              Protocol (XMPP): Address Format", Work in Progress,
              draft-ietf-xmpp-6122bis-24, June 2015.

Appendix A. Differences from RFC 4013 πŸ“

This document builds on the PRECIS framework from [RFC7564]. PRECIS is really different from the stringprep tech [RFC3454] that SASLprep [RFC4013] was built on 😭 The big difference: stringprep profiles allowed everything except what was explicitly banned, while PRECIS profiles ban everything except what's explicitly allowed. (This "inclusion model" was first used for internationalized domain names in [RFC5891], so see [RFC5894] for more tea β˜•) It's really important to keep this in mind when you compare this document to SASLprep [RFC4013] πŸ’…

Here are the substantive changes from RFC 4013:

  • A single SASLprep algorithm was replaced by three separate algorithms: one for usernames with case mapping, one for usernames with case preservation, and one for passwords.
  • The new preparation algorithms use PRECIS instead of a stringprep profile. The new algorithms work independently of Unicode versions.
  • As recommended in the PRECIS framework, the Unicode normalization form was changed from NFKC to NFC.
  • Some Unicode code points that were mapped to nothing in RFC 4013 are simply disallowed by PRECIS.

Acknowledgements 🫢

This document borrows some text from [RFC4013] and [RFC6120].

Huge thanks to the people who gave helpful feedback: Marc Blanchet, Ben Campbell, Alan DeKok, Joe Hildebrand, Jeffrey Hutzelman, Simon Josefsson, Jonathan Lennox, James Manger, Matt Miller, Chris Newman, Yutaka OIWA, Pete Resnick, Andrew Sullivan, Nico Williams, and Yoshiro YONEYA. Nico Williams especially deserves a standing ovation πŸ‘‘ because he wrote the text that was used in Section 3.4. Also thanks to Takahiro NEMOTO and Yoshiro YONEYA for implementation feedback 🌸

Robert Sparks and Derek Atkins reviewed the document on behalf of the General Area Review Team and the Security Directorate, respectively 🌟

Benoit Claise and Stephen Farrell gave helpful input during IESG review πŸ’œ

Thanks to Matt Miller as document shepherd, Marc Blanchet and Yoshiro YONEYA as working group chairs, and Pete Resnick and Barry Leiba as area directors πŸŽ€

Peter Saint-Andre wishes to acknowledge Cisco Systems, Inc., for employing him during his work on earlier draft versions of this document πŸ¦‹

Authors' Addresses πŸ’Œ

   Peter Saint-Andre
   &yet

   Email: peter@andyet.com
   URI:   https://andyet.com/


   Alexey Melnikov
   Isode Ltd
   5 Castle Business Village
   36 Station Road
   Hampton, Middlesex  TW12 2BX
   United Kingdom

   Email: Alexey.Melnikov@isode.com
πŸ“¦ where this page comes from