Skip to content

Interest in refining password generation to follow apple style? #65

@jepler

Description

@jepler

I'm not an apple fanboy but I find that the password generation algorithm introduced with ios 12 (2018) has good properties:

  • The format is engineered to have over 70 bits of entropy
  • Due to its widespread use by apple devices, it is a form accepted by substantially all websites & applications
  • It is designed to be easier to transmit by speaking and for easier entry on bad devices like TVs & mobile devices
  • It never includes symbols that are special in the shell

The main limitation is that

  • There is no way to select an arbitrary password length or entropy, the length and format is always fixed.

I found this video by an Apple engineer helpful as an overview of the format: https://www.youtube.com/watch?v=-0dwX2kf6Oc

I have implemented the algorithm (with the exception of bad word avoidance) in bash as a passage extension. According to my calculations it actually produces a password with around 72 bits of entropy.

Here are some example passwords generated with this method:

duvbas-CaqdEs-nenba4
xujfyv-xyCta7-gytXab
dyrvyg-daqzAs-Sebwy2
puSxan-jetga9-meqXav
wegxyC-4ufteb-Tyjtab
suxreQ-7aCfen-decjuq
sanrah-9Ysbuf-kenvyZ
kurcax-6ewjam-zAnGub
# Generate passwords in a form inspired by iPhoneOS, with around 72 bits of entropy
# 
# These passwords are designed to be easier to remember and to type on mobile keyboards
# and embedded devices.
# 
# They consist of:
#     * 3 "words" each made of 2 nonsense "syllables"
#     * with one consonant at the start, end, or next to a hyphen changed to a digit
#     * with 2 of the 18 letters in uppercase
#     * words are separated by dashes
#     * a single digit is always at the end
# 
# Further,
#     * characters subject to confusion are minimized (i/l/1 are not used, 0/o are not used)
# 
# However,
#     * does not filter objectionable sequences like Apple does (and yes it generated something
#       offensive while I was testing it)
#
# The password generated in this way is estimated to have 72 bits of entropy

vowels="aeuy" # removing o, i (confusion)
consonants="bcdfghjkmnpqrstvwxz" # removing l (confusion)
digits="23456789" # removing 0, 1 (confusion)
digit_positions="0 5 7 12 14 19"

select_char () {
    LC_ALL=C tr -dc "$1" < /dev/urandom | dd 2>/dev/null bs=1 count=1
}

select_elem () {
    if [ $# -gt 255 ]; then die "can only select from small arrays"; fi
    while true; do
        i=$(dd 2>/dev/null bs=1 count=1 < /dev/urandom | od -Anone -tu1)
        if [ $i -lt $# ]; then break; fi
    done
    shift $i
    echo "$1"
}

syllable () {
    select_char $consonants
    select_char $vowels
    select_char $consonants
}

twosyl () {
    syllable
    syllable
}

replace () {
    echo ${1:0:$2}${3}${1:$(($2+1))}
}

upcase () {
    c=${1:$2:1}
    replace $1 $2 `echo $c | tr a-z A-Z`
}

char_indices () {
    for i in `seq 0 $((${#1}-1))`; do
        c=${1:$i:1}
        case "$c" in
        ([a-z]) echo "$i" ;;
        esac
    done
}

s=$(twosyl)-$(twosyl)-$(twosyl)

idx=$(select_elem $digit_positions)
s=$(replace $s $idx $(select_char $digits))
s=$(upcase "$s" $(select_elem $(char_indices "$s")))
s=$(upcase "$s" $(select_elem $(char_indices "$s")))

echo "$s"
if [ $# -ne 0 ]; then
    echo "$s" | cmd_insert --multiline "$1"
else
    echo "(Supply a name to insert a generated password)"
fi

If there is interest, I could turn this into a PR against passage, integrating it as a command or replacing the existing passage generate command. However, if there is not interest then I am happy to keep it as an extension for myself.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions