roughtime

command module
v1.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 7, 2026 License: BSD-2-Clause Imports: 18 Imported by: 0

README

roughtime

PkgGoDev GitHub license

A Roughtime protocol implementation in Go. Roughtime is a protocol for secure rough time synchronization, providing cryptographically signed timestamps with proof of server authenticity. This implementation covers Google-Roughtime and IETF drafts 01–19.

Interoperability testing is available at ietf-wg-ntp/Roughtime-interop-code.

Protocol

The protocol package implements the Roughtime wire format for both server and client use. Ten wire format groups handle all version differences:

Wire Group Versions Key Differences
Google Google-Roughtime 64B nonce, SHA-512 (64B), Unix µs, no header
Draft 01 01 ROUGHTIM header, SHA-512/32B, MJD µs, 64B nonce, NONC in SREP
Draft 02 02 SHA-512/256 (distinct algorithm), NONC in SREP
Draft 03 03, 04 NONC moved to top-level response, SHA-512/32B
Draft 05 05, 06 32B nonce
Draft 07 07 SHA-512/256, delegation context without trailing hyphens
Draft 08 08, 09 Unix seconds, ZZZZ padding
Draft 10 10, 11 SRV tag, RADI ≥ 3
Draft 12 12, 13 New delegation context, full-packet Merkle leaf, VERS in SREP
Draft 14 14, 15, 16, 17, 18, 19 TYPE tag in request and response

Version negotiation selects the highest mutually supported version. Drafts 12–19 share version number 0x8000000c on the wire; the TYPE tag in the request distinguishes 12–13 from 14+.

Server

ParseRequest auto-detects Google vs IETF framing and extracts request fields. SelectVersion negotiates the best mutually supported version. NewCertificate creates a signed online delegation certificate. CreateReplies builds signed responses for a batch of requests.

Client

CreateRequest builds a padded Roughtime request for any supported version. VerifyReply authenticates the server's response: it verifies the delegation certificate, the signed response signature, the Merkle proof, and validates that the midpoint falls within the delegation window.

nonce, request, err := protocol.CreateRequest(
    []protocol.Version{protocol.VersionDraft12},
    rand.Reader,
)
// ... send request over UDP, receive reply ...
midpoint, radius, err := protocol.VerifyReply(
    []protocol.Version{protocol.VersionDraft12},
    reply, rootPublicKey, nonce, request,
)

See client/main.go for a complete working example.

Server

The root package is a UDP Roughtime server. It reads a hex-encoded Ed25519 root key seed from disk, generates online delegation certificates, and automatically refreshes them before expiry.

roughtime -root-key /path/to/seed.hex [-port 2002] [-log-level info]

The server uses a fixed worker pool sized to the CPU count, a sync.Pool for read buffers, and atomic certificate swaps for lock-free request handling. Responses that would exceed the request size are dropped per the amplification protection requirement. The server shuts down gracefully on SIGINT/SIGTERM, draining in-flight requests before exiting. Operational telemetry is emitted as structured JSON via zap, including a per-minute stats line with received, responded, and dropped counters. Set -log-level debug to enable per-request logging during troubleshooting.

Client

The client command queries one or more Roughtime servers and prints authenticated timestamps with clock drift. It supports single-server mode and multi-server mode via a JSON server list. IETF servers receive all supported versions in a single VER tag, letting the server pick the best match.

go run client/main.go -addr time.txryan.com:2002 -pubkey iBVjxg/1j7y1+kQUTBYdTabxCppesU/07D4PMDJk2WA=
go run client/main.go -servers client/ecosystem.json

Debug

The debug command probes a Roughtime server to discover its supported protocol versions and prints a full diagnostic dump of the request, response, signatures, and delegation certificate.

go run debug/main.go -addr time.txryan.com:2002 -pubkey iBVjxg/1j7y1+kQUTBYdTabxCppesU/07D4PMDJk2WA=

Public Server

A public Roughtime server is available at time.txryan.com:2002. Additional details can be found at time.txryan.com.

