Cryptographically secure API-key generation for Gleam.
Apiculture v0.3.0 gives the common case a complete modern format while keeping every important part configurable. Generate one random API key with the defaults, change those defaults when an integration needs it, import UUIDs and ULIDs without losing control of the final format, and inspect or parse the result as structured data instead of treating it as an opaque string.
- Start here
- The v0.3.0 default
- The business of API keys
- Why prefixes matter
- Why checksums matter
- Generate a default key
- Modify the defaults
- Use random bytes or direct alphabet sampling
- Work with UUIDs and ULIDs
- Parse and validate serialized keys
- Inspect a
Key - Choose an encoding
- Checksums and verification
- Builder and terminal operations
- Errors and validation
- Operational guidance
- Installation
- v0.3.0 API reference
- License
If you only need a new API key, use the string convenience function:
import apiculture as ab
pub fn create_api_key() -> Result(String, ab.Error) {
ab.key_new_as_string()
}If you need to inspect the sections, verify the checksum, or keep the raw
content bytes, generate a Key instead:
import apiculture as ab
pub fn create_inspectable_key() -> Result(ab.Key, ab.Error) {
ab.key_new()
}For a custom format, begin with a KeyConfig and finish with
key_generate:
import apiculture as ab
pub fn create_partner_key() -> Result(ab.Key, ab.Error) {
ab.key_new_as_config()
|> ab.key_with_prefix("partner")
|> ab.key_with_random_bytes(24)
|> ab.key_with_encoding(ab.base58())
|> ab.key_generate
}There are three different values to keep in mind:
KeyConfigis an unfinished generation plan.Keyis a finalized key with retained structural metadata.Stringis the serialized value sent to a client or stored as a token.
key_new_as_config() creates the first. key_generate creates the second.
key_to_string or key_new_as_string() gives you the third.
The default API is intentionally opinionated. Calling key_new() or
key_new_as_string() does not make you assemble entropy, encoding, prefix,
separator, and checksum choices manually.
The default configuration is:
| Section | Default |
|---|---|
| Prefix | sk |
| Separator | _ |
| Content source | 16 cryptographically secure random bytes |
| Content encoding | Base62 |
| Checksum name | crc32 |
| Checksum | Four CRC32 bytes |
The serialized shape is:
sk_<content>_crc32_<checksum>
For example:
sk_3q2Z7x9P2R8LmNkJd4Hf6Y_crc32_2AB9XQ
The example is illustrative; generated values are random and will be different every time. The content is the secret material. The prefix, separator, checksum name, and checksum make the value identifiable and parseable, but they do not replace secret storage or access control.
let assert Ok(value) = ab.key_new_as_string()Use this when the caller only needs the finished token:
pub fn issue_key() -> Result(String, ab.Error) {
ab.key_new_as_string()
}let assert Ok(key) = ab.key_new()
let serialized = ab.key_to_string(key)
let content_bytes = ab.key_content_bytes(key)
let is_valid = ab.key_verify_checksum(key)key_new() returns a finalized Key; it is not a builder. Use
key_new_as_config() when you want to customize generation.
The default parser expects all of the following:
- exactly four
_-separated sections - the
skprefix - Base62 content
- exactly 16 content bytes
- the lowercase checksum name
crc32 - a four-byte Base62-encoded checksum
- a CRC32 that matches the content bytes
This strictness is intentional. A default key is not merely a random string with some decoration around it. It is a small, self-describing wire format.
An API key is a credential issued by one system so another system can call it without a human password, browser session, or interactive login. In practice, that makes an API key a compact bearer credential: whoever possesses a valid key may be able to act as its owner until the key is revoked, rotated, or otherwise restricted.
Generating the random value is only one part of the business problem. A useful API-key system also needs to answer operational questions:
- What product, service, or environment issued this credential?
- Can a scanner recognize it in a repository or CI log?
- Can a copied value be checked for accidental truncation or corruption?
- Can support and security teams classify it quickly during an incident?
- Can the server validate the format before looking up the credential?
- Can the organization revoke, rotate, scope, and audit it?
A naked random Base62 value addresses only the entropy question. It can be excellent secret material and still be poor operational data. It looks like a session identifier, a database value, a tracking ID, or ordinary application text. That ambiguity makes secret discovery and incident response harder.
Apiculture treats the serialized key as both:
- A secret, because the content must be unpredictable and protected.
- An operational signal, because its shape should help software and people identify, classify, validate, and handle it correctly.
This is why v0.3.0 makes a prefix and checksum part of the default design. They are not claims that a decorated string is magically safer. They are practical metadata and integrity mechanisms around high-entropy content.
Apiculture generates and formats key material. It does not provide:
- a database for issued credentials
- authentication middleware
- authorization or scopes
- revocation or rotation storage
- rate limiting
- audit logging
- encryption at rest
- protection after a key has been exposed
Your application still needs a lifecycle around the value. Usually that means storing a hash or keyed digest for lookup, showing the secret only at creation time, assigning scopes, recording creation and last-use metadata, and offering revocation and rotation.
A prefix is a short, recognizable label at the start of the serialized key.
The default is sk; an application can choose a more specific label such as
pk, service, partner, or test when its surrounding format requires it.
Secret scanners and repository tools often start with a candidate pattern. A stable prefix gives them a strong signal that a string is intended to be a credential rather than a random identifier. The structured default can be matched with a pattern such as:
sk_[A-Za-z0-9]+_crc32_[A-Za-z0-9]+
The prefix is not secret, so it is safe and useful for scanners to know. The actual content remains unpredictable.
Organizations commonly have several key families:
sk_... application secret key
pk_... public or publishable key
test_... non-production credential
partner_... integration credential
The label can tell an operator which product or environment should be investigated before they decode or query anything. It can also help a server route validation to the right credential store.
A key that visibly belongs to a specific system is less likely to be pasted into the wrong dashboard, environment, or configuration field. This is a human-factors benefit, not a cryptographic one.
Keep prefixes:
- short enough to scan and type
- stable across the lifetime of a format
- meaningful to operators and tooling
- free of the configured separator
- non-sensitive; never put a tenant secret or authorization data in it
If a legacy integration requires an unprefixed value, use
key_disable_prefix explicitly rather than weakening the default for every
caller.
A checksum is a compact integrity signal computed from the content bytes. In the default format, CRC32 is rendered as four bytes and then encoded with the same Base62 encoding as the content.
API keys are copied through systems that can truncate or alter text:
- a user copies only part of a value from a terminal
- a line-wrapping or export step drops characters
- a support ticket changes a character
- a configuration template inserts or removes text
- a value is pasted into the wrong field
Recomputing CRC32 lets the receiver reject a damaged value before treating it as a real credential lookup. This is especially useful for diagnostics, imports, and secret-scanning workflows.
The default includes the literal checksum name crc32:
sk_<content>_crc32_<checksum>
That name tells a parser which algorithm the trailing section represents. It also leaves room for future named algorithms without requiring a parser to guess from the checksum length.
CRC32 is not intended to:
- make a weak secret strong
- hide the content
- resist a deliberate attacker
- replace password hashing
- replace authenticated encryption
CRC32 is fast and useful for accidental corruption detection. The security of the credential comes from the unpredictable random content and from the application's storage, authorization, and revocation controls.
An attacker who can modify a key can generally recompute a non-cryptographic checksum. A valid checksum says that the serialized checksum matches the content under the selected algorithm. It does not prove who issued the key or whether the key is currently authorized.
import apiculture as ab
pub fn issue_default_key() -> Result(String, ab.Error) {
ab.key_new_as_string()
}import apiculture as ab
pub fn inspect_default_key() -> Result(
#(String, Int, Bool),
ab.Error,
) {
let assert Ok(key) = ab.key_new()
Ok(#(
ab.key_to_string(key),
ab.key_content_byte_count(key),
ab.key_verify_checksum(key),
))
}Each call obtains fresh cryptographically secure random bytes. Do not generate one key and reuse it for unrelated users or integrations merely because the content is long enough.
import apiculture as ab
import gleam/list
pub fn issue_many(count: Int) -> Result(List(String), ab.Error) {
list.try_map(list.range(1, count), fn(_) {
ab.key_new_as_string()
})
}The uniqueness of a generated key is probabilistic, as with all random identifiers. The default carries 128 bits of random content, which is intended to make accidental collisions and guessing infeasible for ordinary API-key issuance volumes.
The v0.3.0 builder starts from an opinionated, ready-to-generate configuration:
let config = ab.key_new_as_config()
ab.key_config_is_ready(config)
// TrueBuilder functions return another KeyConfig, so they work naturally in a
pipeline. The final call is either key_generate for random content or one of
the terminal import functions for existing identifier content.
let assert Ok(key) =
ab.key_new_as_config()
|> ab.key_with_prefix("service")
|> ab.key_generateThe result keeps the default Base62 content, _ separator, and CRC32 sections
while replacing only the prefix.
let assert Ok(key) =
ab.key_new_as_config()
|> ab.key_with_random_bytes(32)
|> ab.key_generatekey_with_random_bytes(32) means 32 random bytes, or 256 bits, before
encoding. It does not mean 32 serialized characters.
let assert Ok(key) =
ab.key_new_as_config()
|> ab.key_with_encoding(ab.base58())
|> ab.key_generateWhen the configuration generates random bytes, the selected encoding renders those bytes as the content section. The checksum is rendered with that same encoding.
let assert Ok(key) =
ab.key_new_as_config()
|> ab.key_with_separator(".")
|> ab.key_generateThe separator is structural. It is used at every configured boundary:
sk.<content>.crc32.<checksum>
This is mainly for interoperability. _ is the recommended default because
it is easy to recognize, scan, split, and transport.
let assert Ok(key) =
ab.key_new_as_config()
|> ab.key_with_checksum_bytes(2)
|> ab.key_generateThe checksum algorithm still computes CRC32, but only the requested number of leading checksum bytes is serialized and retained. Use the default four bytes unless an external format requires a shorter section.
let assert Ok(key) =
ab.key_new_as_config()
|> ab.key_with_prefix("partner")
|> ab.key_with_separator("_")
|> ab.key_with_random_bytes(24)
|> ab.key_with_encoding(ab.base58())
|> ab.key_with_checksum(ab.crc32())
|> ab.key_with_checksum_bytes(4)
|> ab.key_generateThis is still a structured key. It is simply a structured key with an application-specific contract that your scanners, parsers, and consumers must share.
The default is deliberately stronger operationally than a bare random string. Use the explicit opt-outs only when an existing wire format requires them:
let assert Ok(no_prefix) =
ab.key_new_as_config()
|> ab.key_disable_prefix
|> ab.key_generate
let assert Ok(no_checksum_name) =
ab.key_new_as_config()
|> ab.key_disable_checksum_name
|> ab.key_generate
let assert Ok(no_checksum) =
ab.key_new_as_config()
|> ab.key_disable_checksum
|> ab.key_generatekey_disable_checksum_name keeps CRC32 but removes the serialized algorithm
name. key_disable_checksum removes both the checksum and its name. The
latter is the largest reduction in validation and should be intentional.
let assert Ok(key) =
ab.key_new_as_config()
|> ab.key_disable_prefix
|> ab.key_generateIts shape is:
<content>_crc32_<checksum>
let assert Ok(key) =
ab.key_new_as_config()
|> ab.key_disable_prefix
|> ab.key_disable_checksum_name
|> ab.key_generateIts shape is:
<content>_<checksum>
That shape is supported, but it is not the v0.3.0 recommendation because it loses the strongest classification and self-description signals.
Apiculture supports two different random-generation operations. They are both secure when used correctly, but they answer different design questions.
This is the default and the usual choice for credentials. Secure random bytes are generated first, then encoded for transport:
let assert Ok(key) =
ab.key_new_as_config()
|> ab.key_with_random_bytes(16)
|> ab.key_with_encoding(ab.base62())
|> ab.key_generateThe security quantity is the byte count. The encoded character count depends on the encoding and is not the same thing as the entropy count.
Use direct sampling when the output must contain a specific number of characters from a specific alphabet:
import apiculture as ab
import apiculture/alphabets
let assert Ok(key) =
ab.key_new_as_config()
|> ab.key_with_random_chars(24)
|> ab.key_with_alphabet(alphabets.base58())
|> ab.key_generateApiculture uses rejection sampling rather than a simple byte modulo. That avoids over-representing some characters when the alphabet size does not divide the byte range evenly.
Prefer random bytes plus encoding when:
- the credential's entropy is the primary requirement
- you want a stable byte count
- the content may later be decoded back to bytes
- you are using the opinionated default
Prefer direct alphabet sampling when:
- the serialized content must have an exact character count
- the alphabet has human-factors requirements
- you do not need the content to represent arbitrary random bytes under an encoding
UUIDs and ULIDs are already identifiers. They are not automatically secrets, and they are not automatically API keys. A UUID or ULID may be predictable, enumerable, or exposed in logs. Use these import APIs when you need to put an existing 128-bit identifier into a consistent API-key-shaped format, not as a replacement for generating high-entropy credentials.
import apiculture as ab
let assert Ok(key) =
ab.key_from_uuid("019f3663-9b00-7a38-9427-16621a576830")
let value = ab.key_to_string(key)
// sk_<Base62 UUID bytes>_crc32_<checksum>key_from_uuid is terminal. It parses the UUID, converts it to its canonical
16 bytes, applies the default format, and returns a finalized Key.
let assert Ok(key) =
ab.key_from_ulid("01KWV69C49DSTWZBJ1SAC42E7V")The terminal helper accepts the canonical 26-character ULID representation and
returns a formatted Key using the same default sk, Base62, _, crc32
layout.
Use bytes_from_uuid or bytes_from_ulid when formatting needs to be a
separate, chainable step:
import apiculture as ab
pub fn format_existing_ulid() -> Result(String, ab.Error) {
let assert Ok(bytes) =
ab.bytes_from_ulid("01KWV69C49DSTWZBJ1SAC42E7V")
let assert Ok(key) =
ab.key_new_as_config()
|> ab.key_with_prefix("order")
|> ab.key_with_encoding(ab.base32_crockford())
|> ab.key_with_checksum(ab.crc32())
|> ab.key_with_checksum_bytes(4)
|> ab.key_from_bytes(bytes)
Ok(ab.key_to_string(key))
}This separation is useful when:
- the source type is selected dynamically
- the same bytes need several output formats
- you want to validate or store the canonical bytes before formatting
- the formatting pipeline is shared by UUID, ULID, and other binary sources
bytes_from_* returns raw bytes, not a partially built KeyConfig and not a
serialized key. key_from_bytes is the terminal step.
When the source type is known and you want one terminal operation, use the configured helper:
let config =
ab.key_new_as_config()
|> ab.key_with_prefix("customer")
|> ab.key_with_encoding(ab.base58())
|> ab.key_with_checksum(ab.crc32())
let assert Ok(key) =
ab.key_from_uuid_with_config(
config,
"019f3663-9b00-7a38-9427-16621a576830",
)The ULID equivalent is key_from_ulid_with_config(config, input).
Malformed UUID and ULID input returns Error(MalformedInput). UUID parsing
accepts the usual hyphenated form and UUID URN prefix. ULID parsing validates
the 26-character Crockford representation and rejects values whose leading
bits exceed the ULID range.
Parsing is the reverse of serialization, but it is intentionally strict. The parser does not guess an encoding or silently accept a malformed checksum.
import apiculture as ab
pub fn validate_candidate(candidate: String) -> Bool {
case ab.key_parse(candidate) {
Ok(key) -> ab.key_verify_checksum(key)
Error(_) -> False
}
}key_parse uses key_default_format() internally. A successful result has:
- canonical Base62 content
- 16 content bytes
- the expected
skprefix - the expected lowercase
crc32name - four checksum bytes
- a checksum that matches the content
The returned value is a normal Key, so it can be passed to all inspection
helpers and serialized again with key_to_string.
Start from the default format and change the parse-relevant properties:
let format =
ab.key_default_format()
|> ab.key_format_with_prefix("partner")
|> ab.key_format_with_encoding(ab.base58())
|> ab.key_format_with_content_bytes(24)
let result = ab.key_parse_with_format(candidate, format)KeyFormat describes the serialized shape only. It does not describe whether
the source was random bytes, a UUID, or a ULID; that information cannot be
recovered from the string.
let format =
ab.key_default_format()
|> ab.key_format_without_prefix
|> ab.key_format_without_checksum_name
let result = ab.key_parse_with_format(candidate, format)The parser still validates every section that the format declares. There is no unverified default parser: callers who want to inspect damaged candidates should handle the parse error rather than treating a partially valid value as an authenticated credential.
The parser distinguishes malformed structure from checksum failure:
MalformedInputmeans the sections, encoding, canonical form, or expected lengths are invalid.ChecksumMismatchmeans the checksum section is structurally valid but does not match the content bytes.
Both cases should normally reject the candidate. The distinction is useful for diagnostics and tests, not for granting access.
A generated or parsed Key retains its structural sections. Use the direct
accessors for ordinary application code.
let assert Ok(key) = ab.key_new()
let serialized = ab.key_to_string(key)
let prefix = ab.key_prefix_value(key)
let separator = ab.key_separator_value(key)
let has_prefix = ab.key_has_prefix(key)
let has_checksum = ab.key_has_checksum(key)
let content = ab.key_content_value(key)
let content_bytes = ab.key_content_bytes(key)
let content_byte_count = ab.key_content_byte_count(key)
let content_char_count = ab.key_content_char_count(key)
let checksum_name = ab.key_checksum_name(key)
let checksum_value = ab.key_checksum_value(key)
let checksum_bytes = ab.key_checksum_bytes(key)
let checksum_byte_count = ab.key_checksum_byte_count(key)
let checksum_char_count = ab.key_checksum_char_count(key)key_bytes remains available as an alias for the raw content bytes. Prefer
key_content_bytes in new code because it makes the distinction from checksum
bytes explicit.
When a tool needs the complete structure together, use key_sections:
let sections = ab.key_sections(key)The KeySections value contains:
- optional
prefix - optional
separator - encoded
content_value - raw
content_bytes - optional
checksum_name - optional encoded
checksum_value - optional raw
checksum_bytes
This is convenient for diagnostics, reporting, secret-scanning adapters, and format-aware tooling.
The default verifier uses CRC32:
let valid = ab.key_verify_checksum(key)Use the explicit algorithm form when validating a key built with an explicitly selected checksum algorithm:
let valid = ab.key_verify_checksum_with_algo(key, ab.crc32())A key without a checksum returns False from either verifier. Verification is
local and does not prove that a server has issued or authorized the key.
Encodings transform bytes into transport-safe strings. They affect the visible length and character set, but the entropy comes from the underlying bytes.
| Function | Character set or purpose |
|---|---|
hex_lower() |
Lowercase hexadecimal |
hex_upper() |
Uppercase hexadecimal |
base32_rfc() |
RFC 4648 Base32 with padding |
base32_rfc_unpadded() |
RFC 4648 Base32 without padding |
base32_hex() |
Base32hex |
base32_crockford() |
Human-oriented Crockford Base32 |
base32_z() |
z-base-32 |
base36() |
Base36 |
base58() |
Bitcoin-style Base58 |
base62() |
Uppercase/lowercase letters and digits |
base64() |
Standard Base64 |
base64_url() |
URL-safe Base64 |
let assert Ok(hex_key) =
ab.key_new_as_config()
|> ab.key_with_encoding(ab.hex_lower())
|> ab.key_generateIf a format needs a fixed character count instead of a fixed byte count, use
direct alphabet sampling with key_with_random_chars and
key_with_alphabet.
The parser checks that decoding and re-encoding produces the exact supplied
section. This rejects alternate spellings and makes serialized values
canonical. When you change an encoding, provide the matching KeyFormat to
key_parse_with_format.
CRC32 is the checksum currently provided by apiculture:
let algorithm = ab.crc32()You can use the low-level checksum helpers when integrating with another format:
let expected =
ab.checksum_format(
ab.crc32(),
content_bytes,
fn(bytes) { ab.encoding_encode(ab.hex_lower(), bytes) },
)When the surrounding protocol already has the raw expected checksum bytes,
checksum_verify(ab.crc32(), content_bytes, expected_bytes) verifies them.
The key builder is usually preferable because it retains the rendered and raw
checksum sections together.
The API separates configuration from finalization so a pipeline does not accidentally confuse a source identifier with a finished credential.
These return KeyConfig and can be chained:
key_new_as_configkey_with_random_byteskey_with_random_charskey_with_alphabetkey_with_encodingkey_with_prefixkey_with_separatorkey_with_checksumkey_with_checksum_byteskey_disable_prefixkey_disable_checksum_namekey_disable_checksum
These return Result(Key, Error):
key_generate(config)generates new random content according to the plan.key_from_bytes(config, bytes)formats existing bytes.key_from_uuid(input)parses and formats a UUID with defaults.key_from_uuid_with_config(config, input)uses a custom UUID format.key_from_ulid(input)parses and formats a ULID with defaults.key_from_ulid_with_config(config, input)uses a custom ULID format.
Use key_config_is_ready when building a configuration incrementally:
let config =
ab.key_new_as_config()
|> ab.key_with_random_chars(24)
|> ab.key_with_alphabet(ab.base58())
case ab.key_config_is_ready(config) {
True -> ab.key_generate(config)
False -> Error(ab.invalid_byte_count_error())
}Most pipelines can simply call key_generate; the readiness function is most
useful when configuration comes from application data or several optional
branches.
Public operations return Result rather than silently producing a malformed
value. The error type includes:
| Error | Meaning |
|---|---|
EmptyAlphabet |
The custom alphabet has no characters. |
SingleCharacterAlphabet |
A one-character alphabet cannot provide useful randomness. |
DuplicateCharacters |
The alphabet contains duplicate symbols. |
SecureRandomUnavailable |
Secure randomness is unavailable on the target. |
InvalidByteCount |
A byte or character count is zero, negative, or incomplete. |
InvalidEncoding |
An encoding configuration is invalid. |
MalformedInput |
UUID, ULID, serialized key, or encoded input is malformed. |
ChecksumMismatch |
A parsed checksum does not match the content. |
Do not fall back to timestamps, counters, String.hash, or a non-secure random
source when key_new or key_generate returns an error. A credential generator
should fail closed and make the availability problem visible.
For a server receiving a serialized key:
- Parse the expected format.
- Reject malformed values and checksum mismatches.
- Look up the credential using a protected representation of the content.
- Check revocation, scope, tenant, environment, and status.
- Record appropriate audit metadata without logging the secret.
Parsing and checksum verification are input hygiene. They are not an authorization decision.
Avoid logging the serialized key in request logs, exceptions, metrics, tracing spans, support messages, or analytics events. A prefix is safe to use as a search signal, but the content is a bearer credential.
If diagnostics need correlation, log a short non-reversible fingerprint or an internal credential ID instead of the key.
The exact storage design belongs to the application, but a common pattern is:
- show the full secret only once at creation
- store a cryptographic hash or keyed digest of the content for lookup
- store prefix, owner, scopes, environment, creation time, and expiry separately
- support revocation and rotation
- use constant-time comparisons where applicable
- protect the storage and encryption keys independently
The checksum is not a substitute for this storage representation.
Prefixes such as test and live can reduce operator mistakes and improve
scanning, but they do not enforce environment isolation. Enforce environment
boundaries in authorization and credential storage too.
If a key appears in a public repository, CI output, chat, a ticket, or a screenshot, assume it is compromised. Revoke it, issue a replacement, and investigate where it was used. A matching CRC32 does not make exposure safe.
The default v0.3.0 layout is a wire contract. If your application publishes a
custom prefix, separator, encoding, or checksum length, document that format
and use a matching KeyFormat for parsing. Do not silently change the format
of already-issued values.
Add apiculture to a Gleam project:
gleam add apicultureThen import the top-level API:
import apiculture as abThe package uses gleam_crypto for secure randomness, yabase for encoding,
and crc32 for the default checksum implementation.
| Function | Result | Use |
|---|---|---|
key_new() |
Result(Key, Error) |
Generate a default structured key. |
key_new_as_string() |
Result(String, Error) |
Generate and serialize a default key. |
key_new_as_config() |
KeyConfig |
Start a customizable default configuration. |
key_generate(config) |
Result(Key, Error) |
Finalize a random-generation configuration. |
key_config_is_ready(config) |
Bool |
Check whether a configuration can be finalized. |
| Function | Use |
|---|---|
bytes_from_uuid(input) |
Parse a UUID into 16 canonical bytes. |
bytes_from_ulid(input) |
Parse a ULID into 16 canonical bytes. |
key_from_bytes(config, bytes) |
Format existing bytes as a key. |
key_from_uuid(input) |
Import a UUID using the default format. |
key_from_uuid_with_config(config, input) |
Import a UUID using a custom format. |
key_from_ulid(input) |
Import a ULID using the default format. |
key_from_ulid_with_config(config, input) |
Import a ULID using a custom format. |
| Function | Returns |
|---|---|
key_to_string(key) / key_value(key) |
Serialized key string. |
key_bytes(key) |
Raw content bytes; compatibility alias. |
key_prefix_value(key) |
Option(String) prefix. |
key_separator_value(key) |
Option(String) separator. |
key_has_prefix(key) |
Whether a prefix is present. |
key_has_checksum(key) |
Whether a checksum is present. |
key_content_value(key) |
Encoded content section. |
key_content_bytes(key) |
Raw content bytes. |
key_content_byte_count(key) |
Content byte count. |
key_content_char_count(key) |
Encoded content character count. |
key_checksum_name(key) |
Option(String) algorithm name. |
key_checksum_value(key) |
Option(String) encoded checksum. |
key_checksum_bytes(key) |
Option(BitArray) raw checksum. |
key_checksum_byte_count(key) |
Checksum byte count, or 0. |
key_checksum_char_count(key) |
Option(Int) encoded checksum length. |
key_sections(key) |
All sections grouped as KeySections. |
key_verify_checksum(key) |
Verify with default CRC32. |
key_verify_checksum_with_algo(key, checksum) |
Verify with an explicit algorithm. |
| Function | Effect |
|---|---|
key_with_random_bytes(config, count) |
Select secure random bytes. |
key_with_random_chars(config, count) |
Select direct alphabet sampling. |
key_with_alphabet(config, alphabet) |
Set the direct-sampling alphabet. |
key_with_encoding(config, encoding) |
Set the content/checksum encoding. |
key_with_prefix(config, prefix) |
Set a prefix. |
key_with_separator(config, separator) |
Set every structural separator. |
key_with_checksum(config, checksum) |
Set the checksum algorithm. |
key_with_checksum_bytes(config, count) |
Set retained checksum byte count. |
key_disable_prefix(config) |
Remove the prefix. |
key_disable_checksum_name(config) |
Keep the checksum, remove its name. |
key_disable_checksum(config) |
Remove checksum and checksum name. |
| Function | Use |
|---|---|
key_default_format() |
Get the strict default KeyFormat. |
key_parse(input) |
Parse the default sk_<content>_crc32_<checksum> format. |
key_parse_with_format(input, format) |
Parse an explicitly configured format. |
key_format_with_prefix(format, prefix) |
Change expected prefix. |
key_format_without_prefix(format) |
Remove expected prefix. |
key_format_with_separator(format, separator) |
Change expected separator. |
key_format_with_encoding(format, encoding) |
Change expected encoding. |
key_format_with_checksum(format, checksum) |
Set expected checksum. |
key_format_without_checksum_name(format) |
Remove expected checksum name. |
key_format_without_checksum(format) |
Remove expected checksum. |
key_format_with_checksum_bytes(format, count) |
Set expected checksum size. |
key_format_with_content_bytes(format, count) |
Set expected content size. |
The top-level encoding constructors are hex_lower, hex_upper,
base32_rfc, base32_rfc_unpadded, base32_hex, base32_crockford,
base32_z, base36, base58, base62, base64, and base64_url.
The checksum API includes crc32, checksum_format, and checksum_verify.
Custom alphabets can be created with new_alphabet and inspected with
alphabet_characters and alphabet_size.
MIT License - Copyright (c) 2026 Antonio Ognio
Made with ❤️ from 🇵🇪. El Perú es clave 🔑.
