PHPackages                             paragonie/password\_lock - 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. [Security](/categories/security)
4. /
5. paragonie/password\_lock

ActiveLibrary[Security](/categories/security)

paragonie/password\_lock
========================

Wraps Bcrypt-SHA2 in Authenticated Encryption

v3.2.0(2y ago)19348.7k↓31.1%32[1 issues](https://github.com/paragonie/password_lock/issues)[1 PRs](https://github.com/paragonie/password_lock/pulls)1MITPHPPHP ^7.3|^8CI failing

Since Jun 8Pushed 1y ago11 watchersCompare

[ Source](https://github.com/paragonie/password_lock)[ Packagist](https://packagist.org/packages/paragonie/password_lock)[ RSS](/packages/paragonie-password-lock/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (4)Versions (10)Used By (1)

Password Lock
=============

[](#password-lock)

[![Build Status](https://github.com/paragonie/password_lock/actions/workflows/ci.yml/badge.svg)](https://github.com/paragonie/password_lock/actions)[![Static Analysis](https://github.com/paragonie/password_lock/actions/workflows/psalm.yml/badge.svg)](https://github.com/paragonie/password_lock/actions)[![Latest Stable Version](https://camo.githubusercontent.com/ee6f668e970c89c49fdcb41f34bb4a5591eb05c308534ceada15e9a5dd08f7fa/68747470733a2f2f706f7365722e707567782e6f72672f70617261676f6e69652f70617373776f72645f6c6f636b2f762f737461626c65)](https://packagist.org/packages/paragonie/password_lock)[![Latest Unstable Version](https://camo.githubusercontent.com/05558d947ff79df3a2f6497e86b334c320236396ee868756055bd24dec544a3c/68747470733a2f2f706f7365722e707567782e6f72672f70617261676f6e69652f70617373776f72645f6c6f636b2f762f756e737461626c65)](https://packagist.org/packages/paragonie/password_lock)[![License](https://camo.githubusercontent.com/56102bd03b9290526fedf904bc58768260e8915cdf624a43dd63a5fe75557c1f/68747470733a2f2f706f7365722e707567782e6f72672f70617261676f6e69652f70617373776f72645f6c6f636b2f6c6963656e7365)](https://packagist.org/packages/paragonie/password_lock)[![Downloads](https://camo.githubusercontent.com/d27dc26b32f47dbb271140b6d8c3f7b13e53bfaa970cdf60748585b68ad26877/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f70617261676f6e69652f70617373776f72645f6c6f636b2e737667)](https://packagist.org/packages/paragonie/password_lock)

**MIT Licensed** - feel free to use to enhance the security of any of your PHP projects

Wraps 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.

Depends on [defuse/php-encryption](https://github.com/defuse/php-encryption) for authenticated symmetric-key encryption.

How is this different than "peppering"?
---------------------------------------

[](#how-is-this-different-than-peppering)

Peppering 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.

A 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.

How much more secure is this than just using bcrypt?
----------------------------------------------------

[](#how-much-more-secure-is-this-than-just-using-bcrypt)

- You don't have to worry about the 72 character limit for bcrypt
- You don't have to worry about accidentally creating a null-byte truncation vulnerability
- 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.

Here's a [proof-of-concept](http://3v4l.org/61VZq) for the first two points.

But realistically, this library is only about as a secure as bcrypt.

Usage Examples
--------------

[](#usage-examples)

### Hash Password, Encrypt Hash, Authenticate Ciphertext

[](#hash-password-encrypt-hash-authenticate-ciphertext)

```
use \ParagonIE\PasswordLock\PasswordLock;
use \Defuse\Crypto\Key;

$key = Key::createNewRandomKey();
if (isset($_POST['password'])) {
    if (!is_string($_POST['password'])) {
        die("Password must be a string");
    }
    $storeMe = PasswordLock::hashAndEncrypt($_POST['password'], $key);
}
```

### Verify MAC, Decrypt Ciphertext, Verify Password

[](#verify-mac-decrypt-ciphertext-verify-password)

```
if (isset($_POST['password'])) {
    if (!is_string($_POST['password'])) {
        die("Password must be a string");
    }
    if (PasswordLock::decryptAndVerify($_POST['password'], $storeMe, $key)) {
        // Success!
    }
}
```

### Determine if a re-hash is necessary

[](#determine-if-a-re-hash-is-necessary)

```
use ParagonIE\PasswordLock\PasswordLock;
/**
 * @var string $encryptedPwhash
 * @var Defuse\Crypto\Key $key
 */

if (PasswordLock::needsRehash($encryptedPwhash, $key)) {
    // Recalculate PasswordLock::hashAndEncrypt()
}
```

### Re-encrypt a hash with a different encryption key

[](#re-encrypt-a-hash-with-a-different-encryption-key)

```
$newKey = \Defuse\Crypto\Key::createNewRandomKey();
$newHash = PasswordLock::rotateKey($storeMe, $key, $newKey);
```

### Migrate from Version 1 of the library

[](#migrate-from-version-1-of-the-library)

```
$newHash = PasswordLock::upgradeFromVersion1(
    $_POST['password'],
    $oldHash,
    $oldKey,
    $newKey
);
```

Support Contracts
-----------------

[](#support-contracts)

If your company uses this library in their products or services, you may be interested in [purchasing a support contract from Paragon Initiative Enterprises](https://paragonie.com/enterprise).

###  Health Score

45

—

FairBetter than 93% of packages

Maintenance31

Infrequent updates — may be unmaintained

Popularity48

Moderate usage in the ecosystem

Community25

Small or concentrated contributor base

Maturity64

Established project with proven stability

 Bus Factor1

Top contributor holds 66.2% 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.

###  Release Activity

Cadence

Every ~407 days

Recently: every ~727 days

Total

9

Last Release

740d ago

Major Versions

1.1.0 → v2.0.02016-04-23

v2.0.0 → v3.0.02016-05-18

v2.0.1 → v3.0.12016-05-20

PHP version history (3 changes)v3.0.0PHP &gt;= 7.0

v3.0.3PHP ^7|^8

v3.1.0PHP ^7.3|^8

### Community

Maintainers

![](https://www.gravatar.com/avatar/05d241256cda885139a5697d3bb536b5cec3b430c1adb9c524bf92a37a55758d?d=identicon)[paragonie-scott](/maintainers/paragonie-scott)

---

Top Contributors

[![paragonie-scott](https://avatars.githubusercontent.com/u/11591518?v=4)](https://github.com/paragonie-scott "paragonie-scott (51 commits)")[![paragonie-security](https://avatars.githubusercontent.com/u/15914520?v=4)](https://github.com/paragonie-security "paragonie-security (21 commits)")[![mrw](https://avatars.githubusercontent.com/u/50996?v=4)](https://github.com/mrw "mrw (1 commits)")[![johnbillion](https://avatars.githubusercontent.com/u/208434?v=4)](https://github.com/johnbillion "johnbillion (1 commits)")[![prisis](https://avatars.githubusercontent.com/u/2716058?v=4)](https://github.com/prisis "prisis (1 commits)")[![staabm](https://avatars.githubusercontent.com/u/120441?v=4)](https://github.com/staabm "staabm (1 commits)")[![user-error-pixel](https://avatars.githubusercontent.com/u/47761650?v=4)](https://github.com/user-error-pixel "user-error-pixel (1 commits)")

---

Tags

encryptionpasswordhashinghash

###  Code Quality

TestsPHPUnit

Static AnalysisPsalm

Type Coverage Yes

### Embed Badge

![Health badge](/badges/paragonie-password-lock/health.svg)

```
[![Health](https://phpackages.com/badges/paragonie-password-lock/health.svg)](https://phpackages.com/packages/paragonie-password-lock)
```

###  Alternatives

[phpseclib/phpseclib

PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.

5.6k434.8M1.3k](/packages/phpseclib-phpseclib)[ircmaxell/password-compat

A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password\_hash

2.1k56.8M122](/packages/ircmaxell-password-compat)[symfony/password-hasher

Provides password hashing utilities

814137.2M91](/packages/symfony-password-hasher)[paragonie/halite

High-level cryptography interface powered by libsodium

1.2k9.4M63](/packages/paragonie-halite)[passwordlib/passwordlib

A Password Hashing Library

377220.6k6](/packages/passwordlib-passwordlib)[paragonie/ciphersweet

Searchable field-level encryption library for relational databases

4641.2M21](/packages/paragonie-ciphersweet)

PHPackages © 2026

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