{
  "name": "time.txryan.com",
  "version": "IETF-Roughtime",
  "publicKeyType": "ed25519",
  "publicKey": "iBVjxg/1j7y1+kQUTBYdTabxCppesU/07D4PMDJk2WA=",
  "addresses": [
    {
      "protocol": "udp",
      "address": "time.txryan.com:2002"
    }
  ]
}

Testing

go test ./protocol/
go test -race ./protocol/

Example Output

Client

Single server:

$ go run client/main.go -addr time.txryan.com:2002 -pubkey iBVjxg/1j7y1+kQUTBYdTabxCppesU/07D4PMDJk2WA=
Address:   time.txryan.com:2002
Version:   draft-ietf-ntp-roughtime-12
Midpoint:  2026-04-07T03:19:21Z
Radius:    3s
Window:    [2026-04-07T03:19:18Z, 2026-04-07T03:19:24Z]
RTT:       44ms
Local:     2026-04-07T03:19:21.11307Z
Drift:     -113ms
Status:    in-sync

Multiple servers:

$ go run client/main.go -servers client/ecosystem.json
NAME                            ADDRESS                         VERSION         MIDPOINT              RADIUS    RTT         DRIFT         STATUS
Cloudflare-Roughtime-2          roughtime.cloudflare.com:2003   draft-11        2026-04-07T03:19:23Z  ±1s       19ms        -168ms        in-sync
time.txryan.com                 time.txryan.com:2002            draft-12        2026-04-07T03:19:23Z  ±3s       45ms        -194ms        in-sync
roughtime.se                    roughtime.se:2002               draft-12        2026-04-07T03:19:23Z  ±1s       141ms       -291ms        in-sync

3/3 servers responded
Consensus drift:    -194ms (median of 3 samples)
Consensus midpoint: 2026-04-07T03:19:23Z
Drift spread:       122ms (min=-291ms, max=-168ms)
Debug
$ go run debug/main.go -addr time.txryan.com:2002 -pubkey iBVjxg/1j7y1+kQUTBYdTabxCppesU/07D4PMDJk2WA=
=== Version Probe: time.txryan.com:2002 ===
  draft-ietf-ntp-roughtime-12              OK
  draft-ietf-ntp-roughtime-10              OK
  draft-ietf-ntp-roughtime-08              OK
  draft-ietf-ntp-roughtime-07              OK
  draft-ietf-ntp-roughtime-05              OK
  draft-ietf-ntp-roughtime-03              OK
  draft-ietf-ntp-roughtime-02              OK
  draft-ietf-ntp-roughtime-01              OK
  Google-Roughtime                         OK

Supported versions: draft-12, draft-10, draft-08, draft-07, draft-05, draft-03, draft-02, draft-01, Google
Negotiated:         draft-ietf-ntp-roughtime-12

=== Request ===
Size: 1024 bytes
00000000  52 4f 55 47 48 54 49 4d  f4 03 00 00 04 00 00 00  |ROUGHTIM........|
00000010  04 00 00 00 24 00 00 00  28 00 00 00 56 45 52 00  |....$...(...VER.|
00000020  4e 4f 4e 43 54 59 50 45  5a 5a 5a 5a 0c 00 00 80  |NONCTYPEZZZZ....|
00000030  14 b7 2d f3 2f 0e 30 d3  ba 1d 97 ef 44 e3 34 85  |..-./.0.....D.4.|
00000040  b3 88 87 47 1f bb c0 1c  40 ec 0f f3 1b dc 9e d8  |...G....@.......|
00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
...

--- Request Tags ---
  VER: 0c000080
  NONC: 14b72df32f0e30d3ba1d97ef44e33485b38887471fbbc01c40ec0ff31bdc9ed8
  TYPE: 00000000
  ZZZZ: (940 bytes of padding)

=== Response ===
Size: 472 bytes
00000000  52 4f 55 47 48 54 49 4d  cc 01 00 00 08 00 00 00  |ROUGHTIM........|
00000010  40 00 00 00 44 00 00 00  64 00 00 00 68 00 00 00  |@...D...d...h...|
00000020  68 00 00 00 f0 00 00 00  88 01 00 00 53 49 47 00  |h...........SIG.|
00000030  56 45 52 00 4e 4f 4e 43  54 59 50 45 50 41 54 48  |VER.NONCTYPEPATH|
00000040  53 52 45 50 43 45 52 54  49 4e 44 58 9d 4d 38 a9  |SREPCERTINDX.M8.|
00000050  44 82 3a ad de 29 d2 f7  c4 39 c4 fa 30 1e 70 2a  |D.:..)...9..0.p*|
...

