Using Ruby to Generate Sha512 Crypt-Style Hashes Formatted for /Etc/Shadow

Using ruby to generate SHA512 crypt-style hashes formatted for /etc/shadow?

After further research:

  • The mkpasswd command, which on debian is in the whois package (weird):

    mkpasswd -m sha-512

  • String#crypt does actually call the platform's native crypt() call, however OSX (up to 10.6) does not include support for alternate ciphers. "password".crypt('$6$somesalt') will work on Linux platforms.

Platform-independently generate Linux password in Modular Crypt Format (MFC) SHA512 for /etc/shadow in Ruby

As you discovered, the crypt method is platform-dependent. The algorithms it has available depend on the host. macOS only supports DES. Modern Linux distros will likely support every modern cipher. Windows -- well that's a total crapshoot and depends on how you're running Ruby. (Are you using WSL? Running Ruby directly on Windows? Something else?)

It's best to leave crypt out of the picture and use a library to handle it for you. First, install unix-crypt:

gem install unix-crypt

Then use it to generate your hash:

require 'unix_crypt'

# This is the hash you generated on Linux with crypt for your example
expected_hash = '$6$123SaLt9$idgUFrrwVkpDMcoHj7SAYH0UwCY6LymbsR9yTDrelYgcZ2wstoynmLIY83qBF0/BIT4Od.rQL2g3n2jEG/VXp/'

# Generate the same hash using unix-crypt instead
hash = UnixCrypt::SHA512.build('mypassword', '123SaLt9')

# Verify they match (returns true)
expected_hash == hash

This works for me on macOS where your original example does not:

"mypassword".crypt("$6$" + "123SaLt9")
=> "$6MrNddDu3Hf6"

So it should probably work on Windows as well. If it doesn't then I recommend you look at how your Windows users are running Ruby and switch them over to Windows Subsystem for Linux and have them use the specific Linux distro that you are using.

Once they have Linux up and running they can install Ruby and from the perspective of the Ruby interpreter it will be running on Linux, not Windows, so its access to crypt algorithms should be the same as what you have, and you should be able to use crypt as you did in your original example.

Alternatively, you can use the unix-crypt library from my example as a more universally compatible method of generating the hashes regardless of distro.

How to convert php crypt function (SHA512) to ruby?

irb(main):001:0> salt = 'fGn9LR75';
irb(main):002:0* hash = 'test'.crypt('$6$' + salt);
irb(main):003:0* hash
=> "$6$fGn9LR75$YpI/vJHjEhvrYp5/eUSRinpiXdMthCxFWSEo0ktFNUaRBsA7pCWYzzmQptmnfyHno9YEJFNHYuESj3nAQmSzc1"

The crypt() algorithm for SHA256/512 is not simply a base64-encoded hash. It's an intentionally crazy process which involves multiple hashes running in parallel.

Is it possible to generate a longer hash value with string#crypt?

String#crypt ignores any extra characters, so only the first two are used.

"foobar".crypt("abc") # => abVbJXzHUY99s
"foobar".crypt("abd") # => abVbJXzHUY99s

Instead, you can use SHA1 to give you a 40 character encryption and allow any length of salt.

require 'digest/sha1'
Digest::SHA1.hexdigest("foobar" + "abc") # => 17dd6cae99582672c4b2ccc78fe4ad0888559ce7
Digest::SHA1.hexdigest("foobar" + "abd") # => 8aba27fd409286946504ac78098c41549d182316

UPDATE: as Gaius pointed out, SHA1 is not best for production. Instead use SHA256 or SHA512. See his response for details.

python, get encrypted user password from shadow

Try the spwd module

Platforms: Unix

New in version 2.5.

This module provides access to the Unix shadow password database. It is available on various Unix versions.

You must have enough privileges to access the shadow password database (this usually means you have to be root).

Shadow password database entries are reported as a tuple-like object, whose attributes correspond to the members of the spwd structure (Attribute field below, see ):

>>> import spwd
>>> spwd.getspnam('root')
spwd.struct_spwd(sp_nam='root', sp_pwd='!', sp_lstchg=15238, sp_min=0, sp_max=99999, sp_warn=7, sp_inact=-1, sp_expire=-1, sp_flag=-1)

Remember, you need to have read permission of /etc/shadow for this to work

Generate cross-platform compatible Blowfish hash (PHP/Ruby)

The BCrypt gem does what we need:

BCrypt::Engine.hash_secret("bob", "$2a$10$ ... salt here ...")

How best to upgrade to password_* functions from hash('sha512','salt')

Hashes created with password_hash will have a very distinctive $2y$ string at the beginning (or similar $..$, as long as you're operating with the current default Blowfish cypher), while SHA256 will simply be all hex values. Therefore, you can simply test whether a value is a legacy hash value or a password_hash value:

function isLegacyHash($hash) {
return !preg_match('/^\$\w{2}\$/', $hash);
}

Using this, you can keep both types of hashes in a single field and upgrade them when the user logs in. Alternatively, you could simply set a flag in a column like hash_version.

Ruby where is etc module file and can it be customized?

In general, you can use

SomeClass.method(:foo).source_location

to find out where (on disk) a method is defined. I don't think this was available in ruby 1.8, but even it is the result is nil, because these methods are implemented in C. The ruby 1.9 implementation is here for example. Somewhere in /usr/lib/ruby/1.8 there should be an etc.so (on linux or etc.bundle on os x and so on)

This doesn't mean that you can't overwrite the method, but it does mean that you can't just edit the source as you would with a plain .rb file (you'd have to recompile the extension afterwards and move it to the correct location, which is system dependant)



Related Topics



Leave a reply



Submit