Ensure that RSASHA1 is not used for the zone-signing key in Cloud DNS DNSSEC
A Cloud DNS managed zone signed with RSASHA1 rests on SHA-1, a hash with known chosen-prefix collisions. The control requires that the zone-signing key spec of a DNSSEC-enabled managed zone names an algorithm other than RSASHA1.
What the benchmark asks for
Cloud DNS stores two key specs on a managed zone, one for the key-signing key and one for the zone-signing key. The control reads the zone-signing entry and fails the zone when its algorithm is RSASHA1. The key-signing entry is a separate control, so a zone can fail one and pass the other.
Google has withdrawn SHA1 from general use. Cloud DNS now allows no algorithm outside the four in its table, so no project signs a new zone with RSASHA1.
Changing a DNSSEC setting on a zone that already has DNSSEC enabled does nothing. The new values are only read when DNSSEC moves from off to on, so remediation is an off and on cycle rather than an edit.
How it works
DNSSEC signs record sets, not responses. The zone-signing key signs every record set in the zone and publishes each signature as an RRSIG record. The key-signing key signs only the DNSKEY record set. The parent zone, which for example.com is com, publishes a DS record holding a hash of the key-signing key. A validating resolver follows that chain down from the root, so the zone-signing key is where the signatures a resolver actually checks come from.
RSASHA1 is algorithm 5 in the IANA DNS security algorithm registry. Under it, the signer hashes the record set with SHA-1 and signs that 160-bit hash with RSA. The signature therefore inherits the collision resistance of SHA-1 and nothing stronger. The "SHA-1 is a Shambles" research demonstrated a chosen-prefix collision in 2020 for roughly 45,000 US dollars of GPU time, and that cost has only fallen since.
If an attacker can get content of their choosing signed by the zone, they can build a second record set that hashes to the same value and attach the real RRSIG to it. Resolvers validate it, because the signature is genuine and the hash matches. Zones hand out that capability more often than it looks. A TXT record for a domain verification token, a CNAME a product team can set for their own subdomain, or any record written by automation that takes input from a request.
Key length compounds this. Cloud DNS accepts a 1024-bit or a 2048-bit RSASHA1 zone-signing key, so a zone running the shorter one is weak at the hash and at the modulus together.
The alternatives Cloud DNS offers are RSASHA256, RSASHA512, ECDSAP256SHA256 and ECDSAP384SHA384, which the IANA registry numbers 8, 10, 13 and 14. A zone-signing key under either RSA algorithm takes 1024 or 2048 bits, where a key-signing key under the same algorithm takes 2048 only. The ECDSA key lengths follow the curve for both key types, 256 bits for ECDSAP256SHA256 and 384 bits for ECDSAP384SHA384. Left to itself Cloud DNS signs zones with RSASHA256 at 1024 bits for the zone-signing key.
What the control does not cover
The control reads the managed zone resource in Google Cloud. It does not look at the parent zone, so it cannot tell whether a DS record exists at the registrar, whether that DS record still points at a key that has been removed, or whether the chain of trust resolves at all. A zone can carry a flawless ECDSAP256SHA256 key spec and be unsigned in practice because nobody ever published the DS record.
NSEC3 hashes owner names with SHA-1, and that will look alarming next to this control, but it is a different property. NSEC3 depends on preimage resistance, which SHA-1 still holds, while signing depends on collision resistance, which it does not. The live concern with NSEC3 is iteration count, where RFC 9276 asks for zero extra iterations and an empty salt because high counts cost the resolver more than they cost an attacker.
Finally, signing is only half the system. A record signed with ECDSAP256SHA256 protects nobody querying through a resolver that does not validate, and the control cannot see which resolvers a client uses.
What it costs to comply
The cost is an outage risk on the whole zone, not an engineering day.
Because settings are only applied when DNSSEC is switched on, the zone must pass through an unsigned state. During that window the DS record in the parent still claims the zone is signed. Every validating resolver that has the DS record cached returns SERVFAIL for every name in the zone, and SERVFAIL presents to users as a total outage rather than a missing record. The same thing happens at the end if the new keys are published before the old DS record is withdrawn.
That makes the registrar the slow part. The DS record lives in the parent zone and is changed through the registrar or the registry, often through a web form, sometimes behind a support ticket with a turnaround measured in hours. The sequence has two waits in it, each at least as long as the TTL the parent publishes on its DS record. Plan the change as a maintenance window and tell whoever owns the services under the zone, because a mistake takes down mail, APIs and the web site together.
Response size changes, and it changes in your favor. An ECDSAP256SHA256 signature is 64 bytes against 256 bytes for 2048-bit RSA, so DNSKEY and RRSIG responses stay smaller, fit in a UDP datagram more often, and give less leverage to a reflection attack.
There are cases where the work is not worth doing. If the zone has no DS record at the parent, nothing validates its signatures, and the real decision is whether to complete the chain of trust or turn DNSSEC off, not which algorithm to pick. If the zone is being retired or moved to another provider inside the quarter, fold the change into that move rather than doing two risky cutovers. Older validators are the one reason to keep it, and the benchmark recognizes that case. Treat that as a reason to replace whatever needs it, because the project allowlist and the support contract it already needs are not a long-term position.
How to check your environment
The benchmark audits one named zone at a time. To find the candidates in a project first, list the zones with their DNSSEC state and key specs:
gcloud dns managed-zones list --format="table(name,dnsName,visibility,dnssecConfig.state,dnssecConfig.defaultKeySpecs)"A zone whose state is off is not signing with anything today, though its stored key specs still decide what it uses the next time DNSSEC is switched on. The benchmark's own audit call returns the same fields for a single zone:
gcloud dns managed-zones describe ZONE_NAME --format="json(dnsName,dnssecConfig.state,dnssecConfig.defaultKeySpecs)"defaultKeySpecs is the configuration that will be used the next time DNSSEC is switched on. The keys actually signing the zone right now are a separate resource:
gcloud dns dns-keys list --zone=ZONE_NAME --format="table(id,keyTag,type,algorithm,isActive)"Read the rows where type is zoneSigning. If one of those is rsasha1 and isActive is true, the zone is signing with it today. Checking both places catches the case where the stored spec was edited while DNSSEC was already on, which leaves the configuration looking correct and the live keys unchanged.
From outside Google Cloud, ask the zone directly and read the algorithm number in the DNSKEY records:
dig +dnssec DNSKEY example.comA 256 flag marks a zone-signing key and a 257 flag marks a key-signing key. The algorithm number is the third field of the record, so a 256 3 5 key is the failure this control describes.
The remediation commands work with Google Cloud CLI 221.0.0 or later.
How to implement it
Work through the sequence in order and do not compress the waits.
Remove the DS record for the zone at the registrar first, then wait for the parent's DS TTL to expire so that no resolver still holds the old anchor. Turn DNSSEC off:
gcloud dns managed-zones update ZONE_NAME --dnssec-state offRe-enable it with the algorithm you want. ECDSAP256SHA256 is the better default for a new signing setup, because it gives 128-bit security in a 64-byte signature:
gcloud dns managed-zones update ZONE_NAME --dnssec-state on \
--ksk-algorithm ecdsap256sha256 --ksk-key-length 256 \
--zsk-algorithm ecdsap256sha256 --zsk-key-length 256 \
--denial-of-existence nsec3Use rsasha256 with a key length of 2048 instead if a downstream validator or a registrar DS form restricts you to RSA.
Then read the new key-signing key and publish its DS record at the registrar:
gcloud dns dns-keys describe KEY_ID --zone=ZONE_NAME --format="json(keyTag,digests,algorithm)"The zone is unsigned in the eyes of a validating resolver from the moment the old DS record expires until the new one propagates, which is the correct state to be in. An unsigned zone resolves. A signed zone with the wrong DS record does not.
To stop new zones from arriving with RSASHA1, pin the key specs in whatever creates zones rather than relying on a later scan. In Terraform, google_dns_managed_zone takes the same values:
dnssec_config {
state = "on"
default_key_specs {
key_type = "zoneSigning"
algorithm = "ecdsap256sha256"
key_length = 256
}
default_key_specs {
key_type = "keySigning"
algorithm = "ecdsap256sha256"
key_length = 256
}
}Set those blocks in a shared module and give teams the module rather than the resource, so the algorithm is not a field anyone fills in by hand. Google's withdrawal of SHA1 does most of this work already, since Cloud DNS no longer accepts RSASHA1 at all. The gap that remains is zones brought in from another provider, where the import carries the old key specs across, so make the key specs an explicit check in whatever runbook covers a DNS migration.
Further reading
- Advanced DNSSEC signing options covers the supported algorithms and key lengths, the denial-of-existence choices, and the rule that settings only apply when DNSSEC is switched on.
- DNSSEC overview and Manage DNSSEC configuration cover the
DSrecord handover with the registrar. - The IANA DNS Security Algorithm Numbers registry lists the number assigned to each DNSSEC algorithm, including 5 for RSASHA1 and 8, 10, 13 and 14 for the alternatives Cloud DNS offers.
- RFC 8624 gives the IETF position on which signing algorithms to use and which to retire.
- RFC 9276 explains why NSEC3 iteration counts and salts should be minimal.
- NIST retires SHA-1 sets out why the algorithm is withdrawn, after the 2020 chosen-prefix collision made the attack practical.
