Description of problem:
rubygem-bcrypt is broken by libxcrypt
Version-Release number of selected component (if applicable):
$ rpm -q libxcrypt
Steps to Reproduce:
The rubygem-bcrypt build fails.
What draw my attention from the build log is this test failure failure:
2) Generating BCrypt hashes should be interoperable with other implementations
Failure/Error: expect(BCrypt::Engine.hash_secret(secret, salt)).to eql(test_vector)
(compared using eql?)
# /usr/share/gems/gems/rspec-support-3.7.0/lib/rspec/support.rb:97:in `block in <module:Support>'
... snip ...
As you can see, there are some unexpected null characters included at the end of the string. This is the code where libxcrypt is called:
To me, it seems that the crypt_ra function does not sanitize either the "data" parameter or probably the "size" is wrong.
The rubygem-bcrypt test suite and the build must pass.
Ping? Could you please look into it?
Thx for fixing this. Does it mean that the libxcrypt is not 100% compatible with libcrypt and changes the return values intentionally?
(In reply to Vít Ondruch from comment #3)
> Hi Björn,
> Thx for fixing this. Does it mean that the libxcrypt is not 100% compatible
> with libcrypt and changes the return values intentionally?
you're welcome! Well, the actual problem was not about so much about libxcrypt; there are no changes libxcrypt makes to any return value, but some internal implementations are different from glibc's libcrypt:
On pure C-level it doesn't make any difference to the consuming code (return values are 100% binary compatible on this level and are conforming to ANSI-C standards).
In this case the C-code of the built ruby-extension was the real problem, since it made the blunt assumption that the internal implementation of OpenWall's reference implementation would be the same for *any* other implementation as well:
* The `bc_salt()` function was treating the return value of `crypt_gensalt()`
as binary data instead as a valid C-string and thus it was full of
trailing 0-bytes (libxcrypt uses a 192 byte sized char buffer as return
value, which is perfectly valid for C-code as a 0-byte in a C-string
terminates it). This broke most of the code and tests.
* The `bc_crypt()` function was discarding the return value of `crypt()` and
instead assumed the opaque (and thus implementation dependant) void-pointer
(void can be any structure of data by the C-standard) to `data` would just
return a valid C-string, when in fact the return value *is* a valid
C-string with the wanted information for all implementations of `crypt()`
implied by POSIX.
I hope that this clarifies, what my patch does, a bit.
Thx a lot for insights.