UsefulKey

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 a secret is configured; also overridable via customHashKey)
    • 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 with customHashKey: (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 and KEY helpers, or fully via customGenerateKey.
  • Recommendations:
    • Public APIs: URL-safe random strings, length 32–56 chars (entropy-first). Example: KEY.URLSafe(40).
    • Internal service keys: KEY.Hex(32) or KEY.URLSafe(32+).
    • Avoid UUID v4 alone for public keys; it has less entropy per character than recommended random strings.

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