TechnitiumSoftware/DnsServer · error · ArgumentOutOfRangeException

NSEC3 salt length valid range is 0-32

Error message

NSEC3 salt length valid range is 0-32

What it means

Thrown by the (ksk,zsk) overload of PrimaryZone.SignZone when useNSec3 is true and saltLength > 32. RFC 5151 NSEC3 salt is bounded; the guard raises ArgumentOutOfRangeException(nameof(saltLength)) before allocating the salt buffer.

Source

Thrown at DnsServerCore/Dns/Zones/PrimaryZone.cs:458

                    }
                }
            }
        }

        public void SignZone(DnssecPrivateKey kskPrivateKey, DnssecPrivateKey zskPrivateKey, uint dnsKeyTtl, bool useNSec3, ushort iterations = 0, byte saltLength = 0)
        {
            if (kskPrivateKey.KeyType != DnssecPrivateKeyType.KeySigningKey)
                throw new ArgumentException("The private key must be a Key Signing Key.", nameof(kskPrivateKey));

            if (zskPrivateKey.KeyType != DnssecPrivateKeyType.ZoneSigningKey)
                throw new ArgumentException("The private key must be a Zone Signing Key.", nameof(zskPrivateKey));

            byte[] salt = null;

            if (useNSec3)
            {
                if (saltLength > 32)
                    throw new ArgumentOutOfRangeException(nameof(saltLength), "NSEC3 salt length valid range is 0-32");

                if (saltLength > 0)
                {
                    salt = new byte[saltLength];
                    RandomNumberGenerator.Fill(salt);
                }
                else
                {
                    salt = [];
                }
            }

            SignZone([kskPrivateKey, zskPrivateKey], dnsKeyTtl, useNSec3, iterations, salt);
        }

        public void SignZone(IReadOnlyCollection<DnssecPrivateKey> dnssecPrivateKeys, uint dnsKeyTtl, bool useNSec3, ushort iterations = 0, byte[] salt = null)
        {
            //do validations

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Pass saltLength in the valid 0-32 range (0 means no salt).
  2. Prefer a small salt (e.g., 8 bytes) — larger salts add resolver cost without security benefit.
  3. Validate saltLength against the 0-32 bound before calling.

Example fix

// before
zone.SignZone(ksk, zsk, ttl, true, iterations: 0, saltLength: 64);

// after
int saltLength = Math.Clamp(requestedSalt, 0, 32);
zone.SignZone(ksk, zsk, ttl, true, iterations: 0, saltLength: saltLength);
Defensive patterns

Strategy: validation

Validate before calling

if (saltLength > 32) throw new ArgumentOutOfRangeException(nameof(saltLength));
zone.SignZone(ksk, zsk, ttl, useNSec3: true, iterations, saltLength);

Type guard

static bool IsValidNsec3SaltLength(int len) => len >= 0 && len <= 32;

Prevention

When it happens

Trigger: zone.SignZone(ksk, zsk, ttl, useNSec3: true, saltLength: 64).

Common situations: Hardcoding an oversized salt; copying salt-length from a hash config meant for a different algorithm.

Related errors


AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13). Data as JSON: /api/errors/c1000563aa3f3b31. Report an issue: GitHub.