skip to content

How does SNMPv3's USM turn one user's password into a different key on every agent, and what does that key localisation protect against?

level: seniorimportance: should knowfreq 20%

answer

  1. stretch, hash, then hash again
  2. a megabyte of repeated password
  3. digest, engine ID, digest
  4. the authoritative engine's ID
  5. a stolen key stays local

basics

~20 s

USM repeats the password to 1,048,576 octets and hashes it into a key, then hashes that key, the authoritative engine's snmpEngineID and the key again. Each agent stores only its localized result, so a stolen key opens no agent with a different engine ID.

solid answer

~50 s

RFC 3414 derives keys in two steps. **Password to key** (Appendix A.2): repeat the password to fill 1,048,576 octets and hash it - MD5 or SHA-1 for the RFC 3414 protocols, the matching SHA-2 function under RFC 7860 - giving `Ku`. **Localisation** (section 2.6): hash `Ku || snmpEngineID || Ku`, using the authoritative engine's ID, giving `Kul`. The agent stores only `Kul`; RFC 3414 says the password or non-localized key MUST NOT be stored on a managed device. So one compromised switch yields a key valid for that engine alone: the RFC's design goal is that neither the password nor another engine's key can be derived from any set of localized keys. Localisation does **not** save a weak or leaked password - anyone who knows it can localize to every engine - so RFC 3414 demands at least 8 characters, and engine IDs must be unique, or two agents share a key.

code

pseudocode · 13 lines
pseudocode
// RFC 3414 Appendix A.2, then section 2.6
// H = MD5 or SHA-1 (RFC 3414); the protocol's SHA-2 function (RFC 7860)
function passwordToKey(password):
    require length(password) >= 8
    stream = repeat(password) truncated to 1048576 octets
    return H(stream)                        // Ku

function localize(Ku, authoritativeEngineID):
    return H(Ku || authoritativeEngineID || Ku)   // Kul

Ku    = passwordToKey(nocPassword)
Kul_A = localize(Ku, engineID_A)   // stored on agent A only
Kul_B = localize(Ku, engineID_B)   // differs from Kul_A

go deeper

for a junior

Recall that one SNMPv3 password becomes a different key on every device because each device's engine ID is mixed into the hash.

for a middle

Explain both steps: the megabyte of repeated password hashed into Ku, then Ku, engine ID and Ku hashed into the stored localized key.

for a senior

Diagnose what breaks it in production: engine IDs that change with hardware, cloned engine IDs, shared auth and privacy secrets, and why notification keys follow the authoritative engine.

for a principal

Argue how much a fleet-wide password really risks once keys are localized, and when per-device credentials or a certificate-based transport model justify their operating cost.

