├── .dockerignore ├── .editorconfig ├── .github └── workflows │ └── ci.yaml ├── .gitignore ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── Dockerfile ├── LICENSE ├── README.md ├── docker-target.sh ├── flake.lock ├── flake.nix └── src ├── add_key.rs ├── bin └── gfh-keygen.rs ├── config.rs ├── main.rs ├── util.rs └── yubikey.rs /.dockerignore: -------------------------------------------------------------------------------- 1 | /target 2 | /result 3 | /.github 4 | /.vscode 5 | Dockerfile -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | indent_size = 4 -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | push: 7 | branches: 8 | - main 9 | tags: 10 | - v* 11 | 12 | jobs: 13 | build-linux: 14 | strategy: 15 | matrix: 16 | platform: 17 | - name: x86_64 18 | target: amd64 19 | runs-on: ubuntu-latest 20 | - name: aarch64 21 | target: arm64 22 | runs-on: [self-hosted, linux, ARM64] 23 | 24 | runs-on: ${{ matrix.platform.runs-on }} 25 | 26 | steps: 27 | - uses: actions/checkout@v4 28 | with: 29 | fetch-depth: 0 30 | 31 | - uses: cachix/install-nix-action@v26 32 | with: 33 | github_access_token: ${{ secrets.GITHUB_TOKEN }} 34 | 35 | - run: nix build 36 | 37 | - name: Upload ${{ matrix.platform.name }} 38 | uses: actions/upload-artifact@v4 39 | with: 40 | name: gfh-linux-${{ matrix.platform.name }} 41 | path: | 42 | ./result/bin/gfh 43 | ./result/bin/gfh-keygen 44 | 45 | build-macos: 46 | runs-on: macos-11 47 | strategy: 48 | matrix: 49 | target: 50 | - x86_64 51 | - aarch64 52 | steps: 53 | - uses: actions/checkout@v4 54 | 55 | - name: Install target 56 | uses: actions-rust-lang/setup-rust-toolchain@v1 57 | with: 58 | toolchain: stable-apple-darwin 59 | target: ${{ matrix.target }}-apple-darwin 60 | 61 | - name: Build 62 | run: cargo build --release --target ${{ matrix.target }}-apple-darwin 63 | 64 | - uses: actions/upload-artifact@v4 65 | with: 66 | name: gfh-macos-${{ matrix.target }} 67 | path: | 68 | target/${{ matrix.target }}-apple-darwin/release/gfh 69 | target/${{ matrix.target }}-apple-darwin/release/gfh-keygen 70 | 71 | build-windows: 72 | runs-on: windows-2022 73 | steps: 74 | - uses: actions/checkout@v4 75 | 76 | - name: Install target 77 | uses: actions-rust-lang/setup-rust-toolchain@v1 78 | with: 79 | toolchain: stable-x86_64-pc-windows-msvc 80 | target: x86_64-pc-windows-msvc 81 | 82 | - name: Build 83 | run: cargo build --release --target x86_64-pc-windows-msvc 84 | 85 | - uses: actions/upload-artifact@v4 86 | with: 87 | name: "gfh-windows-x86_64" 88 | path: | 89 | target/x86_64-pc-windows-msvc/release/gfh.exe 90 | target/x86_64-pc-windows-msvc/release/gfh-keygen.exe 91 | 92 | # TODO: clippy lints & rustfmt 93 | 94 | create-release: 95 | runs-on: ubuntu-20.04 96 | if: startsWith(github.ref, 'refs/tags/') 97 | needs: 98 | - build-linux 99 | - build-macos 100 | - build-windows 101 | steps: 102 | - uses: actions/checkout@v4 103 | - uses: actions/download-artifact@v4 104 | 105 | - name: Rename files 106 | run: | 107 | mkdir out && cd out 108 | 109 | declare -a arr=( 110 | "windows-x86_64" 111 | "macos-x86_64" 112 | "macos-aarch64" 113 | "linux-x86_64" 114 | "linux-aarch64" 115 | ) 116 | 117 | for target in "${arr[@]}" 118 | do 119 | inputfiles="../gfh-$target/*" 120 | 121 | if [[ "$target" == *windows* ]]; then 122 | filename="gfh-$target.zip" 123 | 7z -y a $filename $inputfiles 124 | else 125 | filename="gfh-$target.tar.gz" 126 | tar czf $filename $inputfiles 127 | fi 128 | 129 | sha256sum "$filename" >> "checksums.txt" 130 | done 131 | 132 | - name: Create draft release 133 | uses: softprops/action-gh-release@v2 134 | with: 135 | body: Update the description for the release! 136 | draft: true 137 | files: ./out/* 138 | 139 | # - name: Update Homebrew tap 140 | # uses: mislav/bump-homebrew-formula-action@v2 141 | # with: 142 | # formula-name: gfh 143 | # homebrew-tap: Ovyerus/homebrew-tap 144 | # env: 145 | # COMMITTER_TOKEN: ${{ secrets.TAP_COMMITTER_TOKEN }} 146 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /result 3 | .direnv 4 | .envrc -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to gfh will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0), 6 | and this project adheres to 7 | [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 8 | 9 | ## [0.1.0] - 2022-11-13 10 | 11 | Initial public release of gfh. 12 | 13 | [unreleased]: https://github.com/Ovyerus/gfh/compare/v0.1.0...HEAD 14 | [0.1.0]: https://github.com/Ovyerus/gfh/releases/tag/v0.1.0 15 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "aes" 7 | version = "0.8.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "433cfd6710c9986c576a25ca913c39d66a6474107b406f34f91d4a8923395241" 10 | dependencies = [ 11 | "cfg-if", 12 | "cipher", 13 | "cpufeatures", 14 | ] 15 | 16 | [[package]] 17 | name = "android_system_properties" 18 | version = "0.1.5" 19 | source = "registry+https://github.com/rust-lang/crates.io-index" 20 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 21 | dependencies = [ 22 | "libc", 23 | ] 24 | 25 | [[package]] 26 | name = "anyhow" 27 | version = "1.0.66" 28 | source = "registry+https://github.com/rust-lang/crates.io-index" 29 | checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" 30 | 31 | [[package]] 32 | name = "asn1-rs" 33 | version = "0.5.1" 34 | source = "registry+https://github.com/rust-lang/crates.io-index" 35 | checksum = "cf6690c370453db30743b373a60ba498fc0d6d83b11f4abfd87a84a075db5dd4" 36 | dependencies = [ 37 | "asn1-rs-derive", 38 | "asn1-rs-impl", 39 | "displaydoc", 40 | "nom", 41 | "num-traits", 42 | "rusticata-macros", 43 | "thiserror", 44 | "time 0.3.17", 45 | ] 46 | 47 | [[package]] 48 | name = "asn1-rs-derive" 49 | version = "0.4.0" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" 52 | dependencies = [ 53 | "proc-macro2", 54 | "quote", 55 | "syn", 56 | "synstructure", 57 | ] 58 | 59 | [[package]] 60 | name = "asn1-rs-impl" 61 | version = "0.1.0" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" 64 | dependencies = [ 65 | "proc-macro2", 66 | "quote", 67 | "syn", 68 | ] 69 | 70 | [[package]] 71 | name = "atty" 72 | version = "0.2.14" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 75 | dependencies = [ 76 | "hermit-abi", 77 | "libc", 78 | "winapi", 79 | ] 80 | 81 | [[package]] 82 | name = "autocfg" 83 | version = "1.1.0" 84 | source = "registry+https://github.com/rust-lang/crates.io-index" 85 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 86 | 87 | [[package]] 88 | name = "base16ct" 89 | version = "0.1.1" 90 | source = "registry+https://github.com/rust-lang/crates.io-index" 91 | checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" 92 | 93 | [[package]] 94 | name = "base64" 95 | version = "0.13.1" 96 | source = "registry+https://github.com/rust-lang/crates.io-index" 97 | checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" 98 | 99 | [[package]] 100 | name = "base64ct" 101 | version = "1.5.3" 102 | source = "registry+https://github.com/rust-lang/crates.io-index" 103 | checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" 104 | 105 | [[package]] 106 | name = "bitflags" 107 | version = "1.3.2" 108 | source = "registry+https://github.com/rust-lang/crates.io-index" 109 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 110 | 111 | [[package]] 112 | name = "block-buffer" 113 | version = "0.10.3" 114 | source = "registry+https://github.com/rust-lang/crates.io-index" 115 | checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" 116 | dependencies = [ 117 | "generic-array", 118 | ] 119 | 120 | [[package]] 121 | name = "block-padding" 122 | version = "0.3.2" 123 | source = "registry+https://github.com/rust-lang/crates.io-index" 124 | checksum = "0a90ec2df9600c28a01c56c4784c9207a96d2451833aeceb8cc97e4c9548bb78" 125 | dependencies = [ 126 | "generic-array", 127 | ] 128 | 129 | [[package]] 130 | name = "bumpalo" 131 | version = "3.11.1" 132 | source = "registry+https://github.com/rust-lang/crates.io-index" 133 | checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" 134 | 135 | [[package]] 136 | name = "byteorder" 137 | version = "1.4.3" 138 | source = "registry+https://github.com/rust-lang/crates.io-index" 139 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 140 | 141 | [[package]] 142 | name = "cbc" 143 | version = "0.1.2" 144 | source = "registry+https://github.com/rust-lang/crates.io-index" 145 | checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" 146 | dependencies = [ 147 | "cipher", 148 | ] 149 | 150 | [[package]] 151 | name = "cc" 152 | version = "1.0.74" 153 | source = "registry+https://github.com/rust-lang/crates.io-index" 154 | checksum = "581f5dba903aac52ea3feb5ec4810848460ee833876f1f9b0fdeab1f19091574" 155 | 156 | [[package]] 157 | name = "cfg-if" 158 | version = "1.0.0" 159 | source = "registry+https://github.com/rust-lang/crates.io-index" 160 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 161 | 162 | [[package]] 163 | name = "chrono" 164 | version = "0.4.22" 165 | source = "registry+https://github.com/rust-lang/crates.io-index" 166 | checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" 167 | dependencies = [ 168 | "iana-time-zone", 169 | "js-sys", 170 | "num-integer", 171 | "num-traits", 172 | "time 0.1.44", 173 | "wasm-bindgen", 174 | "winapi", 175 | ] 176 | 177 | [[package]] 178 | name = "cipher" 179 | version = "0.4.3" 180 | source = "registry+https://github.com/rust-lang/crates.io-index" 181 | checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e" 182 | dependencies = [ 183 | "crypto-common", 184 | "inout", 185 | ] 186 | 187 | [[package]] 188 | name = "clap" 189 | version = "4.0.19" 190 | source = "registry+https://github.com/rust-lang/crates.io-index" 191 | checksum = "8e67816e006b17427c9b4386915109b494fec2d929c63e3bd3561234cbf1bf1e" 192 | dependencies = [ 193 | "atty", 194 | "bitflags", 195 | "clap_derive", 196 | "clap_lex", 197 | "once_cell", 198 | "strsim", 199 | "termcolor", 200 | ] 201 | 202 | [[package]] 203 | name = "clap_derive" 204 | version = "4.0.18" 205 | source = "registry+https://github.com/rust-lang/crates.io-index" 206 | checksum = "16a1b0f6422af32d5da0c58e2703320f379216ee70198241c84173a8c5ac28f3" 207 | dependencies = [ 208 | "heck", 209 | "proc-macro-error", 210 | "proc-macro2", 211 | "quote", 212 | "syn", 213 | ] 214 | 215 | [[package]] 216 | name = "clap_lex" 217 | version = "0.3.0" 218 | source = "registry+https://github.com/rust-lang/crates.io-index" 219 | checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" 220 | dependencies = [ 221 | "os_str_bytes", 222 | ] 223 | 224 | [[package]] 225 | name = "codespan-reporting" 226 | version = "0.11.1" 227 | source = "registry+https://github.com/rust-lang/crates.io-index" 228 | checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" 229 | dependencies = [ 230 | "termcolor", 231 | "unicode-width", 232 | ] 233 | 234 | [[package]] 235 | name = "const-oid" 236 | version = "0.7.1" 237 | source = "registry+https://github.com/rust-lang/crates.io-index" 238 | checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" 239 | 240 | [[package]] 241 | name = "const-oid" 242 | version = "0.9.0" 243 | source = "registry+https://github.com/rust-lang/crates.io-index" 244 | checksum = "722e23542a15cea1f65d4a1419c4cfd7a26706c70871a13a04238ca3f40f1661" 245 | 246 | [[package]] 247 | name = "cookie-factory" 248 | version = "0.3.2" 249 | source = "registry+https://github.com/rust-lang/crates.io-index" 250 | checksum = "396de984970346b0d9e93d1415082923c679e5ae5c3ee3dcbd104f5610af126b" 251 | 252 | [[package]] 253 | name = "core-foundation-sys" 254 | version = "0.8.3" 255 | source = "registry+https://github.com/rust-lang/crates.io-index" 256 | checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" 257 | 258 | [[package]] 259 | name = "cpufeatures" 260 | version = "0.2.5" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" 263 | dependencies = [ 264 | "libc", 265 | ] 266 | 267 | [[package]] 268 | name = "crossterm" 269 | version = "0.25.0" 270 | source = "registry+https://github.com/rust-lang/crates.io-index" 271 | checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" 272 | dependencies = [ 273 | "bitflags", 274 | "crossterm_winapi", 275 | "libc", 276 | "mio", 277 | "parking_lot", 278 | "signal-hook", 279 | "signal-hook-mio", 280 | "winapi", 281 | ] 282 | 283 | [[package]] 284 | name = "crossterm_winapi" 285 | version = "0.9.0" 286 | source = "registry+https://github.com/rust-lang/crates.io-index" 287 | checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c" 288 | dependencies = [ 289 | "winapi", 290 | ] 291 | 292 | [[package]] 293 | name = "crypto-bigint" 294 | version = "0.3.2" 295 | source = "registry+https://github.com/rust-lang/crates.io-index" 296 | checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21" 297 | dependencies = [ 298 | "generic-array", 299 | "subtle", 300 | ] 301 | 302 | [[package]] 303 | name = "crypto-bigint" 304 | version = "0.4.9" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" 307 | dependencies = [ 308 | "generic-array", 309 | "rand_core", 310 | "subtle", 311 | "zeroize", 312 | ] 313 | 314 | [[package]] 315 | name = "crypto-common" 316 | version = "0.1.6" 317 | source = "registry+https://github.com/rust-lang/crates.io-index" 318 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 319 | dependencies = [ 320 | "generic-array", 321 | "typenum", 322 | ] 323 | 324 | [[package]] 325 | name = "ctap-hid-fido2" 326 | version = "3.4.2" 327 | source = "registry+https://github.com/rust-lang/crates.io-index" 328 | checksum = "43150cf02f8e7c3caa32d5704a908bcdbd31899f6b9cc11ad6e0e42c9b7280ac" 329 | dependencies = [ 330 | "aes", 331 | "anyhow", 332 | "base64", 333 | "byteorder", 334 | "cbc", 335 | "hex", 336 | "hidapi", 337 | "num", 338 | "pad", 339 | "ring", 340 | "serde", 341 | "serde_cbor", 342 | "strum", 343 | "strum_macros", 344 | "x509-parser", 345 | ] 346 | 347 | [[package]] 348 | name = "cxx" 349 | version = "1.0.80" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | checksum = "6b7d4e43b25d3c994662706a1d4fcfc32aaa6afd287502c111b237093bb23f3a" 352 | dependencies = [ 353 | "cc", 354 | "cxxbridge-flags", 355 | "cxxbridge-macro", 356 | "link-cplusplus", 357 | ] 358 | 359 | [[package]] 360 | name = "cxx-build" 361 | version = "1.0.80" 362 | source = "registry+https://github.com/rust-lang/crates.io-index" 363 | checksum = "84f8829ddc213e2c1368e51a2564c552b65a8cb6a28f31e576270ac81d5e5827" 364 | dependencies = [ 365 | "cc", 366 | "codespan-reporting", 367 | "once_cell", 368 | "proc-macro2", 369 | "quote", 370 | "scratch", 371 | "syn", 372 | ] 373 | 374 | [[package]] 375 | name = "cxxbridge-flags" 376 | version = "1.0.80" 377 | source = "registry+https://github.com/rust-lang/crates.io-index" 378 | checksum = "e72537424b474af1460806647c41d4b6d35d09ef7fe031c5c2fa5766047cc56a" 379 | 380 | [[package]] 381 | name = "cxxbridge-macro" 382 | version = "1.0.80" 383 | source = "registry+https://github.com/rust-lang/crates.io-index" 384 | checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7" 385 | dependencies = [ 386 | "proc-macro2", 387 | "quote", 388 | "syn", 389 | ] 390 | 391 | [[package]] 392 | name = "data-encoding" 393 | version = "2.3.2" 394 | source = "registry+https://github.com/rust-lang/crates.io-index" 395 | checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57" 396 | 397 | [[package]] 398 | name = "der" 399 | version = "0.5.1" 400 | source = "registry+https://github.com/rust-lang/crates.io-index" 401 | checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c" 402 | dependencies = [ 403 | "const-oid 0.7.1", 404 | "crypto-bigint 0.3.2", 405 | "pem-rfc7468 0.3.1", 406 | ] 407 | 408 | [[package]] 409 | name = "der" 410 | version = "0.6.0" 411 | source = "registry+https://github.com/rust-lang/crates.io-index" 412 | checksum = "13dd2ae565c0a381dde7fade45fce95984c568bdcb4700a4fdbe3175e0380b2f" 413 | dependencies = [ 414 | "const-oid 0.9.0", 415 | "pem-rfc7468 0.6.0", 416 | "zeroize", 417 | ] 418 | 419 | [[package]] 420 | name = "der-parser" 421 | version = "8.1.0" 422 | source = "registry+https://github.com/rust-lang/crates.io-index" 423 | checksum = "42d4bc9b0db0a0df9ae64634ac5bdefb7afcb534e182275ca0beadbe486701c1" 424 | dependencies = [ 425 | "asn1-rs", 426 | "displaydoc", 427 | "nom", 428 | "num-bigint", 429 | "num-traits", 430 | "rusticata-macros", 431 | ] 432 | 433 | [[package]] 434 | name = "des" 435 | version = "0.8.1" 436 | source = "registry+https://github.com/rust-lang/crates.io-index" 437 | checksum = "ffdd80ce8ce993de27e9f063a444a4d53ce8e8db4c1f00cc03af5ad5a9867a1e" 438 | dependencies = [ 439 | "cipher", 440 | ] 441 | 442 | [[package]] 443 | name = "digest" 444 | version = "0.10.5" 445 | source = "registry+https://github.com/rust-lang/crates.io-index" 446 | checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" 447 | dependencies = [ 448 | "block-buffer", 449 | "crypto-common", 450 | "subtle", 451 | ] 452 | 453 | [[package]] 454 | name = "dirs" 455 | version = "4.0.0" 456 | source = "registry+https://github.com/rust-lang/crates.io-index" 457 | checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" 458 | dependencies = [ 459 | "dirs-sys", 460 | ] 461 | 462 | [[package]] 463 | name = "dirs-sys" 464 | version = "0.3.7" 465 | source = "registry+https://github.com/rust-lang/crates.io-index" 466 | checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" 467 | dependencies = [ 468 | "libc", 469 | "redox_users", 470 | "winapi", 471 | ] 472 | 473 | [[package]] 474 | name = "displaydoc" 475 | version = "0.2.3" 476 | source = "registry+https://github.com/rust-lang/crates.io-index" 477 | checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886" 478 | dependencies = [ 479 | "proc-macro2", 480 | "quote", 481 | "syn", 482 | ] 483 | 484 | [[package]] 485 | name = "dyn-clone" 486 | version = "1.0.9" 487 | source = "registry+https://github.com/rust-lang/crates.io-index" 488 | checksum = "4f94fa09c2aeea5b8839e414b7b841bf429fd25b9c522116ac97ee87856d88b2" 489 | 490 | [[package]] 491 | name = "ecdsa" 492 | version = "0.14.8" 493 | source = "registry+https://github.com/rust-lang/crates.io-index" 494 | checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" 495 | dependencies = [ 496 | "der 0.6.0", 497 | "elliptic-curve", 498 | "rfc6979", 499 | "signature", 500 | ] 501 | 502 | [[package]] 503 | name = "elliptic-curve" 504 | version = "0.12.3" 505 | source = "registry+https://github.com/rust-lang/crates.io-index" 506 | checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" 507 | dependencies = [ 508 | "base16ct", 509 | "crypto-bigint 0.4.9", 510 | "der 0.6.0", 511 | "digest", 512 | "ff", 513 | "generic-array", 514 | "group", 515 | "hkdf", 516 | "pem-rfc7468 0.6.0", 517 | "pkcs8 0.9.0", 518 | "rand_core", 519 | "sec1", 520 | "subtle", 521 | "zeroize", 522 | ] 523 | 524 | [[package]] 525 | name = "ff" 526 | version = "0.12.1" 527 | source = "registry+https://github.com/rust-lang/crates.io-index" 528 | checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" 529 | dependencies = [ 530 | "rand_core", 531 | "subtle", 532 | ] 533 | 534 | [[package]] 535 | name = "generic-array" 536 | version = "0.14.6" 537 | source = "registry+https://github.com/rust-lang/crates.io-index" 538 | checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" 539 | dependencies = [ 540 | "typenum", 541 | "version_check", 542 | ] 543 | 544 | [[package]] 545 | name = "getrandom" 546 | version = "0.2.8" 547 | source = "registry+https://github.com/rust-lang/crates.io-index" 548 | checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" 549 | dependencies = [ 550 | "cfg-if", 551 | "libc", 552 | "wasi 0.11.0+wasi-snapshot-preview1", 553 | ] 554 | 555 | [[package]] 556 | name = "gfh" 557 | version = "0.0.4" 558 | dependencies = [ 559 | "anyhow", 560 | "clap", 561 | "ctap-hid-fido2", 562 | "inquire", 563 | "sha2", 564 | "shellexpand", 565 | "yubikey", 566 | ] 567 | 568 | [[package]] 569 | name = "group" 570 | version = "0.12.1" 571 | source = "registry+https://github.com/rust-lang/crates.io-index" 572 | checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" 573 | dependencies = [ 574 | "ff", 575 | "rand_core", 576 | "subtle", 577 | ] 578 | 579 | [[package]] 580 | name = "half" 581 | version = "1.8.2" 582 | source = "registry+https://github.com/rust-lang/crates.io-index" 583 | checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" 584 | 585 | [[package]] 586 | name = "heck" 587 | version = "0.4.0" 588 | source = "registry+https://github.com/rust-lang/crates.io-index" 589 | checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" 590 | 591 | [[package]] 592 | name = "hermit-abi" 593 | version = "0.1.19" 594 | source = "registry+https://github.com/rust-lang/crates.io-index" 595 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 596 | dependencies = [ 597 | "libc", 598 | ] 599 | 600 | [[package]] 601 | name = "hex" 602 | version = "0.4.3" 603 | source = "registry+https://github.com/rust-lang/crates.io-index" 604 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 605 | 606 | [[package]] 607 | name = "hidapi" 608 | version = "1.4.2" 609 | source = "registry+https://github.com/rust-lang/crates.io-index" 610 | checksum = "9d26e1151deaab68f34fbfd16d491a2a0170cf98d69d3efa23873b567a4199e1" 611 | dependencies = [ 612 | "cc", 613 | "libc", 614 | "pkg-config", 615 | ] 616 | 617 | [[package]] 618 | name = "hkdf" 619 | version = "0.12.3" 620 | source = "registry+https://github.com/rust-lang/crates.io-index" 621 | checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" 622 | dependencies = [ 623 | "hmac", 624 | ] 625 | 626 | [[package]] 627 | name = "hmac" 628 | version = "0.12.1" 629 | source = "registry+https://github.com/rust-lang/crates.io-index" 630 | checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" 631 | dependencies = [ 632 | "digest", 633 | ] 634 | 635 | [[package]] 636 | name = "iana-time-zone" 637 | version = "0.1.53" 638 | source = "registry+https://github.com/rust-lang/crates.io-index" 639 | checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" 640 | dependencies = [ 641 | "android_system_properties", 642 | "core-foundation-sys", 643 | "iana-time-zone-haiku", 644 | "js-sys", 645 | "wasm-bindgen", 646 | "winapi", 647 | ] 648 | 649 | [[package]] 650 | name = "iana-time-zone-haiku" 651 | version = "0.1.1" 652 | source = "registry+https://github.com/rust-lang/crates.io-index" 653 | checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" 654 | dependencies = [ 655 | "cxx", 656 | "cxx-build", 657 | ] 658 | 659 | [[package]] 660 | name = "inout" 661 | version = "0.1.3" 662 | source = "registry+https://github.com/rust-lang/crates.io-index" 663 | checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" 664 | dependencies = [ 665 | "block-padding", 666 | "generic-array", 667 | ] 668 | 669 | [[package]] 670 | name = "inquire" 671 | version = "0.5.2" 672 | source = "registry+https://github.com/rust-lang/crates.io-index" 673 | checksum = "e6055ce38cac9b10ac819ed4a509d92ccbc60808152c19ff9121c98198964272" 674 | dependencies = [ 675 | "bitflags", 676 | "crossterm", 677 | "dyn-clone", 678 | "lazy_static", 679 | "newline-converter", 680 | "thiserror", 681 | "unicode-segmentation", 682 | "unicode-width", 683 | ] 684 | 685 | [[package]] 686 | name = "itoa" 687 | version = "1.0.4" 688 | source = "registry+https://github.com/rust-lang/crates.io-index" 689 | checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" 690 | 691 | [[package]] 692 | name = "js-sys" 693 | version = "0.3.60" 694 | source = "registry+https://github.com/rust-lang/crates.io-index" 695 | checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" 696 | dependencies = [ 697 | "wasm-bindgen", 698 | ] 699 | 700 | [[package]] 701 | name = "lazy_static" 702 | version = "1.4.0" 703 | source = "registry+https://github.com/rust-lang/crates.io-index" 704 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 705 | dependencies = [ 706 | "spin", 707 | ] 708 | 709 | [[package]] 710 | name = "libc" 711 | version = "0.2.137" 712 | source = "registry+https://github.com/rust-lang/crates.io-index" 713 | checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" 714 | 715 | [[package]] 716 | name = "libm" 717 | version = "0.2.5" 718 | source = "registry+https://github.com/rust-lang/crates.io-index" 719 | checksum = "292a948cd991e376cf75541fe5b97a1081d713c618b4f1b9500f8844e49eb565" 720 | 721 | [[package]] 722 | name = "link-cplusplus" 723 | version = "1.0.7" 724 | source = "registry+https://github.com/rust-lang/crates.io-index" 725 | checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" 726 | dependencies = [ 727 | "cc", 728 | ] 729 | 730 | [[package]] 731 | name = "lock_api" 732 | version = "0.4.9" 733 | source = "registry+https://github.com/rust-lang/crates.io-index" 734 | checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" 735 | dependencies = [ 736 | "autocfg", 737 | "scopeguard", 738 | ] 739 | 740 | [[package]] 741 | name = "log" 742 | version = "0.4.17" 743 | source = "registry+https://github.com/rust-lang/crates.io-index" 744 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 745 | dependencies = [ 746 | "cfg-if", 747 | ] 748 | 749 | [[package]] 750 | name = "memchr" 751 | version = "2.5.0" 752 | source = "registry+https://github.com/rust-lang/crates.io-index" 753 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 754 | 755 | [[package]] 756 | name = "minimal-lexical" 757 | version = "0.2.1" 758 | source = "registry+https://github.com/rust-lang/crates.io-index" 759 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 760 | 761 | [[package]] 762 | name = "mio" 763 | version = "0.8.5" 764 | source = "registry+https://github.com/rust-lang/crates.io-index" 765 | checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" 766 | dependencies = [ 767 | "libc", 768 | "log", 769 | "wasi 0.11.0+wasi-snapshot-preview1", 770 | "windows-sys", 771 | ] 772 | 773 | [[package]] 774 | name = "newline-converter" 775 | version = "0.2.2" 776 | source = "registry+https://github.com/rust-lang/crates.io-index" 777 | checksum = "1f71d09d5c87634207f894c6b31b6a2b2c64ea3bdcf71bd5599fdbbe1600c00f" 778 | dependencies = [ 779 | "unicode-segmentation", 780 | ] 781 | 782 | [[package]] 783 | name = "nom" 784 | version = "7.1.1" 785 | source = "registry+https://github.com/rust-lang/crates.io-index" 786 | checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" 787 | dependencies = [ 788 | "memchr", 789 | "minimal-lexical", 790 | ] 791 | 792 | [[package]] 793 | name = "num" 794 | version = "0.4.0" 795 | source = "registry+https://github.com/rust-lang/crates.io-index" 796 | checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" 797 | dependencies = [ 798 | "num-bigint", 799 | "num-complex", 800 | "num-integer", 801 | "num-iter", 802 | "num-rational", 803 | "num-traits", 804 | ] 805 | 806 | [[package]] 807 | name = "num-bigint" 808 | version = "0.4.3" 809 | source = "registry+https://github.com/rust-lang/crates.io-index" 810 | checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" 811 | dependencies = [ 812 | "autocfg", 813 | "num-integer", 814 | "num-traits", 815 | ] 816 | 817 | [[package]] 818 | name = "num-bigint-dig" 819 | version = "0.8.1" 820 | source = "registry+https://github.com/rust-lang/crates.io-index" 821 | checksum = "566d173b2f9406afbc5510a90925d5a2cd80cae4605631f1212303df265de011" 822 | dependencies = [ 823 | "byteorder", 824 | "lazy_static", 825 | "libm", 826 | "num-integer", 827 | "num-iter", 828 | "num-traits", 829 | "rand", 830 | "serde", 831 | "smallvec", 832 | "zeroize", 833 | ] 834 | 835 | [[package]] 836 | name = "num-complex" 837 | version = "0.4.2" 838 | source = "registry+https://github.com/rust-lang/crates.io-index" 839 | checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19" 840 | dependencies = [ 841 | "num-traits", 842 | ] 843 | 844 | [[package]] 845 | name = "num-integer" 846 | version = "0.1.45" 847 | source = "registry+https://github.com/rust-lang/crates.io-index" 848 | checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" 849 | dependencies = [ 850 | "autocfg", 851 | "num-traits", 852 | ] 853 | 854 | [[package]] 855 | name = "num-iter" 856 | version = "0.1.43" 857 | source = "registry+https://github.com/rust-lang/crates.io-index" 858 | checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" 859 | dependencies = [ 860 | "autocfg", 861 | "num-integer", 862 | "num-traits", 863 | ] 864 | 865 | [[package]] 866 | name = "num-rational" 867 | version = "0.4.1" 868 | source = "registry+https://github.com/rust-lang/crates.io-index" 869 | checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" 870 | dependencies = [ 871 | "autocfg", 872 | "num-bigint", 873 | "num-integer", 874 | "num-traits", 875 | ] 876 | 877 | [[package]] 878 | name = "num-traits" 879 | version = "0.2.15" 880 | source = "registry+https://github.com/rust-lang/crates.io-index" 881 | checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" 882 | dependencies = [ 883 | "autocfg", 884 | "libm", 885 | ] 886 | 887 | [[package]] 888 | name = "oid-registry" 889 | version = "0.6.0" 890 | source = "registry+https://github.com/rust-lang/crates.io-index" 891 | checksum = "7d4bda43fd1b844cbc6e6e54b5444e2b1bc7838bce59ad205902cccbb26d6761" 892 | dependencies = [ 893 | "asn1-rs", 894 | ] 895 | 896 | [[package]] 897 | name = "once_cell" 898 | version = "1.16.0" 899 | source = "registry+https://github.com/rust-lang/crates.io-index" 900 | checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" 901 | 902 | [[package]] 903 | name = "os_str_bytes" 904 | version = "6.3.1" 905 | source = "registry+https://github.com/rust-lang/crates.io-index" 906 | checksum = "3baf96e39c5359d2eb0dd6ccb42c62b91d9678aa68160d261b9e0ccbf9e9dea9" 907 | 908 | [[package]] 909 | name = "p256" 910 | version = "0.11.1" 911 | source = "registry+https://github.com/rust-lang/crates.io-index" 912 | checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" 913 | dependencies = [ 914 | "ecdsa", 915 | "elliptic-curve", 916 | "sha2", 917 | ] 918 | 919 | [[package]] 920 | name = "p384" 921 | version = "0.11.2" 922 | source = "registry+https://github.com/rust-lang/crates.io-index" 923 | checksum = "dfc8c5bf642dde52bb9e87c0ecd8ca5a76faac2eeed98dedb7c717997e1080aa" 924 | dependencies = [ 925 | "ecdsa", 926 | "elliptic-curve", 927 | "sha2", 928 | ] 929 | 930 | [[package]] 931 | name = "pad" 932 | version = "0.1.6" 933 | source = "registry+https://github.com/rust-lang/crates.io-index" 934 | checksum = "d2ad9b889f1b12e0b9ee24db044b5129150d5eada288edc800f789928dc8c0e3" 935 | dependencies = [ 936 | "unicode-width", 937 | ] 938 | 939 | [[package]] 940 | name = "parking_lot" 941 | version = "0.12.1" 942 | source = "registry+https://github.com/rust-lang/crates.io-index" 943 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 944 | dependencies = [ 945 | "lock_api", 946 | "parking_lot_core", 947 | ] 948 | 949 | [[package]] 950 | name = "parking_lot_core" 951 | version = "0.9.4" 952 | source = "registry+https://github.com/rust-lang/crates.io-index" 953 | checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" 954 | dependencies = [ 955 | "cfg-if", 956 | "libc", 957 | "redox_syscall", 958 | "smallvec", 959 | "windows-sys", 960 | ] 961 | 962 | [[package]] 963 | name = "pbkdf2" 964 | version = "0.11.0" 965 | source = "registry+https://github.com/rust-lang/crates.io-index" 966 | checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" 967 | dependencies = [ 968 | "digest", 969 | ] 970 | 971 | [[package]] 972 | name = "pcsc" 973 | version = "2.7.0" 974 | source = "registry+https://github.com/rust-lang/crates.io-index" 975 | checksum = "7e29e4de78a433aeecd06fb5bd55a0f9fde11dc85a14c22d482972c7edc4fdc4" 976 | dependencies = [ 977 | "bitflags", 978 | "pcsc-sys", 979 | ] 980 | 981 | [[package]] 982 | name = "pcsc-sys" 983 | version = "1.2.0" 984 | source = "registry+https://github.com/rust-lang/crates.io-index" 985 | checksum = "e1b7bfecba2c0f1b5efb0e7caf7533ab1c295024165bcbb066231f60d33e23ea" 986 | dependencies = [ 987 | "pkg-config", 988 | ] 989 | 990 | [[package]] 991 | name = "pem-rfc7468" 992 | version = "0.3.1" 993 | source = "registry+https://github.com/rust-lang/crates.io-index" 994 | checksum = "01de5d978f34aa4b2296576379fcc416034702fd94117c56ffd8a1a767cefb30" 995 | dependencies = [ 996 | "base64ct", 997 | ] 998 | 999 | [[package]] 1000 | name = "pem-rfc7468" 1001 | version = "0.6.0" 1002 | source = "registry+https://github.com/rust-lang/crates.io-index" 1003 | checksum = "24d159833a9105500e0398934e205e0773f0b27529557134ecfc51c27646adac" 1004 | dependencies = [ 1005 | "base64ct", 1006 | ] 1007 | 1008 | [[package]] 1009 | name = "pkcs1" 1010 | version = "0.3.3" 1011 | source = "registry+https://github.com/rust-lang/crates.io-index" 1012 | checksum = "a78f66c04ccc83dd4486fd46c33896f4e17b24a7a3a6400dedc48ed0ddd72320" 1013 | dependencies = [ 1014 | "der 0.5.1", 1015 | "pkcs8 0.8.0", 1016 | "zeroize", 1017 | ] 1018 | 1019 | [[package]] 1020 | name = "pkcs8" 1021 | version = "0.8.0" 1022 | source = "registry+https://github.com/rust-lang/crates.io-index" 1023 | checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0" 1024 | dependencies = [ 1025 | "der 0.5.1", 1026 | "spki 0.5.4", 1027 | "zeroize", 1028 | ] 1029 | 1030 | [[package]] 1031 | name = "pkcs8" 1032 | version = "0.9.0" 1033 | source = "registry+https://github.com/rust-lang/crates.io-index" 1034 | checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" 1035 | dependencies = [ 1036 | "der 0.6.0", 1037 | "spki 0.6.0", 1038 | ] 1039 | 1040 | [[package]] 1041 | name = "pkg-config" 1042 | version = "0.3.26" 1043 | source = "registry+https://github.com/rust-lang/crates.io-index" 1044 | checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" 1045 | 1046 | [[package]] 1047 | name = "ppv-lite86" 1048 | version = "0.2.17" 1049 | source = "registry+https://github.com/rust-lang/crates.io-index" 1050 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" 1051 | 1052 | [[package]] 1053 | name = "proc-macro-error" 1054 | version = "1.0.4" 1055 | source = "registry+https://github.com/rust-lang/crates.io-index" 1056 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 1057 | dependencies = [ 1058 | "proc-macro-error-attr", 1059 | "proc-macro2", 1060 | "quote", 1061 | "syn", 1062 | "version_check", 1063 | ] 1064 | 1065 | [[package]] 1066 | name = "proc-macro-error-attr" 1067 | version = "1.0.4" 1068 | source = "registry+https://github.com/rust-lang/crates.io-index" 1069 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 1070 | dependencies = [ 1071 | "proc-macro2", 1072 | "quote", 1073 | "version_check", 1074 | ] 1075 | 1076 | [[package]] 1077 | name = "proc-macro2" 1078 | version = "1.0.47" 1079 | source = "registry+https://github.com/rust-lang/crates.io-index" 1080 | checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" 1081 | dependencies = [ 1082 | "unicode-ident", 1083 | ] 1084 | 1085 | [[package]] 1086 | name = "quote" 1087 | version = "1.0.21" 1088 | source = "registry+https://github.com/rust-lang/crates.io-index" 1089 | checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" 1090 | dependencies = [ 1091 | "proc-macro2", 1092 | ] 1093 | 1094 | [[package]] 1095 | name = "rand" 1096 | version = "0.8.5" 1097 | source = "registry+https://github.com/rust-lang/crates.io-index" 1098 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 1099 | dependencies = [ 1100 | "libc", 1101 | "rand_chacha", 1102 | "rand_core", 1103 | ] 1104 | 1105 | [[package]] 1106 | name = "rand_chacha" 1107 | version = "0.3.1" 1108 | source = "registry+https://github.com/rust-lang/crates.io-index" 1109 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 1110 | dependencies = [ 1111 | "ppv-lite86", 1112 | "rand_core", 1113 | ] 1114 | 1115 | [[package]] 1116 | name = "rand_core" 1117 | version = "0.6.4" 1118 | source = "registry+https://github.com/rust-lang/crates.io-index" 1119 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 1120 | dependencies = [ 1121 | "getrandom", 1122 | ] 1123 | 1124 | [[package]] 1125 | name = "redox_syscall" 1126 | version = "0.2.16" 1127 | source = "registry+https://github.com/rust-lang/crates.io-index" 1128 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 1129 | dependencies = [ 1130 | "bitflags", 1131 | ] 1132 | 1133 | [[package]] 1134 | name = "redox_users" 1135 | version = "0.4.3" 1136 | source = "registry+https://github.com/rust-lang/crates.io-index" 1137 | checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" 1138 | dependencies = [ 1139 | "getrandom", 1140 | "redox_syscall", 1141 | "thiserror", 1142 | ] 1143 | 1144 | [[package]] 1145 | name = "rfc6979" 1146 | version = "0.3.1" 1147 | source = "registry+https://github.com/rust-lang/crates.io-index" 1148 | checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" 1149 | dependencies = [ 1150 | "crypto-bigint 0.4.9", 1151 | "hmac", 1152 | "zeroize", 1153 | ] 1154 | 1155 | [[package]] 1156 | name = "ring" 1157 | version = "0.16.20" 1158 | source = "registry+https://github.com/rust-lang/crates.io-index" 1159 | checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" 1160 | dependencies = [ 1161 | "cc", 1162 | "libc", 1163 | "once_cell", 1164 | "spin", 1165 | "untrusted", 1166 | "web-sys", 1167 | "winapi", 1168 | ] 1169 | 1170 | [[package]] 1171 | name = "rsa" 1172 | version = "0.6.1" 1173 | source = "registry+https://github.com/rust-lang/crates.io-index" 1174 | checksum = "4cf22754c49613d2b3b119f0e5d46e34a2c628a937e3024b8762de4e7d8c710b" 1175 | dependencies = [ 1176 | "byteorder", 1177 | "digest", 1178 | "num-bigint-dig", 1179 | "num-integer", 1180 | "num-iter", 1181 | "num-traits", 1182 | "pkcs1", 1183 | "pkcs8 0.8.0", 1184 | "rand_core", 1185 | "smallvec", 1186 | "subtle", 1187 | "zeroize", 1188 | ] 1189 | 1190 | [[package]] 1191 | name = "rusticata-macros" 1192 | version = "4.1.0" 1193 | source = "registry+https://github.com/rust-lang/crates.io-index" 1194 | checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" 1195 | dependencies = [ 1196 | "nom", 1197 | ] 1198 | 1199 | [[package]] 1200 | name = "rustversion" 1201 | version = "1.0.9" 1202 | source = "registry+https://github.com/rust-lang/crates.io-index" 1203 | checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" 1204 | 1205 | [[package]] 1206 | name = "scopeguard" 1207 | version = "1.1.0" 1208 | source = "registry+https://github.com/rust-lang/crates.io-index" 1209 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 1210 | 1211 | [[package]] 1212 | name = "scratch" 1213 | version = "1.0.2" 1214 | source = "registry+https://github.com/rust-lang/crates.io-index" 1215 | checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" 1216 | 1217 | [[package]] 1218 | name = "sec1" 1219 | version = "0.3.0" 1220 | source = "registry+https://github.com/rust-lang/crates.io-index" 1221 | checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" 1222 | dependencies = [ 1223 | "base16ct", 1224 | "der 0.6.0", 1225 | "generic-array", 1226 | "pkcs8 0.9.0", 1227 | "subtle", 1228 | "zeroize", 1229 | ] 1230 | 1231 | [[package]] 1232 | name = "secrecy" 1233 | version = "0.8.0" 1234 | source = "registry+https://github.com/rust-lang/crates.io-index" 1235 | checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" 1236 | dependencies = [ 1237 | "zeroize", 1238 | ] 1239 | 1240 | [[package]] 1241 | name = "serde" 1242 | version = "1.0.147" 1243 | source = "registry+https://github.com/rust-lang/crates.io-index" 1244 | checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" 1245 | 1246 | [[package]] 1247 | name = "serde_cbor" 1248 | version = "0.11.2" 1249 | source = "registry+https://github.com/rust-lang/crates.io-index" 1250 | checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" 1251 | dependencies = [ 1252 | "half", 1253 | "serde", 1254 | ] 1255 | 1256 | [[package]] 1257 | name = "sha1" 1258 | version = "0.10.5" 1259 | source = "registry+https://github.com/rust-lang/crates.io-index" 1260 | checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" 1261 | dependencies = [ 1262 | "cfg-if", 1263 | "cpufeatures", 1264 | "digest", 1265 | ] 1266 | 1267 | [[package]] 1268 | name = "sha2" 1269 | version = "0.10.6" 1270 | source = "registry+https://github.com/rust-lang/crates.io-index" 1271 | checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" 1272 | dependencies = [ 1273 | "cfg-if", 1274 | "cpufeatures", 1275 | "digest", 1276 | ] 1277 | 1278 | [[package]] 1279 | name = "shellexpand" 1280 | version = "2.1.2" 1281 | source = "registry+https://github.com/rust-lang/crates.io-index" 1282 | checksum = "7ccc8076840c4da029af4f87e4e8daeb0fca6b87bbb02e10cb60b791450e11e4" 1283 | dependencies = [ 1284 | "dirs", 1285 | ] 1286 | 1287 | [[package]] 1288 | name = "signal-hook" 1289 | version = "0.3.14" 1290 | source = "registry+https://github.com/rust-lang/crates.io-index" 1291 | checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" 1292 | dependencies = [ 1293 | "libc", 1294 | "signal-hook-registry", 1295 | ] 1296 | 1297 | [[package]] 1298 | name = "signal-hook-mio" 1299 | version = "0.2.3" 1300 | source = "registry+https://github.com/rust-lang/crates.io-index" 1301 | checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" 1302 | dependencies = [ 1303 | "libc", 1304 | "mio", 1305 | "signal-hook", 1306 | ] 1307 | 1308 | [[package]] 1309 | name = "signal-hook-registry" 1310 | version = "1.4.0" 1311 | source = "registry+https://github.com/rust-lang/crates.io-index" 1312 | checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" 1313 | dependencies = [ 1314 | "libc", 1315 | ] 1316 | 1317 | [[package]] 1318 | name = "signature" 1319 | version = "1.6.4" 1320 | source = "registry+https://github.com/rust-lang/crates.io-index" 1321 | checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" 1322 | dependencies = [ 1323 | "digest", 1324 | "rand_core", 1325 | ] 1326 | 1327 | [[package]] 1328 | name = "smallvec" 1329 | version = "1.10.0" 1330 | source = "registry+https://github.com/rust-lang/crates.io-index" 1331 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" 1332 | 1333 | [[package]] 1334 | name = "spin" 1335 | version = "0.5.2" 1336 | source = "registry+https://github.com/rust-lang/crates.io-index" 1337 | checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" 1338 | 1339 | [[package]] 1340 | name = "spki" 1341 | version = "0.5.4" 1342 | source = "registry+https://github.com/rust-lang/crates.io-index" 1343 | checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27" 1344 | dependencies = [ 1345 | "base64ct", 1346 | "der 0.5.1", 1347 | ] 1348 | 1349 | [[package]] 1350 | name = "spki" 1351 | version = "0.6.0" 1352 | source = "registry+https://github.com/rust-lang/crates.io-index" 1353 | checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" 1354 | dependencies = [ 1355 | "base64ct", 1356 | "der 0.6.0", 1357 | ] 1358 | 1359 | [[package]] 1360 | name = "strsim" 1361 | version = "0.10.0" 1362 | source = "registry+https://github.com/rust-lang/crates.io-index" 1363 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 1364 | 1365 | [[package]] 1366 | name = "strum" 1367 | version = "0.24.1" 1368 | source = "registry+https://github.com/rust-lang/crates.io-index" 1369 | checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" 1370 | 1371 | [[package]] 1372 | name = "strum_macros" 1373 | version = "0.24.3" 1374 | source = "registry+https://github.com/rust-lang/crates.io-index" 1375 | checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" 1376 | dependencies = [ 1377 | "heck", 1378 | "proc-macro2", 1379 | "quote", 1380 | "rustversion", 1381 | "syn", 1382 | ] 1383 | 1384 | [[package]] 1385 | name = "subtle" 1386 | version = "2.4.1" 1387 | source = "registry+https://github.com/rust-lang/crates.io-index" 1388 | checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" 1389 | 1390 | [[package]] 1391 | name = "subtle-encoding" 1392 | version = "0.5.1" 1393 | source = "registry+https://github.com/rust-lang/crates.io-index" 1394 | checksum = "7dcb1ed7b8330c5eed5441052651dd7a12c75e2ed88f2ec024ae1fa3a5e59945" 1395 | dependencies = [ 1396 | "zeroize", 1397 | ] 1398 | 1399 | [[package]] 1400 | name = "syn" 1401 | version = "1.0.103" 1402 | source = "registry+https://github.com/rust-lang/crates.io-index" 1403 | checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" 1404 | dependencies = [ 1405 | "proc-macro2", 1406 | "quote", 1407 | "unicode-ident", 1408 | ] 1409 | 1410 | [[package]] 1411 | name = "synstructure" 1412 | version = "0.12.6" 1413 | source = "registry+https://github.com/rust-lang/crates.io-index" 1414 | checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" 1415 | dependencies = [ 1416 | "proc-macro2", 1417 | "quote", 1418 | "syn", 1419 | "unicode-xid", 1420 | ] 1421 | 1422 | [[package]] 1423 | name = "termcolor" 1424 | version = "1.1.3" 1425 | source = "registry+https://github.com/rust-lang/crates.io-index" 1426 | checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" 1427 | dependencies = [ 1428 | "winapi-util", 1429 | ] 1430 | 1431 | [[package]] 1432 | name = "thiserror" 1433 | version = "1.0.37" 1434 | source = "registry+https://github.com/rust-lang/crates.io-index" 1435 | checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" 1436 | dependencies = [ 1437 | "thiserror-impl", 1438 | ] 1439 | 1440 | [[package]] 1441 | name = "thiserror-impl" 1442 | version = "1.0.37" 1443 | source = "registry+https://github.com/rust-lang/crates.io-index" 1444 | checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" 1445 | dependencies = [ 1446 | "proc-macro2", 1447 | "quote", 1448 | "syn", 1449 | ] 1450 | 1451 | [[package]] 1452 | name = "time" 1453 | version = "0.1.44" 1454 | source = "registry+https://github.com/rust-lang/crates.io-index" 1455 | checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" 1456 | dependencies = [ 1457 | "libc", 1458 | "wasi 0.10.0+wasi-snapshot-preview1", 1459 | "winapi", 1460 | ] 1461 | 1462 | [[package]] 1463 | name = "time" 1464 | version = "0.3.17" 1465 | source = "registry+https://github.com/rust-lang/crates.io-index" 1466 | checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" 1467 | dependencies = [ 1468 | "itoa", 1469 | "serde", 1470 | "time-core", 1471 | "time-macros", 1472 | ] 1473 | 1474 | [[package]] 1475 | name = "time-core" 1476 | version = "0.1.0" 1477 | source = "registry+https://github.com/rust-lang/crates.io-index" 1478 | checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" 1479 | 1480 | [[package]] 1481 | name = "time-macros" 1482 | version = "0.2.6" 1483 | source = "registry+https://github.com/rust-lang/crates.io-index" 1484 | checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" 1485 | dependencies = [ 1486 | "time-core", 1487 | ] 1488 | 1489 | [[package]] 1490 | name = "typenum" 1491 | version = "1.15.0" 1492 | source = "registry+https://github.com/rust-lang/crates.io-index" 1493 | checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" 1494 | 1495 | [[package]] 1496 | name = "unicode-ident" 1497 | version = "1.0.5" 1498 | source = "registry+https://github.com/rust-lang/crates.io-index" 1499 | checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" 1500 | 1501 | [[package]] 1502 | name = "unicode-segmentation" 1503 | version = "1.10.0" 1504 | source = "registry+https://github.com/rust-lang/crates.io-index" 1505 | checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" 1506 | 1507 | [[package]] 1508 | name = "unicode-width" 1509 | version = "0.1.10" 1510 | source = "registry+https://github.com/rust-lang/crates.io-index" 1511 | checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" 1512 | 1513 | [[package]] 1514 | name = "unicode-xid" 1515 | version = "0.2.4" 1516 | source = "registry+https://github.com/rust-lang/crates.io-index" 1517 | checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" 1518 | 1519 | [[package]] 1520 | name = "untrusted" 1521 | version = "0.7.1" 1522 | source = "registry+https://github.com/rust-lang/crates.io-index" 1523 | checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" 1524 | 1525 | [[package]] 1526 | name = "uuid" 1527 | version = "1.2.1" 1528 | source = "registry+https://github.com/rust-lang/crates.io-index" 1529 | checksum = "feb41e78f93363bb2df8b0e86a2ca30eed7806ea16ea0c790d757cf93f79be83" 1530 | dependencies = [ 1531 | "getrandom", 1532 | ] 1533 | 1534 | [[package]] 1535 | name = "version_check" 1536 | version = "0.9.4" 1537 | source = "registry+https://github.com/rust-lang/crates.io-index" 1538 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 1539 | 1540 | [[package]] 1541 | name = "wasi" 1542 | version = "0.10.0+wasi-snapshot-preview1" 1543 | source = "registry+https://github.com/rust-lang/crates.io-index" 1544 | checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" 1545 | 1546 | [[package]] 1547 | name = "wasi" 1548 | version = "0.11.0+wasi-snapshot-preview1" 1549 | source = "registry+https://github.com/rust-lang/crates.io-index" 1550 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1551 | 1552 | [[package]] 1553 | name = "wasm-bindgen" 1554 | version = "0.2.83" 1555 | source = "registry+https://github.com/rust-lang/crates.io-index" 1556 | checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" 1557 | dependencies = [ 1558 | "cfg-if", 1559 | "wasm-bindgen-macro", 1560 | ] 1561 | 1562 | [[package]] 1563 | name = "wasm-bindgen-backend" 1564 | version = "0.2.83" 1565 | source = "registry+https://github.com/rust-lang/crates.io-index" 1566 | checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" 1567 | dependencies = [ 1568 | "bumpalo", 1569 | "log", 1570 | "once_cell", 1571 | "proc-macro2", 1572 | "quote", 1573 | "syn", 1574 | "wasm-bindgen-shared", 1575 | ] 1576 | 1577 | [[package]] 1578 | name = "wasm-bindgen-macro" 1579 | version = "0.2.83" 1580 | source = "registry+https://github.com/rust-lang/crates.io-index" 1581 | checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" 1582 | dependencies = [ 1583 | "quote", 1584 | "wasm-bindgen-macro-support", 1585 | ] 1586 | 1587 | [[package]] 1588 | name = "wasm-bindgen-macro-support" 1589 | version = "0.2.83" 1590 | source = "registry+https://github.com/rust-lang/crates.io-index" 1591 | checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" 1592 | dependencies = [ 1593 | "proc-macro2", 1594 | "quote", 1595 | "syn", 1596 | "wasm-bindgen-backend", 1597 | "wasm-bindgen-shared", 1598 | ] 1599 | 1600 | [[package]] 1601 | name = "wasm-bindgen-shared" 1602 | version = "0.2.83" 1603 | source = "registry+https://github.com/rust-lang/crates.io-index" 1604 | checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" 1605 | 1606 | [[package]] 1607 | name = "web-sys" 1608 | version = "0.3.60" 1609 | source = "registry+https://github.com/rust-lang/crates.io-index" 1610 | checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" 1611 | dependencies = [ 1612 | "js-sys", 1613 | "wasm-bindgen", 1614 | ] 1615 | 1616 | [[package]] 1617 | name = "winapi" 1618 | version = "0.3.9" 1619 | source = "registry+https://github.com/rust-lang/crates.io-index" 1620 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1621 | dependencies = [ 1622 | "winapi-i686-pc-windows-gnu", 1623 | "winapi-x86_64-pc-windows-gnu", 1624 | ] 1625 | 1626 | [[package]] 1627 | name = "winapi-i686-pc-windows-gnu" 1628 | version = "0.4.0" 1629 | source = "registry+https://github.com/rust-lang/crates.io-index" 1630 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1631 | 1632 | [[package]] 1633 | name = "winapi-util" 1634 | version = "0.1.5" 1635 | source = "registry+https://github.com/rust-lang/crates.io-index" 1636 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 1637 | dependencies = [ 1638 | "winapi", 1639 | ] 1640 | 1641 | [[package]] 1642 | name = "winapi-x86_64-pc-windows-gnu" 1643 | version = "0.4.0" 1644 | source = "registry+https://github.com/rust-lang/crates.io-index" 1645 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1646 | 1647 | [[package]] 1648 | name = "windows-sys" 1649 | version = "0.42.0" 1650 | source = "registry+https://github.com/rust-lang/crates.io-index" 1651 | checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" 1652 | dependencies = [ 1653 | "windows_aarch64_gnullvm", 1654 | "windows_aarch64_msvc", 1655 | "windows_i686_gnu", 1656 | "windows_i686_msvc", 1657 | "windows_x86_64_gnu", 1658 | "windows_x86_64_gnullvm", 1659 | "windows_x86_64_msvc", 1660 | ] 1661 | 1662 | [[package]] 1663 | name = "windows_aarch64_gnullvm" 1664 | version = "0.42.0" 1665 | source = "registry+https://github.com/rust-lang/crates.io-index" 1666 | checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" 1667 | 1668 | [[package]] 1669 | name = "windows_aarch64_msvc" 1670 | version = "0.42.0" 1671 | source = "registry+https://github.com/rust-lang/crates.io-index" 1672 | checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" 1673 | 1674 | [[package]] 1675 | name = "windows_i686_gnu" 1676 | version = "0.42.0" 1677 | source = "registry+https://github.com/rust-lang/crates.io-index" 1678 | checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" 1679 | 1680 | [[package]] 1681 | name = "windows_i686_msvc" 1682 | version = "0.42.0" 1683 | source = "registry+https://github.com/rust-lang/crates.io-index" 1684 | checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" 1685 | 1686 | [[package]] 1687 | name = "windows_x86_64_gnu" 1688 | version = "0.42.0" 1689 | source = "registry+https://github.com/rust-lang/crates.io-index" 1690 | checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" 1691 | 1692 | [[package]] 1693 | name = "windows_x86_64_gnullvm" 1694 | version = "0.42.0" 1695 | source = "registry+https://github.com/rust-lang/crates.io-index" 1696 | checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" 1697 | 1698 | [[package]] 1699 | name = "windows_x86_64_msvc" 1700 | version = "0.42.0" 1701 | source = "registry+https://github.com/rust-lang/crates.io-index" 1702 | checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" 1703 | 1704 | [[package]] 1705 | name = "x509" 1706 | version = "0.2.0" 1707 | source = "registry+https://github.com/rust-lang/crates.io-index" 1708 | checksum = "ca3cec94c3999f31341553f358ef55f65fc031291a022cd42ec0ce7219560c76" 1709 | dependencies = [ 1710 | "chrono", 1711 | "cookie-factory", 1712 | ] 1713 | 1714 | [[package]] 1715 | name = "x509-parser" 1716 | version = "0.14.0" 1717 | source = "registry+https://github.com/rust-lang/crates.io-index" 1718 | checksum = "e0ecbeb7b67ce215e40e3cc7f2ff902f94a223acf44995934763467e7b1febc8" 1719 | dependencies = [ 1720 | "asn1-rs", 1721 | "base64", 1722 | "data-encoding", 1723 | "der-parser", 1724 | "lazy_static", 1725 | "nom", 1726 | "oid-registry", 1727 | "rusticata-macros", 1728 | "thiserror", 1729 | "time 0.3.17", 1730 | ] 1731 | 1732 | [[package]] 1733 | name = "yubikey" 1734 | version = "0.6.0" 1735 | source = "registry+https://github.com/rust-lang/crates.io-index" 1736 | checksum = "350b1730eb4a5734a5167bda0d400f2a28d05a9e69003c3f37163bb240f2d9c6" 1737 | dependencies = [ 1738 | "chrono", 1739 | "cookie-factory", 1740 | "der-parser", 1741 | "des", 1742 | "elliptic-curve", 1743 | "hmac", 1744 | "log", 1745 | "nom", 1746 | "num-bigint-dig", 1747 | "num-integer", 1748 | "num-traits", 1749 | "p256", 1750 | "p384", 1751 | "pbkdf2", 1752 | "pcsc", 1753 | "rand_core", 1754 | "rsa", 1755 | "secrecy", 1756 | "sha1", 1757 | "sha2", 1758 | "subtle", 1759 | "subtle-encoding", 1760 | "uuid", 1761 | "x509", 1762 | "x509-parser", 1763 | "zeroize", 1764 | ] 1765 | 1766 | [[package]] 1767 | name = "zeroize" 1768 | version = "1.5.7" 1769 | source = "registry+https://github.com/rust-lang/crates.io-index" 1770 | checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" 1771 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gfh" 3 | version = "0.0.4" 4 | edition = "2021" 5 | description = "Git FIDO helper - use multiple FIDO keys to sign Git commits" 6 | authors = ["Michael Mitchell "] 7 | license = "MIT" 8 | readme = "README.md" 9 | homepage = "https://github.com/Ovyerus/gfh" 10 | repository = "https://github.com/Ovyerus/gfh" 11 | keywords = ["cli", "fido", "git", "ssh", "signing"] 12 | categories = ["command-line-utilities", "development-tools"] 13 | 14 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 15 | 16 | [profile.release] 17 | strip = true 18 | 19 | [dependencies] 20 | anyhow = "1.0" 21 | clap = { version = "4.0.19", features = ["derive"] } 22 | ctap-hid-fido2 = "3.4.2" 23 | inquire = "0.5.2" 24 | # Uncomment once we actually need osshkeys. Or port over the key conversion stuff manually. 25 | # openssl = { version = "0.10.42", features = ["vendored"] } 26 | # osshkeys = "0.6.2" 27 | sha2 = "0.10.6" 28 | shellexpand = "2.1.2" 29 | yubikey_api = { package = "yubikey", version = "0.6.0" } 30 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rust:1.68-alpine3.17 AS builder 2 | 3 | ARG TARGETARCH 4 | ENV TARGETARCH=${TARGETARCH} 5 | WORKDIR /build 6 | 7 | COPY docker-target.sh . 8 | 9 | ENV CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse 10 | ENV RUST_BACKTRACE=1 11 | 12 | RUN apk add musl-dev git perl make gcc eudev-dev eudev pcsc-lite-dev pcsc-lite linux-headers 13 | RUN ln -s "/usr/bin/$(sh ./docker-target.sh)-alpine-linux-musl-gcc" /usr/bin/musl-gcc 14 | RUN rustup target add "$(sh ./docker-target.sh)-unknown-linux-musl" 15 | 16 | COPY . . 17 | 18 | # ENV RUSTFLAGS=-Clinker=rust-lld 19 | RUN cargo build --release --target "$(sh ./docker-target.sh)-unknown-linux-musl" 20 | 21 | FROM alpine:3.17 22 | 23 | WORKDIR /gfh 24 | RUN apk add dumb-init 25 | 26 | COPY --from=builder /build/target/*-unknown-linux-musl/release/gfh . 27 | COPY --from=builder /build/target/*-unknown-linux-musl/release/gfh-keygen . 28 | 29 | ENTRYPOINT [ "dumb-init", "--" ] 30 | CMD [ "./gfh", "--version" ] 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2022 Ovyerus 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so, 8 | subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gfh 2 | 3 | > Git FIDO helper, or God Fucking Help me. 4 | 5 | gfh is a tool for helping you sign your commits in Git with resident SSH keys 6 | stored on multiple FIDO devices. 7 | 8 |

