skip to content

In Kerberos PKINIT, what replaces the client's password-derived long-term key when a certificate authenticates the AS exchange?

level: seniorimportance: should knowfreq 40%

answer

  1. no password, so nothing to derive from
  2. a signature instead of a timestamp
  3. the reply key is established, not derived
  4. paChecksum binds signature to this request
  5. the ticket-granting ticket is still krbtgt-sealed

basics

~20 s

A signature replaces the proof and a freshly established reply key replaces the password-derived key: the client signs its pre-authentication data, and the KDC returns a reply key by key transport or key agreement, which then protects the AS-REP's enc-part.

solid answer

~40 s

Under PKINIT (RFC 4556) the client sends `PA-PK-AS-REQ` padata instead of `PA-ENC-TIMESTAMP`. It carries a signed `AuthPack` whose `PKAuthenticator` includes a `paChecksum` computed over the encoded request body, binding the signature to that exact `AS-REQ`. The KDC validates the certificate against the trust anchors it holds, requires the PKINIT extended key usage, and maps the certificate to a principal — normally through the `id-pkinit-san` subject alternative name — refusing with `KDC_ERR_CLIENT_NOT_TRUSTED (62)` if it will not. It answers with `PA-PK-AS-REP`, delivering a **reply key** either encrypted to the client's public key or derived from a key-agreement exchange. That reply key protects the `AS-REP` `enc-part`. What does not change: the ticket-granting ticket inside is still sealed under the realm's `krbtgt` key.

code

pseudocode · 21 lines
pseudocode
// KDC handling of PA-PK-AS-REQ padata in an AS-REQ

receive AS_REQ with padata PA-PK-AS-REQ(signedAuthPack)

if signature over signedAuthPack does not verify:
    return KRB-ERROR(KDC_ERR_PREAUTH_FAILED)

if certificate not acceptable under the trust anchors held
   or PKINIT extended key usage absent:
    return KRB-ERROR(KDC_ERR_CLIENT_NOT_TRUSTED)

principal = map_certificate_to_principal(id-pkinit-san, realm policy)
if principal is none or principal != AS_REQ.cname:
    return KRB-ERROR(KDC_ERR_CLIENT_NOT_TRUSTED)

if recompute(paChecksum) != PKAuthenticator.paChecksum over KDC-REQ-BODY:
    return KRB-ERROR(KDC_ERR_PREAUTH_FAILED)

reply_key = transport_to_client_public_key() or agree_with_client_public_value()
return AS-REP( ticket sealed under krbtgt key,
               enc-part encrypted under reply_key )

go deeper

for a junior

Recall that PKINIT lets a certificate and its private key stand in for a password at the first Kerberos exchange, so no password-derived key exists for that account.

for a middle

Explain the substitution precisely: a signed AuthPack replaces the encrypted timestamp, and a transported or agreed reply key replaces the long-term key that protected the AS-REP enc-part.

for a senior

Show what stays the same — the krbtgt-sealed ticket-granting ticket and its bearer nature — and read KDC_ERR_CLIENT_NOT_TRUSTED (62) as a trust-anchor or name-mapping decision.

for a principal

Weigh what the realm takes on: certificate issuance, trust anchors and revocation posture become authentication dependencies, and the accounts that keep password-derived keys decide how much is actually gained.

