I am trying to generate a hashed password as in /etc/shadow file, using bash script. The user is prompted for the password which is saved in a variable PSWD. I have extracted the Hash and the salt value from the /etc/shadow file and saved them in a variables HVAL and SVAL respectively.

Now in order to generate a hashed password using Password and the Salt value, I need to use command given below (Reference):

$ perl -e 'print crypt("password","\$6\$salt\$") . "\n"'

In the above command, I must replace "password" with the $PSWD variable, "6" with $HVAL and "salt" with $SVAL variable.

I've tried exporting above variables and replacing them in the perl command, as shown below, but it was totally messed up.

perl -e 'print crypt("$ENV{"PSWD"}","\$$ENV{"HVAL"}\$$ENV{"SVAL"}\$") . "\n"'

What will be the corrections?

  • @StéphaneChazelas- I've used the backticks while assigning the output to a variable, still it is not working. – Mandar Shinde Aug 2 '15 at 6:46
  • Yes, there's also the problem of the quotes, you'd need "$ENV{\"VAR\"}" though "$ENV{VAR}" would be enough, see my answer. – Stéphane Chazelas Aug 2 '15 at 6:51
  • If the password is being changed: The hash should be re-generated. If only testing the password then ok. – user79743 Aug 3 '15 at 13:10

The problem is with your double quotes. Here you don't need to quote those hash keys as they are simple identifiers. From perldoc perldata:

In fact, a simple identifier within such curlies is forced to be a string, and likewise within a hash subscript. Neither need quoting. Our earlier example, $days{'Feb'} can be written as $days{Feb} and the quotes will be assumed automatically. But anything more complicated in the subscript will be interpreted as an expression. This means for example that $version{2.0}++ is equivalent to $version{2}++, not to $version{'2.0'}++.


perl -le 'print crypt($ENV{PSWD},"\$$ENV{HVAL}\$$ENV{SVAL}\$")'

If you're using it inside backticks, you'd need to double your backslashes as in:

var=`perl -le 'print crypt($ENV{PSWD},"\\$$ENV{HVAL}\\$$ENV{SVAL}\$")'`

Best is to use the $(...) form of command substitution instead:

var=$(perl -le 'print crypt($ENV{PSWD},"\$$ENV{HVAL}\$$ENV{SVAL}\$")')
  • A comment that the vars are passed in the environment to avoid being seen in ps -ef will help understand the command concept. – user79743 Aug 3 '15 at 13:14

The sequence to get to the correct quote starts with the original command:

perl -e 'print crypt("password","\$6\$salt\$") . "\n"'

Let's add some space:

perl -e 'print crypt("  password  ","\$  6  \$  salt  \$") . "\n"'

Let's change the vars to their equivalents:

perl -e 'print crypt("  $ENV{PSWD}  ","\$  $ENV{HVAL}  \$  $ENV{SVAL}  \$") . "\n"'

The equivalents should not be quoted, as in quotes they fail:

perl -e 'print "$ENV{PSWD}" . "\n"'      # correct.
perl -e 'print "$ENV{"PSWD"}" . "\n"'    # fail.

And finally, lets remove the spaces inserted above:

perl -e 'print crypt("$ENV{PSWD}","\$$ENV{HVAL}\$$ENV{SVAL}\$") . "\n"'

then, the command may be assigned to a variable.

var="$(  perl -e 'print crypt("$ENV{PSWD}","\$$ENV{HVAL}\$$ENV{SVAL}\$") . "\n"'  )"

With exported values: PSWD=password, HVAL=6, SVAL=saltsalt I get:


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.