Fast WireGuard vanity key generator in Rust. About 400x the Go tool.
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-29 21:09:38 +00:00
src [work-k9at] Double key search speed (#1) 2026-10-28 22:37:00 +00:00
.gitignore Fast Rust WireGuard vanity keygen 2026-10-28 22:32:15 +01:00
Cargo.lock Fast Rust WireGuard vanity keygen 2026-10-28 22:32:15 +01:00
Cargo.toml [work-thsk.41] Cargo.toml: repository URL -> watchfire (#2) 2026-10-29 21:09:38 +00:00
LICENSE Fast Rust WireGuard vanity keygen 2026-10-28 22:32:15 +01:00
README.md [work-k9at] Double key search speed (#1) 2026-10-28 22:37:00 +00:00

wg-vanity

A fast WireGuard vanity key generator in Rust. It finds key pairs whose public key starts with a word you choose, or matches a regex.

It is a rewrite of axllent/wireguard-vanity-keygen with the same flags and output. It is about 950 times faster.

Speed

Ryzen 7 5800X (8 cores, 16 threads):

Tool 1 thread 15 threads
wireguard-vanity-keygen (Go) 23,583 keys/s 212,566 keys/s
wg-vanity 21,500,900 keys/s 203,330,406 keys/s

A regex without a literal ^abc start runs at about half speed, because each key must be base64 encoded and matched.

How it is fast

The Go tool does one full scalar multiply per key (about 2,500 field multiplies). This tool does not.

  • Each lane holds a random clamped private key k and a center point P = kB. Let G = 8B. Adding 8 keeps the key clamped, so k + 8i is always a valid WireGuard private key.
  • A step tests P + iG for i from -128 to 128, then moves P by 257G. The points iG are a fixed table.
  • P + iG and P - iG need the same division, by u(iG) - u(P). Only their u is needed to test them, so v is only kept for the center.
  • All divisions in a step are shared with batch inversion (Montgomery's trick).
  • That is about 2.5 multiplies and 1 square per key.
  • Field elements use four 64-bit limbs. On x86-64 with BMI2 and ADX (Intel Broadwell, AMD Zen and later) multiply and square use mulx, adcx and adox. Other CPUs use the portable Rust code.
  • The first base64 char comes from the low limb of u, so most keys are rejected before a full encode.

Safety

  • Each lane starts from a fresh key from the OS random source.
  • Keys in one lane differ by a known amount. A lane is reseeded after every match, and its other keys from that step are not reported, so no two reported keys are related.
  • Every reported key is checked with x25519-dalek before it is printed. A mismatch aborts the program.

Usage

wg-vanity [OPTIONS] <SEARCH>...

  -s, --summary          print results only when all are found
  -c, --case-sensitive   case sensitive match
  -t, --threads <N>      threads (default: all CPUs)
  -l, --limit <N>        results per search, exits after (default 1)
  -T, --timeout <T>      quit after T (s/m/h suffix, bare number is minutes)
  -j, --json <FILE>      write results to JSON file
  -v, --version          show version
$ wg-vanity -l 2 test "^pc7[+/]"
Calculating speed: 85,442,662 calculations per second using 16 threads
Case-insensitive search, exiting after 2 results
Probability for "test": 1 in 1,048,576 (approx 0 seconds per match)
Probability for "^pc7[+/]" cannot be calculated as it is a regular expression

Differences from the Go tool:

  • Odds use 1 in 32 for a case-insensitive letter. The Go tool uses 1 in 38.
  • A key that matches two searches is printed once.
  • Regexes ending in =$ work. The Go tool rejects every regex with =.
  • There is no self-update.

Build

cargo build --release
cargo test --release

-C target-cpu=native gave no gain on Zen 3.

License

MIT. See LICENSE.