## The one thing PKINIT changes In an ordinary Kerberos AS exchange the client proves it knows a **long-term key derived from a password**, and the KDC encrypts the reply's `enc-part` — which carries the session key — under that same key. **PKINIT**, defined by **RFC 4556**, replaces both halves of that arrangement: - the **proof** becomes a digital signature made with the private key belonging to the client's certificate, carried in `PA-PK-AS-REQ` padata in place of `PA-ENC-TIMESTAMP`; - the **reply key** is established during the exchange rather than derived from a password, and it is what protects the `AS-REP` `enc-part`. Everything else about the AS exchange is unchanged, and this is the point candidates most often lose. ## What the client sends The `PA-PK-AS-REQ` carries a signed `AuthPack`. Inside it, a `PKAuthenticator` carries the client's time fields, the request `nonce`, and the **`paChecksum`** — a checksum computed over the encoded request body. That checksum is the binding: without it a signature made for one request could be lifted onto another, since the signature is over the authenticator, not over the whole message. The signed content is identified by the `id-pkinit-authData` content type (`1.3.6.1.5.2.3.1`). The client may also offer a public value for key agreement, which selects how the reply key will be established. ## What the KDC decides 1. **Is this certificate acceptable?** The KDC validates it against the trust anchors it has been given. Path building and certificate structure are the PKI layer's business; what Kerberos adds is that the client certificate must assert the **extended key usage** the specification defines for PKINIT clients, and the KDC's own certificate must assert its counterpart. 2. **Whose certificate is it?** The certificate must map to a principal in the realm. The specification defines the **`id-pkinit-san`** subject alternative name for carrying a Kerberos principal name directly; where it is absent, the realm's own mapping policy decides. 3. **Was it signed for this request?** The `paChecksum` is recomputed over the received request body and compared. If the KDC will not accept the certificate as an identity, it answers `KDC_ERR_CLIENT_NOT_TRUSTED (62)`. If the pre-authentication data fails to verify, `KDC_ERR_PREAUTH_FAILED`. ## How the reply key arrives `PA-PK-AS-REP` delivers the reply key one of two ways: - **key transport** — the KDC encrypts the reply key to the client's public key; - **key agreement** — both sides contribute public values and each derives the same reply key. **RFC 8636** defines the `id-pkinit-kdf` key-derivation function identifiers used for that derivation, so the two ends agree on how the shared value becomes a key. Either way, the reply key is what the `AS-REP` `enc-part` is encrypted under, and inside that `enc-part` the client finds the **session key** for the ticket-granting ticket exactly as it would have in a password exchange. ## What is unchanged, and why it matters | part of the exchange | password AS exchange | PKINIT AS exchange | |---|---|---| | pre-authentication proof | `PA-ENC-TIMESTAMP` under the long-term key | signed `AuthPack` in `PA-PK-AS-REQ` | | key protecting the `enc-part` | client's long-term key | reply key, transported or agreed | | ticket-granting ticket sealing key | realm's `krbtgt` key | realm's `krbtgt` key — **unchanged** | | what the client can read | `enc-part` only | `enc-part` only | So PKINIT removes the **password-derived long-term key** for that principal, and with it the offline guessing target that pre-authentication data and that account's own key present. It does **not** change what the resulting ticket-granting ticket is: a bearer credential sealed under `krbtgt`, valid until it expires, usable by anyone who obtains it together with its session key. Nor does it help a *service* principal whose key is still password-derived — a service ticket for that principal is sealed the same way as before. What PKINIT adds is a dependency: the KDC's decision now rests on a set of trust anchors and on certificate validity, so a clock, a revocation posture or a mis-issued certificate become authentication concerns in a way they were not before. **Version note.** RFC 4556 specifies the `paChecksum` as a SHA-1 checksum over the request body and anticipates migration away from it. **RFC 8636** is the agility update: it allows stronger checksum algorithms and defines the `id-pkinit-kdf` identifiers. Treat them as two documents with two positions, not as one statement about what any deployment does today.

  • Why does the PKAuthenticator carry a paChecksum at all, when the AuthPack is already signed?
    The signature covers the `AuthPack`, not the whole `AS-REQ`. Without a checksum over the encoded request body, a signed authenticator could be lifted onto a different request — different requested lifetimes, flags or target — and still verify. The `paChecksum` binds the signature to this exact request body, so the KDC is answering the request that was signed.
  • After PKINIT, is the account still exposed to offline guessing?
    Its own password-derived long-term key is gone, so there is nothing of that account's to guess offline — no pre-authentication ciphertext derived from a password and no key derived from one. But any ticket it obtains is still a bearer credential, and service tickets it requests are sealed under the service principals' keys, which may well still be password-derived.
  • The KDC returns KDC_ERR_CLIENT_NOT_TRUSTED (62) although the certificate is valid and in date. What would you check?
    Whether the KDC accepts the issuing authority as a trust anchor at all, whether the certificate asserts the extended key usage PKINIT requires of a client, and whether it maps to the principal in `cname` — typically through `id-pkinit-san`. The error is a trust and mapping decision, not a statement about certificate validity.

A clerk who stamps a requisition with a seal only he can make, instead of reciting a word the storeman also knows: the storeman can check the stamp without ever being able to produce it, and there is no shared word left for anyone to overhear and guess at.

saying these in an interview costs you the question

  • Says PKINIT replaces the ticket-granting ticket's krbtgt sealing
  • Thinks the certificate itself becomes the ticket
  • Claims PKINIT makes the resulting ticket non-transferable
  • Ignores the paChecksum and treats the signature as binding the request
  • Assumes the KDC needs no certificate of its own
  • Merges RFC 4556 and RFC 8636 into one claim about checksums