{"id":21565845,"url":"https://github.com/basesecrete/active_hashcash","last_synced_at":"2025-05-15T18:08:52.149Z","repository":{"id":41414943,"uuid":"506556788","full_name":"BaseSecrete/active_hashcash","owner":"BaseSecrete","description":"Protect Rails applications against bots and brute force attacks without annoying humans.","archived":false,"fork":false,"pushed_at":"2025-02-27T08:57:07.000Z","size":872,"stargazers_count":212,"open_issues_count":3,"forks_count":10,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-02T22:49:35.571Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/BaseSecrete.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-06-23T08:25:39.000Z","updated_at":"2025-03-07T05:39:20.000Z","dependencies_parsed_at":"2025-01-19T06:03:40.437Z","dependency_job_id":"d313b3c6-a4b8-4f68-8ab9-002d19d6b2ff","html_url":"https://github.com/BaseSecrete/active_hashcash","commit_stats":{"total_commits":23,"total_committers":1,"mean_commits":23.0,"dds":0.0,"last_synced_commit":"151445838b1dad092675baf41b75c5cb822ce89e"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BaseSecrete%2Factive_hashcash","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BaseSecrete%2Factive_hashcash/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BaseSecrete%2Factive_hashcash/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BaseSecrete%2Factive_hashcash/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BaseSecrete","download_url":"https://codeload.github.com/BaseSecrete/active_hashcash/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247755557,"owners_count":20990620,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-24T10:22:03.047Z","updated_at":"2025-04-08T00:35:20.565Z","avatar_url":"https://github.com/BaseSecrete.png","language":"Ruby","readme":"# ActiveHashcash\n\n\u003cimg align=\"right\" width=\"200px\" src=\"logo.png\" alt=\"Active Hashcash logo\"/\u003e\n\nActiveHashcash protects Rails applications against bots and brute force attacks without annoying humans.\n\nHashcash is proof-of-work algorithm, invented by Adam Back in 1997, to protect systems against denial of service attacks.\nActiveHashcash is an easy way to protect any Rails application against brute force attacks and bots.\n\nThe idea is to force clients to spend some time to solve a hard problem that is very easy to verify for the server.\nWe have developed ActiveHashcash after seeing brute force attacks against our Rails application monitoring service [RorVsWild](https://rorvswild.com).\n\nActiveHashcash is ideal to set up on sensitive forms such as login and registration.\nWhile the user is filling the form, the problem is solved in JavaScript and set the result into a hidden input text.\nThe form cannot be submitted while the proof of work has not been found.\nThen the user submits the form, and the stamp is verified by the controller in a before action.\n\nIt blocks bots that do not interpret JavaScript since the proof of work is not computed.\nMore sophisticated bots and brute force attacks are slow down.\nMoreover the complexity increases automatically for IP addresses sending many requests.\nThus it becomes very CPU costly for attackers.\n\nFinally legitimate users are not annoyed by asking to solve a puzzle or clicking on the all images containing a bus.\nHere is a [demo on a registration form](https://www.rorvswild.com/session) :\n\n![Active Hashcash GIF preview](demo.gif)\n\n---\n\n\u003cimg align=\"left\" height=\"24px\" src=\"rorvswild_logo.jpg\" alt=\"RorVsWild logo\"/\u003eMade by \u003ca href=\"https://www.rorvswild.com\"\u003eRorVsWild\u003c/a\u003e, performances \u0026 exceptions monitoring for Ruby on Rails applications.\n\n---\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem \"active_hashcash\"\n```\n\nRequire hashcash from your JavaScript manifest.\n\n```js\n//= require hashcash\n```\n\nOR\n\nLink hashcash to your JavaScript manifest and load it to your head.\n\n```js\n//= link hashcash.js\n```\n\n```erb\n\u003c%= javascript_include_tag \"hashcash\", \"data-turbo-track\": \"reload\", defer: true %\u003e\n```\n\nAdd a Hashcash hidden field into the form you want to protect.\n\n```erb\n\u003cform\u003e\n  \u003c%= hashcash_hidden_field_tag %\u003e\n\u003c/form\u003e\n```\n\nThen you have to define a `before_action :check_hashcash` in you controller.\n\n```ruby\nclass SessionController \u003c ApplicationController\n  include ActiveHashcash\n\n  # Only the action receiving the form needs to be protected\n  before_action :check_hashcash, only: :create\nend\n```\n\nTo customize some behaviour, you can override most of the methods which begins with `hashcash_`.\nSimply have a look to `active_hashcash.rb`.\n\nStamps are stored into into the database to prevents from spending them more than once.\nYou must run a migration:\n\n```\nrails active_hashcash:install:migrations\nrails db:migrate\n```\n\n### Dashboard\n\nThere is a mountable dashboard which allows to see all spent stamps.\nIt's not mandatory, but useful for monitoring purpose.\n\n![ActiveHashcash dashboard](active_hashcash_dashboard.png \"ActiveHashcash dashboard\")\n\n```ruby\n# config/routes.rb\nmount ActiveHashcash::Engine, at: \"hashcash\"\n```\n\nActiveHashcash cannot guess how you handle user authentication, because it is different for all Rails applications.\nSo you have to monkey patch `ActiveHashcash::ApplicationController` in order to inject your own mechanism.\nThe patch can be saved wherever you want.\nFor example, I like to have all the patches in one place, so I put them in `lib/patches`.\n\n```ruby\n# lib/patches/active_hashcash.rb\n\nActiveHashcash::ApplicationController.class_eval do\n    before_action :require_admin\n\n    def require_admin\n      # This example supposes there are current_user and User#admin? methods\n      raise ActionController::RoutingError.new(\"Not found\") unless current_user.try(:admin?)\n    end\n  end\nend\n```\n\nThen you have to require the monkey patch.\nBecause it's loaded via require, it won't be reloaded in development.\nSince you are not supposed to change this file often, it should not be an issue.\n\n```ruby\n# config/application.rb\nconfig.after_initialize do\n  require \"patches/active_hashcash\"\nend\n```\n\nIf you use Devise, you can check the permission directly from routes.rb:\n\n```ruby\n# config/routes.rb\nauthenticate :user, -\u003e (u) { u.admin? } do # Supposing there is a User#admin? method\n  mount ActiveHashcash::Engine, at: \"hashcash\" # http://localhost:3000/hashcash\nend\n```\n\nBy default ActiveHashcash will extend `ActionController::Base`, but you can change it to any controller you want.\n\n```ruby\n# config/initializers/active_hashcash.rb\nRails.application.configure do\n  ActiveHashcash.base_controller_class = \"AdminController\"\nend\n```\n\n### Before version 0.3.0\n\nYou must have Redis in order to prevent double spent stamps. Otherwise it will be useless.\nIt automatically tries to connect with the environment variables `ACTIVE_HASHCASH_REDIS_URL` or `REDIS_URL`.\nYou can also manually set the URL with `ActiveHashcash.redis_url = redis://user:password@localhost:6379`.\n\nYou should call `ActiveHashcash::Store#clean` once a day, to remove expired stamps.\n\nTo upgrade from 0.2.0 you must run the migration :\n\n```\nrails active_hashcash:install:migrations\nrails db:migrate\n```\n\n## Complexity\n\nComplexity is the most important parameter. By default its value is 20 and requires most of the time 5 to 20 seconds to be solved on a decent laptop.\nThe user won't wait that long, since he needs to fill the form while the problem is solving.\nHowever, if your application includes people with slow and old devices, then consider lowering this value, to 16 or 18.\n\nYou can change the minimum complexity with `ActiveHashcash.bits = 20`.\n\nSince version 0.3.0, the complexity increases with the number of stamps spent during le last 24H from the same IP address.\nThus it becomes very efficient to slow down brute force attacks.\n\n## Limitations\n\nThe JavaScript implementation is 10 to 20 times slower than the official C version.\nI first used the SubtleCrypto API but it is surprisingly slower than a custom SHA1 implementation.\nMaybe I did in an inefficient way 2df3ba5?\nAnother idea would be to compile the work algorithm in wasm.\n\nUnfortunately, I'm not a JavaScript expert.\nMaybe you have good JS skills to optimize it?\nAny help would be appreciate to better fights bots and brute for attacks!\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/BaseSecrete/active_hashcash.\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n\nMade by Alexis Bernard at [RorVsWild](https://www.rorvswild.com).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbasesecrete%2Factive_hashcash","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbasesecrete%2Factive_hashcash","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbasesecrete%2Factive_hashcash/lists"}