Are unix/linux sha256/sha512 passwords in /etc/shadow key-strengthened?
Yes. They use a crypt procedure that does a default of 5000 rounds of hashing. The sha256-crypt/sha512-crypt procedure is described here
and in java
Can I change the number of rounds?
Yes. Simply edit
/etc/pam.d/common-password (or solaris equivalent) and add 'rounds=73500` at the end of the line that looks similar to:
password [success=2 default=ignore] pam_unix.so obscure sha512 rounds=73500
and then change your password using passwd. Why 73500? Well, timing crypt with rounds=5000, I was getting about 3.4 ms per password. (5000*50/3.4 ~ 73500). You can check if a password in your /etc/shadow files was done an abnormal number of rounds if it looks starts with
$6$ indicates the crypt procedure used (sha256-crypt is $5$, sha512-crypt $6$) followed by number of rounds and then the salt.
But I want bcrypt; Can I switch to that:
Check /etc/pam.d/ and (1) change all references of
pam_unix2.so (check that the file is there) and (2) then change
blowfish in /etc/pam.d/common-password
One noticeable difference between bcrypt vs sha512-crypt; is that bcrypt work-factor scales exponentially; e.g., a work-factor of 12, should take double as long as a work-factor of 11, while sha512-crypt rounds scale linearly (e.g.,
rounds=10000 should take twice as long as
rounds=5000). This is simply because bcrypt says do 2work-factor rounds. As a quick benchmark on my machine, one bcrypt round is more expensive than a sha512-crypt round; with a rough equivalence of ~4 ms with
work-factor=6 (26=64 bcrypt-rounds). But as both can be scaled up this should not be an issue until the number of rounds overflow the unsigned 32-bit/64-bit
int (when rounds = 4 billion or 1019 respectively).
Python timing Stuff With sha512-crypt
You can check crypt via python (in linux this performs just as fast as the C version as it just is a thin wrapper for the crypt library written in C)
>>> import crypt
>>> crypt.crypt('testtest', '$6$6LzxTFam$')
In python on my machine with the crypt module it takes about 3.4 ms per sha512-crypt password at 5000 rounds and ~50 ms with 73500 rounds.
>>> import timeit
>>> timer = timeit.Timer("crypt.crypt('testtest', '$6$6LzxTFam$')", setup="import crypt")
# with 73500 rounds:
>>> timeit.Timer("crypt.crypt('testtest', '$6$rounds=73500$RFzXTGB$')", 'import crypt').timeit(1000)