DNSSEC-KEYGEN(1)

πŸ’– dnssec-keygen β€” the DNSSEC key generation tool (BIND 9) πŸ’–

okay so this is the manual page for dnssec-keygen, straight out of the BIND 9 docs, and it's a big one bestie β€” we're doing it in two parts because there's genuinely that much lore. part 1 is right here. grab a snack πŸ“


✨ NAME ✨

dnssec-keygen β€” the DNSSEC key generation tool, aka the little guy that makes your cryptographic keys πŸŽ€


✨ SYNOPSIS ✨

dnssec-keygen [-3] [-A date/offset] [-a algorithm] [-b keysize] [-C] [-c
class] [-D date/offset] [-d bits] [-D sync date/offset] [-E engine] [-f
flag] [-F] [-G] [-h] [-I date/offset] [-i interval] [-K directory] [-k
policy] [-L ttl] [-l file] [-n nametype] [-M tag_min:tag_max] [-P
date/offset] [-P sync date/offset] [-p protocol] [-q] [-R date/offset]
[-S key] [-s strength] [-T rrtype] [-t type] [-V] [-v level] {name}

yes, -D shows up twice and -P shows up twice up there β€” that's not a typo on my end, that's literally what the page says, so I'm keeping it exactly as-is πŸ’…


✨ DESCRIPTION ✨

