{"id":20790377,"url":"https://github.com/paragonie/password_lock","last_synced_at":"2025-05-15T12:03:33.707Z","repository":{"id":30799757,"uuid":"34356830","full_name":"paragonie/password_lock","owner":"paragonie","description":"Wraps Bcrypt-SHA2 in Authenticated Encryption","archived":false,"fork":false,"pushed_at":"2025-01-03T21:05:56.000Z","size":55,"stargazers_count":195,"open_issues_count":2,"forks_count":35,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-05-15T04:47:53.115Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://paragonie.com/projects","language":"PHP","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/paragonie.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","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":"2015-04-21T23:06:06.000Z","updated_at":"2025-01-12T17:52:41.000Z","dependencies_parsed_at":"2024-06-18T18:37:23.111Z","dependency_job_id":"8d3f02ba-1563-4cb9-9073-f77d23803c1f","html_url":"https://github.com/paragonie/password_lock","commit_stats":{"total_commits":65,"total_committers":7,"mean_commits":9.285714285714286,"dds":0.2615384615384615,"last_synced_commit":"86bed0c25eed864dd4d44fec19ec2abfce5c6658"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paragonie%2Fpassword_lock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paragonie%2Fpassword_lock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paragonie%2Fpassword_lock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paragonie%2Fpassword_lock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/paragonie","download_url":"https://codeload.github.com/paragonie/password_lock/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254276352,"owners_count":22043860,"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-17T15:34:25.500Z","updated_at":"2025-05-15T12:03:33.668Z","avatar_url":"https://github.com/paragonie.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Password Lock\n\n[![Build Status](https://github.com/paragonie/password_lock/actions/workflows/ci.yml/badge.svg)](https://github.com/paragonie/password_lock/actions)\n[![Static Analysis](https://github.com/paragonie/password_lock/actions/workflows/psalm.yml/badge.svg)](https://github.com/paragonie/password_lock/actions)\n[![Latest Stable Version](https://poser.pugx.org/paragonie/password_lock/v/stable)](https://packagist.org/packages/paragonie/password_lock)\n[![Latest Unstable Version](https://poser.pugx.org/paragonie/password_lock/v/unstable)](https://packagist.org/packages/paragonie/password_lock)\n[![License](https://poser.pugx.org/paragonie/password_lock/license)](https://packagist.org/packages/paragonie/password_lock)\n[![Downloads](https://img.shields.io/packagist/dt/paragonie/password_lock.svg)](https://packagist.org/packages/paragonie/password_lock)\n\n**MIT Licensed** - feel free to use to enhance the security of any of your PHP projects\n\nWraps Bcrypt-SHA384 in Authenticated Encryption. Published by [Paragon Initiative Enterprises](https://paragonie.com). Check out our other [open source projects](https://paragonie.com/projects) too.\n\nDepends on [defuse/php-encryption](https://github.com/defuse/php-encryption) for authenticated symmetric-key encryption.\n\n## How is this different than \"peppering\"?\n\nPeppering strategies are usually accomplished through a keyed hash function (e.g. HMAC-SHA256) and applies to the password before it's passed to the salted hash API (i.e. bcrypt). If your pepper/HMAC key is ever compromised, you have to reset every user's password and it becomes a headache.\n\nA hash then encrypt strategy offers **agility**; if your secret key is compromised (but, miraculously, the hashes are not), you can decrypt all of your users' hashes then re-encrypt them with a new key and they'll never suffer the inconvenience of an unscheduled password reset.\n\n## How much more secure is this than just using bcrypt?\n\n* You don't have to worry about the 72 character limit for bcrypt\n* You don't have to worry about accidentally creating a null-byte truncation vulnerability\n* If your database gets hacked, and your database is on a separate machine from your webserver, the attacker has to first decrypt the hashes before attempting to crack any of them.\n\nHere's a [proof-of-concept](http://3v4l.org/61VZq) for the first two points.\n\nBut realistically, this library is only about as a secure as bcrypt.\n\n## Usage Examples\n\n### Hash Password, Encrypt Hash, Authenticate Ciphertext\n\n```php\nuse \\ParagonIE\\PasswordLock\\PasswordLock;\nuse \\Defuse\\Crypto\\Key;\n\n$key = Key::createNewRandomKey();\nif (isset($_POST['password'])) {\n    if (!is_string($_POST['password'])) {\n        die(\"Password must be a string\");\n    }\n    $storeMe = PasswordLock::hashAndEncrypt($_POST['password'], $key);\n}\n```\n \n### Verify MAC, Decrypt Ciphertext, Verify Password\n\n```php\nif (isset($_POST['password'])) {\n    if (!is_string($_POST['password'])) {\n        die(\"Password must be a string\");\n    }\n    if (PasswordLock::decryptAndVerify($_POST['password'], $storeMe, $key)) {\n        // Success!\n    }\n}\n```\n\n### Determine if a re-hash is necessary\n\n```php\nuse ParagonIE\\PasswordLock\\PasswordLock;\n/**\n * @var string $encryptedPwhash\n * @var Defuse\\Crypto\\Key $key\n */\n\nif (PasswordLock::needsRehash($encryptedPwhash, $key)) {\n    // Recalculate PasswordLock::hashAndEncrypt()\n}\n```\n\n### Re-encrypt a hash with a different encryption key\n\n```php\n$newKey = \\Defuse\\Crypto\\Key::createNewRandomKey();\n$newHash = PasswordLock::rotateKey($storeMe, $key, $newKey);\n```\n\n### Migrate from Version 1 of the library\n\n```php\n$newHash = PasswordLock::upgradeFromVersion1(\n    $_POST['password'],\n    $oldHash,\n    $oldKey,\n    $newKey\n);\n```\n\n## Support Contracts\n\nIf your company uses this library in their products or services, you may be\ninterested in [purchasing a support contract from Paragon Initiative Enterprises](https://paragonie.com/enterprise).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparagonie%2Fpassword_lock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fparagonie%2Fpassword_lock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparagonie%2Fpassword_lock/lists"}