Fast WireGuard vanity key generator in Rust. About 400x the Go tool.
- Rust 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| src | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| LICENSE | ||
| README.md | ||
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
kand a center pointP = kB. LetG = 8B. Adding 8 keeps the key clamped, sok + 8iis always a valid WireGuard private key. - A step tests
P + iGforifrom -128 to 128, then movesPby257G. The pointsiGare a fixed table. P + iGandP - iGneed the same division, byu(iG) - u(P). Only theiruis needed to test them, sovis 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,adcxandadox. 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-dalekbefore 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.