13 Commits
Author SHA1 Message Date
nelsbrock c22d4bdb27 chore: release version 0.4.0 2026-05-22 19:53:19 +02:00
nelsbrock 3439e51865 chore: upgrade and update dependencies 2026-05-22 19:52:13 +02:00
nelsbrock a07aaca068 feat: rename --stop-after to --count/-n 2026-05-22 19:51:41 +02:00
nelsbrock 20c0a919c5 refactor: replace with_context calls with context calls 2026-05-10 18:13:47 +02:00
nelsbrock 3ea0de1cdb refactor: remove ref_self variable 2026-05-10 18:08:14 +02:00
nelsbrock 9f992caef9 refactor: fix some pedantic clippy lints 2026-05-10 18:02:54 +02:00
nelsbrock c8bedabe1f fix: determine workers count before prompting for password 2026-05-10 17:51:43 +02:00
nelsbrock e8b83d41cb make small improvements to CLI
- set meaningful value names for options
- add backticks around CLI options in user-facing messages
2026-05-10 17:34:56 +02:00
nelsbrock 6af66fd292 add --workers option 2026-05-10 17:28:01 +02:00
nelsbrock bc07cba585 remove unnecessary clone() 2026-05-10 16:21:11 +02:00
nelsbrock c6b5020795 release version 0.3.0 2026-05-09 16:30:04 +02:00
nelsbrock c74dcd0f01 add --userid option 2026-05-09 16:27:59 +02:00
nelsbrock 06e528ac09 upgrade and update dependencies 2026-05-09 16:27:32 +02:00
5 changed files with 264 additions and 190 deletions
Generated
+155 -142
View File
@@ -105,9 +105,9 @@ dependencies = [
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.5.0" version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
[[package]] [[package]]
name = "base64" name = "base64"
@@ -145,7 +145,16 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3"
dependencies = [ dependencies = [
"bit-vec", "bit-vec 0.8.0",
]
[[package]]
name = "bit-set"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34ddef2995421ab6a5c779542c81ee77c115206f4ad9d5a8e05f4ff49716a3dd"
dependencies = [
"bit-vec 0.9.1",
] ]
[[package]] [[package]]
@@ -155,10 +164,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
[[package]] [[package]]
name = "bitflags" name = "bit-vec"
version = "2.11.0" version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51"
[[package]]
name = "bitflags"
version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3"
[[package]] [[package]]
name = "blake2" name = "blake2"
@@ -200,9 +215,9 @@ dependencies = [
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.20.2" version = "3.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
[[package]] [[package]]
name = "bzip2" name = "bzip2"
@@ -234,9 +249,9 @@ dependencies = [
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.2.59" version = "1.2.62"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98"
dependencies = [ dependencies = [
"find-msvc-tools", "find-msvc-tools",
"shlex", "shlex",
@@ -289,9 +304,9 @@ dependencies = [
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.6.0" version = "4.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
@@ -311,9 +326,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_derive" name = "clap_derive"
version = "4.6.0" version = "4.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
@@ -420,9 +435,9 @@ checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555"
[[package]] [[package]]
name = "either" name = "either"
version = "1.15.0" version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"
[[package]] [[package]]
name = "ena" name = "ena"
@@ -446,25 +461,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [ dependencies = [
"libc", "libc",
"windows-sys 0.52.0", "windows-sys 0.61.2",
] ]
[[package]] [[package]]
name = "fancy-regex" name = "fancy-regex"
version = "0.17.0" version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72cf461f865c862bb7dc573f643dd6a2b6842f7c30b07882b56bd148cc2761b8" checksum = "e1e1dacd0d2082dfcf1351c4bdd566bbe89a2b263235a2b50058f1e130a47277"
dependencies = [ dependencies = [
"bit-set", "bit-set 0.8.0",
"regex-automata", "regex-automata",
"regex-syntax", "regex-syntax",
] ]
[[package]] [[package]]
name = "fastrand" name = "fastrand"
version = "2.3.0" version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
[[package]] [[package]]
name = "find-msvc-tools" name = "find-msvc-tools"
@@ -474,14 +489,13 @@ checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
[[package]] [[package]]
name = "fingerprunk" name = "fingerprunk"
version = "0.2.2" version = "0.4.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"clap", "clap",
"ctrlc", "ctrlc",
"fancy-regex", "fancy-regex",
"num-integer", "num-integer",
"num_cpus",
"rpassword", "rpassword",
"sequoia-openpgp", "sequoia-openpgp",
] ]
@@ -508,6 +522,30 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]]
name = "futures-core"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
[[package]]
name = "futures-task"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"
[[package]]
name = "futures-util"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
dependencies = [
"futures-core",
"futures-task",
"pin-project-lite",
"slab",
]
[[package]] [[package]]
name = "generic-array" name = "generic-array"
version = "0.14.7" version = "0.14.7"
@@ -520,9 +558,9 @@ dependencies = [
[[package]] [[package]]
name = "generic-array" name = "generic-array"
version = "1.3.5" version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eaf57c49a95fd1fe24b90b3033bee6dc7e8f1288d51494cb44e627c295e38542" checksum = "dab9e9188e97a93276e1fe7b56401b851e2b45a46d045ca658100c1303ada649"
dependencies = [ dependencies = [
"rustversion", "rustversion",
"typenum", "typenum",
@@ -571,9 +609,9 @@ dependencies = [
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.16.1" version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
[[package]] [[package]]
name = "heck" name = "heck"
@@ -581,12 +619,6 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
[[package]] [[package]]
name = "iana-time-zone" name = "iana-time-zone"
version = "0.1.65" version = "0.1.65"
@@ -712,9 +744,9 @@ dependencies = [
[[package]] [[package]]
name = "idna_adapter" name = "idna_adapter"
version = "1.2.1" version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714"
dependencies = [ dependencies = [
"icu_normalizer", "icu_normalizer",
"icu_properties", "icu_properties",
@@ -722,12 +754,12 @@ dependencies = [
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.13.1" version = "2.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown 0.16.1", "hashbrown 0.17.1",
"serde", "serde",
"serde_core", "serde_core",
] ]
@@ -764,10 +796,12 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]] [[package]]
name = "js-sys" name = "js-sys"
version = "0.3.94" version = "0.3.99"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11"
dependencies = [ dependencies = [
"cfg-if",
"futures-util",
"once_cell", "once_cell",
"wasm-bindgen", "wasm-bindgen",
] ]
@@ -783,12 +817,12 @@ dependencies = [
[[package]] [[package]]
name = "lalrpop" name = "lalrpop"
version = "0.22.2" version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba4ebbd48ce411c1d10fb35185f5a51a7bfa3d8b24b4e330d30c9e3a34129501" checksum = "98a80a963123205c7157323c99611bc4abb65dcbd62ef46dc4bac74a3941bc75"
dependencies = [ dependencies = [
"ascii-canvas", "ascii-canvas",
"bit-set", "bit-set 0.9.1",
"ena", "ena",
"itertools 0.14.0", "itertools 0.14.0",
"lalrpop-util", "lalrpop-util",
@@ -804,12 +838,11 @@ dependencies = [
[[package]] [[package]]
name = "lalrpop-util" name = "lalrpop-util"
version = "0.22.2" version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5baa5e9ff84f1aefd264e6869907646538a52147a755d494517a8007fb48733" checksum = "884f3e747ed2dcee867cda1b0c31a048f9e20de2d916a248949319921a2e666e"
dependencies = [ dependencies = [
"regex-automata", "regex-automata",
"rustversion",
] ]
[[package]] [[package]]
@@ -820,15 +853,15 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
[[package]] [[package]]
name = "libbz2-rs-sys" name = "libbz2-rs-sys"
version = "0.2.2" version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c4a545a15244c7d945065b5d392b2d2d7f21526fba56ce51467b06ed445e8f7" checksum = "34b357333733e8260735ba5894eb928c02ecc69c78715f01a8019e7fa7f2db4c"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.184" version = "0.2.186"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
[[package]] [[package]]
name = "libloading" name = "libloading"
@@ -897,14 +930,14 @@ dependencies = [
[[package]] [[package]]
name = "nettle" name = "nettle"
version = "7.4.0" version = "7.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44e6ff4a94e5d34a1fd5abbd39418074646e2fa51b257198701330f22fcd6936" checksum = "2578a3627c28fefb60f1680e20e85f38bd8c8bf98c288b370489a573b0640907"
dependencies = [ dependencies = [
"getrandom 0.2.17", "getrandom 0.4.2",
"libc", "libc",
"nettle-sys", "nettle-sys",
"thiserror 1.0.69", "thiserror",
"typenum", "typenum",
] ]
@@ -930,9 +963,9 @@ checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
[[package]] [[package]]
name = "nix" name = "nix"
version = "0.31.2" version = "0.31.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"cfg-if", "cfg-if",
@@ -968,16 +1001,6 @@ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "num_cpus"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b"
dependencies = [
"hermit-abi",
"libc",
]
[[package]] [[package]]
name = "objc2" name = "objc2"
version = "0.6.4" version = "0.6.4"
@@ -1041,28 +1064,35 @@ dependencies = [
[[package]] [[package]]
name = "petgraph" name = "petgraph"
version = "0.7.1" version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455"
dependencies = [ dependencies = [
"fixedbitset", "fixedbitset",
"hashbrown 0.15.5",
"indexmap", "indexmap",
] ]
[[package]] [[package]]
name = "phf_shared" name = "phf_shared"
version = "0.11.3" version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266"
dependencies = [ dependencies = [
"siphasher", "siphasher",
] ]
[[package]] [[package]]
name = "pkg-config" name = "pin-project-lite"
version = "0.3.32" version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
[[package]]
name = "pkg-config"
version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e"
[[package]] [[package]]
name = "potential_utf" name = "potential_utf"
@@ -1159,23 +1189,23 @@ checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
[[package]] [[package]]
name = "rpassword" name = "rpassword"
version = "7.4.0" version = "7.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66d4c8b64f049c6721ec8ccec37ddfc3d641c4a7fca57e8f2a89de509c73df39" checksum = "5ac5b223d9738ef56e0b98305410be40fa0941bf6036c56f1506751e43552d64"
dependencies = [ dependencies = [
"libc", "libc",
"rtoolbox", "rtoolbox",
"windows-sys 0.59.0", "windows-sys 0.61.2",
] ]
[[package]] [[package]]
name = "rtoolbox" name = "rtoolbox"
version = "0.0.3" version = "0.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7cc970b249fbe527d6e02e0a227762c9108b2f49d81094fe357ffc6d14d7f6f" checksum = "50a0e551c1e27e1731aba276dbeaeac73f53c7cd34d1bda485d02bd1e0f36844"
dependencies = [ dependencies = [
"libc", "libc",
"windows-sys 0.52.0", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@@ -1194,7 +1224,7 @@ dependencies = [
"errno", "errno",
"libc", "libc",
"linux-raw-sys", "linux-raw-sys",
"windows-sys 0.52.0", "windows-sys 0.61.2",
] ]
[[package]] [[package]]
@@ -1226,9 +1256,9 @@ checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
[[package]] [[package]]
name = "sequoia-openpgp" name = "sequoia-openpgp"
version = "2.2.0" version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0620e44a7d514adf7df87b44db235f13b81fed7ddc265adb26f014d42626ac47" checksum = "c847f0f148cf238c3aec88d092fd3c4301c21e906829ea9e415ea7531f7ec094"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"argon2", "argon2",
@@ -1248,7 +1278,7 @@ dependencies = [
"regex", "regex",
"regex-syntax", "regex-syntax",
"sha1collisiondetection", "sha1collisiondetection",
"thiserror 2.0.18", "thiserror",
"xxhash-rust", "xxhash-rust",
] ]
@@ -1283,9 +1313,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.149" version = "1.0.150"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
dependencies = [ dependencies = [
"itoa", "itoa",
"memchr", "memchr",
@@ -1301,14 +1331,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f606421e4a6012877e893c399822a4ed4b089164c5969424e1b9d1e66e6964b" checksum = "1f606421e4a6012877e893c399822a4ed4b089164c5969424e1b9d1e66e6964b"
dependencies = [ dependencies = [
"digest", "digest",
"generic-array 1.3.5", "generic-array 1.4.1",
] ]
[[package]] [[package]]
name = "sha3" name = "sha3"
version = "0.10.8" version = "0.10.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" checksum = "77fd7028345d415a4034cf8777cd4f8ab1851274233b45f84e3d955502d93874"
dependencies = [ dependencies = [
"digest", "digest",
"keccak", "keccak",
@@ -1328,9 +1358,15 @@ checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214"
[[package]] [[package]]
name = "siphasher" name = "siphasher"
version = "1.0.2" version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649"
[[package]]
name = "slab"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
[[package]] [[package]]
name = "smallvec" name = "smallvec"
@@ -1346,9 +1382,9 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
[[package]] [[package]]
name = "string_cache" name = "string_cache"
version = "0.8.9" version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" checksum = "a18596f8c785a729f2819c0f6a7eae6ebeebdfffbfe4214ae6b087f690e31901"
dependencies = [ dependencies = [
"new_debug_unreachable", "new_debug_unreachable",
"parking_lot", "parking_lot",
@@ -1400,7 +1436,7 @@ dependencies = [
"getrandom 0.4.2", "getrandom 0.4.2",
"once_cell", "once_cell",
"rustix", "rustix",
"windows-sys 0.52.0", "windows-sys 0.61.2",
] ]
[[package]] [[package]]
@@ -1409,16 +1445,7 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8c27177b12a6399ffc08b98f76f7c9a1f4fe9fc967c784c5a071fa8d93cf7e1" checksum = "d8c27177b12a6399ffc08b98f76f7c9a1f4fe9fc967c784c5a071fa8d93cf7e1"
dependencies = [ dependencies = [
"windows-sys 0.59.0", "windows-sys 0.61.2",
]
[[package]]
name = "thiserror"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [
"thiserror-impl 1.0.69",
] ]
[[package]] [[package]]
@@ -1427,18 +1454,7 @@ version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
dependencies = [ dependencies = [
"thiserror-impl 2.0.18", "thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn",
] ]
[[package]] [[package]]
@@ -1464,9 +1480,9 @@ dependencies = [
[[package]] [[package]]
name = "typenum" name = "typenum"
version = "1.19.0" version = "1.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
@@ -1522,11 +1538,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]] [[package]]
name = "wasip2" name = "wasip2"
version = "1.0.2+wasi-0.2.9" version = "1.0.3+wasi-0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6"
dependencies = [ dependencies = [
"wit-bindgen", "wit-bindgen 0.57.1",
] ]
[[package]] [[package]]
@@ -1535,14 +1551,14 @@ version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
dependencies = [ dependencies = [
"wit-bindgen", "wit-bindgen 0.51.0",
] ]
[[package]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
version = "0.2.117" version = "0.2.122"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"once_cell", "once_cell",
@@ -1553,9 +1569,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-macro" name = "wasm-bindgen-macro"
version = "0.2.117" version = "0.2.122"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6"
dependencies = [ dependencies = [
"quote", "quote",
"wasm-bindgen-macro-support", "wasm-bindgen-macro-support",
@@ -1563,9 +1579,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-macro-support" name = "wasm-bindgen-macro-support"
version = "0.2.117" version = "0.2.122"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e"
dependencies = [ dependencies = [
"bumpalo", "bumpalo",
"proc-macro2", "proc-macro2",
@@ -1576,9 +1592,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-shared" name = "wasm-bindgen-shared"
version = "0.2.117" version = "0.2.122"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@@ -1623,7 +1639,7 @@ version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.61.2",
] ]
[[package]] [[package]]
@@ -1685,15 +1701,6 @@ dependencies = [
"windows-link", "windows-link",
] ]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.59.0" version = "0.59.0"
@@ -1785,6 +1792,12 @@ dependencies = [
"wit-bindgen-rust-macro", "wit-bindgen-rust-macro",
] ]
[[package]]
name = "wit-bindgen"
version = "0.57.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
[[package]] [[package]]
name = "wit-bindgen-core" name = "wit-bindgen-core"
version = "0.51.0" version = "0.51.0"
@@ -1901,9 +1914,9 @@ dependencies = [
[[package]] [[package]]
name = "zerofrom" name = "zerofrom"
version = "0.1.7" version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272"
dependencies = [ dependencies = [
"zerofrom-derive", "zerofrom-derive",
] ]
+5 -6
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "fingerprunk" name = "fingerprunk"
version = "0.2.2" version = "0.4.0"
authors = ["Niklas Elsbrock <mail@nelsbrock.de>"] authors = ["Niklas Elsbrock <mail@nelsbrock.de>"]
edition = "2024" edition = "2024"
description = "CLI tool for brute-forcing OpenPGP keys with cool fingerprints" description = "CLI tool for brute-forcing OpenPGP keys with cool fingerprints"
@@ -11,10 +11,9 @@ categories = ["command-line-utilities"]
[dependencies] [dependencies]
anyhow = "1.0.102" anyhow = "1.0.102"
clap = { version = "4.6.0", features = ["derive"] } clap = { version = "4.6.1", features = ["derive"] }
ctrlc = "3.5.2" ctrlc = "3.5.2"
fancy-regex = "0.17.0" fancy-regex = "0.18.0"
num-integer = "0.1.46" num-integer = "0.1.46"
num_cpus = "1.17.0" rpassword = "7.5.2"
rpassword = "7.4.0" sequoia-openpgp = "2.3.0"
sequoia-openpgp = "2.2.0"
+2 -2
View File
@@ -18,11 +18,11 @@ at `secret.asc`. The regex for this is `^C0FFEE`. Now, simply use the following
the search: the search:
```sh ```sh
fingerprunk -r '^C0FFEE' >> secret.asc fingerprunk -r '^C0FFEE' -u "Your Name <your.email@example.org>" >> secret.asc
``` ```
Fingerprunk will now generate many keys and write out all keys with matching fingerprints to Fingerprunk will now generate many keys and write out all keys with matching fingerprints to
standard output (here: `secret.asc`). standard output (here: `secret.asc`), adding the provided user ID.
If you want Fingerprunk to output password-encrypted keys use the `-p` flag and you will be prompted If you want Fingerprunk to output password-encrypted keys use the `-p` flag and you will be prompted
for a password. for a password.
+56 -29
View File
@@ -3,13 +3,13 @@
use std::{ use std::{
fmt::{self, Write}, fmt::{self, Write},
io, io,
num::NonZeroU64, num::NonZero,
sync::{ sync::{
atomic::{AtomicBool, AtomicU64, Ordering}, atomic::{AtomicBool, AtomicU64, Ordering},
mpsc, mpsc,
}, },
thread, thread,
time::{Duration, Instant}, time::{Duration, Instant, SystemTime},
}; };
use fancy_regex::Regex; use fancy_regex::Regex;
@@ -18,7 +18,7 @@ use sequoia_openpgp::{
Cert, Packet, armor, Cert, Packet, armor,
crypto::Password, crypto::Password,
packet::{ packet::{
Key, Key, UserID,
key::{Key4, PrimaryRole, SecretParts}, key::{Key4, PrimaryRole, SecretParts},
prelude::SignatureBuilder, prelude::SignatureBuilder,
}, },
@@ -38,8 +38,10 @@ enum Message {
pub struct Config { pub struct Config {
pub regex: Regex, pub regex: Regex,
pub status_enabled: bool, pub status_enabled: bool,
pub stop_after: Option<NonZeroU64>, pub count: Option<NonZero<u64>>,
pub password: Option<Password>, pub password: Option<Password>,
pub userids: Vec<UserID>,
pub workers: NonZero<usize>,
} }
#[derive(Debug)] #[derive(Debug)]
@@ -82,24 +84,20 @@ impl Fingerprunk {
} }
thread::scope(|scope| { thread::scope(|scope| {
let ref_self = &self;
let status_displayer = if self.config.status_enabled { let status_displayer = if self.config.status_enabled {
Some( Some(
thread::Builder::new() thread::Builder::new()
.name("status_displayer".to_string()) .name("status_displayer".to_string())
.spawn_scoped(scope, move || ref_self.status_displayer_thread())?, .spawn_scoped(scope, || self.status_displayer_thread())?,
) )
} else { } else {
None None
}; };
for num in 0..num_cpus::get() { for num in 0..self.config.workers.get() {
let sender = sender.clone();
thread::Builder::new() thread::Builder::new()
.name(format!("worker-{num:03}")) .name(format!("worker-{num:03}"))
.spawn_scoped(scope, move || ref_self.worker_thread(sender))?; .spawn_scoped(scope, || self.worker_thread(&sender))?;
} }
let mut stdout = io::stdout().lock(); let mut stdout = io::stdout().lock();
@@ -108,12 +106,12 @@ impl Fingerprunk {
for message in receiver { for message in receiver {
match message { match message {
Message::Key(key) => { Message::Key(key) => {
let cert = self.key_to_cert(&key)?; let cert = self.key_to_cert(key)?;
self.serialize_cert(cert, &mut stdout)?; self.serialize_cert(&cert, &mut stdout)?;
// Increase "found" counter and stop if enough matches have been found // Increase "found" counter and stop if enough matches have been found
let prev = self.counter_found.fetch_add(1, Ordering::Relaxed); let prev = self.counter_found.fetch_add(1, Ordering::Relaxed);
if self.config.stop_after.is_some_and(|s| prev + 1 == s.get()) { if self.config.count.is_some_and(|s| prev + 1 == s.get()) {
break; break;
} }
} }
@@ -133,7 +131,7 @@ impl Fingerprunk {
}) })
} }
fn worker_thread(&self, sender: mpsc::SyncSender<Message>) { fn worker_thread(&self, sender: &mpsc::SyncSender<Message>) {
let mut fingerprint_hex = String::with_capacity(20 * 2); let mut fingerprint_hex = String::with_capacity(20 * 2);
while !self.stop.load(Ordering::Relaxed) { while !self.stop.load(Ordering::Relaxed) {
@@ -159,35 +157,50 @@ impl Fingerprunk {
.expect("should check regex without error") .expect("should check regex without error")
} }
fn key_to_cert(&self, key: &SecretKey) -> anyhow::Result<Cert> { fn key_to_cert(&self, mut key: SecretKey) -> anyhow::Result<Cert> {
let sig = SignatureBuilder::new(SignatureType::DirectKey) let creation_time = SystemTime::now();
.set_hash_algo(HashAlgorithm::SHA512)
.set_preferred_hash_algorithms(vec![HashAlgorithm::SHA512, HashAlgorithm::SHA256])?
.set_preferred_symmetric_algorithms(vec![
SymmetricAlgorithm::AES256,
SymmetricAlgorithm::AES128,
])?;
let mut signer = key let mut signer = key
.clone() .clone()
.into_keypair() .into_keypair()
.expect("key should have a secret"); .expect("key should have a secret");
let sig = sig.sign_direct_key(&mut signer, key.parts_as_public())?;
let secret_key_packet = Packet::SecretKey({ // Sign keypair
let mut key = key.clone(); let key_sig = create_sig_builder(SignatureType::DirectKey, creation_time)?
.sign_direct_key(&mut signer, key.parts_as_public())?;
// Create certificate
let mut cert = Cert::try_from(Packet::SecretKey({
if let Some(ref password) = self.config.password { if let Some(ref password) = self.config.password {
let (k, mut secret) = key.take_secret(); let (k, mut secret) = key.take_secret();
secret.encrypt_in_place(&k, password)?; secret.encrypt_in_place(&k, password)?;
key = k.add_secret(secret).0; key = k.add_secret(secret).0;
} }
key key
}); }))?;
Cert::try_from(vec![secret_key_packet, Packet::from(sig)]) let mut packets = vec![Packet::from(key_sig)];
// Sign user IDs
let mut next_is_primary = true;
for user_id in self.config.userids.iter().cloned() {
let mut sig_builder =
create_sig_builder(SignatureType::PositiveCertification, creation_time)?;
if next_is_primary {
sig_builder = sig_builder.set_primary_userid(true)?;
next_is_primary = false;
}
let sig = user_id.bind(&mut signer, &cert, sig_builder)?;
packets.push(user_id.into());
packets.push(sig.into());
} }
fn serialize_cert(&self, cert: Cert, to: impl io::Write) -> anyhow::Result<()> { cert = cert.insert_packets(packets)?.0;
Ok(cert)
}
fn serialize_cert(&self, cert: &Cert, to: impl io::Write) -> anyhow::Result<()> {
let mut comments = cert.armor_headers(); let mut comments = cert.armor_headers();
comments.push(format!( comments.push(format!(
"Generated with Fingerprunk. Regex: {}", "Generated with Fingerprunk. Regex: {}",
@@ -256,3 +269,17 @@ impl Fingerprunk {
); );
} }
} }
fn create_sig_builder(
typ: SignatureType,
creation_time: SystemTime,
) -> Result<SignatureBuilder, anyhow::Error> {
SignatureBuilder::new(typ)
.set_signature_creation_time(creation_time)?
.set_hash_algo(HashAlgorithm::SHA512)
.set_preferred_hash_algorithms(vec![HashAlgorithm::SHA512, HashAlgorithm::SHA256])?
.set_preferred_symmetric_algorithms(vec![
SymmetricAlgorithm::AES256,
SymmetricAlgorithm::AES128,
])
}
+46 -11
View File
@@ -1,12 +1,13 @@
use std::{ use std::{
io::{self, IsTerminal}, io::{self, IsTerminal},
num::NonZeroU64, num::NonZero,
}; };
use anyhow::{Context as AnyhowContext, anyhow}; use anyhow::{Context, anyhow};
use clap::{ArgAction, Parser, ValueEnum}; use clap::{ArgAction, Parser, ValueEnum};
use fancy_regex::Regex; use fancy_regex::Regex;
use fingerprunk::Fingerprunk; use fingerprunk::Fingerprunk;
use sequoia_openpgp::packet::UserID;
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command(version, about, long_about = None)] #[command(version, about, long_about = None)]
@@ -30,15 +31,32 @@ struct Args {
status: StatusEnabled, status: StatusEnabled,
/// Stop once the specified number of matching keys has been found. /// Stop once the specified number of matching keys has been found.
#[arg(long)] #[arg(short = 'n', long, value_name = "NUM")]
stop_after: Option<NonZeroU64>, count: Option<NonZero<u64>>,
/// Prompt for a password and use it to encrypt found keys. /// Prompt for a password and use it to encrypt matching keys.
/// ///
/// By default, found keys are printed to stdout unencrypted. Use this if you actually plan to /// By default, found keys are printed to stdout unencrypted. Use this if you actually plan to
/// use generated keys. /// use generated keys.
#[arg(short, long, action = ArgAction::SetTrue)] #[arg(short, long, action = ArgAction::SetTrue)]
password: bool, password: bool,
/// Add the given user ID to matching keys.
#[arg(short, long = "userid")]
userid: Vec<UserID>,
/// Explicitly do not add user IDs to matching keys.
///
/// Disables the warning about importing keys without user IDs into GnuPG.
#[arg(long, conflicts_with = "userid", action = ArgAction::SetTrue)]
no_userid: bool,
/// Use the specified amount of worker threads.
///
/// If not specified, the amount of worker threads will be set to the amount of the machine's
/// available parallelism.
#[arg(long, value_name = "NUM")]
workers: Option<NonZero<usize>>,
} }
#[derive(ValueEnum, Clone, Copy, Debug, Default)] #[derive(ValueEnum, Clone, Copy, Debug, Default)]
@@ -62,16 +80,33 @@ impl StatusEnabled {
fn main() -> anyhow::Result<()> { fn main() -> anyhow::Result<()> {
let args = Args::parse(); let args = Args::parse();
let workers = match args.workers {
Some(workers) => workers,
None => std::thread::available_parallelism().context(
"unable to determine available parallelism, \
use `--workers <NUM>` to specify amount of worker threads",
)?,
};
if !args.no_userid && args.userid.is_empty() {
eprintln!(
"WARNING: No user ID was provided.\n\
You may experience problems importing generated keys into GnuPG.\n\
Use `--userid <USERID>` to add a user ID.\n"
);
}
let password = if args.password { let password = if args.password {
let password = rpassword::prompt_password( let password = rpassword::prompt_password(
"Enter password for encrypting found keys (leave empty for no encryption): ", "Enter password for encrypting found keys (leave empty for no encryption): ",
) )
.with_context(|| "Failed to prompt password")?; .context("Failed to prompt password")?;
if password.is_empty() { if password.is_empty() {
None None
} else { } else {
let password_retype = rpassword::prompt_password("Retype password: ") let password_retype = rpassword::prompt_password("Retype password: ")
.with_context(|| "Failed to prompt password retype")?; .context("Failed to prompt password retype")?;
if password_retype == password { if password_retype == password {
Some(password.into()) Some(password.into())
} else { } else {
@@ -85,11 +120,11 @@ fn main() -> anyhow::Result<()> {
let config = fingerprunk::Config { let config = fingerprunk::Config {
regex: args.regex, regex: args.regex,
status_enabled: args.status.evaluate(), status_enabled: args.status.evaluate(),
stop_after: args.stop_after, count: args.count,
password, password,
userids: args.userid,
workers,
}; };
Fingerprunk::new_from_config(config).run()?; Fingerprunk::new_from_config(config).run()
Ok(())
} }