Dear community,
I have been trying to perform NTS measurements (using code in python) to provide more information about an NTP server (see sidn.ntpinfo.nl) for several weeks, but I need assistance in some areas. If you have the necessary expertise and could explain to me precisely how to build the NTS request, especially the AEAD part, it would be very helpful. If my question does not fit this discussion forum, I apologize, but I did not know how to reach some experts in this field!
I tried different approaches, but I think I missed something. If you find something wrong in my explanation, please tell me.
I managed to perform the Key Exchange part and I have got the aead 15 (AES_SIV_256), 32-byte c2s and s2c keys, and 8 cookies, each of 96 bytes. (I tried to measure time.cloudflare .com)
I know I need some extension fields in my request: UID, Cookie and AEAD extension fields. (From what I have seen, I may omit the cookie placeholder because I am not requesting any new cookies)
I think I successfully built the UID and the cookie extension fields:
-
UID extension field has 4+32=36 bytes (32 bytes were random bytes (type 0x0104). I am pretty sure I built it correctly.
-
Cookie extension field has 4+ length of a cookie = 100 bytes. (type 0x0204) Padding was not necessary as the length of a cookie has 96 bytes in this case.
However, I have problems with the AEAD part. For aead 15, the aead extension field should have 40 bytes. 2+2+nonce length+ciphertext length (or at least I saw some raw data using wireshark that worked with 40 bytes)
I used a 16 random bytes nonce.
Regarding the ciphertext, RFC 8915 says:
“The output of the negotiated AEAD algorithm. The structure of this field is determined by the negotiated algorithm, but it typically contains an authentication tag in addition to the actual ciphertext. The end of the field is zero-padded to a word (four octets) boundary.”
But what needs to be encrypted? Because the RFC also says that the UID and Cookie extension field “MUST NOT be encrypted”, which suggests the encrypted part is basically nothing. So, does it mean that plaintext is just “” (nothing)?
There is also something called “associated data”, which is the concatenation of header+UID+Cookie ext. field. This only needs to be authenticated.
Plaintext, associated data, the nonce and the c2s key are then used together to authenticate and the output of this process is a ciphertext. This ciphertext seems to contain both encrypted data + authentication tag. Should I use the whole ciphertext in the aead ext field, or should I use only the authentication tag? I simulated an example with chrony and wireshark and they used 40-byte aead extension field.
If you want more technical details, I used Python 3.13 with AES from Crypto.Cipher.
If you could explain to me how the request is built and what exactly the terms mean for the aead 15 case, I would be grateful!
link to RFC 8915: RFC 8915 - Network Time Security for the Network Time Protocol
link to a page that explains NTS: Network Time Security – New NTP Authentication Mechanism | Weberblog.net
Thank you,
Serban Orza