0

I am trying to make a bash script that will generate a password. The script also has a "Forgot password" option. Because the password has random characters, it's hard to remember, so when a user forgets the pass it can be regenerated but, of course, there have to be security questions.

I figured out the part where I can ask a user 3 questions and generate a password. For example: username, favorite food and url. The part I can't seem to figure out is where a user can regenerate the password. I think I need to somehow store 3 variables (username, favoriteFood, url) but I have no idea how. This is the code that I have:

#!/bin/bash

pause(){
  read -p "Press [Enter] key to continue..." fackEnterKey
}

one(){
    echo "Enter your usename"
    read username
    echo "Whats your favorite food"
    read favoriteFood
    echo "Enter URL"
    read url
    choose() { echo ${1:RANDOM%${#1}:1} $RANDOM; }
        pass="$({ choose '!@#$%^\&'
        choose '0123456789'
        choose 'abcdefghijklmnopqrstuvwxyz'
        choose 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
        for i in $( seq 1 $(( 4 + RANDOM % 8 )) )
            do
                choose '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
            done
        } | sort -R | awk '{printf "%s",$1}')"
    echo "Your pass is:"$pass    
    pause
}
#this is the part where i am stuck 
two(){
    echo "Enter username"
    read username2
    echo "Whats your favorite food"
    read favoriteFood2
    echo "Enter URL"
    read url2
    if [ username==username2 -a favoriteFood==favoriteFood2 -a url==url2 ] #this only works if the scirpt is not closed.
        then 
            echo $pass
        else
            echo "not found"
    fi        
        pause
}

show_menus() {
    clear
    echo "~~~~~~~~~~~~~~~~~~~~~"    
    echo " M A I N - M E N U"
    echo "~~~~~~~~~~~~~~~~~~~~~"
    echo "1. Generate password"
    echo "2. Forgot password"
    echo "3. Exit"
}
read_options(){
    local choice
    read -p "Enter choice [ 1 - 3] " choice
    case $choice in
        1) one ;;
        2) two ;;
        3) exit 0;;
        *) echo -e "${RED}Error...${STD}" && sleep 2
    esac
}
trap '' SIGINT SIGQUIT SIGTSTP
while true
do

    show_menus
    read_options
done
  • 3
    Do you want to regenerate the same password? If so, that's really not recommended since it means that, by definition, your passwords are not secure and, instead, there is an algorithm producing them. Alternatively, you'd need to use a database to store them. Why not just re-generate a new password like everyone else does? – terdon Dec 10 '16 at 13:15
3

If you want to be able to reproduce the same generated password if the user enters the same 3 answers again, just don't create a random password but derive the password from the answers only. That way your password is no longer truly random but only pseudo-random (seems random to humans, but is determined by the input only), but that's likely a smaller security problem than storing the passwords in plain-text in a password database.

I've written a short example that takes in 3 answers $answer1, $answer2, $answer3 and a numeric $length parameter that determines the output password length (max. 86 characters):

$ answer1=bytecommander
$ answer2=pizza
$ answer3=askubuntu.com
$ length=12

$ printf '%s-%s-%s%n' "$answer1" "$answer2" "$answer3" | sha512sum | xxd -r -p | base64 -w0 | grep -Eo "^.{$length}"
fBuIlC+lXiuW

The command looks complicated, but how it works is actually pretty easy:

  • printf '%s-%s-%s%n' "$answer1" "$answer2" "$answer3" simply concatenate the three answer strings together using - as delimiter and adding a newline. You can use any other method that converts your user input into one single string, it doesn't matter as long as you just always use the same.
  • sha512sum reads from standard input (where the output of the command above is piped) and calculates the SHA-512 hash of it. This is a string of 129 hexadecimal (0-9, a-f) characters.
  • xxd -r -p converts the hexadecimal characters to binary code.
  • base64 -w0 converts the binary code to Base 64 (a-z, A-Z, 0-9, +, /).
  • grep -Eo "^.{$length}" prints the first $length characters of the result. You should not specify a length greater than 86 (there are 88 characters, but the last two will always be ==).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.