{"id":13454944,"url":"https://github.com/simonepri/upash","last_synced_at":"2025-04-12T17:45:39.228Z","repository":{"id":52453192,"uuid":"99278592","full_name":"simonepri/upash","owner":"simonepri","description":"🔒Unified API for password hashing algorithms","archived":false,"fork":false,"pushed_at":"2021-04-28T21:38:24.000Z","size":512,"stargazers_count":538,"open_issues_count":7,"forks_count":24,"subscribers_count":12,"default_branch":"master","last_synced_at":"2024-10-29T19:59:51.671Z","etag":null,"topics":["api","argon","bcrypt","brute-force","cli","credential","credentials","hash-functions","hashing","nodejs","password","pbkdf2","rainbow-table","secure","security","timing-attacks","unified","universal","upash","verification"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/upash","language":"JavaScript","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/simonepri.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"license","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-08-03T22:01:45.000Z","updated_at":"2024-10-23T13:52:35.000Z","dependencies_parsed_at":"2022-08-31T04:11:49.258Z","dependency_job_id":null,"html_url":"https://github.com/simonepri/upash","commit_stats":null,"previous_names":["simonepri/credential-plus"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonepri%2Fupash","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonepri%2Fupash/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonepri%2Fupash/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonepri%2Fupash/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simonepri","download_url":"https://codeload.github.com/simonepri/upash/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248609545,"owners_count":21132915,"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":["api","argon","bcrypt","brute-force","cli","credential","credentials","hash-functions","hashing","nodejs","password","pbkdf2","rainbow-table","secure","security","timing-attacks","unified","universal","upash","verification"],"created_at":"2024-07-31T08:00:59.657Z","updated_at":"2025-04-12T17:45:39.203Z","avatar_url":"https://github.com/simonepri.png","language":"JavaScript","readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/simonepri/upash\"\u003e\n    \u003cimg src=\"https://github.com/simonepri/upash/raw/master/media/upash.png\" alt=\"upash\" width=\"300\"/\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003c!-- CI - TravisCI --\u003e\n  \u003ca href=\"https://travis-ci.com/simonepri/upash\"\u003e\n    \u003cimg src=\"https://img.shields.io/travis/com/simonepri/upash/master.svg?label=MacOS%20%26%20Linux\" alt=\"Mac/Linux Build Status\" /\u003e\n  \u003c/a\u003e\n  \u003c!-- CI - AppVeyor --\u003e\n  \u003ca href=\"https://ci.appveyor.com/project/simonepri/upash\"\u003e\n    \u003cimg src=\"https://img.shields.io/appveyor/ci/simonepri/upash/master.svg?label=Windows\" alt=\"Windows Build status\" /\u003e\n  \u003c/a\u003e\n  \u003c!-- Coverage - Codecov --\u003e\n  \u003ca href=\"https://codecov.io/gh/simonepri/upash\"\u003e\n    \u003cimg src=\"https://img.shields.io/codecov/c/github/simonepri/upash/master.svg\" alt=\"Codecov Coverage report\" /\u003e\n  \u003c/a\u003e\n  \u003c!-- DM - Snyk --\u003e\n  \u003ca href=\"https://snyk.io/test/github/simonepri/upash?targetFile=package.json\"\u003e\n    \u003cimg src=\"https://snyk.io/test/github/simonepri/upash/badge.svg?targetFile=package.json\" alt=\"Known Vulnerabilities\" /\u003e\n  \u003c/a\u003e\n  \u003c!-- DM - David --\u003e\n  \u003ca href=\"https://david-dm.org/simonepri/upash\"\u003e\n    \u003cimg src=\"https://david-dm.org/simonepri/upash/status.svg\" alt=\"Dependency Status\" /\u003e\n  \u003c/a\u003e\n\n  \u003cbr/\u003e\n\n  \u003c!-- Code Style - XO-Prettier --\u003e\n  \u003ca href=\"https://github.com/xojs/xo\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/code_style-XO+Prettier-5ed9c7.svg\" alt=\"XO Code Style used\" /\u003e\n  \u003c/a\u003e\n  \u003c!-- Test Runner - AVA --\u003e\n  \u003ca href=\"https://github.com/avajs/ava\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/test_runner-AVA-fb3170.svg\" alt=\"AVA Test Runner used\" /\u003e\n  \u003c/a\u003e\n  \u003c!-- Test Coverage - Istanbul --\u003e\n  \u003ca href=\"https://github.com/istanbuljs/nyc\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/test_coverage-NYC-fec606.svg\" alt=\"Istanbul Test Coverage used\" /\u003e\n  \u003c/a\u003e\n  \u003c!-- Init - ni --\u003e\n  \u003ca href=\"https://github.com/simonepri/ni\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/initialized_with-ni-e74c3c.svg\" alt=\"NI Scaffolding System used\" /\u003e\n  \u003c/a\u003e\n  \u003c!-- Release - np --\u003e\n  \u003ca href=\"https://github.com/sindresorhus/np\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/released_with-np-6c8784.svg\" alt=\"NP Release System used\" /\u003e\n  \u003c/a\u003e\n\n  \u003cbr/\u003e\n\n  \u003c!-- Mentioned - Awesome NodeJS --\u003e\n  \u003ca href=\"https://github.com/sindresorhus/awesome-nodejs#security\"\u003e\n    \u003cimg src=\"https://awesome.re/mentioned-badge.svg\" alt=\"Mentioned in Awesome NodeJS\" /\u003e\n  \u003c/a\u003e\n  \u003c!-- Version - npm --\u003e\n  \u003ca href=\"https://www.npmjs.com/package/upash\"\u003e\n    \u003cimg src=\"https://img.shields.io/npm/v/upash.svg\" alt=\"Latest version on npm\" /\u003e\n  \u003c/a\u003e\n  \u003c!-- License - MIT --\u003e\n  \u003ca href=\"https://github.com/simonepri/upash/tree/master/license\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/license/simonepri/upash.svg\" alt=\"Project license\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  🔒 \u003cb\u003eU\u003c/b\u003enified API for \u003cb\u003ePAS\u003c/b\u003esword \u003cb\u003eH\u003c/b\u003eashing algorithms\n\n  \u003cbr/\u003e\n\n  \u003csub\u003e\n    Coded with ❤️ by \u003ca href=\"#authors\"\u003eSimone Primarosa\u003c/a\u003e.\n  \u003c/sub\u003e\n\u003c/p\u003e\n\n## Synopsis\nPassword breaches have become more and more frequent.  \nSee: [Yahoo][breach:yahoo] ([twice][breach:yahoo2]), [LinkedIn][breach:linkedin], [Adobe][breach:adobe],\n[Ashley Madison][breach:ashley-madison], and [a whole lot more][breach:hibp-breaches].\n\nIndeed, the above examples doubles as a list of \"how NOT to do password\nstorage\": simple hashing, unsalted values, misuse of encryption, and failed\npassword migration. (For more information on why these are bad, see our [introduction to password hashing theory][docs:password-hashing-theory])\n\nThere are two possible interpretations here: first, companies do not put adequate resources in securing passwords; and secondly, getting password hashing right is hard. Furthermore, even if you have followed previous best practice, keeping it right is another technical challenge: algorithm choices, security levels, parameter selection change regularly.\n\n## Make passwords painless\n\u003cimg src=\"https://github.com/simonepri/upash/raw/master/media/api.png\" alt=\"upash api\" width=\"400\" align=\"right\"/\u003e\n\nThe upash ([pronounced u-pash][upash:pronounce]) project aims is to allow you to\nhave a clean and easy-to-use API to use any password hashing algorithm\nseamlessly in your application.\n***\n\n#### Highlights\n- Simple API for all password hashing algorithms\n- Easy to maintain and [upgradable](#upgrading-your-password-hashing-algorithm) logic\n- Easy to test configurations through the [CLI](#test-configurations-through-the-cli)\n- Step by step [migration guide](#migrating-your-existing-password-hashing-solution)\n- Comprehensive list of supported [hashing algorithms](#recommended-algorithms-implementations)\n\nDo you believe that this is useful? Has it saved you time? Or maybe you simply like it?  \nIf so, [support my work with a Star ⭐️][start] and [follow me 📩][github:simonepri].\n\n## Usage\nThe upash solution is straight-forward but it is important to follow all the\nsteps carefully.\n\nFirstly, you need to install this package.\n\n```bash\nnpm install --save upash\n```\nThen, you need to choose from the\n[list of supported password hashing algorithms](#recommended-algorithms-implementations)\nthe one that best suits your needs and install that too.  \nIn the following, we will assume that you choose `@phc/argon2`, that is also a\nsuitable solution in case you don't know which one fits better for you.\n\n```bash\nnpm install --save @phc/argon2\n```\n\nFinally, you can enjoy the easy APIs.\n\n```js\nconst upash = require('upash');\n\n// Install the algorithm of your choice.\nupash.install('argon2', require('@phc/argon2'));\n\n// Hash API\nconst hashstr = await upash.hash('password');\n// =\u003e \"$argon2id$v=19$m=4096,t=3,p=1$PcEZHj1maR/+ZQynyJHWZg$2jEN4xcww7CYp1jakZB1rxbYsZ55XH2HgjYRtdZtubI\"\n\n// Verify API\nconst match = await upash.verify(hashstr, 'password');\n// =\u003e true\n```\n\nYou can store the hash returned by the `hash` function directly into your database.\n\nYou can also install more than one algorithm at once.  \nThis is really handy when you want to update your current password hashing\nalgorithm.\n\n```js\nconst upash = require('upash');\n\n// Install the algorithms of your choice.\nupash.install('pbkdf2', require('@phc/pbkdf2'));\nupash.install('argon2', require('@phc/argon2'));\n\n// You can explicitly tell upash which algorithm to use.\nconst hashstr_pbkdf2 = await upash.use('pbkdf2').hash('password');\n// =\u003e \"$pbkdf2-sha512$i=10000$O484sW7giRw+nt5WVnp15w$jEUMVZ9adB+63ko/8Dr9oB1jWdndpVVQ65xRlT+tA1GTKcJ7BWlTjdaiILzZAhIPEtgTImKvbgnu8TS/ZrjKgA\"\n\n// If you don't do so it will automatically use the last one installed.\nconst hashstr_argon2 = await upash.hash('password');\n// =\u003e \"$argon2i$v=19$m=4096,t=3,p=1$mTFYKhlcxmjS/v6Y8aEd5g$IKGY+vj0MdezVEKHQ9bvjpROoR5HPun5/AUCjQrHSIs\"\n\n// When you verify upash will automatically choose the algorithm to use based\n// on the identifier contained in the hash string.\nconst match_pbkdf2 = await upash.verify(hashstr_pbkdf2, 'password');\n// =\u003e true\n\n// This will allow you to easily migrate from an algorithm to another.\nconst match_argon2 = await upash.verify(hashstr_argon2, 'password');\n// =\u003e true\n```\n\n## Recommended algorithms implementations\nThe following is a curated list of algorithms that adhere to the upash APIs\nguidelines and are ready to work at a production level straight out of the box.  \nAll the functions come pre-configured but fine-tuning is always a good practice.  \nThe defaults are maintained by the community and the aim of this project is also\nto bring together experts to be able to provide you reasonably secure default\nconfigurations.\n\n#### Packages that are implemented natively (Node.js only)\n- [@phc/argon2][alg:@phc/argon2] - 🔒 Node.JS argon2 password hashing algorithm following the PHC string format.\n- [@phc/pbkdf2][alg:@phc/pbkdf2] - 🔒 Node.JS pbkdf2 password hashing algorithm following the PHC string format.\n- [@phc/scrypt][alg:@phc/scrypt] - 🔒 Node.JS scrypt password hashing algorithm following the PHC string format.\n- [@phc/bcrypt][alg:@phc/bcrypt] - 🔒 Node.JS bcrypt password hashing algorithm following the PHC string format.\n\n#### Packages that are implemented in JavaScript (Browser compatible)\n- WIP\n\n\u003e If you wanna help me with these [DM me on twitter][twitter:simoneprimarosa].\n\n#### Packages that are implemented in WebAssembly (Browser compatible)\n- WIP\n\n\u003e If you wanna help me with these [DM me on twitter][twitter:simoneprimarosa].\n\nWant your package listed here? [Open an issue][new issue] and we will review it.\n\n## Test configurations through the CLI\n\u003cimg src=\"https://github.com/simonepri/upash/raw/master/media/cli.gif\" alt=\"upash cli\" width=\"400\" align=\"right\"/\u003e\n\nGenerally, each function allows configuration of 'work factors’.\nUnderlying mechanisms used to achieve irreversibility and govern work factors\n(such as time, space, and parallelism) vary between functions.  \n\nYou want to adjust the work factor to keep pace with threats' increasing hardware\ncapabilities so as to impede attackers while providing acceptable user experience\nand scale.\n\nA common rule of thumb for tuning the work factor (or cost) is to make the\nfunction run as slow as possible without affecting the users' experience and\nwithout increasing the need for extra hardware over budget.\n\nThe CLI lets you hash and verify password directly from your terminal.  \nYou can use it to test work, memory and parallelism parameters on different\nmachines.\n\nFor installation and usage information about the CLI, see the\n[upash-cli][gh:upash-cli] page.\n\n## Migrating your existing password hashing solution\nIf you are not building a new application, chances are high that you have\nalready implemented some hash/verify logic for your passwords.  \nThe [migration guide][docs:migration-guide] provides some good guidance on how\nto accomplish an upgrade in place without adversely affecting existing user\naccounts and future proofing your upgrade so you can seamlessly upgrade again\n(which you eventually will need to do).\n\nPlease if you do not find a migration documentation that fits your case,\n[open an issue][new issue].\n\n## Upgrading your password hashing algorithm\nUpgrading the hashing algorithm used to hash passwords inside your application\ncan be a really painful operation if not done well.\nYou should take a lot of attention in order to not adversely affect existing\nuser accounts.  \n\n[This article][docs:ext:upgrade-algorithm] is a nice start that should give you\nsome ideas on what are the problems related to that process.  \n\nExample of implementations can be found in the\n[upgrade algorithm guide][docs:upgrade-algorithm].\n\n## API\n\u003cdl\u003e\n\u003cdt\u003e\u003ca href=\"#install\"\u003einstall(name, algorithm)\u003c/a\u003e\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eInstalls a compatible password hashing function.\u003c/p\u003e\n\u003c/dd\u003e\n\u003cdt\u003e\u003ca href=\"#uninstall\"\u003euninstall(name)\u003c/a\u003e\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eUninstalls a password hashing function previously installed.\u003c/p\u003e\n\u003c/dd\u003e\n\u003cdt\u003e\u003ca href=\"#list\"\u003elist()\u003c/a\u003e ⇒ \u003ccode\u003eArray.\u0026lt;string\u0026gt;\u003c/code\u003e\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eGets the list of the installed password hashing functions.\u003c/p\u003e\n\u003c/dd\u003e\n\u003cdt\u003e\u003ca href=\"#use\"\u003euse(name)\u003c/a\u003e ⇒ \u003ccode\u003eObject\u003c/code\u003e\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eSelects manually which password hashing function to use.\nYou can call hash and verify on the object returned.\u003c/p\u003e\n\u003c/dd\u003e\n\u003cdt\u003e\u003ca href=\"#which\"\u003ewhich(hashstr)\u003c/a\u003e ⇒ \u003ccode\u003estring\u003c/code\u003e | \u003ccode\u003enull\u003c/code\u003e\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eReturns the name of the algorithm that has generated the hash string.\u003c/p\u003e\n\u003c/dd\u003e\n\u003cdt\u003e\u003ca href=\"#verify\"\u003everify(hashstr, password)\u003c/a\u003e ⇒ \u003ccode\u003ePromise.\u0026lt;boolean\u0026gt;\u003c/code\u003e\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eDetermines whether or not the hash provided matches the hash generated for\nthe given password choosing the right algorithm based on the identifier\ncontained in the hash.\u003c/p\u003e\n\u003c/dd\u003e\n\u003cdt\u003e\u003ca href=\"#hash\"\u003ehash(password, [options])\u003c/a\u003e ⇒ \u003ccode\u003ePromise.\u0026lt;string\u0026gt;\u003c/code\u003e\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eComputes the hash string of the given password using the \u0026#39;last\u0026#39; algorithm\ninstalled.\u003c/p\u003e\n\u003c/dd\u003e\n\u003c/dl\u003e\n\n\u003ca name=\"install\"\u003e\u003c/a\u003e\n\n### install(name, algorithm)\nInstalls a compatible password hashing function.\n\n**Kind**: global function  \n**Access**: public  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | \u003ccode\u003estring\u003c/code\u003e | The name of the password hashing function. |\n| algorithm | \u003ccode\u003eObject\u003c/code\u003e | The password hashing function object. |\n| algorithm.hash | \u003ccode\u003efunction\u003c/code\u003e | A function that takes a password and returns a cryptographically secure password hash string. |\n| algorithm.verify | \u003ccode\u003efunction\u003c/code\u003e | A function that takes a secure password hash string and a password and returns whether or not the password is valid for the given hash string. |\n| algorithm.identifiers | \u003ccode\u003efunction\u003c/code\u003e | A function that returns the list of identifiers that this password hashing algorithm is able to generate / verify. |\n\n\u003ca name=\"uninstall\"\u003e\u003c/a\u003e\n\n### uninstall(name)\nUninstalls a password hashing function previously installed.\n\n**Kind**: global function  \n**Access**: public  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | \u003ccode\u003estring\u003c/code\u003e | The name of the algorithm to uninstall or 'last' to uninstall the last one installed. |\n\n\u003ca name=\"list\"\u003e\u003c/a\u003e\n\n### list() ⇒ \u003ccode\u003eArray.\u0026lt;string\u0026gt;\u003c/code\u003e\nGets the list of the installed password hashing functions.\n\n**Kind**: global function  \n**Returns**: \u003ccode\u003eArray.\u0026lt;string\u0026gt;\u003c/code\u003e - The array of the available password hashing\nfunctions.  \n**Access**: public  \n\u003ca name=\"use\"\u003e\u003c/a\u003e\n\n### use(name) ⇒ \u003ccode\u003eObject\u003c/code\u003e\nSelects manually which password hashing function to use.\nYou can call hash and verify on the object returned.\n\n**Kind**: global function  \n**Returns**: \u003ccode\u003eObject\u003c/code\u003e - The password hashing function object.  \n**Access**: public  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | \u003ccode\u003estring\u003c/code\u003e \\| \u003ccode\u003eundefined\u003c/code\u003e | The name of the algorithm to use. |\n\n\u003ca name=\"which\"\u003e\u003c/a\u003e\n\n### which(hashstr) ⇒ \u003ccode\u003estring\u003c/code\u003e \\| \u003ccode\u003enull\u003c/code\u003e\nReturns the name of the algorithm that has generated the hash string.\n\n**Kind**: global function  \n**Returns**: \u003ccode\u003estring\u003c/code\u003e \\| \u003ccode\u003enull\u003c/code\u003e - The name of password hashing algorithm.  \n**Access**: public  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| hashstr | \u003ccode\u003estring\u003c/code\u003e | Secure hash string generated from this package. |\n\n\u003ca name=\"verify\"\u003e\u003c/a\u003e\n\n### verify(hashstr, password) ⇒ \u003ccode\u003ePromise.\u0026lt;boolean\u0026gt;\u003c/code\u003e\nDetermines whether or not the hash provided matches the hash generated for\nthe given password choosing the right algorithm based on the identifier\ncontained in the hash.\n\n**Kind**: global function  \n**Returns**: \u003ccode\u003ePromise.\u0026lt;boolean\u0026gt;\u003c/code\u003e - A boolean that is true if the hash computed\nfor the password matches.  \n**Access**: public  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| hashstr | \u003ccode\u003estring\u003c/code\u003e | Secure hash string generated from this package. |\n| password | \u003ccode\u003estring\u003c/code\u003e | User's password input. |\n\n\u003ca name=\"hash\"\u003e\u003c/a\u003e\n\n### hash(password, [options]) ⇒ \u003ccode\u003ePromise.\u0026lt;string\u0026gt;\u003c/code\u003e\nComputes the hash string of the given password using the 'last' algorithm\ninstalled.\n\n**Kind**: global function  \n**Returns**: \u003ccode\u003ePromise.\u0026lt;string\u0026gt;\u003c/code\u003e - The generated secure hash string.  \n**Access**: public  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| password | \u003ccode\u003estring\u003c/code\u003e | The password to hash. |\n| [options] | \u003ccode\u003eObject\u003c/code\u003e | Optional configurations related to the hashing function. See the algorithm specific documentation for the options supported. |\n\n## Contributing\nContributions are REALLY welcome and if you find a security flaw in this code,\nPLEASE [report it][new issue].  \n\n## Authors\n- **Simone Primarosa** - *Github* ([@simonepri][github:simonepri]) • *Twitter* ([@simoneprimarosa][twitter:simoneprimarosa])\n\nSee also the list of [contributors][contributors] who participated in this project.\n\n## License\nThis project is licensed under the MIT License - see the [license][license] file for details.\n\n\u003c!-- Links --\u003e\n[start]: https://github.com/simonepri/upash#start-of-content\n[new issue]: https://github.com/simonepri/upash/issues/new\n[contributors]: https://github.com/simonepri/upash/contributors\n\n[license]: https://github.com/simonepri/upash/tree/master/license\n\n[gh:upash-cli]: https://github.com/simonepri/upash-cli\n\n[alg:@phc/argon2]: https://github.com/simonepri/upash-argon2\n[alg:@phc/scrypt]: https://github.com/simonepri/upash-scrypt\n[alg:@phc/bcrypt]: https://github.com/simonepri/upash-bcrypt\n[alg:@phc/pbkdf2]: https://github.com/simonepri/upash-pbkdf2\n\n[github:simonepri]: https://github.com/simonepri\n[twitter:simoneprimarosa]: http://twitter.com/intent/user?screen_name=simoneprimarosa\n\n[argon2:password-competition]: https://password-hashing.net/\n[upash:pronounce]: https://translate.google.com/translate_tts?ie=UTF-8\u0026client=tw-ob\u0026tl=en\u0026q=u-pash\n\n[docs:migration-guide]: https://github.com/simonepri/upash/tree/master/docs/migrate-your-solution.md\n[docs:upgrade-algorithm]: https://github.com/simonepri/upash/tree/master/docs/upgrade-algorithm.md\n[docs:password-hashing-theory]: https://github.com/simonepri/upash/tree/master/docs/password-hashing-theory.md\n[docs:ext:upgrade-algorithm]: https://veggiespam.com/painless-password-hash-upgrades/\n\n[breach:yahoo]: https://help.yahoo.com/kb/account/SLN27925.html\n[breach:yahoo2]: https://help.yahoo.com/kb/account/sln28092.html\n[breach:linkedin]: https://motherboard.vice.com/en_us/article/78kk4z/another-day-another-hack-117-million-linkedin-emails-and-password\n[breach:adobe]: https://www.troyhunt.com/adobe-credentials-and-serious/\n[breach:ashley-madison]: https://krebsonsecurity.com/2015/07/online-cheating-site-ashleymadison-hacked/\n[breach:hibp-breaches]: https://haveibeenpwned.com/PwnedWebsites\n","funding_links":[],"categories":["Packages","JavaScript","\u003ca id=\"9eee96404f868f372a6cbc6769ccb7f8\"\u003e\u003c/a\u003e新添加的","包","目录","Cryptography","Security","cli"],"sub_categories":["Security","\u003ca id=\"31185b925d5152c7469b963809ceb22d\"\u003e\u003c/a\u003e新添加的","安全","安全相关","Dependencies","Unsorted"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimonepri%2Fupash","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimonepri%2Fupash","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimonepri%2Fupash/lists"}