Code Monkey home page Code Monkey logo

ruby-argon2's Introduction

Ruby Argon2 Gem

This Ruby Gem provides FFI bindings, and a simplified interface, to the Argon2 algorithm. Argon2 is the official winner of the Password Hashing Competition, a several year project to identify a successor to bcrypt/PBKDF/scrypt methods of securely storing passwords. This is an independant project and not official from the PHC team.

Build Status Code Climate Coverage Status

Design

This project has several key tenets to its design:

  • The reference Argon2 implementation is to be used "unaltered". To ensure compliance with this goal, and encourage regular updates from upstream, the upstream library is implemented as a git submodule, and is intended to stay that way.
  • The FFI interface is kept as slim as possible, with wrapper classes preferred to implementing context structs in FFI
  • Security and maintainability take top priority. This can have an impact on platform support. A PR that contains platform specific code paths is unlikely to be accepted.
  • Tested platforms are MRI Ruby 2.7 and 3.0. No assertions are made on other platforms.
  • Errors from the C interface are raised as Exceptions. There are a lot of exception classes, but they tend to relate to things like very broken input, and code bugs. Calls to this library should generally not require a rescue.
  • Test suites should aim for 100% code coverage.
  • Default work values should not be considered constants. I will increase them from time to time.
  • Many Rubocop errors have been disabled, but any commit should avoid new alerts or demonstrate their necessity.

Usage

Require this in your Gemfile like a typical Ruby gem:

require 'argon2'

