Limits, defaults and tunables¶
Every numeric threshold and package-level default the module declares, with its value and — importantly — whether this module actually acts on it.
The key strength floor¶
A key entering a trust set must be one of:
- Ed25519, in either OpenPGP packet form (the legacy EdDSA algorithm 22, or the modern Ed25519 algorithm), at any size; or
- RSA, sign-capable or general, at 3072 bits or more.
Everything else is refused with ErrWeakKey. The rejected list is explicit —
DSA, ElGamal, ECDH, ECDSA, X25519, X448, Ed448, and RSA-encrypt-only — and a
final catch-all rejects any algorithm a future go-crypto release introduces,
so an unknown algorithm fails closed rather than slipping in.
The floor is 3072 bits, not configurable, and not exported. It is applied
twice: once when the trust set is constructed, and again at verification time
through packet.Config.MinRSABits, so a weak key cannot validate a signature
even if it reached the trust set by some path that skipped construction.
Signing-capable subkeys are checked too. When a subkey's binding signature
carries valid key flags, the Sign flag decides whether it is checked; when
the flags are absent the subkey is treated as signing-capable and checked
anyway. A weak subkey under a strong primary is refused.
Size caps on untrusted input¶
Both are exported vars in verify, so a tool author with an unusual release
layout can raise them.
| Variable | Value | Enforced by this module? |
|---|---|---|
verify.MaxWKDResponseSize |
65536 (64 KiB) | Yes. The WKD fetch reads at most this many bytes and returns ErrWKDResponseTooLarge beyond it. |
verify.MaxSignatureSize |
8192 (8 KiB) | No. Nothing in this module reads it. It documents the cap a downstream release-fetcher should apply to a detached-signature download; a GPG detached signature is typically 400–800 bytes. |
openpgpkey.DetachSign has no size cap: it reads its whole io.Reader
into memory. Bound the reader yourself when the input is not something you
produced.
Compile-time defaults this module does not read¶
verify declares four Default* variables. They exist so a tool author can
set enforcement policy in main() for a downstream self-updater. Nothing in
this module reads any of them — in particular, setting DefaultKeySource
does not change what BuildKeyResolver does with an empty KeySource (that
independently defaults to "both").
| Variable | Value | What it is for |
|---|---|---|
DefaultRequireSignature |
false |
Whether a downstream updater refuses an unsigned release. Left off until a project has shipped an embedded key in a prior release, so existing installs are not locked out. |
DefaultKeySource |
"both" |
The key-source mode a downstream updater starts from. |
DefaultRequireExternalCrosscheck |
false |
Whether a downstream updater treats a WKD outage as fatal. |
DefaultExternalKeyEmail |
"" |
The release address a downstream updater derives its WKD URL from. |
If you are wiring this module directly, ignore these four and populate
KeyResolverConfig instead.
All six variables above are var, not const, so they are mutable at run time
and process-global. Nothing synchronises access to them: set them during
initialisation, before any goroutine reads them.
Network defaults¶
| Setting | Value | Notes |
|---|---|---|
| Default WKD HTTP timeout | 30 seconds | Applied only when KeyResolverConfig.HTTPClient is nil. NewWKDResolver requires a client and substitutes nothing. |
| Redirect policy | Go's default | The default client sets no CheckRedirect, so up to ten redirects are followed and a redirect from the WKD host to an http:// URL will be followed. The https:// check applies to the initial URL only. Inject a client with a redirect policy if that matters to you. |
| TLS floor | Go's default | Nothing here raises the minimum TLS version or pins certificates. Inject a hardened client to do so. |
| WKD fallback | advanced then direct | The direct URL is tried only when the advanced URL returns HTTP 404. Any other failure — network, TLS, non-200, oversize, weak key — is returned without trying the direct URL. |
| Caching | none | Resolve performs its I/O on every call. Cache above the resolver if you need to. |
minisign limits¶
| Constant | Value | Notes |
|---|---|---|
minisign.KeyIDLen |
8 | Bytes of key identifier, derived as SHA-256(public_key)[:8]. |
minisign.MaxUntrustedComment |
1024 | The reference implementation's COMMENTMAXBYTES. |
minisign.MaxTrustedComment |
8192 | The reference implementation's TRUSTEDCOMMENTMAXBYTES. |
Both limits are counted in bytes, not runes, and are enforced here because
nothing downstream enforces them: neither the minisign-verify crate that
cargo-binstall uses nor jedisct1's Rust minisign crate applies any comment
length check. An over-long comment would therefore verify everywhere this
module is tested and then fail against upstream minisign -V.
The trusted-comment limit is rarely the binding one in practice. The global signature's message is the artefact signature concatenated with the trusted comment, and an HSM caps its signing message at 4096 bytes, so a KMS-backed signer runs out of room first.
Signing costs exactly two signer calls — one over the 64-byte artefact digest, one over the global signature's message. Budget for both when signing a wide target matrix against a metered KMS.
WKD output file permissions¶
WriteWKDTree writes files 0644 and directories 0755. That is deliberate:
a Web Key Directory exists to be served publicly, so world-readable is the
correct mode rather than an oversight.
Related¶
- Configuration fields — the fields these defaults back.
- Errors — the sentinels these limits raise.
- What this module does not do.