dnssec-keygen generates keys for DNSSEC (Secure DNS), as defined in RFC 2535 (https://datatracker.ietf.org/doc/html/rfc2535.html) and RFC 4034 (https://datatracker.ietf.org/doc/html/rfc4034.html). that's the whole elevator pitch, no cap πŸ›—

the name of the key is specified on the command line, bestie. and for DNSSEC keys specifically, that name must match the name of the zone you're generating the key for. no matchy-matchy, no key-y-key-y 😭


✨ OPTIONS ✨

so many options. all of them. here we go πŸƒβ€β™€οΈπŸ’¨

  • -3 β€” uses an NSEC3-capable algorithm to generate a DNSSEC key. if you use this with an algorithm that has both NSEC and NSEC3 versions, the NSEC3 version gets picked; for example, dnssec-keygen -3 -a RSASHA1 specifies the NSEC3RSASHA1 (deprecated) algorithm. it's giving "pick the shiny new one" ✨
  • -a algorithm β€” picks the cryptographic algorithm. for DNSSEC keys, algorithm must be one of RSASHA1 (deprecated), NSEC3RSASHA1 (deprecated), RSASHA256, RSASHA512, ECDSAP256SHA256, ECDSAP384SHA384, ED25519, or ED448. these values are case-insensitive. some abbreviations are supported too, like ECDSA256 for ECDSAP256SHA256 and ECDSA384 for ECDSAP384SHA384. if RSASHA1 (deprecated) is specified along with the -3 option, NSEC3RSASHA1 (deprecated) is used instead. this parameter must be specified β€” except when you're using the -S option, which copies the algorithm from the predecessor key. 🫢 in prior releases, HMAC algorithms could be generated for use as TSIG keys, but that feature was removed in BIND 9.13.0. use tsig-keygen to generate TSIG keys now. rip to a real one πŸ’€
  • -b keysize β€” specifies the number of bits in the key. the choice of key size depends on the algorithm: RSA keys must be between 1024 and 4096 bits; Diffie-Hellman keys must be between 128 and 4096 bits. elliptic curve algorithms don't need this parameter at all, they're low maintenance like that πŸ¦‹ if the key size isn't specified, some algorithms have pre-defined defaults. for example, RSA keys for use as DNSSEC zone-signing keys have a default size of 1024 bits; RSA keys for use as key-signing keys (KSKs, generated with -f KSK) default to 2048 bits.
  • -C β€” enables compatibility mode, which generates an old-style key, without any timing metadata. by default, dnssec-keygen includes the key's creation date in the metadata stored with the private key; other dates may be set there as well, including publication date, activation date, etc. keys that include this data may be incompatible with older versions of BIND, so the -C option suppresses them. vintage mode, essentially 🎞️
  • -c class β€” says the DNS record containing the key should have the specified class. if you don't specify, class IN is used. the default default-est default 🌸
  • -d bits β€” specifies the key size in bits. for the algorithms RSASHA1, NSEC3RSASA1, RSASHA256, and RSASHA512 the key size must be between 1024 and 4096 bits; DH size is between 128 and 4096 bits. this option is ignored for algorithms ECDSAP256SHA256, ECDSAP384SHA384, ED25519, and ED448. (and yes, NSEC3RSASA1 is spelled exactly like that in the page β€” leaving it verbatim, don't come for me πŸ™ˆ)
  • -E engine β€” specifies the cryptographic hardware to use, when applicable. when BIND 9 is built with OpenSSL, this needs to be set to the OpenSSL engine identifier that drives the cryptographic accelerator or hardware service module (usually pkcs11).
  • -f flag β€” sets the specified flag in the flag field of the KEY/DNSKEY record. the only recognized flags are ZSK (Zone-Signing Key), KSK (Key-Signing Key) and REVOKE. note that ZSK is not a physical flag in the DNSKEY record β€” it's merely used to explicitly tell the tool that you want to create a ZSK. setting -f in conjunction with -k will result in generating keys that only match the given role set with this option. roleplay, but make it cryptography πŸ‘‘
  • -F β€” turns on FIPS (US Federal Information Processing Standards) mode if the underlying cryptographic library supports running in FIPS mode. government-issued vibes πŸ›οΈ
  • -G β€” generates a key, but does not publish it or sign with it. this option is incompatible with -P and -A. a key that simply exists and minds its own business πŸ’…
  • -h β€” prints a short summary of the options and arguments to dnssec-keygen. the "help me bestie" button 🫢
  • -K directory β€” sets the directory in which the key files are to be written. where the babies live 🏠
  • -k policy β€” creates keys for a specific dnssec-policy. if a policy uses multiple keys, dnssec-keygen generates multiple keys. this also creates a .state file to keep track of the key state.
heads up: this option creates keys according to the dnssec-policy configuration, hence it cannot be used at the same time as many of the other options that dnssec-keygen provides. it's a whole different mode, don't mix it 🚫
  • -L ttl β€” sets the default TTL to use for this key when it's converted into a DNSKEY RR. this is the TTL used when the key is imported into a zone, unless there was already a DNSKEY RRset in place, in which case the existing TTL takes precedence. if this value isn't set and there's no existing DNSKEY RRset, the TTL defaults to the SOA TTL. setting the default TTL to 0 or none is the same as leaving it unset. same energy, different spelling ✨
  • -l file β€” provides a configuration file that contains a dnssec-policy statement (matching the policy set with -k). they're a matching set, like a charm bracelet πŸŽ€
  • -M tag_min:tag_max β€” sets the range of acceptable key tag values that dnssec-keygen will produce. if the key tag of the new key, or the key tag of the revoked version of the new key, is outside this range, the new key will be rejected and another new key will be generated. this is designed to be used when generating keys in a multi-signer scenario, where each operator is given a range of key tags to prevent collisions among different operators. the valid values for tag_min and tag_max are [0..65535]. the default allows all key tag values to be produced. this option is ignored when -k policy is specified. everybody gets their own lane, no crashing into each other πŸš—πŸ’¨
  • -n nametype β€” specifies the owner type of the key. the value of nametype must either be ZONE (for a DNSSEC zone key (KEY/DNSKEY)), HOST or ENTITY (for a key associated with a host (KEY)), USER (for a key associated with a user (KEY)), or OTHER (DNSKEY). these values are case-insensitive. the default is ZONE for DNSKEY generation. pick your fighter 🌈
  • -p protocol β€” sets the protocol value for the generated key, for use with -T KEY. the protocol is a number between 0 and 255. the default is 3 (DNSSEC). other possible values for this argument are listed in RFC 2535 (https://datatracker.ietf.org/doc/html/rfc2535.html) and its successors. go read, i'll wait πŸ“–
  • -q β€” sets quiet mode, which suppresses unnecessary output, including progress indication. without this option, when dnssec-keygen is run interactively to generate an RSA or DSA key pair, it prints a string of symbols to stderr indicating the progress of the key generation. a . means that a random number has been found which passed an initial sieve test; + means a number has passed a single round of the Miller-Rabin primality test; and a space ( ) means that the number has passed all the tests and is a satisfactory key. it's like a little loading bar but made of punctuation, obsessed 😭
  • -S key β€” creates a new key which is an explicit successor to an existing key. the name, algorithm, size, and type of the key are set to match the existing key. the activation date of the new key is set to the inactivation date of the existing one. the publication date is set to the activation date minus the prepublication interval, which defaults to 30 days. passing the torch, main character energy πŸ”₯
  • -s strength β€” specifies the strength value of the key. the strength is a number between 0 and 15, and currently has no defined purpose in DNSSEC. it's decorative, your honor πŸ’…
  • -T rrtype β€” specifies the resource record type to use for the key. rrtype must be either DNSKEY or KEY. the default is DNSKEY when using a DNSSEC algorithm, but it can be overridden to KEY for use with SIG(0).
  • -t type β€” indicates the type of the key for use with -T KEY. type must be one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. the default is AUTHCONF. AUTH refers to the ability to authenticate data, and CONF to the ability to encrypt data. auth and conf, the original power couple πŸ‘―β€β™€οΈ
  • -V β€” prints version information. "who are you" but polite 🌸
  • -v level β€” sets the debugging level. turn it up if things get weird πŸ”

and that's the options section done, but we are not done done bestie β€” there's more page coming in part 2, so don't wander off πŸ¦‹

⏰ TIMING OPTIONS ⏰

ok so before we get into the flags, bestie, we gotta talk about how you're allowed to write a date, because there are like five whole ways and you only need one πŸ’–

  • YYYYMMDD β€” short and sweet
  • YYYYMMDDHHMMSS β€” the longer one (this is literally the format used inside key files, iykyk)
  • 'Day Mon DD HH:MM:SS YYYY' β€” that's the one dnssec-settime -p prints out at you
  • UNIX epoch time β€” the one dnssec-settime -up spits out
  • the literal string now β€” iconic, no notes ✨

and here's the fun part πŸŽ€ you can stick a + or - and an offset right after your time argument, and it'll do the math for you. and if you're using now, you can just... leave now out entirely before the offset, slay.

the offset can then be followed by one of these suffixes so it knows what unit you mean:

  • y β€” years (defined as 365 24-hour days, leap years fully ignored, no cap)
  • mo β€” months (defined as 30 24-hour days)
  • w β€” weeks
  • d β€” days
  • h β€” hours
  • mi β€” minutes

no suffix at all? then your offset is computed in seconds. periodt.

and to unset a date, you use none, never, or unset. bye date πŸ‘‹


  • -P date/offset β€” sets the date when the key gets published to the zone. after that date, the key is in the zone but it is not being used to sign it. if you don't set it, and you haven't used the -G option, the default is the current date.
    • sync date/offset β€” sets the date when the CDS and CDNSKEY records that match this key get published to the zone. 🫢
  • -A date/offset β€” sets the date when the key gets activated. after that date, the key is in the zone and it is used to sign it. if you don't set it, and you haven't used -G, default is the current date. and here's the cute little domino effect: if you set this but you don't set -P, then the publication date gets set to the activation date minus the prepublication interval. math! πŸ’…
  • -R date/offset β€” sets the date when the key gets revoked. after that date the key is flagged as revoked. it's still in the zone and it's still used to sign it. just, y'know, marked πŸ’€
  • -I date/offset β€” sets the date when the key gets retired. after that date, the key is still included in the zone, but it is not used to sign it anymore. semi-retired, we love a soft launch 🌸
  • -D date/offset β€” sets the date when the key gets deleted. after that date, the key is no longer included in the zone at all. (but ngl it might still be chilling in the key repository, so don't @ me.)
    • sync date/offset β€” sets the date when the CDS and CDNSKEY records that match this key get deleted. πŸ’€
  • -i interval β€” sets the prepublication interval for a key. if it's set, then your publication and activation dates have to be separated by at least this much time. and if you specify the activation date but not the publication date, the publication date defaults to this much time before activation. conversely (yes, conversely, I said it πŸŽ€), if you specify the publication date but not the activation date, activation gets set to this much time after publication.

if the key is being created as an explicit successor to another key, the default prepublication interval is 30 days; otherwise it's zero.

and just like with date offsets: if the argument is followed by one of the suffixes y, mo, w, d, h, or mi, the interval is measured in years, months, weeks, days, hours, or minutes respectively. no suffix? seconds. always seconds. πŸ•°οΈ


πŸ”‘ GENERATED KEYS πŸ”‘

when dnssec-keygen finishes successfully, it prints a string to standard output that looks like Knnnn.+aaa+iiiii. that's the identification string for the key it just generated ✨ here's what's in it:

  • nnnn is the key name.
  • aaa is the numeric representation of the algorithm.
  • iiiii is the key identifier (or footprint).

dnssec-keygen also creates two files, with names based on that printed string:

  • Knnnn.+aaa+iiiii.key β€” contains the public key πŸ”“
  • Knnnn.+aaa+iiiii.private β€” contains the private key πŸ”

the .key file contains a DNSKEY or KEY record. when a zone is being signed by named or dnssec-signzone -S, DNSKEY records get included automatically. in other cases, you can insert the .key file into a zone file manually, or with an $INCLUDE statement. easy πŸ’…

the .private file contains algorithm-specific fields. and for obvious security reasons, this file does not have general read permission. do not touch. do not share. do not screenshot. πŸ™ˆ


🌈 EXAMPLE 🌈

ok let's actually do this. to generate an ECDSAP256SHA256 zone-signing key for the zone example.com, you issue:

dnssec-keygen -a ECDSAP256SHA256 example.com

and the command prints a string of the form:

Kexample.com.+013+26160

in this example, dnssec-keygen creates the files Kexample.com.+013+26160.key and Kexample.com.+013+26160.private. boom. you're a cryptographer now πŸ‘‘

and to generate a matching key-signing key, you issue:

dnssec-keygen -a ECDSAP256SHA256 -f KSK example.com

literally that easy πŸ¦‹


πŸ‘€ SEE ALSO πŸ‘€

go read them, bestie, they're giving lore πŸ“š


πŸ‘‘ Author πŸ‘‘

Internet Systems Consortium

2026, Internet Systems Consortium


ok that's the whole page!! this was version 9.20.30, dated 2026-10-12, and it's the DNSSEC-KEYGEN(1) manual page, mwah πŸ’‹ go sign some zones, you absolute icon 🌟

πŸ“¦ where this page comes from