## The problem localisation solves A NOC engineer cannot remember a separate SNMPv3 password for every switch, router and firewall. But if every device held the same key, stealing it from the least-protected device - a configuration backup, a decommissioned box, a compromised agent - would unlock all of them. RFC 3414 resolves this with a compromise it credits to earlier work on **localized keys**: the user keeps one password, yet the secret shared with each **authoritative SNMP engine** is different. ## Step 1 - password to key RFC 3414 Appendix A.2 turns a human password into a fixed-length key `Ku`: 1. Repeat the password end to end until the string is exactly **1,048,576 octets** long, truncating the last copy. 2. Hash that string. For HMAC-MD5-96 the hash is MD5 (a 16-octet key); for HMAC-SHA-96 it is SHA-1 (20 octets). RFC 7860 section 9.3 says the HMAC-SHA-2 protocols SHOULD use the same algorithm with their own SHA-2 function. RFC 3414 section 11.2 explains why a transformation is needed at all: human passwords are often shorter than the 16 or 20 octets the protocols need, and brute force against a short character set is easy. Two practical consequences follow from the repetition: implementations must refuse passwords shorter than **8 characters**, and a password that merely repeats itself gains nothing - the RFC's own example is that `bertbert` and `bertbertbert` give the same key. ## Step 2 - localisation Section 2.6 then binds `Ku` to one engine: 1. Take the **snmpEngineID** of the authoritative engine. 2. Concatenate `Ku`, the engine ID and `Ku` again. 3. Hash the result with the same function. The output is the **localized key** `Kul` for this user at this engine. The same derivation produces the privacy key from the privacy password. CBC-DES then uses the first 8 octets as the DES key and the last 8 as a pre-IV; CFB128-AES-128 (RFC 3826) uses the first 128 bits as the AES key. ## Which engine's ID is used USM always localizes to the **authoritative** engine of the exchange, and which side that is depends on the PDU class (RFC 3414 section 1.5.1): | Message | Authoritative engine | Key localized to | |---|---|---| | Get, GetNext, GetBulk, Set | the agent that receives it | the agent's engine ID | | Trap (unconfirmed) | the agent that sends it | the sending agent's engine ID | | Inform (confirmed) | the manager that receives it | the manager's engine ID | So a manager receiving authenticated Traps from 500 agents holds 500 localized keys for the same user, one per sending engine; an agent sending authenticated Informs must learn the manager's engine ID and localize to it. ## What it protects, and what it does not - **Protects:** a key read out of one device - from its storage, a backup, a memory dump - authenticates only to that device's engine. RFC 3414 section 11.2 states the goal: it should be practically impossible to determine the password, or the key for another engine, from any combination of localized keys. - **Protects:** the device never holds the password. RFC 3414 makes this a rule - the password or non-localized key MUST NOT be stored on a managed device; the localized key SHALL be stored, if at all. - **Does not protect a leaked password.** Whoever knows the password can run both steps for any engine ID; RFC 3414 says plainly that key localisation will not help then. - **Does not protect a weak password.** Anyone who records one authenticated message can test candidate passwords against its HMAC offline; localisation changes the engine ID in each guess, not the number of guesses. - **Does not survive duplicate engine IDs.** RFC 3411 requires an engine ID to be unique within an administrative domain. Two agents cloned with the same ID derive the same `Kul`, so one compromised agent hands over the other's key. ## Operating consequences - **An engine ID change invalidates stored keys.** If an agent derives its engine ID from hardware - RFC 3411 allows formats built from an IPv4 or IPv6 address or a MAC address - a chassis swap gives it a new ID. A restored configuration still holds keys localized to the old ID, so every HMAC fails until the users are re-entered with their passwords and localized again. - **Separate authentication and privacy secrets.** RFC 3414 calls one password for both "very poor security practice". - **Rotate without sending keys in clear.** USM's `usmUserAuthKeyChange` and `usmUserPrivKeyChange` objects update a localized key remotely in a way that does not need privacy protection.

  • After a chassis swap, SNMPv3 polls to a switch fail authentication though the password is unchanged; why?
    If the agent builds its `snmpEngineID` from hardware such as a MAC address, the new chassis has a new ID. The manager rediscovers it and localizes the password to the new ID, while the restored configuration still holds keys localized to the old one, so the HMACs differ and `usmStatsWrongDigests` climbs. Re-enter the users so the device localizes again, or configure the engine ID explicitly.
  • Why must every agent in the estate have a distinct snmpEngineID?
    Both of USM's engine-binding defences key off it. Two agents with the same ID - typically a cloned image - derive identical localized keys from one password, so a key stolen from one works on the other, and a message addressed to one engine is equally acceptable to its twin. RFC 3411 requires the ID to be unique within an administrative domain.
  • For SNMPv3 notifications, whose engine ID is a user's key localized to?
    The authoritative engine's. A Trap is unconfirmed, so its sender - the agent - is authoritative: the receiving manager needs that user's key localized to each sending agent. An Inform is confirmed, so the receiving manager is authoritative: the agent discovers the manager's engine ID and localizes to it.

saying these in an interview costs you the question

  • The agent stores the user's password and derives keys when needed.
  • Key localisation makes a short password safe to use.
  • Get requests use a key localized to the manager's engine ID.
  • One password for authentication and privacy is fine because keys are localized.
  • A key extracted from one router authenticates to every router with that user.