9 | Getting Started 10 | - 11 | Usage 12 | - 13 | Installation 14 |

15 | 16 | **NB:** Currently this project has only been tested with the YubiKey 5C NFC. Any 17 | FIDO2 certified device _should_ be compatible, but please let me know if you 18 | encountered any issues with particular devices, or also if it works fine so that 19 | I can have a running list of all keys that are verified working. 20 | 21 | ## Getting Started 22 | 23 | Before you get started with gfh, you'll need to make sure that you already have 24 | a resident SSH key on your FIDO key(s). The simplest way to do this is via 25 | `ssh-keygen -t ed25519-sk -O resident`, but there are better guides online if 26 | you need some different stuff. 27 | 28 | If you don't own multiple FIDO keys/only use one resident SSH key, then you more 29 | than likely do not need to use gfh. This tool has a very niche use case due to 30 | Git not supporting multiple `signingkey`s. If you only use one resident SSH key 31 | for signing your commits, you can just use that config option without gfh. 32 | 33 | ### Caveats 34 | 35 | I've only personally validated gfh as working on macOS, some friends of mine has 36 | had it work fine on Windows (10 & 11), but I haven't had any luck with that 37 | myself. 38 | 39 | 45 | 46 | On Linux, gfh seems to fail with 47 | `warning: gpg.ssh.defaultKeyCommand succeeded but returned no keys: key::...`, 48 | which makes no sense, because the format it expects is evidently there. A friend 49 | of mine has said that running `` eval `ssh-agent` `` (or `eval (ssh-agent -c)` 50 | as the Fish equivalent) solved the issue for them, however I haven't had any 51 | luck with this personally so YMMV. 52 | 53 | If you ever find out a consistent workaround for these problems, please let me 54 | know and I'll try and see if I can reproduce them. 55 | 56 | ## Usage 57 | 58 | The simplest way to add your keys to gfh is via `gfh -a`. This will prompt you 59 | to select the FIDO key to use, as well as the path to the public key (or private 60 | key) to use with it (this must be a resident key that you generated for that 61 | particular FIDO device). 62 | 63 | If you prefer, you can edit the config manually by creating a file at 64 | `~/.config/gfh/keys` with the following format: 65 | 66 | ``` 67 | serial::~/.ssh/id_ed25519_sk 68 | serial::~/.ssh/id_ecdsa_sk 69 | ``` 70 | 71 | (Blank lines & lines starting with `#` will be ignored, but won't be retained if 72 | you use `gfh -a`) 73 | 74 | After importing your keys to gfh, run the following commands to set up SSH 75 | signing with Git: 76 | 77 | ```sh 78 | git config --global commit.gpgsign true 79 | git config --global tag.gpgsign true 80 | git config --global gpg.format "ssh" 81 | git config --global gpg.ssh.program "gfh-keygen" 82 | git config --global gpg.ssh.defaultKeyCommand "gfh" 83 | ``` 84 | 85 | If you're on Windows, change the last two commands to set `gfh-keygen.exe` and 86 | `gfh.exe` respectively. 87 | 88 | (You shouldn't set `user.signingkey` because gfh will handle that for you 89 | automatically.) 90 | 91 | If all goes according to plan, you should be able to create a new commit or tag 92 | with your FIDO key plugged in, and Git will correctly prompt you to sign with 93 | it. 94 | 95 | ## Installation 96 | 97 | ### Releases are currently pending fixed CI builds, in the meantime you can install via Cargo just fine. 98 | 99 | Static binary builds of gfh are available on our 100 | [releases page](https://github.com/Ovyerus/gfh/releases) for Windows (x86), Mac 101 | (ARM & x86), and Linux (various architectures). 102 | 103 | ### Homebrew 104 | 105 | `brew install ovyerus/tap/gfh` 106 | 107 | ### Scoop 108 | 109 | ``` 110 | scoop bucket add ovyerus https://github.com/Ovyerus/bucket 111 | scoop install gfh 112 | ``` 113 | 114 | ### AUR (unofficial) 115 | 116 | An unofficial AUR package from [wale](https://github.com/wale) is available at 117 | https://aur.archlinux.org/packages/gfh. You can use your favourite AUR helper, 118 | or you can install it manually like so: 119 | 120 | ``` 121 | git clone https://aur.archlinux.org/gfh.git 122 | cd gfh 123 | makepkg -fsri 124 | ``` 125 | 126 | ### Crate 127 | 128 | `cargo install gfh` 129 | 130 | ### From source 131 | 132 | Pull this repository and run `cargo build --release`, and look for the `gfh` and 133 | `gfh-keygen` binaries in `./target/release/`. 134 | 135 | When building from source or from Cargo, on Linux you will need the following 136 | packages: `pkg-config libpcsclite-dev libudev-dev` 137 | 138 | ## License 139 | 140 | This program is licensed under the MIT license (see [LICENSE](./LICENSE) or 141 | https://opensource.org/licenses/MIT). 142 | -------------------------------------------------------------------------------- /docker-target.sh: -------------------------------------------------------------------------------- 1 | # Script to remap Docker's `$TARGETARCH` to more appropriate values for rustup. 2 | if [ "$TARGETARCH" = "amd64" ]; then 3 | echo "x86_64" 4 | elif [ "$TARGETARCH" = "arm64" ]; then 5 | echo "aarch64" 6 | else 7 | echo "$TARGETARCH" 8 | fi -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "crane": { 4 | "inputs": { 5 | "nixpkgs": [ 6 | "nixpkgs" 7 | ] 8 | }, 9 | "locked": { 10 | "lastModified": 1699548976, 11 | "narHash": "sha256-xnpxms0koM8mQpxIup9JnT0F7GrKdvv0QvtxvRuOYR4=", 12 | "owner": "ipetkov", 13 | "repo": "crane", 14 | "rev": "6849911446e18e520970cc6b7a691e64ee90d649", 15 | "type": "github" 16 | }, 17 | "original": { 18 | "owner": "ipetkov", 19 | "repo": "crane", 20 | "type": "github" 21 | } 22 | }, 23 | "flake-utils": { 24 | "inputs": { 25 | "systems": "systems" 26 | }, 27 | "locked": { 28 | "lastModified": 1694529238, 29 | "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", 30 | "owner": "numtide", 31 | "repo": "flake-utils", 32 | "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", 33 | "type": "github" 34 | }, 35 | "original": { 36 | "owner": "numtide", 37 | "repo": "flake-utils", 38 | "type": "github" 39 | } 40 | }, 41 | "nixpkgs": { 42 | "locked": { 43 | "lastModified": 1699781429, 44 | "narHash": "sha256-UYefjidASiLORAjIvVsUHG6WBtRhM67kTjEY4XfZOFs=", 45 | "owner": "NixOS", 46 | "repo": "nixpkgs", 47 | "rev": "e44462d6021bfe23dfb24b775cc7c390844f773d", 48 | "type": "github" 49 | }, 50 | "original": { 51 | "owner": "NixOS", 52 | "ref": "nixos-unstable", 53 | "repo": "nixpkgs", 54 | "type": "github" 55 | } 56 | }, 57 | "root": { 58 | "inputs": { 59 | "crane": "crane", 60 | "flake-utils": "flake-utils", 61 | "nixpkgs": "nixpkgs", 62 | "rust-overlay": "rust-overlay" 63 | } 64 | }, 65 | "rust-overlay": { 66 | "inputs": { 67 | "flake-utils": [ 68 | "flake-utils" 69 | ], 70 | "nixpkgs": [ 71 | "nixpkgs" 72 | ] 73 | }, 74 | "locked": { 75 | "lastModified": 1699928012, 76 | "narHash": "sha256-7WfRTTBdkRJgjiJRsSShMXlfmOG1X0FqNdHaLATAL+w=", 77 | "owner": "oxalica", 78 | "repo": "rust-overlay", 79 | "rev": "e485313fc485700a9f1f9b8b272ddc0621d08357", 80 | "type": "github" 81 | }, 82 | "original": { 83 | "owner": "oxalica", 84 | "repo": "rust-overlay", 85 | "type": "github" 86 | } 87 | }, 88 | "systems": { 89 | "locked": { 90 | "lastModified": 1681028828, 91 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 92 | "owner": "nix-systems", 93 | "repo": "default", 94 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 95 | "type": "github" 96 | }, 97 | "original": { 98 | "owner": "nix-systems", 99 | "repo": "default", 100 | "type": "github" 101 | } 102 | } 103 | }, 104 | "root": "root", 105 | "version": 7 106 | } 107 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "Git FIDO helper - use multiple FIDO keys to sign Git commits"; 3 | 4 | inputs = { 5 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 6 | flake-utils.url = "github:numtide/flake-utils"; 7 | 8 | crane = { 9 | url = "github:ipetkov/crane"; 10 | inputs.nixpkgs.follows = "nixpkgs"; 11 | }; 12 | 13 | rust-overlay = { 14 | url = "github:oxalica/rust-overlay"; 15 | inputs.nixpkgs.follows = "nixpkgs"; 16 | inputs.flake-utils.follows = "flake-utils"; 17 | }; 18 | }; 19 | 20 | outputs = { 21 | nixpkgs, 22 | rust-overlay, 23 | flake-utils, 24 | crane, 25 | ... 26 | }: 27 | flake-utils.lib.eachDefaultSystem ( 28 | system: let 29 | # TODO: musl https://github.com/ipetkov/crane/blob/master/examples/cross-musl/flake.nix 30 | pkgs = import nixpkgs { 31 | inherit system; 32 | overlays = [(import rust-overlay)]; 33 | }; 34 | 35 | # TODO: cross compilation 36 | craneLib = crane.lib.${system}; 37 | rust = pkgs.rust-bin.stable.latest.default; # TODO: lock 38 | 39 | stdenv = 40 | if pkgs.stdenv.isLinux 41 | then pkgs.stdenv 42 | else pkgs.clangStdenv; 43 | 44 | commonArgs = { 45 | src = craneLib.cleanCargoSource (craneLib.path ./.); 46 | 47 | buildInputs = with pkgs; 48 | [pcsclite] 49 | ++ (lib.optional stdenv.isLinux [eudev]) 50 | ++ (lib.optional stdenv.isDarwin [libiconvReal]); 51 | 52 | nativeBuildInputs = with pkgs; 53 | [pkg-config] 54 | ++ (lib.optional stdenv.isDarwin (with darwin.apple_sdk; [ 55 | frameworks.AppKit 56 | frameworks.CoreFoundation 57 | frameworks.IOKit 58 | frameworks.PCSC 59 | ])); 60 | }; 61 | 62 | artifacts = craneLib.buildDepsOnly commonArgs; 63 | 64 | gfh = craneLib.buildPackage (commonArgs // {inherit artifacts;}); 65 | in { 66 | packages.default = gfh; 67 | devShells.default = with pkgs; 68 | mkShell { 69 | nativeBuildInputs = commonArgs.nativeBuildInputs; 70 | buildInputs = [rust] ++ commonArgs.buildInputs; 71 | }; 72 | } 73 | ); 74 | } 75 | -------------------------------------------------------------------------------- /src/add_key.rs: -------------------------------------------------------------------------------- 1 | use anyhow::{anyhow, Context, Result}; 2 | // use ctap_hid_fido2::{util::to_hex_str, Cfg, FidoKeyHidFactory}; 3 | use ctap_hid_fido2::util::to_hex_str; 4 | use inquire::{Select, Text}; 5 | use shellexpand::tilde; 6 | // use osshkeys::PublicKey; 7 | use std::{collections::HashMap, fmt::Display, fs, path::Path}; 8 | 9 | use crate::{ 10 | config, 11 | util, 12 | // util::{self, FidoDevice}, 13 | // yubikey, 14 | }; 15 | 16 | struct FidoDescriptorAndEntity { 17 | id: Vec, 18 | name: String, 19 | display_name: String, 20 | } 21 | 22 | impl Display for FidoDescriptorAndEntity { 23 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 24 | write!( 25 | f, 26 | "{}... {} ({})", 27 | &to_hex_str(&self.id)[..7], 28 | self.display_name, 29 | self.name 30 | ) 31 | } 32 | } 33 | 34 | pub fn run>(path: P) -> Result<()> { 35 | let keys = util::get_all_devices()?; 36 | 37 | if keys.is_empty() { 38 | return Err(anyhow!("was not able to find any connected FIDO keys")); 39 | } 40 | 41 | // TODO: wrapper fn that returns the sole result if len == 1? 42 | let key = Select::new("Select which key to import:", keys) 43 | .prompt() 44 | .with_context(|| "failed to create key selection input")?; 45 | let ssh_key = loop { 46 | let answer = Text::new("Path to the associated SSH key:") 47 | .prompt() 48 | .with_context(|| "failed to create key path text input")?; 49 | let expanded = tilde(&answer).into_owned(); 50 | 51 | match fs::File::open(&expanded) { 52 | Ok(_) => { 53 | // Using expanded here since canonicalize does not like `~`. Maybe manually replace the home path with `~` in user input? 54 | let tmp = fs::canonicalize(expanded).unwrap(); 55 | break tmp.to_str().unwrap().to_owned(); 56 | } 57 | Err(_) => println!("Failed to read file. Try something else."), 58 | } 59 | }; 60 | 61 | // let mut cfg = config::read_config(&path).or_else(|e| match e.kind() { 62 | // std::io::ErrorKind::NotFound => Ok(HashMap::new()), 63 | // _ => Err(Error::ConfigRead), 64 | // })?; 65 | let mut cfg = 66 | config::read_config(&path).or_else(|e| match e.downcast_ref::() { 67 | None => Err(e), 68 | Some(inner) => match inner.kind() { 69 | std::io::ErrorKind::NotFound => Ok(HashMap::new()), 70 | _ => Err(e), 71 | }, 72 | })?; 73 | 74 | cfg.insert(key.serial(), ssh_key); 75 | config::write_config(path, cfg).unwrap(); 76 | println!("Success!"); 77 | 78 | // let pin = Text::new("Input your key's PIN:").prompt()?; 79 | 80 | // ** Until ED25519 keys get fixed in ctap-hid-fido2/I find a good way to 81 | // pull it from a Yubikey, this auto import feature will need to be on hold. 82 | 83 | // let ssh_key: String = match answer { 84 | // FidoDevice::YubiKey(yubi) => String::from("yubi yubi"), 85 | // FidoDevice::Generic(device) => { 86 | // let rpid = util::sha256("ssh:"); 87 | // let fidokey = FidoKeyHidFactory::create_by_params(&vec![device.param], &Cfg::init())?; 88 | // let creds = 89 | // fidokey.credential_management_enumerate_credentials(Some(&pin), rpid.as_slice())?; 90 | 91 | // let render_options = creds 92 | // .iter() 93 | // .map(|c| FidoDescriptorAndEntity { 94 | // id: c.public_key_credential_descriptor.id.clone(), 95 | // name: c.public_key_credential_user_entity.name.clone(), 96 | // display_name: c.public_key_credential_user_entity.display_name.clone(), 97 | // }) 98 | // .collect::>(); 99 | 100 | // let descriptor = 101 | // Select::new("Select a SSH key from your device:", render_options).prompt()?; 102 | // let cred = creds 103 | // .iter() 104 | // .find(|c| c.public_key_credential_descriptor.id == descriptor.id) 105 | // .unwrap(); 106 | 107 | // // PROBLEM: ed25519 results in blank der & pem. Need to pr to try fix it if possible. 108 | // if cred.public_key.pem.is_empty() { 109 | // panic!("Public key PEM is empty. Probably means that the SSH key is ED25519 which is currently broken for this. Will fix soon!"); 110 | // } 111 | 112 | // let x = PublicKey::from_keystr(&cred.public_key.pem)?; 113 | // let ssh_key = x.serialize()?; 114 | 115 | // ssh_key 116 | // } 117 | // }; 118 | 119 | Ok(()) 120 | } 121 | -------------------------------------------------------------------------------- /src/bin/gfh-keygen.rs: -------------------------------------------------------------------------------- 1 | use shellexpand::tilde; 2 | use std::{ 3 | env, fs, 4 | process::{self, exit}, 5 | }; 6 | 7 | fn main() { 8 | let mut args = env::args().collect::>(); 9 | args.remove(0); // First `argv` is the current filename. 10 | 11 | let (index, _) = args 12 | .iter() 13 | .enumerate() 14 | .find(|(_, arg)| **arg == String::from("-f")) 15 | .expect("git did not provide -f somehow"); 16 | let index = index + 1; // We want the file name, which comes after `-f` 17 | 18 | let file = args[index].clone(); 19 | let new_file = fs::read_to_string(file) 20 | .expect("file should exist") 21 | .trim() 22 | .to_owned(); 23 | let new_file = tilde(&new_file); 24 | args[index] = new_file.into_owned(); 25 | 26 | let status = process::Command::new("ssh-keygen") 27 | .arg("-v") 28 | .args(args) 29 | .status() 30 | .expect("failed to run ssh-keygen"); 31 | 32 | if !status.success() { 33 | exit(status.code().or(Some(1)).unwrap()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/config.rs: -------------------------------------------------------------------------------- 1 | use anyhow::{Context, Result}; 2 | use std::{ 3 | collections::HashMap, 4 | fs::{create_dir_all, read_to_string, write}, 5 | path::Path, 6 | }; 7 | 8 | // use crate::error::{Error, Result}; 9 | 10 | type Config = HashMap; 11 | 12 | pub fn read_config>(path: P) -> Result { 13 | let content = read_to_string(&path).with_context(|| { 14 | format!( 15 | "failed to read config at {}", 16 | path.as_ref().to_string_lossy() 17 | ) 18 | })?; 19 | let cfg = parse_config(&content)?; 20 | Ok(cfg) 21 | } 22 | 23 | pub fn write_config>(path: P, cfg: Config) -> Result<()> { 24 | let serialised = serialise_config(cfg); 25 | let basepath = path.as_ref().parent().unwrap(); 26 | create_dir_all(basepath).with_context(|| { 27 | format!( 28 | "failed to create directory tree `{}` for config", 29 | basepath.to_string_lossy() 30 | ) 31 | })?; 32 | write(&path, serialised).with_context(|| { 33 | format!( 34 | "failed to write config at {}", 35 | path.as_ref().to_string_lossy() 36 | ) 37 | })?; 38 | 39 | Ok(()) 40 | } 41 | 42 | fn parse_config(content: &str) -> Result { 43 | let lines = content.lines().enumerate(); 44 | let mut output = Config::new(); 45 | 46 | for (i, line) in lines { 47 | if line.is_empty() || line.starts_with('#') { 48 | continue; 49 | } 50 | 51 | // TODO: function to validate lines & ensure referenced files exist. 52 | 53 | let (serial, key) = line.split_once("::").expect(&format!( 54 | "malformed line {i} in config. expected `::`" 55 | )); 56 | 57 | output.insert(serial.to_owned(), key.to_owned()); 58 | } 59 | 60 | if output.is_empty() { 61 | panic!("cannot do anything with an empty config! try using `gfh -a` to import a ssh key"); 62 | } 63 | 64 | Ok(output) 65 | } 66 | 67 | fn serialise_config(cfg: Config) -> String { 68 | let mut output = String::new(); 69 | 70 | for (serial, path) in cfg { 71 | output.push_str(&format!("{}::{}\n", serial, path.replace("\\", "\\\\"))); 72 | } 73 | 74 | output 75 | } 76 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use anyhow::{Context, Result}; 2 | use clap::Parser; 3 | // use ctap_hid_fido2::HidInfo; 4 | use shellexpand::tilde; 5 | // use std::{error::Error, fs}; 6 | 7 | mod add_key; 8 | mod config; 9 | mod util; 10 | mod yubikey; 11 | 12 | #[derive(Parser, Debug)] 13 | #[command(author, version, about, long_about = None)] 14 | struct Args { 15 | #[arg(short, long, default_value = "~/.config/gfh/keys")] 16 | file: String, 17 | 18 | #[arg(short, long)] 19 | add: bool, 20 | } 21 | 22 | fn main() -> Result<()> { 23 | let args = Args::parse(); 24 | let path = tilde(&args.file).into_owned(); 25 | 26 | if args.add { 27 | return add_key::run(path); 28 | } 29 | 30 | let cfg = config::read_config(&path).expect("could not read config path"); 31 | let devices = util::get_all_devices()?; 32 | 33 | let selected = devices 34 | .iter() 35 | .find_map(|y| cfg.get(&y.serial())) 36 | .with_context(|| format!("no matching FIDO key found in the config at {path}"))?; 37 | 38 | // TODO: resolve file paths in config relative to the config file? 39 | 40 | // We need to prefix it with `key::` so that Git doesn't reject it. It then 41 | // gets picked up by `bin/gfh-keygen` which does some magic stuff to feed 42 | // the key to `ssh-keygen` 43 | println!("key::{selected}"); 44 | 45 | Ok(()) 46 | } 47 | -------------------------------------------------------------------------------- /src/util.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use core::fmt; 3 | use ctap_hid_fido2::HidInfo; 4 | use sha2::{Digest, Sha256}; 5 | use std::hint::unreachable_unchecked; 6 | use yubikey_api::YubiKey; 7 | 8 | use crate::yubikey; 9 | 10 | pub enum FidoDevice { 11 | YubiKey(YubiKey), 12 | Generic(HidInfo), 13 | } 14 | 15 | impl FidoDevice { 16 | pub fn name(&self) -> String { 17 | match self { 18 | Self::YubiKey(yubi) => yubi.name().to_owned(), 19 | Self::Generic(device) => device.product_string.clone(), 20 | } 21 | } 22 | 23 | pub fn serial(&self) -> String { 24 | match self { 25 | Self::YubiKey(yubi) => yubi.serial().0.to_string(), 26 | Self::Generic(device) => { 27 | let found = device 28 | .info 29 | .split(' ') 30 | .find(|x| x.starts_with("serial_number=")); 31 | 32 | match found { 33 | Some(part) => part.split_once('=').unwrap().1.to_owned(), 34 | None => String::from("unknown"), // None => panic!("failed to find serial ID for {}. Please open an issue so we can try to resolve this!", self.name()), 35 | } 36 | } 37 | } 38 | } 39 | } 40 | 41 | impl fmt::Display for FidoDevice { 42 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 43 | write!(f, "{} - {}", self.serial(), self.name()) 44 | } 45 | } 46 | 47 | pub fn get_generics() -> Vec { 48 | let devices = ctap_hid_fido2::get_fidokey_devices(); 49 | let devices = devices 50 | .iter() 51 | .map(|x| FidoDevice::Generic(x.to_owned())) 52 | .collect::>(); 53 | devices 54 | } 55 | 56 | pub fn get_all_devices() -> Result> { 57 | let fidos = get_generics(); 58 | let mut yubikeys = yubikey::get_yubikeys()?; 59 | let mut fidos = fidos 60 | .into_iter() 61 | .filter(|v| matches!(v, FidoDevice::Generic(_))) 62 | .filter(|x| match x { 63 | FidoDevice::Generic(h) => !h.product_string.to_lowercase().contains("yubikey"), 64 | // Literally only FidoDevice::Generic can be in this vec. 65 | _ => unsafe { unreachable_unchecked() }, 66 | }) 67 | .collect::>(); 68 | 69 | fidos.append(&mut yubikeys); 70 | Ok(fidos) 71 | } 72 | 73 | #[allow(dead_code)] 74 | pub fn sha256(input: &str) -> Vec { 75 | let mut hasher = Sha256::new(); 76 | hasher.update(input); 77 | let output = hasher.finalize(); 78 | output.to_vec() 79 | } 80 | -------------------------------------------------------------------------------- /src/yubikey.rs: -------------------------------------------------------------------------------- 1 | use anyhow::{Context, Result}; 2 | use yubikey_api::Context as YKContext; 3 | 4 | use crate::util::FidoDevice; 5 | 6 | pub fn get_yubikeys() -> Result> { 7 | let mut readers: YKContext = 8 | YKContext::open().with_context(|| "failed to create reader context for yubikeys")?; 9 | let mut output = Vec::::new(); 10 | 11 | for reader in readers.iter()? { 12 | if reader.name().as_ref().to_ascii_lowercase().contains(&"yubikey") { 13 | let yubikey = reader 14 | .open() 15 | .with_context(|| format!("failed to open yubikey {}", reader.name()))?; 16 | output.push(FidoDevice::YubiKey(yubikey)) 17 | } 18 | } 19 | 20 | Ok(output) 21 | } 22 | --------------------------------------------------------------------------------