Security
How UsefulKey handles keys, hashing, metadata, and recommended hardening steps.
Goals and threat model
- UsefulKey is designed so plaintext keys are never stored server-side. Only a one-way hash is persisted in your keystore adapter.
- Verification proves possession of a plaintext key by hashing the presented value and matching it against the stored hash.
- The model assumes attackers may read your database; therefore, plaintext must not be derivable from stored data.
- We recommend setting a secret when you create the UsefulKey instance. This will use HMAC-SHA256 for hashing/verification. This improves resistance to offline guessing if your DB leaks.
Key handling
- Keys are returned exactly once from
uk.createKey(...)
to your application. You must deliver and store them securely on the client side. For example in a cookie or secure storage. - Server-side storage contains only:
keyHash
(default SHA-256; can use HMAC-SHA256 when asecret
is configured; also overridable viacustomHashKey
)- metadata, timestamps, usage counters, and revocation/expiry fields
Hashing
- Default: SHA-256 via a portable provider. You can enable keyed hashing by setting
secret
, which uses HMAC-SHA256. Or override withcustomHashKey: (key) => string
when you have platform-specific crypto. - Requirements for custom hashing:
- Deterministic and collision-resistant
- Output encoding must be stable (hex recommended)
- Never store plaintext or reversible transforms of the key.
Key formats and length
- Key format is controlled by
defaultKeyKind
andKEY
helpers, or fully viacustomGenerateKey
. - Recommendations:
- Public APIs: URL-safe random strings, length 32–56 chars (entropy-first). Example:
KEY.URLSafe(40)
. - Internal service keys:
KEY.Hex(32)
orKEY.URLSafe(32+)
. - Avoid UUID v4 alone for public keys; it has less entropy per character than recommended random strings.
- Public APIs: URL-safe random strings, length 32–56 chars (entropy-first). Example:
Metadata safety
- Metadata is application-defined. Treat it as non-sensitive unless you encrypt or avoid storing secrets entirely.
- Use metadata for: plan, scopes, tenant, feature flags, etc.
Generating secret key for UsefulKey
You are responsible for generating, storing and managing a secret key. This is used to hash keys and is required for the HMAC-SHA256 hashing algorithm. See the Configuration section for more information on how to set the secret key.
You can use something like openSSL to generate a secret key:
openssl rand -hex 32