-
-
Notifications
You must be signed in to change notification settings - Fork 48
Description
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)"
fiIf 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.