--- Response Tags ---
  SIG: 9d4d38a944823aadde29d2f7c439c4fa301e702a1e82dff2ec5b4706f20ba203cc293c0c4e596552afe5347d271b2f6bd5946987c78cc984f9765b5a2c277d07
  VER: 0c000080
  NONC: 14b72df32f0e30d3ba1d97ef44e33485b38887471fbbc01c40ec0ff31bdc9ed8
  PATH: (empty)
  SREP: (136 bytes)
  CERT: (152 bytes)
  INDX: 00000000
  TYPE: 01000000

=== Verified Result ===
Round-trip time: 45.450542ms
Midpoint:        2026-04-07T03:19:25Z
Radius:          3s
Local time:      2026-04-07T03:19:25.489584Z
Clock drift:     -490ms
Amplification:   ok (reply 472 ≤ request 1024)

=== Response Details ===
Version:         0x8000000c (draft-ietf-ntp-roughtime-12)
Signature:       9d4d38a944823aadde29d2f7c439c4fa301e702a1e82dff2ec5b4706f20ba203cc293c0c4e596552afe5347d271b2f6bd5946987c78cc984f9765b5a2c277d07
Nonce:           14b72df32f0e30d3ba1d97ef44e33485b38887471fbbc01c40ec0ff31bdc9ed8
Merkle index:    0
Merkle path:     0 node(s)

=== Signed Response (SREP) ===
Merkle root:     ef921db6451f2da5ee90c186e39a0cf508fdfdd8c0e3616bdd3c4a2750c22c8b
Midpoint (raw):  1775531965 (2026-04-07T03:19:25Z)
Radius (raw):    3
VER in SREP:     0x8000000c (draft-ietf-ntp-roughtime-12)
VERS in SREP:    draft-01, draft-02, draft-03, draft-04, draft-05, draft-06, draft-07, draft-08, draft-09, draft-10, draft-11, draft-12

=== Certificate ===
Signature:       d7c29a2d28346a15a776597b39bd192a79af88746f1f569f140932b5e9d0fe28148b7807f107c9f08297040f1cda1296956b5167722a4dcd4181855ba1d8d002
Online key:      94a5cd8e2cdabb62dbd92d760e8dd177a27a2e42fc7d068744358d52bac05ed8
Not before:      2026-03-30T05:53:29Z
Not after:       2026-05-18T05:53:29Z
Expires in:      986h34m4s
Cert validity:   ok (midpoint within window)

License

Copyright (c) 2026 Tanner Ryan. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

Documentation

Overview

Command roughtime is a UDP Roughtime server that listens for requests and responds with signed timestamps. The server automatically refreshes its online signing certificate before expiry. See the protocol package for supported versions.

Directories

Path Synopsis
Command client queries one or more Roughtime servers and prints the authenticated timestamps.
Command client queries one or more Roughtime servers and prints the authenticated timestamps.
Command debug probes a Roughtime server to discover its supported protocol versions and prints a full diagnostic dump of the request, response, signatures, and delegation certificate.
Command debug probes a Roughtime server to discover its supported protocol versions and prints a full diagnostic dump of the request, response, signatures, and delegation certificate.
Package protocol implements the Roughtime wire protocol for both server and client use.
Package protocol implements the Roughtime wire protocol for both server and client use.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL