PHPackages                             chrisholland/hashtuner - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. chrisholland/hashtuner

ActiveProject

chrisholland/hashtuner
======================

Framework for tuning settings for password-hashing functions

1411PHPCI failing

Since Dec 22Pushed 1mo ago3 watchersCompare

[ Source](https://github.com/elchris/hashtuner)[ Packagist](https://packagist.org/packages/chrisholland/hashtuner)[ RSS](/packages/chrisholland-hashtuner/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependenciesVersions (4)Used By (0)

hashtuner
=========

[](#hashtuner)

Framework to automatically suggest settings for password hashing functions, starting with Argon2id. This library was inspired by [Bryan Burman's article](https://www.twelve21.io/how-to-choose-the-right-parameters-for-argon2/).

It requires php 8.0 or greater.

It can be used:

- as an executable from the command line, which outputs a JSON payload containing target settings
- integrated in any PHP system thru Object-Oriented API

[![Maintainability](https://camo.githubusercontent.com/0997e3499418c8d0ce2b3033ff9359dffcc53aad1fb93264726c9aa99f501e65/68747470733a2f2f6170692e636f6465636c696d6174652e636f6d2f76312f6261646765732f37646162326436383637636537623063366136652f6d61696e7461696e6162696c697479)](https://codeclimate.com/github/elchris/hashtuner/maintainability)[![Test Coverage](https://camo.githubusercontent.com/cfeeb21184ccfd9e0c4e8af5d5f391778aa53c86996bc4619411d56efc294245/68747470733a2f2f6170692e636f6465636c696d6174652e636f6d2f76312f6261646765732f37646162326436383637636537623063366136652f746573745f636f766572616765)](https://codeclimate.com/github/elchris/hashtuner/test_coverage)[![CircleCI](https://camo.githubusercontent.com/a4b8f6a00f09190382117bdd9280ec89c9c013030aacf1642b64b2cd2c8f071a/68747470733a2f2f636972636c6563692e636f6d2f67682f656c63687269732f6861736874756e65722e7376673f7374796c653d737667)](https://circleci.com/gh/elchris/hashtuner)

What it does
============

[](#what-it-does)

Various algorithms give us different "levers" to control the cost of computing a hash.

Argon2id
--------

[](#argon2id)

With a minimum of `3 iterations`, it strives to dominate the cost of password hashing with memory, up to a specified `hard memory limit`, to achieve an execution time within a given range.

Once it achieves [75%](https://github.com/elchris/hashtuner/blob/21030235f40cbce82cdba8b8a2333d91334b3198/src/Strategy/TwoDimensionsTunerStrategy.php#L14) of the upper execution time limit, or the `hard memory limit` has been reached, it stops augmenting the memory then tries to get even closer to the upper execution time limit by augmenting iterations.

For the time-being, "`threads`" are locked-down to `1`, because the libsodium integration with password\_hash won't accept a value other than `1`. - Insert link to article explaining this behavior here -

Hard Memory Limit
=================

[](#hard-memory-limit)

- Estimate a server's available memory for concurrent password-hashing processes, say `8GB`
- Estimate a worst-case scenario for concurrent users logging-in at a given time, say `50`.
- Divide the two: 8GB / 50 = 160MB
- `Hard Memory Limit` should be set to `160000` aka 160,000KB

Quickest Usage with Phar File
=============================

[](#quickest-usage-with-phar-file)

- Download [hashtuner.phar](https://github.com/elchris/hashtuner/blob/main/hashtuner.phar)
- scp it to your server

Usage with Defaults
-------------------

[](#usage-with-defaults)

```
php ./hashtuner.phar

```

- Assumes your `hard memory limit` is the value of "`mem_limit`" in php.ini
    - in most instances, this is way too high.
- Assumes a `desired execution time` between `0.5 and 1.0 seconds`

Usage with Custom Hard Memory Limit
-----------------------------------

[](#usage-with-custom-hard-memory-limit)

```
php ./hashtuner.phar 128000

```

- Sets your `hard memory limit` to roughly `128 Megabytes`
- Assumes a `desired execution time` between `0.5 and 1.0 seconds`

Usage with Custom Hard Memory Limit and Desired Execution Time
--------------------------------------------------------------

[](#usage-with-custom-hard-memory-limit-and-desired-execution-time)

```
php ./hashtuner.phar 128000 0.8 1.3

```

- Sets your `hard memory limit` to roughly `128 Megabytes`
- Sets your `desired execution time` between `0.8 and 1.3 seconds`

Usage in a Project: Composer
============================

[](#usage-in-a-project-composer)

Installation
------------

[](#installation)

```
composer require chrisholland/hashtuner

```

API
---

[](#api)

```
(new ArgonTuner())->getTunedSettings()->toJson()

```

```
(new ArgonTuner())->getTunedSettingsForMemoryLimit(128000)->toJson()

```

```
(new ArgonTuner())->getTunedSettingsForSpeedAndMemoryLimit(
0.5,
1.0,
128000
)->toJson()

```

More Reading
============

[](#more-reading)

Symfony
-------

[](#symfony)

- [Native Password Hasher in Symfony 4.3](https://symfony.com/blog/new-in-symfony-4-3-native-password-encoder)
- [Adding Password Rehashing Capibilities in Symfony](https://github.com/symfony/symfony/pull/31153)

Other Links
-----------

[](#other-links)

- [Paragonie's Argon2 Refiner](https://github.com/paragonie/argon2-refiner)
- [Modern Hashing Algorithms](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#modern-algorithms)

Coding Practices &amp; Contributions
====================================

[](#coding-practices--contributions)

Contributions are welcome and gratefuly appreciated. Please ensure that every commit includes a new test signaling intent, or a fix to an existing test to correct erroneous or missing assumptions.

Standards
---------

[](#standards)

- [Style](https://github.com/PHPCSStandards/PHP_CodeSniffer): [PSR-2](https://www.php-fig.org/psr/psr-2/)
- [PHPStan](https://github.com/phpstan/phpstan): Level [7](https://github.com/elchris/hashtuner/blob/f539db5a0aa0f72110f921cdd893c403b3536895/phpstan.neon#L4)

Driving Code, with Tests
------------------------

[](#driving-code-with-tests)

Aside from src/index.php, 100% of this code was driven by tests, which is how I achieved "100% coverage". Having said this, I don't test-drive code to achieve any "code coverage" percentage, I only do it to more quickly understand what I'm trying to deliver, more easily arrive at a solution, and in the end deliver better software, faster than I would without doing any testing whatsoever. A high "code coverage" percentage just happens to be a mere byproduct of this process.

Generate hashtuner.phar with box-project
----------------------------------------

[](#generate-hashtunerphar-with-box-project)

- [install the "box" command](https://github.com/box-project/box/blob/main/doc/installation.md#homebrew)
- run (all settings live box.json):
    - `box compile`

###  Health Score

31

—

LowBetter than 68% of packages

Maintenance60

Regular maintenance activity

Popularity9

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity39

Early-stage or recently created project

 Bus Factor1

Top contributor holds 98.5% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/e466e895d683f11be259d3b1d10a69ea1133f7756ab77f465fa0b1edc9f570bd?d=identicon)[chrisholland](/maintainers/chrisholland)

---

Top Contributors

[![elchris](https://avatars.githubusercontent.com/u/3396192?v=4)](https://github.com/elchris "elchris (131 commits)")[![rodrigoprimo](https://avatars.githubusercontent.com/u/77215?v=4)](https://github.com/rodrigoprimo "rodrigoprimo (1 commits)")[![scrutinizer-auto-fixer](https://avatars.githubusercontent.com/u/6253494?v=4)](https://github.com/scrutinizer-auto-fixer "scrutinizer-auto-fixer (1 commits)")

### Embed Badge

![Health badge](/badges/chrisholland-hashtuner/health.svg)

```
[![Health](https://phpackages.com/badges/chrisholland-hashtuner/health.svg)](https://phpackages.com/packages/chrisholland-hashtuner)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