To utilise default costs (RFC 9106's lower-memory, second recommended parameters):

hasher = Argon2::Password.new
hasher.create("password")

Alternatively, use this shortcut:

Argon2::Password.create("password")
    => "$argon2i$v=19$m=65536,t=2,p=1$61qkSyYNbUgf3kZH3GtHRw$4CQff9AZ0lWd7uF24RKMzqEiGpzhte1Hp8SO7X8bAew"

If your use case can afford the higher memory consumption/cost, you can/should specify to use RFC 9106's first recommended parameters:

hasher = Argon2::Password.new(profile: :rfc_9106_high_memory)
hasher.create("password")
    => "$argon2id$v=19$m=2097152,t=1,p=4$LvHa74Yax7uCWPN7P6/oQQ$V1dMt4dfuYSmLpwUTpKUzg+RrXjWzWHlE6NLowBzsAg"

To generate a hash using one of the other Argon::Profiles names:

# Only use this profile in testing env, it's unsafe!
hasher = Argon2::Password.new(profile: :unsafe_cheapest)
hasher.create("password")
    => "$argon2id$v=19$m=8,t=1,p=1$HZZHG3oTqptqgrxWxFic5g$EUokHMU6m6w2AVIEk1MpZBhVwW9Nj+ESRjPwTBVtWpY"

The list of named cost profiles are:

  • :rfc_9106_high_memory: the first recommended option but is expensive
  • :rfc_9106_low_memory: the second recommended option (default)
  • :pre_rfc_9106: the previous default costs for ruby-argon2 <= v2.2.0, before offering RFC 9106 named profiles
  • :unsafe_cheapest: Strictly for testing, the minimum costs allowed by Argon2 for the fastest hashing speed

To generate a hash using specific time and memory cost:

hasher = Argon2::Password.new(t_cost: 2, m_cost: 16, p_cost: 1)
hasher.create("password")
    => "$argon2i$v=19$m=65536,t=2,p=1$jL7lLEAjDN+pY2cG1N8D2g$iwj1ueduCvm6B9YVjBSnAHu+6mKzqGmDW745ALR38Uo"

You can then use this function to verify a password against a given hash. Will return either true or false.

Argon2::Password.verify_password("password", secure_password)

Version 1.2.x will now allow verifying an Argon2id password:

Argon2::Password.verify_password("password", "$argon2id$v=19$m=262144,t=2,p=1$c29tZXNhbHQ$eP4eyR+zqlZX1y5xCFTkw9m5GYx0L5YWwvCFvtlbLow")
  => true

Argon2 supports an optional key value. This should be stored securely on your server, such as alongside your database credentials. Hashes generated with a key will only validate when presented that key.

KEY = "A key"
argon = Argon2::Password.new(t_cost: 2, m_cost: 16, secret: KEY)
myhash = argon.create("A password")
Argon2::Password.verify_password("A password", myhash, KEY)

Ruby 3 Types

I am now shipping signatures in sig/. The following command sets up a testing interface.

RBS_TEST_TARGET="Argon2::*" bundle exec ruby -r rbs/test/setup bin/console

You should also be able to pass Steep checks:

steep check

These tools will need to be installed manually at this time and will be added to Gemfiles after much further testing.

Version 2.2.0

This version changed the way the build system works to deal with a new version of Rubygems. See #56.

Version 2.0 - Argon 2id

Version 2.x upwards will now default to the Argon2id hash format. This is consistent with current recommendations regarding Argon2 usage. It remains capable of verifying existing hashes.

Important notes regarding version 1.0 upgrade

Version 1.0.0 included a major version bump over 0.1.4 due to several breaking changes. The first of these was an API change, which you can read the background on here.

The second of these is that the reference Argon2 implementation introduced an algorithm change, which produces a hash which is not backwards compatible. This is documented on this PR on the C library. This was a regrettable requirement to address a security concern in the algorithm itself. The two versions of the Argon2 algorithm are numbered 1.0 and 1.3 respectively.

Shortly after this, version 1.0.0 of this gem was released with this breaking change, supporting only Argon2 v1.3. Further time later, the official encoding format was updated, with a spec that included the version number, and the library introduced backward compatibility. This should remove the likelihood of such breaking changes in future.

Platform Issues

The default installation workflow has caused issues with a number of gems under the latest OSX. There is some excellent documentation on the issue and some workarounds in the Jekyll Documentation. With this in mind, OSX is a fully supported OS.

Windows is not. Nobody anywhere has the resources to support Ruby FFI code on Windows.

grsec introduces certain challenges. Please see documentation here.

See the .travis.yml file to see currently tested and supported Ruby versions.

RubyDocs documentation

The usual URL will provide detailed documentation.

FAQ

Don't roll your own crypto!

This gets its own section because someone will raise it. I did not invent or alter this algorithm, or implement it directly. These bindings were written following considerable involvement with the C reference, and a strong focus has been made on following the intent of the algorithm.

It is strongly advised to avoid implementations that utilise off-spec methods of introducing salts, invent imaginary parameters, or which use the word "encryption" in describing the password hashing process

Secure wipe is useless

Although the low level C contains support for "secure memory wipe", any code hitting that layer has copied your password to a dozen places in memory. It should be assumed that such functionality does not exist.

Work maximums may be tighter than reference

The reference implementation is aimed to provide secure hashing for many years. This implementation doesn't want you to DoS yourself in the meantime. Accordingly, some artificial limits exist on work powers. This gem can be much more agile in raising these as technology progresses.

Salts in general

If you are providing your own salt, you are probably using it wrong. The design of any secure hashing system should take care of it for you.

Contributing

Any form of contribution is appreciated, however, please review CONTRIBUTING.md.

Building locally/Tests

To build the gem locally, you will need to run the setup script:

./bin/setup

You can test that the Argon2 C library was properly imported by running the C test suite:

./bin/test

The ruby wrapper test suite includes a property based test. To more strenuously perform this test, you can tune the iterations parameter:

TEST_CHECKS=10000 bundle exec rake test

License

The gem is available as open source under the terms of the MIT License.

ruby-argon2's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

ruby-argon2's Issues

Failure to build on powerpc64le

Hi,

Attempting to install argon2 on powerpc64le fails as follows:

Building native extensions.  This could take a while...
Successfully installed ffi-1.9.10
Successfully installed ffi-compiler-0.1.3
Building native extensions.  This could take a while...
ERROR:  Error installing argon2:
        ERROR: Failed to build gem native extension.

    /usr/local/rvm/rubies/ruby-2.2.2/bin/ruby -r ./siteconf20160226-63-1rv0m7c.rb extconf.rb

make "DESTDIR=" clean
rm -f tests libargon2_wrap.so

make "DESTDIR="
cc -std=c89 -pthread -O3 -Wall -g -march=native -shared -fPIC ../phc-winner-argon2/src/argon2.c ../phc-winner-argon2/src/core.c ../phc-winner-argon2/src/blake2/blake2b.c ../phc-winner-argon2/src/thread.c ../phc-winner-argon2/src/encoding.c argon_wrap.c ../phc-winner-argon2/src/opt.c -o libargon2_wrap.so
cc: error: unrecognized command line option '-march=native'
Makefile:54: recipe for target 'libs' failed
make: *** [libs] Error 1

make failed, exit code 2

Gem files will remain installed in /usr/local/rvm/gems/ruby-2.2.2/gems/argon2-0.1.4 for inspection.
Results logged to /usr/local/rvm/gems/ruby-2.2.2/extensions/powerpc64le-linux/2.2.0/argon2-0.1.4/gem_make.out

This seems to be caused by powerpc gcc not supporting -march. We have -mcpu and friends, but it's probably easiest if you just drop the flag on powerpc.

Thanks in advance!

Argon2::Password.create giving inconsistent results.

When just using Argon2::Password.create I am starting to get different results every time (I have been using this code for over a year tho and it has not been an issue until now).

irb(main):037:0>  Argon2::Password.create('test')
=> "$argon2i$v=19$m=65536,t=2,p=1$3ErJO2+rrc15wMqyZo5lCw$SvhWCpzZXLkm2fHjbu/hvinYDgBpLotgwqovfVsxteA"
irb(main):038:0>  Argon2::Password.create('test')
=> "$argon2i$v=19$m=65536,t=2,p=1$42WXmH1kA6jb3dyVF/yIDg$Jv49rs8vi8TwIpUDp70ix92/aVguMyd2UGZW4+0TJYE"
irb(main):039:0>  Argon2::Password.create('test')
=> "$argon2i$v=19$m=65536,t=2,p=1$wgmydmPv6fsfxoP+lsA6Ag$06h1Jj5ArylVg6MaimCPpqjv0WPMx8/MQpgW1xImClQ"

however if I create an instance like this it works:

irb(main):063:0> hasher = Argon2::Password.new(t_cost: 2, m_cost: 16)
=> #<Argon2::Password:0x0055a8f4a1c190 @t_cost=2, @m_cost=16, @salt="?\xD6,q\xAB\a\x18}\x83\xFB\t\xB9\x81\x86F\xD5", @secret=nil>
irb(main):064:0> hasher.create("test") == hasher.create("test")
=> true

Could this be something environmental that is causing it to always be different? Is this a bug?

Happy to give any other info you may need.

Memory cost definition

Hola!

please, feel free to close this if my question is not in the right place.

So right now I'm trying to move some services from python to ruby and this service hashes all passwords with the Argon2 algorithm. The problem I'm having right now is trying to match the memory cost that is specified by the python app, which uses django defaults: https://github.com/django/django/blob/3b79dab19a2300a4884a3d81baa6c7c1f2dee059/django/contrib/auth/hashers.py#L369-L371

Basically, I need the app to replicate the cost of 100 MiB or m=102400 when hashing. Is this possible? I tried a number between 10 and 16 for m_cost and I couldn't get it.

Any ideas would be great, thanks!

EDIT: Basically I want this number 😅 as m_cost

3.2.2 :003 > Math.log2(102400)
 => 16.643856189774723

:salt_do_not_supply option renamed

This was apparently deliberate in 0ef1e33, but I think you should reconsider as there are valid use cases.

Rodauth (https://github.com/jeremyevans/rodauth) uses this option because it separates the salt from the password hash to prevent attackers from being able to brute force password hashes (attackers cannot brute force passwords if they only have the salt and not the hash). By renaming the option, you broke Rodauth's use of argon2, and if Rodauth doesn't work around this issue by detecting the argon2 version and using the new option name, it would not be able to use argon2 as securely as it uses bcrypt. Please recognize there are valid reasons for providing a salt when creating an argon2 password, and provide a supported way to do so that will not change in minor versions of argon2.

Default argon2.online builds a hash which ruby_argon2 cant verify

If I use https://argon2.online and leave the defaults with a random salt, the generated hash wont be verified correctly by ruby_argon2.

require 'argon2'
=> true
puts Argon2::VERSION
2.3.0
=> nil
hash = '$argon2id$v=19$m=16,t=2,p=1$eXJ0MEtzMDlBMEpGU09MTg$T+6VYkPNTviOIOGoi8RZZA'
=> "$argon2id$v=19$m=16,t=2,p=1$eXJ0MEtzMDlBMEpGU09MTg$T+6VYkPNTviOIOGoi8RZZA"
Argon2::Password.verify_password('password', hash)
=> false

image

If I change the hash length to 32 it works correctly.
I changed the other parameters and that didn't seem to make any difference, just the hash length.

Argon2id binding

Quote from the IETF draft.
https://tools.ietf.org/html/draft-irtf-cfrg-argon2-03#section-9.4

Recommendations
The Argon2id variant with t=1 and maximum available memory is
recommended as a default setting for all environments. This setting
is secure against side-channel attacks and maximizes adversarial
costs on dedicated brute-force hardware.

I wonder if we can get the variant to be the default of ruby-argon2 too?

Fails to load with Rubygems 3.4

I've installed ruby 3.2 on macOS Ventura (13.0.1) with M1 (arm64) using ruby-build. Launching irb and typing require "argon2" I see the following:

/Users/dave/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/ffi-1.15.5/lib/ffi/library.rb:145:in `block in ffi_lib': Could not open library '/Users/dave/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/argon2-2.1.2/ext/argon2_wrap/libargon2_wrap.bundle.dSYM/Contents/Resources/DWARF/libargon2_wrap.bundle': dlopen(/Users/dave/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/argon2-2.1.2/ext/argon2_wrap/libargon2_wrap.bundle.dSYM/Contents/Resources/DWARF/libargon2_wrap.bundle, 0x0005): tried: '/Users/dave/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/argon2-2.1.2/ext/argon2_wrap/libargon2_wrap.bundle.dSYM/Contents/Resources/DWARF/libargon2_wrap.bundle' (unloadable mach-o file type 10 '/Users/dave/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/argon2-2.1.2/ext/argon2_wrap/libargon2_wrap.bundle.dSYM/Contents/Resources/DWARF/libargon2_wrap.bundle'), '/System/Volumes/Preboot/Cryptexes/OS/Users/dave/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/argon2-2.1.2/ext/argon2_wrap/libargon2_wrap.bundle.dSYM/Contents/Resources/DWARF/libargon2_wrap.bundle' (no such file), '/Users/dave/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/argon2-2.1.2/ext/argon2_wrap/libargon2_wrap.bundle.dSYM/Contents/Resources/DWARF/libargon2_wrap.bundle' (unloadable mach-o file type 10 '/Users/dave/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/arg (LoadError)
	from /Users/dave/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/ffi-1.15.5/lib/ffi/library.rb:99:in `map'
	from /Users/dave/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/ffi-1.15.5/lib/ffi/library.rb:99:in `ffi_lib'
	from /Users/dave/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/argon2-2.1.2/lib/argon2/ffi_engine.rb:10:in `<module:Ext>'
	from /Users/dave/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/argon2-2.1.2/lib/argon2/ffi_engine.rb:8:in `<module:Argon2>'
	from /Users/dave/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/argon2-2.1.2/lib/argon2/ffi_engine.rb:6:in `<top (required)>'
	from <internal:/Users/dave/.rbenv/versions/3.2.0/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
	from <internal:/Users/dave/.rbenv/versions/3.2.0/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
	from /Users/dave/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/argon2-2.1.2/lib/argon2.rb:4:in `<top (required)>'
	from <internal:/Users/dave/.rbenv/versions/3.2.0/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:160:in `require'
	from <internal:/Users/dave/.rbenv/versions/3.2.0/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:160:in `rescue in require'
	from <internal:/Users/dave/.rbenv/versions/3.2.0/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:149:in `require'
	from (irb):2:in `<main>'
	from /Users/dave/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/irb-1.6.2/exe/irb:11:in `<top (required)>'
	from /Users/dave/.rbenv/versions/3.2.0/bin/irb:25:in `load'
	from /Users/dave/.rbenv/versions/3.2.0/bin/irb:25:in `<main>'
<internal:/Users/dave/.rbenv/versions/3.2.0/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require': cannot load such file -- argon2 (LoadError)
	from <internal:/Users/dave/.rbenv/versions/3.2.0/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
	from (irb):2:in `<main>'
	from /Users/dave/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/irb-1.6.2/exe/irb:11:in `<top (required)>'
	from /Users/dave/.rbenv/versions/3.2.0/bin/irb:25:in `load'
	from /Users/dave/.rbenv/versions/3.2.0/bin/irb:25:in `<main>'

Running on CI with Github Actions and ruby 3.2 on Ubuntu 22.04.1 (x86_64 arch) I see a similar but different error:

LoadError: cannot find 'argon2_wrap' library
/home/runner/work/my-project-name/my-project-name/vendor/bundle/ruby/3.2.0/gems/ffi-compiler-1.0.1/lib/ffi-compiler/loader.rb:21:in `find'
/home/runner/work/my-project-name/my-project-name/vendor/bundle/ruby/3.2.0/gems/argon2-2.1.2/lib/argon2/ffi_engine.rb:10:in `<module:Ext>'
/home/runner/work/my-project-name/my-project-name/vendor/bundle/ruby/3.2.0/gems/argon2-2.1.2/lib/argon2/ffi_engine.rb:8:in `<module:Argon2>'
/home/runner/work/my-project-name/my-project-name/vendor/bundle/ruby/3.2.0/gems/argon2-2.1.2/lib/argon2/ffi_engine.rb:6:in `<main>'
/home/runner/work/my-project-name/my-project-name/vendor/bundle/ruby/3.2.0/gems/bootsnap-1.15.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require'
/home/runner/work/my-project-name/my-project-name/vendor/bundle/ruby/3.2.0/gems/bootsnap-1.15.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require'
/home/runner/work/my-project-name/my-project-name/vendor/bundle/ruby/3.2.0/gems/argon2-2.1.2/lib/argon2.rb:4:in `<main>'
/home/runner/work/my-project-name/my-project-name/vendor/bundle/ruby/3.2.0/gems/bootsnap-1.15.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require'
/home/runner/work/my-project-name/my-project-name/vendor/bundle/ruby/3.2.0/gems/bootsnap-1.15.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require'
/home/runner/work/my-project-name/my-project-name/config/application.rb:24:in `<top (required)>'
/home/runner/work/my-project-name/my-project-name/config/environment.rb:2:in `require_relative'
/home/runner/work/my-project-name/my-project-name/config/environment.rb:2:in `<top (required)>'
/home/runner/work/my-project-name/my-project-name/Rakefile:3:in `require_relative'
/home/runner/work/my-project-name/my-project-name/Rakefile:3:in `block in <top (required)>'
/home/runner/work/my-project-name/my-project-name/vendor/bundle/ruby/3.2.0/gems/rake-13.0.6/exe/rake:27:in `<top (required)>'
/opt/hostedtoolcache/Ruby/3.2.0/x64/bin/bundle:25:in `load'
/opt/hostedtoolcache/Ruby/3.2.0/x64/bin/bundle:25:in `<main>'
Tasks: TOP => assets:precompile => environment
(See full trace by running task with --trace)

I tried cloning the argon2 repo, and was able to run bin/setup, bin/test, and rake test all without any errors. I looked at https://github.com/technion/ruby-argon2/blob/master/test/test_helper.rb#L3 and found this helped. Steps to reproduce:

  1. Open irb session in the ruby-argon2 directory
  2. Type require "argon2" see failures (same as above for macOS)
  3. Type $LOAD_PATH.unshift File.expand_path("lib")
  4. Type require "argon2" and now it works.

Note the above only works after running bin/setup, even though I've installed argon2 already. This seems to be because when running bin/setup, the correct file in ext/argon2_wrap is created, specifically the libargon_wrap2 file:

On macOS, Ruby 3.1.3 (argon2 loads no issue)

~ ❯❯❯ ls -la .rbenv/versions/3.1.3/lib/ruby/gems/3.1.0/gems/argon2-2.1.2/ext/argon2_wrap/
total 496
drwxr-xr-x  9 dave  staff     288 Dec  5 16:58 .
drwxr-xr-x  4 dave  staff     128 Dec  5 16:58 ..
-rw-r--r--  1 dave  staff    1958 Dec  5 16:58 Makefile
-rw-r--r--  1 dave  staff    4504 Dec  5 16:58 argon_wrap.c
-rw-r--r--  1 dave  staff      98 Dec  5 16:58 extconf.rb
-rwxr-xr-x  1 dave  staff   76450 Dec  5 16:58 libargon2_wrap.bundle
drwxr-xr-x  3 dave  staff      96 Dec  5 16:58 libargon2_wrap.bundle.dSYM
-rwxr-xr-x  1 dave  staff  151552 Dec  5 16:58 libargon2_wrap.so
-rw-r--r--  1 dave  staff    4500 Dec  5 16:58 test.c

On macOS, Ruby 3.2.0 (missing the libargon2_wrap.bundle file, argon2 errors on require)

~ ❯❯❯ ls -la .rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/argon2-2.1.2/ext/argon2_wrap/
total 344
drwxr-xr-x  8 dave  staff     256 Dec 25 12:14 .
drwxr-xr-x  4 dave  staff     128 Dec 25 12:14 ..
-rw-r--r--  1 dave  staff    1958 Dec 25 12:14 Makefile
-rw-r--r--  1 dave  staff    4504 Dec 25 12:14 argon_wrap.c
-rw-r--r--  1 dave  staff      98 Dec 25 12:14 extconf.rb
drwxr-xr-x  3 dave  staff      96 Dec 25 12:14 libargon2_wrap.bundle.dSYM
-rwxr-xr-x  1 dave  staff  151552 Dec 25 12:14 libargon2_wrap.so
-rw-r--r--  1 dave  staff    4500 Dec 25 12:14 test.c

On Ubuntu, Ruby 3.1.3 (argon2 loads no issue)

$ ls -la .rbenv/versions/3.1.3/lib/ruby/gems/3.1.0/gems/argon2-2.1.2/ext/argon2_wrap/
total 256
drwxrwxr-x 2 ubuntu ubuntu   4096 Dec 25 18:10 .
drwxrwxr-x 4 ubuntu ubuntu   4096 Dec 25 18:10 ..
-rw-r--r-- 1 ubuntu ubuntu   1958 Dec 25 18:10 Makefile
-rw-r--r-- 1 ubuntu ubuntu   4504 Dec 25 18:10 argon_wrap.c
-rw-r--r-- 1 ubuntu ubuntu     98 Dec 25 18:10 extconf.rb
-rwxrwxr-x 1 ubuntu ubuntu 227056 Dec 25 18:10 libargon2_wrap.so
-rw-r--r-- 1 ubuntu ubuntu   4500 Dec 25 18:10 test.c

On Ubuntu, Ruby 3.2.0 (missing the libargon2_wrap.so file, argon2 errors on require)

$ ls -la .rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/argon2-2.1.2/ext/argon2_wrap/
total 32
drwxrwxr-x 2 ubuntu ubuntu 4096 Dec 25 17:49 .
drwxrwxr-x 4 ubuntu ubuntu 4096 Dec 25 17:49 ..
-rw-r--r-- 1 ubuntu ubuntu 1958 Dec 25 17:49 Makefile
-rw-r--r-- 1 ubuntu ubuntu 4504 Dec 25 17:49 argon_wrap.c
-rw-r--r-- 1 ubuntu ubuntu   98 Dec 25 17:49 extconf.rb
-rw-r--r-- 1 ubuntu ubuntu 4500 Dec 25 17:49 test.c

I'm not sure if this is an ffi issue, or the way argon2 is using ffi.

Unsigned RubyGem

The argon2 gem is unsigned and cannot be installed with the HighSecurity option:

$ gem install -P HighSecurity argon2
ERROR:  While executing gem ... (Gem::Security::Exception)
    unsigned gems are not allowed by the High Security policy

If this is something you'd consider changing and aren't familiar with the process, https://guides.rubygems.org/security/#building-gems has some good instructions.

Use of ambiguous string lengths in FFI Engine interface

I think there may be an issue around the lengths here. I'm struggling to compile on my mac, or would add tests and/or fix myself.

The length of several strings is measured with "length" in lib/argon2/ffi_engine.rb#L40 before being passed to a C interface that interprets this as a byte length. In Ruby 1.9 and higher, length is defined as the character length of the string, not the byte length. The bytesize method provides the equivalent for bytes:

http://apidock.com/ruby/String/bytesize

Tims-MBP:ruby-argon2 timgoddard$ irb
2.2.1 :001 > subject = "hoş geldiniz"
 => "hoş geldiniz" 
2.2.1 :002 > subject.length
 => 12 
2.2.1 :003 > subject.bytesize
 => 13 
2.2.1 :004 > subject.chars.length
 => 12 
2.2.1 :005 > subject.bytes.length
 => 13 

This may cause errors, or allow an active attacker to produce distinct documents for which this library produces the same hash (effectively an error-based preimage attack).

Add OWASP recommendations as additional profiles?

As mentioned in #62 there is a lot of discussion and disagreement. I wonder if it would be valuable to make OWASP's recommended settings more easily used? I'm swayed by the arguments presented there, personally.

I'm not suggesting a change in defaults, as I'm far from qualified to make that argument.

Github Org for improved SEO

Hi @technion,

Would you be okay with moving the repo location for this to an organization? For example:

  • ruby-argon2/argon2 or
  • ruby-argon2/ruby-argon2

Similar to bcrypt-ruby, this would give better SEO for users trying to find the official ruby binding for Argon2, and allow you to take on more maintainers easily in the future if you choose to do so.

You should be able to create an organization, then transfer the repo to your new organization without much trouble. Github automatically redirects the current repo and all issues/PRs to the new location if you use their transfer feature.

Ship a new version?

Hi! I noticed that the current version of this Gem doesn't build on SmartOS (a Solaris derivative). This is because support for SmartOS / Solaris was added on 28th of may in 2016 (See: https://github.com/P-H-C/phc-winner-argon2/blob/master/Makefile#L88 ) and version 1.1.1 of the gem uses an april 2016 version of Argon2. Could I tempt you to make a 1.1.2 release? I'll buy you a beer for it if your ever in Rotterdam ;-)

FFI Loader cannot locate argon2_wrap on Mac OSX

From clean git checkout, submodules installed, running setup then console:

Tims-MBP:ruby-argon2 timgoddard$ bin/setup 
Fetching gem metadata from https://rubygems.org/.........
Fetching version metadata from https://rubygems.org/..
Resolving dependencies...
Using rake 10.4.2
Using ffi 1.9.10
Using ffi-compiler 0.1.3
Using argon2 0.1.1 from source at .
Using ast 2.2.0
Using parser 2.2.3.0
Using astrolabe 1.3.1
Using bundler 1.10.5
Using docile 1.1.5
Using json 1.8.3
Using simplecov-html 0.10.0
Using simplecov 0.11.1
Using codeclimate-test-reporter 0.4.8
Using minitest 5.8.3
Using powerpack 0.1.1
Using rainbow 2.0.0
Using ruby-progressbar 1.7.5
Using tins 1.6.0
Using rubocop 0.35.1
Bundle complete! 6 Gemfile dependencies, 19 gems now installed.
Use `bundle show [gemname]` to see where a bundled gem is installed.
cc -std=c89 -pthread -O3 -Wall -g -march=native -dynamiclib -install_name @rpath/libargon2_wrap.dylib ../phc-winner-argon2/src/argon2.c ../phc-winner-argon2/src/core.c ../phc-winner-argon2/src/blake2/blake2b.c ../phc-winner-argon2/src/thread.c ../phc-winner-argon2/src/encoding.c argon_wrap.c ../phc-winner-argon2/src/opt.c -o libargon2_wrap.dylib
Tims-MBP:ruby-argon2 timgoddard$ bin/console 
/Users/timgoddard/.rvm/gems/ruby-2.2.1/gems/ffi-compiler-0.1.3/lib/ffi-compiler/loader.rb:21:in `find': cannot find 'argon2_wrap' library (LoadError)
    from /Users/timgoddard/Repo/ruby-argon2/lib/argon2/ffi_engine.rb:8:in `<module:Ext>'
    from /Users/timgoddard/Repo/ruby-argon2/lib/argon2/ffi_engine.rb:6:in `<module:Argon2>'
    from /Users/timgoddard/Repo/ruby-argon2/lib/argon2/ffi_engine.rb:4:in `<top (required)>'
    from /Users/timgoddard/Repo/ruby-argon2/lib/argon2.rb:2:in `require'
    from /Users/timgoddard/Repo/ruby-argon2/lib/argon2.rb:2:in `<top (required)>'
    from bin/console:4:in `require'
    from bin/console:4:in `<main>'

The same issue appears with an installed gem. Not sure it's finding the dylib file.

Error with grsec kernel

I have wrestled for a couple days with a deployment, and thought I would document my struggles for posterity, and others who may encounter a similar issue.

I have been trying to deploy an app to an Alpine Linux instance, using a grsecurity kernel. Every time i would do

require 'argon2

I would get an error (it was unreadable, but that's another issue)

RuntimeError: �M���
from ~/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/ffi-1.9.14/lib/ffi/library.rb:277:in `attach'

After much searching and tearing of hair by the roots (even creating a python wrapper for argon2 and attempting to invoke it from within the app,) I finally stumbled across a partial answer - the code was forbidden by the grsecurity-hardened kernel, specifically the 'mprotect' flag.

I was able to get the code to run by doing the following:

sudo paxctl -c ~/.rbenv/versions/2.3.1/bin/ruby # Convert the binary to using PT_PAX_FLAGS
sudo paxctl -m ~/.rbenv/versions/2.3.1/bin/ruby # disable MPROTECT

I am not sure of the implications of this change, or whether it can be resolved in a different way, but I thought I would put it here so that others could have their say.

On further research, the ffi README references this issue, here, although it was a pain linking this particular error to grsec.

Minimum costs

I want to ensure my test suite is fast, so for the test env I want to use minimum costs. Based on this I think the following should work:

irb(main):007:0> Argon2::Password.new({t_cost: 1, m_cost: 1}).create('test')
Argon2::ArgonHashFail: Argon2::ArgonHashFail
	from /Users/bartdewater/.gem/ruby/2.3.3/gems/argon2-1.1.2/lib/argon2/ffi_engine.rb:59:in `block in hash_argon2i_encode'
	from /Users/bartdewater/.gem/ruby/2.3.3/gems/argon2-1.1.2/lib/argon2/ffi_engine.rb:55:in `initialize'
	from /Users/bartdewater/.gem/ruby/2.3.3/gems/argon2-1.1.2/lib/argon2/ffi_engine.rb:55:in `new'
	from /Users/bartdewater/.gem/ruby/2.3.3/gems/argon2-1.1.2/lib/argon2/ffi_engine.rb:55:in `hash_argon2i_encode'
	from /Users/bartdewater/.gem/ruby/2.3.3/gems/argon2-1.1.2/lib/argon2.rb:24:in `create'
	from (irb):7
	from /opt/rubies/2.3.3/bin/irb:11:in `<main>'

Only from m_cost: 3 I don't get an error. Perhaps a MIN_COST constant (like the Bcrypt gem) could be introduced to make it a bit easier?

Possible to remove hard-coded upper limit on t_cost?

I've been implementing argon2 and in testing using the argon2 CLI I determined that a t_cost of 500 and an m_cost of 12 was ideal and gave 1-second hash times. When I try to use the ruby-argon2 gem, I found that it restricts t to a maximum of 10. This seems strange to me given that the hard-coded limit for m_cost is 2^31 or 2GB. This seems like an unwise amount of memory to use for password hashing in practice, but is allowed, yet iterations is capped at a very low number which, unless you're using a huge amount of RAM, gives very quick hash times on current hardware.

Trying to increase m_cost to get my desired result while keeping t at 10 would be costly in terms of server capacity. I can technically turn m up on my existing hardware as far as 15 (16 gets the process killed), but again, I'd rather not consume that much memory when I can achieve the desired hash time with t. Also, t=10 and m=15 on my hardware is only 409ms.

Is there a reason for this limit, or is it arbitrary? Is it possible to at least move these hard-coded integers to constants so that this limitation can be more safely patched around? Happy to make a PR for this if you're open to it.

Lack of null-byte support (limitation of encodings)

The current implementation requires that this passes the password as a c-string without a length, so no null bytes can exist in the password string. This may seriously limit, for example, the ability to use this on strings in some encodings (UTF-16).

Incompatible with other versions of Argon2

Hi,

Is there any way to make this library compatible with these Javascript versions of Argon2:

Both of these agree with each other regarding hashes generated:

https://argon2.online/
https://github.com/ranisalt/node-argon2

both of the Javascript ones produce the same hash for the given parameters. However this library gives a different hash for the same input parameters.

for example:

Argon2::Engine.hash_argon2i("password","superdupersalt",2, 16)
# d0d101ed0cf5030421f927e714d73e9ccf1f3e824d94b3d3fa49e9aa128b3afe

but in Javascript using ()

password = "password"
salt = "superdupersalt"
memory = 16
iterations = 2
parallel = 1
16742c5cdfcf7d771b2bce3e95cd44071ee7718fd191b50a9fb183da3b1e5888

and using the node-argon2 library:

password = "password"
salt = "superdupersalt"
memory = 16
iterations = 2

const hash = await argon2.hash(password, {
        type: argon2.argon2i,
        hashLength: 32,
        timeCost: iterations,
        memoryCost: memory,
        parallelism: 1,
        raw: true,
        salt
    });
16742c5cdfcf7d771b2bce3e95cd44071ee7718fd191b50a9fb183da3b1e5888

Please could you let me know if you know why this library produces different results to the Javascript ones above. And if possible how I can get them to be compatible - whether that be modifying this ruby project or modifying the javascript projects?

Your help greatly appreciated

Thanks

--Kingsley

Error when attempting to use fork

Gemfile:

# frozen_string_literal: true

source 'https://rubygems.org'

git_source(:github) { |repo| "https://github.com/#{repo}.git" }

gem 'argon2', github: 'athix/ruby-argon2', branch: 'feature/additional-helpers'

When running bundle / bundle install I get the following error:

Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    current directory: /home/[REDACTED]/.rvm/gems/ruby-3.0.0@sorcery/bundler/gems/ruby-argon2-acbbf925b8f0/ext/argon2_wrap
/home/[REDACTED]/.rvm/rubies/ruby-3.0.0/bin/ruby -I /home/[REDACTED]/.rvm/rubies/ruby-3.0.0/lib/ruby/3.0.0 -r
./siteconf20210326-54663-cq3tmp.rb extconf.rb

current directory: /home/[REDACTED]/.rvm/gems/ruby-3.0.0@sorcery/bundler/gems/ruby-argon2-acbbf925b8f0/ext/argon2_wrap
make "DESTDIR=" clean
rm -f tests libargon2_wrap.so

current directory: /home/[REDACTED]/.rvm/gems/ruby-3.0.0@sorcery/bundler/gems/ruby-argon2-acbbf925b8f0/ext/argon2_wrap
make "DESTDIR="
make: *** No rule to make target '../phc-winner-argon2/src/argon2.c', needed by 'libs'.  Stop.

make failed, exit code 2

Gem files will remain installed in /home/[REDACTED]/.rvm/gems/ruby-3.0.0@sorcery/bundler/gems/ruby-argon2-acbbf925b8f0 for
inspection.
Results logged to
/home/[REDACTED]/.rvm/gems/ruby-3.0.0@sorcery/bundler/gems/extensions/x86_64-linux/3.0.0/ruby-argon2-acbbf925b8f0/gem_make.out

An error occurred while installing argon2 (2.0.3), and Bundler cannot continue.

In Gemfile:
  argon2

@technion thoughts?

FFI compiler LoadError

loading the gems fails

LoadError: cannot find 'argon2_wrap' library
    from /Users/me/.rvm/gems/ruby-2.2.1/gems/ffi-compiler-0.1.3/lib/ffi-compiler/loader.rb:21:in `find'
    from /Users/me/.rvm/gems/ruby-2.2.1/gems/argon2-0.1.0/lib/argon2/ffi_engine.rb:8:in `<module:Ext>'
    from /Users/me/.rvm/gems/ruby-2.2.1/gems/argon2-0.1.0/lib/argon2/ffi_engine.rb:6:in `<module:Argon2>'
    from /Users/me/.rvm/gems/ruby-2.2.1/gems/argon2-0.1.0/lib/argon2/ffi_engine.rb:4:in `<top (required)>'
    from /Users/me/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:69:in `require'
    from /Users/me/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:69:in `require'
    from /Users/me/.rvm/gems/ruby-2.2.1/gems/argon2-0.1.0/lib/argon2.rb:2:in `<top (required)>'
    from /Users/me/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:128:in `require'
    from /Users/me/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:128:in `rescue in require'
    from /Users/me/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:39:in `require'
    from (irb):1
    from /Users/me/.rvm/rubies/ruby-2.2.1/bin/irb:11:in `<main>'

I don't have any experience with FFI myself. Although extensions in the gemspec seems to be set up as expected?

legacy.rb test unused and in broken state

Currently the legacy test isn't included in the minitest suite due to lacking the _test suffix. Additionally, if you add the suffix and run the tests, it appears to be in a failing state due to a missing constant:

  1) Error:
Legacy#test_legacy_hashes:
NameError: uninitialized constant Legacy::PASS

  2) Error:
Legacy#test_valid_hash_legacy_hashes:
NameError: uninitialized constant Legacy::PASS

Are these tests obsolete / ready to be removed entirely?

Argon2::Password.hash overrides Object#hash in an incompatible manner

Which makes it impossible to use the class as a key in a hash, for instance:

$ irb
irb(main):001:0> require 'argon2'
=> true
irb(main):002:0> h = {}
=> {}
irb(main):003:0> h[Argon2::Password] = 42
ArgumentError: wrong number of arguments (0 for 1)
    from /home/gutov/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/argon2-0.1.4/lib/argon2.rb:25:in `hash'
    from (irb):3
    from /home/gutov/.rbenv/versions/2.1.2/bin/irb:11:in `<main>'

Rubocop issues

I've encountered issues regarding Rubocop (see stack trace below) since I've started to add this gem as a dependency in a gem I was working on.

vendor/bundle/gems/argon2-2.0.2/.rubocop.yml: Metrics/LineLength has the wrong namespace - should be Layout
Error: The `Layout/AlignArray` cop has been renamed to `Layout/ArrayAlignment`.
(obsolete configuration found in vendor/bundle/gems/argon2-2.0.2/.rubocop.yml, please update it)
The `Layout/AlignParameters` cop has been renamed to `Layout/ParameterAlignment`.
(obsolete configuration found in vendor/bundle/gems/argon2-2.0.2/.rubocop.yml, please update it)
The `Layout/IndentArray` cop has been renamed to `Layout/FirstArrayElementIndentation`.
(obsolete configuration found in vendor/bundle/gems/argon2-2.0.2/.rubocop.yml, please update it)

RBS issue - Cannot find type `FFI::Library`

I'm exploring using RBS and Steep with our project, but ran into an issue when running steep check:

../.local/share/rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/argon2-2.2.0/sig/ffi.rbs:4:4: [error] Cannot find type `FFI::Library`
│ Diagnostic ID: RBS::UnknownTypeName
│
└     extend FFI::Library
      ~~~~~~~~~~~~~~~~~~~

Admittedly being new to these tools I don't know if this an issue with argon2 or ffi, but I thought I'd start here since the file it complains about is from this gem.

Ship a new version?

Hey there,

thanks for your work on this! I tried out the library and it seems the API changed significantly on master in comparison to 0.1.4 on Rubygems, most notably the examples mentioning create do not work since the method has been renamed from hash. It would be nice to have a new version shipped so the README on the Github landing page actually matches what you get upon installing the lib.

Cheers!

RubyGems and Github naming mismatch

Hey,

My name is Maciej Mensfeld and I run a research security project called diffend.io.

I've noticed, that you have a mismatch between the repo name on GitHub (ruby-argon2) and the RubyGems one (argon2). This mismatch has been recently used as a brandjacking base for popular libraries like yours thus I took courtesy and "booked" it for you (if you want). If not, I'll just keep it as it is, protecting the argon2 :)

If you want to transfer the ownership just please reach out to me.

Have a great day and thank you

ref https://rubygems.org/gems/ruby-argon2 https://rubygems.org/gems/argon2

Cannot specify memory costs that aren't `2^N`

The current OWASP guidance recommends memory costs (46 MiB, 19 MiB, 12 MiB, 9 MiB, or 7 MiB) that are not expressible in the current notation of m_cost being the N that 2 can be raised to the power of. This is troublesome for those who want to adhere to a recommended memory cost expressed as an absolute value (eg 9,216 KiB).

I understand this lib is adhering to the reference implementation, thinly exposing the m_cost param of 2^N, but perhaps for the sake of greater compatibility with continually evolving recommended values, the m_cost: option should be an absolute value expressed in KiB? This is consistent with Python's argon2-cffi.

Previously:

Argon2::Password.create('password', {m_cost: 16})
    # => "$argon2id$v=19$m=65536,t=2,p=1$pgUSydEmCXecEWFkz2P9iw$8iB2ipvGkQXyuvoJYDz5Ppwy7V2WSEdF7+/XlZYRYAY"

Suggested:

Argon2::Password.create('password', {m_cost: 64 * 1024})
    # => "$argon2id$v=19$m=65536,t=2,p=1$pgUSydEmCXecEWFkz2P9iw$8iB2ipvGkQXyuvoJYDz5Ppwy7V2WSEdF7+/XlZYRYAY"

Argon2::Password.verify_password can only verify passwords with default Salt lengths

The verify_password method will return false when attempting to validate Argon2 encodings generated with a salt length different from the default 16.

This means encodings generated within the gem validate properly but encodings generated outside of the gem will fail when validating with the gem unless the Salt length matches the gem's default.

Moving existing Argon2 encodings into a system using this gem may then require regenerating all encodings.

Below I've put together test cases using the gem's validation and encodings generated via command line using Argon2 v1.3.

Gem Generated Password Validates

irb(main):001:0> require 'argon2'
=> true
irb(main):002:0> test = Argon2::Password.create("password")
=> "$argon2i$v=19$m=65536,t=2,p=1$FMTtGRKnyJlUMvCyoXKZ9g$dQFsMAFHBBdMnp/nQ/wScDqz+fJrUiO+UAGNailZIYU"
irb(main):003:0> Argon2::Password.verify_password("password",test)
=> true

Argon2 1.3 Generated Password Following Gem Defaults Validates

echo -n "password" | ./argon2 LongEnoughSaltLn -t 2 -m 16 -l 32
Type:       Argon2i
Iterations: 2
Memory:     65536 KiB
Parallelism:    1
Hash:       4c172bab9fe7cb8f2063623f97845374f01902864e187a0cba7150255b865f9e
Encoded:    $argon2i$v=19$m=65536,t=2,p=1$TG9uZ0Vub3VnaFNhbHRMbg$TBcrq5/ny48gY2I/l4RTdPAZAoZOGHoMunFQJVuGX54
0.124 seconds
Verification ok
irb(main):004:0> Argon2::Password.verify_password("password","$argon2i$v=19$m=65536,t=2,p=1$TG9uZ0Vub3VnaFNhbHRMbg$TBcrq5/ny48gY2I/l4RTdPAZAoZOGHoMunFQJVuGX54")
=> true

Argon2 1.3 Generated Password With Shorter Salt Fails Validation

$ echo -n "password" | ./argon2 TooShortSaleLen -t 2 -m 16 -l 32
Type:       Argon2i
Iterations: 2
Memory:     65536 KiB
Parallelism:    1
Hash:       8b9f442e0026e46e89fbdfa86703be924578f2d272a1c361e9b1dd923f49e659
Encoded:    $argon2i$v=19$m=65536,t=2,p=1$VG9vU2hvcnRTYWxlTGVu$i59ELgAm5G6J+9+oZwO+kkV48tJyocNh6bHdkj9J5lk
0.122 seconds
Verification ok
irb(main):005:0> Argon2::Password.verify_password("password","$argon2i$v=19$m=65536,t=2,p=1$VG9vU2hvcnRTYWxlTGVu$i59ELgAm5G6J+9+oZwO+kkV48tJyocNh6bHdkj9J5lk")
=> false

Argon2 1.3 Generated Password With Longer Salt Fails Validation

$ echo -n "password" | ./argon2 TooLongSaleLength -t 2 -m 16 -l 32
Type:       Argon2i
Iterations: 2
Memory:     65536 KiB
Parallelism:    1
Hash:       99895e047b06e8dd3e1f8246274c57a0844eeab58d67037f790410f1e1c80e69
Encoded:    $argon2i$v=19$m=65536,t=2,p=1$VG9vTG9uZ1NhbGVMZW5ndGg$mYleBHsG6N0+H4JGJ0xXoIRO6rWNZwN/eQQQ8eHIDmk
0.122 seconds
Verification ok
irb(main):006:0> Argon2::Password.verify_password("password","$argon2i$v=19$m=65536,t=2,p=1$VG9vTG9uZ1NhbGVMZW5ndGg$mYleBHsG6N0+H4JGJ0xXoIRO6rWNZwN/eQQQ8eHIDmk")
=> false

Incorrect initialization checks: `ARGON2_MEMORY_TOO_LITTLE` raised when m_cost < 3

Looking at the source code for v2.2.0 and even master's not-yet-released MIN_M_COST constant, the library checks that an initialization kwarg m_cost value isn't less than 1:

MIN_M_COST = 1

@m_cost = options[:m_cost] || DEFAULT_M_COST
raise ArgonHashFail, "Invalid m_cost" if @m_cost < MIN_M_COST || @m_cost > MAX_M_COST

The minimum value should be 3, not 1-- At least for a Debian 12 docker image (Windows 10 host):

PS C:\Users\Justin> docker run --rm -it ruby:3.2.2 bash
root@dfbcabeafa6d:/# gem install argon2
Fetching ffi-1.15.5.gem
Fetching ffi-compiler-1.0.1.gem
Fetching argon2-2.2.0.gem
Building native extensions. This could take a while...
Successfully installed ffi-1.15.5
Successfully installed ffi-compiler-1.0.1
Building native extensions. This could take a while...
Successfully installed argon2-2.2.0
3 gems installed

A new release of RubyGems is available: 3.4.10 → 3.4.19!
Run `gem update --system 3.4.19` to update your installation.

root@dfbcabeafa6d:/# irb
irb(main):001:0> require 'argon2'
=> true
irb(main):002:0> Argon2::Password.new(t_cost: 1, m_cost: 3, p_cost: 1).create("password")
=> "$argon2id$v=19$m=8,t=1,p=1$RzeGPHz7Fw3eYnpYalvPWg$JXMw3AUrDpFYfuvu2Gmj7yXdofLOXpAQYBzNGAVPJrM"
irb(main):003:0> Argon2::Password.new(t_cost: 1, m_cost: 2, p_cost: 1).create("password")
/usr/local/bundle/gems/argon2-2.2.0/lib/argon2/ffi_engine.rb:91:in `block in hash_argon2id_encode': ARGON2_MEMORY_TOO_LITTLE (Argon2::ArgonHashFail)
        from /usr/local/bundle/gems/argon2-2.2.0/lib/argon2/ffi_engine.rb:87:in `initialize'
        from /usr/local/bundle/gems/argon2-2.2.0/lib/argon2/ffi_engine.rb:87:in `new'
        from /usr/local/bundle/gems/argon2-2.2.0/lib/argon2/ffi_engine.rb:87:in `hash_argon2id_encode'
        from /usr/local/bundle/gems/argon2-2.2.0/lib/argon2.rb:34:in `create'
        from (irb):3:in `<main>'
        from /usr/local/lib/ruby/gems/3.2.0/gems/irb-1.6.2/exe/irb:11:in `<top (required)>'
        from /usr/local/bin/irb:25:in `load'
        from /usr/local/bin/irb:25:in `<main>'
irb(main):004:0> Argon2::Password.new(t_cost: 1, m_cost: 1, p_cost: 1).create("password")
/usr/local/bundle/gems/argon2-2.2.0/lib/argon2/ffi_engine.rb:91:in `block in hash_argon2id_encode': ARGON2_MEMORY_TOO_LITTLE (Argon2::ArgonHashFail)
        from /usr/local/bundle/gems/argon2-2.2.0/lib/argon2/ffi_engine.rb:87:in `initialize'
        from /usr/local/bundle/gems/argon2-2.2.0/lib/argon2/ffi_engine.rb:87:in `new'
        from /usr/local/bundle/gems/argon2-2.2.0/lib/argon2/ffi_engine.rb:87:in `hash_argon2id_encode'
        from /usr/local/bundle/gems/argon2-2.2.0/lib/argon2.rb:34:in `create'
        from (irb):4:in `<main>'
        from /usr/local/lib/ruby/gems/3.2.0/gems/irb-1.6.2/exe/irb:11:in `<top (required)>'
        from /usr/local/bin/irb:25:in `load'
        from /usr/local/bin/irb:25:in `<main>'
irb(main):005:0>

Now I will concede that argon2's minimum memory values is dependent on certain factors around the machine running it. For portability I understand that it may be best to let the ffi'd argon2 engine be responsible for the errors and validation.

That being said, if you were to release the current state of master the following would raise an exception which would violate many author's/developer's assumptions:

Argon2::Password.new(m_cost: Argon2::Password::MIN_M_COST).create("somepassword")
# raises ARGON2_MEMORY_TOO_LITTLE (Argon2::ArgonHashFail)

If possible, the ruby constants should map to or extract from the C constants ARGON2_MIN_MEMORY and its friends in argon2.h: https://github.com/P-H-C/phc-winner-argon2/blob/f57e61e19229e23c4445b85494dbf7c07de721cb/include/argon2.h#L46-L88

No way to verify Argon2 1.0 hashes

In the C library, argon2_verify automatically detects the hash version and thus allows verifying older hashes. On the other hand, ruby-argon2 always sets the version to 1.3, making newer versions of the library useless if you have a database with older hashes.

As Ruby doesn't allow loading multiple versions of a gem simultaneously, there is currently no way to migrate to the current version of ruby-argon2.

Gem fails to build under FreeBSD 12.0

This gem fails to build under FreeBSD 12.0. I've included the FreeBSD build errors below:

`current directory: /usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap
/usr/local/bin/ruby24 -r ./siteconf20190723-30514-1iieq5p.rb extconf.rb

current directory: /usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap
make "DESTDIR=" clean
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 19: Missing dependency operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 21: Need an operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 24: Need an operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 31: Missing dependency operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 32: warning: duplicate script for target "(,)" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 20: warning: using previous script for "(,)" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 33: warning: duplicate script for target "(,)" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 20: warning: using previous script for "(,)" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 34: Need an operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 35: Missing dependency operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 36: warning: duplicate script for target "ifeq" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 33: warning: using previous script for "ifeq" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 36: warning: duplicate script for target "(,)" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 20: warning: using previous script for "(,)" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 37: warning: duplicate script for target "ifeq" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 33: warning: using previous script for "ifeq" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 37: warning: duplicate script for target "(,)" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 20: warning: using previous script for "(,)" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 38: Need an operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 39: Missing dependency operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 40: warning: duplicate script for target "ifeq" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 33: warning: using previous script for "ifeq" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 40: warning: duplicate script for target "(,)" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 20: warning: using previous script for "(,)" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 41: warning: duplicate script for target "ifeq" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 33: warning: using previous script for "ifeq" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 41: warning: duplicate script for target "(,)" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 20: warning: using previous script for "(,)" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 42: Need an operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 43: Missing dependency operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 44: warning: duplicate script for target "ifeq" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 33: warning: using previous script for "ifeq" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 44: warning: duplicate script for target "(,)" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 20: warning: using previous script for "(,)" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 45: warning: duplicate script for target "ifeq" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 33: warning: using previous script for "ifeq" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 45: warning: duplicate script for target "(,)" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 20: warning: using previous script for "(,)" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 46: Need an operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 47: Missing dependency operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 48: warning: duplicate script for target "ifeq" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 33: warning: using previous script for "ifeq" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 48: warning: duplicate script for target "(,)" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 20: warning: using previous script for "(,)" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 49: warning: duplicate script for target "ifeq" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 33: warning: using previous script for "ifeq" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 49: warning: duplicate script for target "(,)" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 20: warning: using previous script for "(,)" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 50: Need an operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 51: Missing dependency operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 56: Need an operator
make: Fatal errors encountered -- cannot continue
make: stopped in /usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap

current directory: /usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap
make "DESTDIR="
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 19: Missing dependency operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 21: Need an operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 24: Need an operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 31: Missing dependency operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 32: warning: duplicate script for target "(,)" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 20: warning: using previous script for "(,)" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 33: warning: duplicate script for target "(,)" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 20: warning: using previous script for "(,)" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 34: Need an operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 35: Missing dependency operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 36: warning: duplicate script for target "ifeq" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 33: warning: using previous script for "ifeq" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 36: warning: duplicate script for target "(,)" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 20: warning: using previous script for "(,)" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 37: warning: duplicate script for target "ifeq" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 33: warning: using previous script for "ifeq" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 37: warning: duplicate script for target "(,)" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 20: warning: using previous script for "(,)" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 38: Need an operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 39: Missing dependency operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 40: warning: duplicate script for target "ifeq" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 33: warning: using previous script for "ifeq" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 40: warning: duplicate script for target "(,)" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 20: warning: using previous script for "(,)" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 41: warning: duplicate script for target "ifeq" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 33: warning: using previous script for "ifeq" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 41: warning: duplicate script for target "(,)" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 20: warning: using previous script for "(,)" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 42: Need an operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 43: Missing dependency operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 44: warning: duplicate script for target "ifeq" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 33: warning: using previous script for "ifeq" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 44: warning: duplicate script for target "(,)" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 20: warning: using previous script for "(,)" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 45: warning: duplicate script for target "ifeq" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 33: warning: using previous script for "ifeq" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 45: warning: duplicate script for target "(,)" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 20: warning: using previous script for "(,)" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 46: Need an operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 47: Missing dependency operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 48: warning: duplicate script for target "ifeq" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 33: warning: using previous script for "ifeq" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 48: warning: duplicate script for target "(,)" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 20: warning: using previous script for "(,)" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 49: warning: duplicate script for target "ifeq" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 33: warning: using previous script for "ifeq" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 49: warning: duplicate script for target "(,)" ignored
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 20: warning: using previous script for "(,)" defined here
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 50: Need an operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 51: Missing dependency operator
make: "/usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap/Makefile" line 56: Need an operator
make: Fatal errors encountered -- cannot continue
make: stopped in /usr/local/lib/ruby/gems/2.4/gems/argon2-2.0.2/ext/argon2_wrap

make failed, exit code 1`

Unable to install latest on master via Bundler

I can build fine if I run bin/setup but if I try to install via bundler I get this error in gem_make.out:

current directory: /home/kfinch/.rvm/gems/ruby-3.0.2/bundler/gems/ruby-argon2-0ef1e33b7d9e/ext/argon2_wrap
/home/kfinch/.rvm/rubies/ruby-3.0.2/bin/ruby -I /home/kfinch/.rvm/rubies/ruby-3.0.2/lib/ruby/3.0.0 -r ./siteconf20211001-193036-cw25ka.rb extconf.rb

current directory: /home/kfinch/.rvm/gems/ruby-3.0.2/bundler/gems/ruby-argon2-0ef1e33b7d9e/ext/argon2_wrap
make DESTDIR\= clean
rm -f tests libargon2_wrap.so

current directory: /home/kfinch/.rvm/gems/ruby-3.0.2/bundler/gems/ruby-argon2-0ef1e33b7d9e/ext/argon2_wrap
make DESTDIR\=
make: *** No rule to make target '../phc-winner-argon2/src/argon2.c', needed by 'libs'.  Stop.

make failed, exit code 2

I'm just trying to get the latest feature that let's me set p_cost. Also wish all options of the argon2 reference command were implemented so I can set the hash length to 64 instead of 32 as the gem has it hardcoded.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.