SHA256 authentication

Hi all,

I am trying to develop a custom NTP server using Python. I have the basic functionality working well. When I started to add authentication, I ran into an issue that RFC5905 defines “message digest” as 128-bit value. This makes sense for MD5 hashes, however, I have seen multiple options to configure clients with SHA1, SHA256, … hashes that are clearly longer than 128-bits.

Can somebody explain me how is this supposed to work? When trying to look at chrony or ntpd implementations, I can’t really find any SHA-related code.

Any relevant source would be great.


I want to say they’re truncated or you can use a longer one if you want to but I’m not sure.

No one asked, but I would personally endorse implementing AES-CMAC instead, which can produce 128-bit MACs anyway. :slight_smile:

(I don’t like the hash-based “MACs” because they don’t use a proper construction like HMAC. Though this is less of a problem with SHA-3, which Chrony supports.)

In NTPv4 messages the digests are truncated to 160 bits to follow the recommendations of RFC 7822 to avoid ambiguities in parsing of extension fields. The last extension field should have at least 28 bytes. In NTPv3 the digests can be as long as you like, there were no extension fields yet. IIRC this is not officially specified anywhere, it’s just what the common implementations do.

Thanks for the reply!

From the RFC 5905 - the digest is 128 bits and keyid is 32 bits. When you say that digest is truncated to 160 bits, does it mean that both those fields are used to carry the digest information? Or simply that digest field should carry 160 bits alone?

Currently, my last piece of data (for NTP4) is “transmit timestamp”. If I understand correctly, I should then:

  • Add zero padding for extension fields (28 bytes)
  • Get digest from sha256(key+data_without_extension_fields)
  • Get the packet data as “data_without_extension_fields+padding+keyid+digest”

Is that about right?

It’s 32 bits for the key ID and first 160 bits of the SHA256 sum. Together that is 24 bytes, which is the maximum length smaller than 28 bytes and divisible by 4.

The SHA256 sum should be calculated over all data preceding the MAC field, including any extension fields.

Does it mean that I am not required to add any extension field and just append MAC after “transmit timestamp” with the total length of 24 bytes?

Yes, extension fields are optional.