Roughenough is an implementation of the Roughtime (RFC 10049) secure time synchronization protocol. Roughenough provides both server and client components for cryptographically verifiable time synchronization.
- Full implementation of the Roughtime RFC 10049 specification
- Command-line client with multiple output formats and server validation
- Performance oriented batching UDP server
- Clients can (optionally) report malfeasance to a remote server for analysis
- Multiple backends for secure key and identity protection (KMS, Secret Manager, Linux KRS, SSH agent, PKCS#11)
- MSRV 1.94.1 (set by the AWS SDK crates), Rust 2024 edition
- Linux, MacOS, or other Unix-like operating system
- Optional: cloud provider credentials for backend key storage
Build all components:
cargo build --releaseBuild the server and client with every optional feature a release ships:
cargo build --release -p roughenough-server --features release
cargo build --release -p roughenough-client --features reportingThe server requires a long-term identity seed file to start. Pass its path
with --seed-file (or the ROUGHENOUGH_SEED_FILE environment variable). For testing
you can use --insecure-zero-seed to run with an all-zero seed.
On Unix-like systems the seed file needs to be a regular file (no symlinks) with
0400 or 0600 file permissions.
The seed file holds text in one of these forms:
- a hex or base64 encoded 32-byte seed, optionally prefixed with
seed:// - an AWS or GCP KMS envelope (
aws-kms://orgcp-kms://) - an AWS or GCP Secret Manager reference (
aws-secret://orgcp-secret://)
The roughenough_keys tool creates the protected forms: generate creates a new
random seed and protects it, protect protects the seed in an existing seed file,
and recover prints the plain seed that a seed file refers to. Build the tool and
the server with the longterm-aws or longterm-gcp feature; see
doc/PROTECTION.md.
# Generate a new mode-0600 plain seed file
(umask 077 && openssl rand -hex 32 > seed.txt)
# Encrypt it with AWS KMS; the output is a seed file the server loads
roughenough_keys protect -i seed.txt --resource aws-kms://arn:aws:kms:... -o roughenough.seed
# Or generate a new seed and store it in GCP Secret Manager
roughenough_keys generate --resource gcp-secret://projects/P/secrets/S -o roughenough.seed
# Print the plain seed that a seed file refers to
roughenough_keys recover -i roughenough.seed# Debug build, testing-only zero seed
cargo run --bin roughenough_server -- --insecure-zero-seed
# Generate a new mode-0600 plain seed file
(umask 077 && openssl rand -hex 32 > roughenough.seed)
# Release build with optimizations and a real seed file
cargo run --release --bin roughenough_server -- --seed-file roughenough.seed
# Run the server binary directly (a read-only file is sufficient)
target/release/roughenough_server --seed-file /run/secrets/roughenough.seedThe server will start listening for UDP requests on the default port (5319, assigned to Roughtime by IANA).
Basic usage:
# Query a Roughtime server
cargo run --bin roughenough_client -- roughtime.int08h.com 5319
# Verify server public key
cargo run --bin roughenough_client -- roughtime.int08h.com 5319 -k <base64-or-hex-key>
# Multiple requests
cargo run --bin roughenough_client -- roughtime.int08h.com 5319 -n 10
# Verbose output
cargo run --bin roughenough_client -- roughtime.int08h.com 5319 -v
# Different time formats
cargo run --bin roughenough_client -- roughtime.int08h.com 5319 --epoch # Unix timestamp
cargo run --bin roughenough_client -- roughtime.int08h.com 5319 --zulu # ISO 8601 UTCOffer draft version 0x8000000c as well as version 1 (see Protocol Versions):
cargo run --bin roughenough_client -- roughtime.example.com 5319 -P bothQuery multiple servers from an RFC compliant JSON list:
cargo run --bin roughenough_client -- -l servers.jsonWith -s, list mode sets the system clock from the last measurement only when
no causality violation is found; otherwise it exits with status 1.
The server answers only Roughtime version 1 (RFC 10049) and ignores requests
that do not offer it. Version 1 signatures use the RFC 10049 context strings,
"Roughtime v1 response signature" and "Roughtime v1 delegation signature".
The client offers version 1 by default. -P both offers version 1 and draft
version 0x8000000c, and -P 19 offers only the draft version. Draft responses
are verified with the draft context strings ("RoughTime v1 ...").
The server forwards the keys backends as online-pkcs11, online-ssh-agent,
longterm-aws, and longterm-gcp; release enables all of them.
- reporting - Enables clients to report malfeasance to a remote server
cargo build -p roughenough-client --features reporting cargo run -p roughenough-client --features reporting --bin roughenough_client -- -l servers.json --report
- test-utils - Test-only: exposes shared fixtures (
roughenough_client::test_utils) for other crates' tests; pulls inroughenough-server. Never enable it in builds you ship
See doc/PROTECTION.md for detailed information on seed protection strategies.
online-linux-krs(default): Store seed in Linux Kernel Keyring for runtime protectiononline-ssh-agentUse SSH agent for seed storage and signing operationsonline-pkcs11PKCS#11 hardware security module integration (Yubikey, HSM, etc)
longterm-awsAWS KMS envelope encryption and AWS Secrets Managerlongterm-gcpGCP Cloud KMS envelope encryption and GCP Secret Manager
Contributions are welcome! See CONTRIBUTING.md for guidelines, the project layout, and development commands.
Thank you to all past and present contributors:
- Stuart Stock (stuart {at} int08h.com)
- Aaron Hill (aa1ronham {at} gmail.com)
- Peter Todd (pete {at} petertodd.org)
- Muncan90 (github.com/muncan90)
- Zicklag (github.com/zicklag)
- Greg at Unrelenting Tech (github.com/unrelentingtech)
- Eric Swanson (github.com/lachesis)
- Marcus Dansarie (github.com/dansarie)
- Marco Davids (github.com/mdavids)
- Tanner Ryan (github.com/tannerryan)
Copyright (c) 2025-2026 the Roughenough Project Contributors.
Roughenough is licensed under either of
- Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
- MIT License (http://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.