Search by

jacyimp / memorable-otp

Human-friendly numeric verification code generator

Maintainers

Package info

github.com/jacyimp/memorable-otp

pkg:composer/jacyimp/memorable-otp

Transparency log

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.0 2026-09-02 07:02 UTC

This package is auto-updated.

Last update: 2026-09-02 07:06:26 UTC


README

Coverage: 100% MSI: 100% PHPStan: max

Human-friendly numeric verification codes for PHP, while keeping as many possible codes as practical.

Install

composer require jacyimp/memorable-otp

Usage

use JacyImp\MemorableOtp\MemorableOtp;

$code = MemorableOtp::readable(6); // e.g. 159915

Supported lengths: 4–10.

MemorableOtp::readable(4); // e.g. 0112
MemorableOtp::readable(6); // e.g. 159915
MemorableOtp::readable(8); // e.g. 49649440

Readability levels

MemorableOtp::readable(6);  // e.g. 159915
MemorableOtp::easy(6);      // e.g. 100212
MemorableOtp::veryEasy(6);  // e.g. 012013
MemorableOtp::superEasy(6); // e.g. 010203
MemorableOtp::uberEasy(6);  // e.g. 121212
Preset Possible codes kept Entropy loss*
readable() up to 50% ≥ 1.0 bit
easy() up to 30% ≥ 1.7 bits
veryEasy() up to 20% ≥ 2.3 bits
superEasy() up to 15% ≥ 2.7 bits
uberEasy() up to 10% ≥ 3.3 bits
  • Actual values vary slightly by code length.

What it recognizes

121212   repeated chunk
112233   grouped sequence
123456   sequence
654321   descending sequence
123321   mirror
010203   chunk sequence
81818    periodic pattern
10020    round-number structure

Long identical runs are penalized to reduce transcription mistakes:

111111

Explicit preset

use JacyImp\MemorableOtp\MemorableOtp;
use JacyImp\MemorableOtp\ReadabilityPreset;

$code = MemorableOtp::generate(
    length: 7,
    preset: ReadabilityPreset::VeryEasy,
); // e.g. 4015642

Equivalent to:

$code = MemorableOtp::veryEasy(7); // e.g. 4015642

Security

Candidates are generated with cryptographically secure randomness and filtered using rejection sampling.

The first candidate that meets the selected readability threshold is returned. Accepted codes are not ranked against each other.

use JacyImp\MemorableOtp\MemorableOtp;
use JacyImp\MemorableOtp\ReadabilityPreset;

$security = MemorableOtp::security(
    length: 7,
    preset: ReadabilityPreset::UberEasy,
);

$security->rawSearchSpace();
$security->acceptedSearchSpace();
$security->entropyBits();
$security->entropyLossBits();
$security->exact;

Normal OTP protections still apply: expiration, attempt limits, rate limiting, one-time use, secure storage, and secure delivery.

Requirements

PHP 8.2+

License

MIT