String#crypt behaving differently that in MRI #1035

nning opened this Issue Sep 22, 2013 · 19 comments


None yet

7 participants


I tried getting a Rails project working on JRuby 1.7.4 and a test
regarding password hashes failed. Passwords hashes are created by:

password.crypt('$6$' + salt)

On JRuby 1.7.4 the output looks like:

$ jruby -e 'p "foobar".crypt(%q($6$2mlKb.sZpswpnZlt))'

On MRI 1.9.3-p448:

$ mri19 -e 'p "foobar".crypt(%q($6$2mlKb.sZpswpnZlt))'

And on MRI 2.0.0-247:

$ mri20 -e 'p "foobar".crypt(%q($6$2mlKb.sZpswpnZlt))'

I am developing on Arch Linux with glibc 2.18, RUBY_DESCRIPTION in JRuby is:

jruby 1.7.4 (1.9.3p392) 2013-05-16 2390d3b on OpenJDK 64-Bit Server VM 1.7.0_40-b31 +indy [linux-amd64]

I found this posting on, which is possibly useful:


One can use Crypt from apache commons codec library as a work around.

if RUBY_PLATFORM == "java"
  require  'commons-codec-1.8.jar'

  class String
    def crypt(salt)
      org.apache.commons.codec.digest.Crypt.crypt(self.to_java_bytes, salt)
@nning nning added a commit to nning/moeil that referenced this issue Dec 14, 2013
@nning nning Work-around for String#crypt bug in JRuby. 8f5033a

Thanks very much for the work-around, @r4um.


Stil broken in 1.7.16.


Had some users hit this recently as well.


This continues to be an issue. Mainline Ruby supports standard DES hashes, MD5 hashes ($1$), SHA-256 hashes ($5$), and SHA-512 hashes ($6$) on all several platforms. Considering that DES is incredibly weak and should not be used by anyone nowadays, the fact that JRuby 's String#crypt implementation only supports it is rather disconcerting.

Edit: It turns out that mainline Ruby supports whatever the underlying system's implementation of crypt(3) supports, which in the case of the vast majority of Linux distros is MD5, SHA-256, and SHA-512. OS X and probably AIX are DES only, Solaris is extensible (read: complicated), FreeBSD is MD5, SHA-256/512, NT-Hash, and Blowfish, and OpenBSD is Blowfish and maybe something else.

@enebo enebo added this to the JRuby 1.7.17 milestone Dec 1, 2014

On OSX, I get the jruby 1.7.4 result for all MRI versions I have 1.8.7, 1.9.3, 2.0.0 and 2.1.5.

JRuby Team member

@tduehr yeah so on MacOS it appears it only supports DES. On most (if not all?) modern Linuxes it uses libcrypt which allows these magic salt strings to select the sort of fingerprint you want to use. jruby 1.7.17 will have support on linux but I am hoping to know which other unixy systems use libcrypt by default.

If people can chime in which other OSes that use libcrypt I will update jnr-posix to properly bind to the underlying native crypt.

As an explanation, up to this point JRuby implemented DES crypt in Java. We/I did not even know that libcrypt allowed other signatures (although I am hardly surprised that noone uses DES anymore). I just figured some other C function existed for those fingerprint types.


It looks like Ruby uses the native crypt(3) implementation on pretty much all systems. System that don't have an implementation of crypt(3) pretty much use a basic implementation identical to that currently provided by JRuby. It looks like the set of systems that don't have one is: Windows. Going down the list of jnr-posix's supported OSes, I'm seeing implementations of crypt(3) (or at least evidence of the existence thereof) for AIX, FreeBSD, Linux, Darwin/OS X, OpenBSD, and Solaris. It's part of the POSIX spec.

JRuby Team member

@elyscape just to clarify you are just saying a native call to crypt but not specifically that all systems are using the same/similar libcrypt linux does right? Because on MacOS I do not see any of the magic salt support for different fingerprint types (nor libcrypt). crypt 3 C (the older DES system has been on all unix variants for as long as I can remember (early eighties)). I am sure it goes back to the genesis of Unix itself.

The change I made to JRuby this week will call out to the native impl which I think is behaving like MRI. My only reservation to the change is on some systems I need to essentially do the equivalent of (-lcrypt) and others it seems to be part of libc. Without trying each one I don't know which ones will fail to load crypt. My previous comment was specifically about this difference and not about crypt existing at all.


The change I made to JRuby this week will call out to the native impl which I think is behaving like MRI.

Thanks, this will resolve this issue, i.e., allow for swithcing between JRuby and MRI, and to interoperate with other system components.

Re the extra types, IIRC, these are glibc extensions, they are not part of the POSIX crypt() function, but I don't think there would be much gained by supplementing the native functionality. At least for me, the biggest problem here is interoperability with the base system.


@enebo: Indeed. I can look into which systems have it as part of libc vs which have it as part of libcrypt in a few hours.

JRuby Team member

@elyscape cool. thanks in advance.



FreeBSD: libcrypt
Linux: libcrypt
Darwin/OS X: libsystem_c (or just libsystem, if you're able to bind to that)
OpenBSD: libc
Solaris: libc

As for AIX, well:


(Sorry, I don't have a good way to get information on AIX)


I tried on AIX 5.2 and it uses crypt from libc (which not surprisingly only supports DES).

JRuby Team member

@nning It sort of looks like there is some service provider api for crypt in AIX 7.1 but knowing IBM I am sure that can be anywhere :)

@elyscape cool thanks.

I have been wondering if I should change jnr-ffi to be able to optionally load libraries and not completely link fail if one of them doesn't exist (while still having a mandatory load API). For jnr-posix, I can imagine on a small custom linux env someone will compile _XOPEN or use busybox or ??? and not provide libcrypt. In how we have jnr-posix implemented now then no native functionality will load if libcrypt is missing. But I guess that does not need to hold up 1.7.17 so long as we hit the vast majority of cases.


For whatever it's worth, on Linux, it looks like libcrypt is provided by glibc, just as a separate .so file for whatever reason. I have no idea if that matters for that, though.

JRuby Team member

Well native crypt here we come....I am hoping we got a reasonable default list for libcrypt folks. If people run into additional problems with new native crypt impl then please open a new issue. This one is done.

@enebo enebo closed this Dec 8, 2014

Thanks for your work on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment