sequoia-sq-1.4.0/.cargo_vcs_info.json0000644000000001361046102023000131470ustar { "git": { "sha1": "558e1461d4f277924b0710f17a5bb56469f74ff2" }, "path_in_vcs": "" }sequoia-sq-1.4.0/.dockerignore000064400000000000000000000001451046102023000143710ustar 00000000000000# don't include the Dockerfile to avoid poisonning the cache Containerfile .dockerignore .git target sequoia-sq-1.4.0/.gitattributes000064400000000000000000000000231046102023000146030ustar 00000000000000* text=auto eol=lf sequoia-sq-1.4.0/.gitignore000064400000000000000000000001131046102023000137000ustar 00000000000000/target/ **/*.rs.bk *~ .gdb_history .dir-locals.el /*.html /*.pdf writelocksequoia-sq-1.4.0/.gitlab-ci.yml000064400000000000000000000043141046102023000143530ustar 00000000000000stages: - pre-check - build - test - deploy include: - component: "gitlab.com/sequoia-pgp/common-ci/sequoia-pipeline@main" inputs: extra_features: ",subplot" variables: SEQUOIA_CRYPTO_POLICY: "" docker-build-push: # Official docker image. image: docker:stable stage: build services: - docker:dind tags: - docker - self-hosted before_script: - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY script: - > docker build --no-cache --file Containerfile --target sq --tag "$IMAGE":latest . # smoke test - docker run "$IMAGE":latest --help - docker push "$IMAGE":latest after_script: [] only: refs: - /docker/i # refs containing 'docker' keyword - tags - web - schedules variables: CI_REGISTRY: "registry.gitlab.com" IMAGE: "$CI_REGISTRY/sequoia-pgp/sequoia-sq" DOCKER_HOST: tcp://docker:2376 pages: stage: build image: jampot.sequoia-pgp.org/sequoia-pgp/build-docker-image/trixie-pandoc:latest script: - ASSET_OUT_DIR=/tmp/assets cargo doc --no-deps -p sequoia-sq - mkdir public - mv -v target/doc public/impl # Man pages. - /tmp/assets/man-pages/man2html.sh --generate - mkdir public/man - mv -v $(for f in $(/tmp/assets/man-pages/man2html.sh --html-files); do echo /tmp/assets/man-pages/$f; done) public/man - echo "/sequoia-sq/man /sequoia-sqv/man/$(/tmp/assets/man-pages/man2html.sh --html-root) 302" >> public/_redirects - mkdir public/subplot - pandoc -s -o public/subplot/sq-subplot.html sq-subplot.md - pandoc -s -o public/subplot/sq-subplot.pdf sq-subplot.md - echo "/sequoia-sq/ /sequoia-sq/man/sq.1.html 302" > public/_redirects - echo "/sequoia-sq/impl /sequoia-sq/impl/sq/index.html 302" >> public/_redirects - echo "/sequoia-sq/subplot /sequoia-sq/subplot/sq-subplot.html 302" >> public/_redirects artifacts: paths: - public pages: false pages-deploy: stage: deploy image: jampot.sequoia-pgp.org/sequoia-pgp/build-docker-image/trixie-pandoc:latest script: echo "publishing" artifacts: paths: - public pages: true rules: - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' sequoia-sq-1.4.0/Cargo.lock0000644000004250651046102023000111360ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 4 [[package]] name = "adler2" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aead" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ "crypto-common 0.1.7", "generic-array 0.14.7", ] [[package]] name = "aes" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", "cpufeatures 0.2.17", "zeroize", ] [[package]] name = "aes-gcm" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" dependencies = [ "aead", "aes", "cipher", "ctr", "ghash", "subtle", ] [[package]] name = "ahash" version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", "once_cell", "version_check", "zerocopy 0.8.53", ] [[package]] name = "aho-corasick" version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] [[package]] name = "aligned" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685" dependencies = [ "as-slice", ] [[package]] name = "android_system_properties" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ "libc", ] [[package]] name = "annotate-snippets" version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "710e8eae58854cdc1790fcb56cca04d712a17be849eeb81da2a724bf4bae2bc4" dependencies = [ "anstyle", "unicode-width", ] [[package]] name = "anstream" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ "windows-sys 0.61.2", ] [[package]] name = "anstyle-wincon" version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", "windows-sys 0.61.2", ] [[package]] name = "anyhow" version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" [[package]] name = "argon2" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" dependencies = [ "base64ct", "blake2", "cpufeatures 0.2.17", "password-hash", ] [[package]] name = "arraydeque" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" [[package]] name = "as-slice" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" dependencies = [ "stable_deref_trait", ] [[package]] name = "ascii-canvas" version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef1e3e699d84ab1b0911a1010c5c106aa34ae89aeac103be5ce0c3859db1e891" dependencies = [ "term", ] [[package]] name = "assert_cmd" version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2aa3a22042e45de04255c7bf3626e239f450200fd0493c1e382263544b20aea6" dependencies = [ "anstyle", "bstr", "libc", "predicates", "predicates-core", "predicates-tree", "wait-timeout", ] [[package]] name = "async-generic" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddf3728566eefa873833159754f5732fb0951d3649e6e5b891cc70d56dd41673" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "async-trait" version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "atomic-waker" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "base16ct" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" [[package]] name = "base64" version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" [[package]] name = "bindgen" version = "0.72.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" dependencies = [ "annotate-snippets", "bitflags 2.13.0", "cexpr", "clang-sys", "itertools 0.13.0", "log", "prettyplease", "proc-macro2", "quote", "regex", "rustc-hash", "shlex 1.3.0", "syn", ] [[package]] name = "bit-set" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" dependencies = [ "bit-vec", ] [[package]] name = "bit-vec" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" [[package]] name = "bitvec" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddcec3d12c579d40898fe0a9a358a803c23e9c52ca3c425707f81c9436211837" dependencies = [ "funty", "radium", "tap", "wyz", ] [[package]] name = "blake2" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" dependencies = [ "digest 0.10.7", ] [[package]] name = "block-buffer" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array 0.14.7", ] [[package]] name = "block-buffer" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" dependencies = [ "hybrid-array 0.4.13", ] [[package]] name = "block-padding" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" dependencies = [ "generic-array 0.14.7", ] [[package]] name = "blowfish" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7" dependencies = [ "byteorder", "cipher", ] [[package]] name = "botan" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d4c7647d67c53194fa0740404c6c508880aef2bfe99a9868dbb4b86f090377" dependencies = [ "botan-sys", ] [[package]] name = "botan-sys" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04285fa0c094cc9961fe435b1b279183db9394844ad82ce483aa6196c0e6da38" [[package]] name = "bstr" version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5cee35f73844aa3014bb606320a6c1f010249dbdf43342fe54b5a4f6a8ed4b79" dependencies = [ "memchr", "regex-automata", "serde_core", ] [[package]] name = "buffered-reader" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7531a07caf83a3fa3b47a233b437ee7910cccfb688555d224338295a0a64fcc" dependencies = [ "bzip2", "flate2", "libc", ] [[package]] name = "bumpalo" version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593" [[package]] name = "bzip2" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3a53fac24f34a81bc9954b5d6cfce0c21e18ec6959f44f56e8e90e4bb7c346c" dependencies = [ "libbz2-rs-sys", ] [[package]] name = "camellia" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3264e2574e9ef2b53ce6f536dea83a69ac0bc600b762d1523ff83fe07230ce30" dependencies = [ "byteorder", "cipher", ] [[package]] name = "capnp" version = "0.25.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4777a3bc19b8f8e5fb2d0196c6b5dfcbbcc8b2fe08ae57f873f2f35f15cfc210" dependencies = [ "embedded-io", ] [[package]] name = "capnp-futures" version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73b69dfddccc57844f9a90f9d72b44b97c326914851ea94fb7da40ef9cad6e8d" dependencies = [ "capnp", "futures-channel", "futures-util", ] [[package]] name = "capnp-rpc" version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c74c337e87f75f3174ffb3513738ab0acc631c04f64cc33b867c60f84771da" dependencies = [ "capnp", "capnp-futures", "futures", ] [[package]] name = "capnpc" version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fca02be865c8c5a78bfc24b9819006ab6b59bef238467203928e26459557af93" dependencies = [ "capnp", ] [[package]] name = "cast5" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26b07d673db1ccf000e90f54b819db9e75a8348d6eb056e9b8ab53231b7a9911" dependencies = [ "cipher", ] [[package]] name = "cbc" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" dependencies = [ "cipher", ] [[package]] name = "cc" version = "1.2.66" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5d6cac793997bd970000024b2934968efe83b382de4fdcf4fcb46b6ee4ad996" dependencies = [ "find-msvc-tools", "shlex 2.0.1", ] [[package]] name = "cexpr" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ "nom", ] [[package]] name = "cfb-mode" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "738b8d467867f80a71351933f70461f5b56f24d5c93e0cf216e59229c968d330" dependencies = [ "cipher", ] [[package]] name = "cfg-if" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" dependencies = [ "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", "windows-link", ] [[package]] name = "cipher" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ "crypto-common 0.1.7", "inout", "zeroize", ] [[package]] name = "clang-sys" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", "libloading", ] [[package]] name = "clap" version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", "clap_derive", ] [[package]] name = "clap_builder" version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstream", "anstyle", "clap_lex", "strsim", "terminal_size", ] [[package]] name = "clap_complete" version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db8b397918185f0161ff3d6fcaa9e4bfc09b8367caf6e1d4a2848e5477ed027b" dependencies = [ "clap", ] [[package]] name = "clap_derive" version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ "heck", "proc-macro2", "quote", "syn", ] [[package]] name = "clap_lex" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "cmac" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8543454e3c3f5126effff9cd44d562af4e31fb8ce1cc0d3dcd8f084515dbc1aa" dependencies = [ "cipher", "dbl", "digest 0.10.7", ] [[package]] name = "cmov" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" [[package]] name = "colorchoice" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "console" version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fe5f465a4f6fee88fad41b85d990f84c835335e85b5d9e6e63e0d06d28cba7c" dependencies = [ "encode_unicode", "libc", "unicode-width", "windows-sys 0.61.2", ] [[package]] name = "const-oid" version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "core-foundation" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", ] [[package]] name = "core-foundation" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" dependencies = [ "core-foundation-sys", "libc", ] [[package]] name = "core-foundation-sys" version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] [[package]] name = "cpufeatures" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" dependencies = [ "libc", ] [[package]] name = "crc32fast" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] [[package]] name = "critical-section" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" [[package]] name = "crossbeam" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" dependencies = [ "crossbeam-channel", "crossbeam-deque", "crossbeam-epoch", "crossbeam-queue", "crossbeam-utils", ] [[package]] name = "crossbeam-channel" version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-deque" version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" version = "0.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-queue" version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crypto-bigint" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array 0.14.7", "rand_core 0.6.4", "subtle", "zeroize", ] [[package]] name = "crypto-common" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array 0.14.7", "rand_core 0.6.4", "typenum", ] [[package]] name = "crypto-common" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" dependencies = [ "hybrid-array 0.4.13", "rand_core 0.10.1", ] [[package]] name = "ctor" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "424e0138278faeb2b401f174ad17e715c829512d74f3d1e81eb43365c2e0590e" dependencies = [ "ctor-proc-macro", "dtor", ] [[package]] name = "ctor-proc-macro" version = "0.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1" [[package]] name = "ctr" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" dependencies = [ "cipher", ] [[package]] name = "ctutils" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" dependencies = [ "cmov", ] [[package]] name = "culpa" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ae0bfe9317b1cb4ff5a56d766ee4b157b3e1f47f11979253570e88d10fd1fd3" dependencies = [ "culpa-macros", ] [[package]] name = "culpa-macros" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1234e1717066d3c71dcf89b75e7b586299e41204d361db56ec51e6ded5014279" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "curve25519-dalek" version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures 0.2.17", "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", "rustc_version", "subtle", "zeroize", ] [[package]] name = "curve25519-dalek-derive" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "cvt" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2ae9bf77fbf2d39ef573205d554d87e86c12f1994e9ea335b0651b9b278bcf1" dependencies = [ "cfg-if", ] [[package]] name = "cx448" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c0cf476284b03eb6c10e78787b21c7abb7d7d43cb2f02532ba6b831ed892fa" dependencies = [ "crypto-bigint", "elliptic-curve", "rand_core 0.6.4", "sha3 0.10.9", "signature 2.2.0", "subtle", "zeroize", ] [[package]] name = "data-encoding" version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" [[package]] name = "dbl" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd2735a791158376708f9347fe8faba9667589d82427ef3aed6794a8981de3d9" dependencies = [ "generic-array 0.14.7", ] [[package]] name = "defmt" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2953bfe4f93bbd20cc71198842756f77d161884c99ebbabc41d80231ded88d1" dependencies = [ "bitflags 1.3.2", "defmt-macros", ] [[package]] name = "defmt-macros" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bad9c72e7ca2137e0dc3813245a0d282fd6daad32fd800af018306a9169b5fe8" dependencies = [ "defmt-parser", "proc-macro2", "quote", "syn", ] [[package]] name = "defmt-parser" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" dependencies = [ "thiserror 2.0.18", ] [[package]] name = "der" version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ "const-oid", "pem-rfc7468", "zeroize", ] [[package]] name = "deranged" version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ "powerfmt", ] [[package]] name = "des" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffdd80ce8ce993de27e9f063a444a4d53ce8e8db4c1f00cc03af5ad5a9867a1e" dependencies = [ "cipher", ] [[package]] name = "descape" version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c1113b908df80c963b107424498e37fba986b424b605729d1492dfbe4b2a630" [[package]] name = "deunicode" version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abd57806937c9cc163efc8ea3910e00a62e2aeb0b8119f1793a978088f8f6b04" [[package]] name = "difflib" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", "const-oid", "crypto-common 0.1.7", "subtle", ] [[package]] name = "digest" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" dependencies = [ "block-buffer 0.12.1", "crypto-common 0.2.2", ] [[package]] name = "directories" version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" dependencies = [ "dirs-sys 0.4.1", ] [[package]] name = "dirs" version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" dependencies = [ "dirs-sys 0.5.0", ] [[package]] name = "dirs-sys" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" dependencies = [ "libc", "option-ext", "redox_users 0.4.6", "windows-sys 0.48.0", ] [[package]] name = "dirs-sys" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", "redox_users 0.5.2", "windows-sys 0.61.2", ] [[package]] name = "displaydoc" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "doc-comment" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "780955b8b195a21ab8e4ac6b60dd1dbdcec1dc6c51c0617964b08c81785e12c9" [[package]] name = "dsa" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48bc224a9084ad760195584ce5abb3c2c34a225fa312a128ad245a6b412b7689" dependencies = [ "digest 0.10.7", "num-bigint-dig", "num-traits", "pkcs8", "rfc6979", "sha2", "signature 2.2.0", "zeroize", ] [[package]] name = "dtor" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "404d02eeb088a82cfd873006cb713fe411306c7d182c344905e101fb1167d301" dependencies = [ "dtor-proc-macro", ] [[package]] name = "dtor-proc-macro" version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" [[package]] name = "dyn-clone" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "eax" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9954fabd903b82b9d7a68f65f97dc96dd9ad368e40ccc907a7c19d53e6bfac28" dependencies = [ "aead", "cipher", "cmac", "ctr", "subtle", ] [[package]] name = "ecb" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a8bfa975b1aec2145850fcaa1c6fe269a16578c44705a532ae3edc92b8881c7" dependencies = [ "cipher", ] [[package]] name = "ecdsa" version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der", "digest 0.10.7", "elliptic-curve", "rfc6979", "signature 2.2.0", "spki", ] [[package]] name = "ed25519" version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ "pkcs8", "signature 2.2.0", ] [[package]] name = "ed25519-dalek" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" dependencies = [ "curve25519-dalek", "ed25519", "rand_core 0.6.4", "serde", "sha2", "subtle", "zeroize", ] [[package]] name = "either" version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" [[package]] name = "elliptic-curve" version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", "base64ct", "crypto-bigint", "digest 0.10.7", "ff", "generic-array 0.14.7", "group", "hkdf", "pem-rfc7468", "pkcs8", "rand_core 0.6.4", "sec1", "serde_json", "serdect", "subtle", "tap", "zeroize", ] [[package]] name = "embedded-io" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9eb1aa714776b75c7e67e1da744b81a129b3ff919c8712b5e1b32252c1f07cc7" [[package]] name = "ena" version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabffdaee24bd1bf95c5ef7cec31260444317e72ea56c4c91750e8b7ee58d5f1" dependencies = [ "log", ] [[package]] name = "encode_unicode" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "encoding_rs" version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] [[package]] name = "endian-type" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" [[package]] name = "enum-as-inner" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" dependencies = [ "heck", "proc-macro2", "quote", "syn", ] [[package]] name = "env_filter" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "900d271a03799a1ee8d1ca9b19893b48ca674a9284fefcfb85f05e74ed314217" dependencies = [ "log", "regex", ] [[package]] name = "env_logger" version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de671bd27a75a797dc9ae289ba1e77276e75e2026408aab65185384e2d5cd3f6" dependencies = [ "anstream", "anstyle", "env_filter", "jiff", "log", ] [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", "windows-sys 0.61.2", ] [[package]] name = "fallible-iterator" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" [[package]] name = "fallible-streaming-iterator" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "fd-lock" version = "4.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" dependencies = [ "cfg-if", "rustix", "windows-sys 0.59.0", ] [[package]] name = "ff" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" dependencies = [ "bitvec", "rand_core 0.6.4", "subtle", ] [[package]] name = "fiat-crypto" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "filetime" version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" dependencies = [ "cfg-if", "libc", ] [[package]] name = "find-msvc-tools" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "fixedbitset" version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "miniz_oxide", ] [[package]] name = "float-cmp" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8" dependencies = [ "num-traits", ] [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "foldhash" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" [[package]] name = "foreign-types" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" dependencies = [ "foreign-types-shared", ] [[package]] name = "foreign-types-shared" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] [[package]] name = "fs2" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" dependencies = [ "libc", "winapi", ] [[package]] name = "fs_at" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14af6c9694ea25db25baa2a1788703b9e7c6648dcaeeebeb98f7561b5384c036" dependencies = [ "aligned", "cfg-if", "cvt", "libc", "nix", "windows-sys 0.52.0", ] [[package]] name = "fs_extra" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" [[package]] name = "funty" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", "futures-executor", "futures-io", "futures-sink", "futures-task", "futures-util", ] [[package]] name = "futures-channel" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", ] [[package]] name = "futures-core" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", "futures-util", ] [[package]] name = "futures-io" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-macro" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "futures-sink" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[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-channel", "futures-core", "futures-io", "futures-macro", "futures-sink", "futures-task", "memchr", "pin-project-lite", "slab", ] [[package]] name = "generator" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" dependencies = [ "cc", "libc", "log", "rustversion", "windows", ] [[package]] name = "generic-array" version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", "zeroize", ] [[package]] name = "generic-array" version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2e55f16dcf0e9c00efbe2e655ffe45fc98e7066b52bc92f8a79e64060a79351" dependencies = [ "rustversion", "typenum", ] [[package]] name = "gethostname" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" dependencies = [ "rustix", "windows-link", ] [[package]] name = "getopts" version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" dependencies = [ "unicode-width", ] [[package]] name = "getrandom" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "js-sys", "libc", "wasi", "wasm-bindgen", ] [[package]] name = "getrandom" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", "r-efi 5.3.0", "wasip2", ] [[package]] name = "getrandom" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", ] [[package]] name = "ghash" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" dependencies = [ "opaque-debug", "polyval", ] [[package]] name = "glob" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "globset" version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3" dependencies = [ "aho-corasick", "bstr", "log", "regex-automata", "regex-syntax", ] [[package]] name = "globwalk" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" dependencies = [ "bitflags 2.13.0", "ignore", "walkdir", ] [[package]] name = "group" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", "rand_core 0.6.4", "subtle", ] [[package]] name = "h2" version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155" dependencies = [ "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", "http", "indexmap", "slab", "tokio", "tokio-util", "tracing", ] [[package]] name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", ] [[package]] name = "hashbrown" version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "foldhash 0.1.5", ] [[package]] name = "hashbrown" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ "foldhash 0.2.0", ] [[package]] name = "hashbrown" version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" [[package]] name = "hashlink" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" dependencies = [ "hashbrown 0.14.5", ] [[package]] name = "hashlink" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" dependencies = [ "hashbrown 0.15.5", ] [[package]] name = "hashlink" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "824e001ac4f3012dd16a264bec811403a67ca9deb6c102fc5049b32c4574b35f" dependencies = [ "hashbrown 0.16.1", ] [[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hickory-client" version = "0.24.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "156579a5cd8d1fc6f0df87cc21b6ee870db978a163a1ba484acd98a4eff5a6de" dependencies = [ "cfg-if", "data-encoding", "futures-channel", "futures-util", "hickory-proto 0.24.4", "once_cell", "radix_trie", "rand 0.8.6", "thiserror 1.0.69", "tokio", "tracing", ] [[package]] name = "hickory-proto" version = "0.24.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92652067c9ce6f66ce53cc38d1169daa36e6e7eb7dd3b63b5103bd9d97117248" dependencies = [ "async-trait", "cfg-if", "data-encoding", "enum-as-inner", "futures-channel", "futures-io", "futures-util", "idna", "ipnet", "once_cell", "openssl", "rand 0.8.6", "thiserror 1.0.69", "tinyvec", "tokio", "tracing", "url", ] [[package]] name = "hickory-proto" version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502" dependencies = [ "async-trait", "cfg-if", "data-encoding", "enum-as-inner", "futures-channel", "futures-io", "futures-util", "idna", "ipnet", "once_cell", "rand 0.9.4", "ring", "thiserror 2.0.18", "tinyvec", "tokio", "tracing", "url", ] [[package]] name = "hickory-resolver" version = "0.24.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbb117a1ca520e111743ab2f6688eddee69db4e0ea242545a604dce8a66fd22e" dependencies = [ "cfg-if", "futures-util", "hickory-proto 0.24.4", "ipconfig", "lru-cache", "once_cell", "parking_lot", "rand 0.8.6", "resolv-conf", "smallvec", "thiserror 1.0.69", "tokio", "tracing", ] [[package]] name = "hickory-resolver" version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc62a9a99b0bfb44d2ab95a7208ac952d31060efc16241c87eaf36406fecf87a" dependencies = [ "cfg-if", "futures-util", "hickory-proto 0.25.2", "ipconfig", "moka", "once_cell", "parking_lot", "rand 0.9.4", "resolv-conf", "smallvec", "thiserror 2.0.18", "tokio", "tracing", ] [[package]] name = "hkdf" version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" dependencies = [ "hmac", ] [[package]] name = "hmac" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ "digest 0.10.7", ] [[package]] name = "html-escape" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46c1ff2d1cbf39efe5af0900ced8a069b5e61557a17544eb0c4a50239937389e" [[package]] name = "http" version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" dependencies = [ "bytes", "itoa", ] [[package]] name = "http-body" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", "http", ] [[package]] name = "http-body-util" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", "http", "http-body", "pin-project-lite", ] [[package]] name = "httparse" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "humansize" version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7" dependencies = [ "libm", ] [[package]] name = "humantime" version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15cdd26707701c53297e2fa6afb323d55fbc1d0810c3aec078ae3ef0424c3c15" [[package]] name = "hybrid-array" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "891d15931895091dea5c47afa5b3c9a01ba634b311919fd4d41388fa0e3d76af" dependencies = [ "typenum", ] [[package]] name = "hybrid-array" version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "818356c5132c1fede50f837ca96afbe78ff42413047f4abb886217845e1b6c8c" dependencies = [ "ctutils", "typenum", "zeroize", ] [[package]] name = "hyper" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" dependencies = [ "atomic-waker", "bytes", "futures-channel", "futures-core", "h2", "http", "http-body", "httparse", "itoa", "pin-project-lite", "smallvec", "tokio", "want", ] [[package]] name = "hyper-rustls" version = "0.27.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" dependencies = [ "http", "hyper", "hyper-util", "rustls", "tokio", "tokio-rustls", "tower-service", ] [[package]] name = "hyper-tls" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", "hyper", "hyper-util", "native-tls", "tokio", "tokio-native-tls", "tower-service", ] [[package]] name = "hyper-util" version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ "base64", "bytes", "futures-channel", "futures-util", "http", "http-body", "hyper", "ipnet", "libc", "percent-encoding", "pin-project-lite", "socket2", "system-configuration", "tokio", "tower-service", "tracing", "windows-registry", ] [[package]] name = "iana-time-zone" version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "log", "wasm-bindgen", "windows-core", ] [[package]] name = "iana-time-zone-haiku" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ "cc", ] [[package]] name = "icu_collections" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", "yoke", "zerofrom", "zerovec", ] [[package]] name = "icu_locale_core" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", "tinystr", "writeable", "zerovec", ] [[package]] name = "icu_normalizer" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ "icu_collections", "icu_normalizer_data", "icu_properties", "icu_provider", "smallvec", "zerovec", ] [[package]] name = "icu_normalizer_data" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" dependencies = [ "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" [[package]] name = "icu_provider" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", "writeable", "yoke", "zerofrom", "zerotrie", "zerovec", ] [[package]] name = "idea" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "075557004419d7f2031b8bb7f44bb43e55a83ca7b63076a8fb8fe75753836477" dependencies = [ "cipher", ] [[package]] name = "idna" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", "utf8_iter", ] [[package]] name = "idna_adapter" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ "icu_normalizer", "icu_properties", ] [[package]] name = "ignore" version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe112b004901c62c2faa11f4f75e9864e0cc5af8da71c9115d184a3aa888749f" dependencies = [ "crossbeam-deque", "globset", "log", "memchr", "regex-automata", "same-file", "walkdir", "winapi-util", ] [[package]] name = "indexmap" version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", "hashbrown 0.17.1", ] [[package]] name = "indicatif" version = "0.18.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9433806cd6b4ec1aba79c021c7e4c58fb4c3b9977c085062e611ac929998fb0c" dependencies = [ "console", "portable-atomic", "unicode-width", "unit-prefix", "web-time", ] [[package]] name = "inout" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ "block-padding", "generic-array 0.14.7", ] [[package]] name = "ipconfig" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d40460c0ce33d6ce4b0630ad68ff63d6661961c48b6dba35e5a4d81cfb48222" dependencies = [ "socket2", "widestring", "windows-registry", "windows-result", "windows-sys 0.61.2", ] [[package]] name = "ipnet" version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "is_terminal_polyfill" version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] [[package]] name = "itertools" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" dependencies = [ "either", ] [[package]] name = "itoa" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jiff" version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccfe6121cbe750cf81efa362d85c0bde7ea298ec43092d3a193baca59cdbd634" dependencies = [ "defmt", "jiff-static", "log", "portable-atomic", "portable-atomic-util", "serde_core", ] [[package]] name = "jiff-static" version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e165e897f662d428f3cd3828a919dbe067c2d42bb1031eede74ef9d27ecdedd2" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "js-sys" version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" dependencies = [ "cfg-if", "futures-util", "wasm-bindgen", ] [[package]] name = "keccak" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" dependencies = [ "cpufeatures 0.2.17", ] [[package]] name = "keccak" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e24a010dd405bd7ed803e5253182815b41bf2e6a80cc3bfc066658e03a198aa" dependencies = [ "cfg-if", "cpufeatures 0.3.0", ] [[package]] name = "kem" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01737161ba802849cfd486b5bd209d38ba4943494c249a8126005170c7621edd" dependencies = [ "crypto-common 0.2.2", "rand_core 0.10.1", ] [[package]] name = "lalrpop" version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba4ebbd48ce411c1d10fb35185f5a51a7bfa3d8b24b4e330d30c9e3a34129501" dependencies = [ "ascii-canvas", "bit-set", "ena", "itertools 0.14.0", "lalrpop-util", "petgraph", "regex", "regex-syntax", "sha3 0.10.9", "string_cache", "term", "unicode-xid", "walkdir", ] [[package]] name = "lalrpop-util" version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5baa5e9ff84f1aefd264e6869907646538a52147a755d494517a8007fb48733" dependencies = [ "regex-automata", "rustversion", ] [[package]] name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ "spin", ] [[package]] name = "libbz2-rs-sys" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34b357333733e8260735ba5894eb928c02ecc69c78715f01a8019e7fa7f2db4c" [[package]] name = "libc" version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libloading" version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", "windows-link", ] [[package]] name = "libm" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" dependencies = [ "libc", ] [[package]] name = "libsqlite3-sys" version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1f111c8c41e7c61a49cd34e44c7619462967221a6443b0ec299e0ac30cfb9b1" dependencies = [ "cc", "pkg-config", "vcpkg", ] [[package]] name = "line-col" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e69cdf6b85b5c8dce514f694089a2cf8b1a702f6cd28607bcb3cf296c9778db" [[package]] name = "linked-hash-map" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "lock_api" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ "scopeguard", ] [[package]] name = "log" version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" [[package]] name = "loom" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" dependencies = [ "cfg-if", "generator", "scoped-tls", "serde", "serde_json", "tracing", "tracing-subscriber", ] [[package]] name = "lru-cache" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" dependencies = [ "linked-hash-map", ] [[package]] name = "marked-yaml" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2eb25a7ab146f4058d67a74dfea52e25c133c575f08ce5851da97d224e3ad8d" dependencies = [ "doc-comment", "hashlink 0.9.1", "serde", "serde_path_to_error", "yaml-rust2 0.9.0", ] [[package]] name = "marked-yaml" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a76cf4e66a8ffccfce983161b0faafe61a5ef03fe875ef2e3deb897e4e915fa" dependencies = [ "doc-comment", "hashlink 0.10.0", "serde", "serde_path_to_error", "yaml-rust2 0.10.4", ] [[package]] name = "matchers" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" dependencies = [ "regex-automata", ] [[package]] name = "md-5" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ "cfg-if", "digest 0.10.7", ] [[package]] name = "memchr" version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" [[package]] name = "memsec" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c797b9d6bb23aab2fc369c65f871be49214f5c759af65bde26ffaaa2b646b492" [[package]] name = "mime" version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "minimal-lexical" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", "simd-adler32", ] [[package]] name = "mio" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" dependencies = [ "libc", "wasi", "windows-sys 0.61.2", ] [[package]] name = "ml-dsa" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "add6b9d92e496f16f4526d68ff29da1483aba4b119baeab8bed3b9e3544a6f3d" dependencies = [ "crypto-common 0.2.2", "ctutils", "hybrid-array 0.4.13", "module-lattice", "shake", "signature 3.0.0", "zeroize", ] [[package]] name = "ml-kem" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e15f3e5b957493873e396a66914e83e616b6afe335cdef7efe5c6e1216aba66" dependencies = [ "hybrid-array 0.4.13", "kem", "module-lattice", "rand_core 0.10.1", "sha3 0.11.0", "zeroize", ] [[package]] name = "module-lattice" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c61b87c9683ab7cb1c6871d261ad5479b6b10ceb52c4352aaca3b5d35a8febe" dependencies = [ "ctutils", "hybrid-array 0.4.13", "num-traits", "zeroize", ] [[package]] name = "moka" version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "957228ad12042ee839f93c8f257b62b4c0ab5eaae1d4fa60de53b27c9d7c5046" dependencies = [ "crossbeam-channel", "crossbeam-epoch", "crossbeam-utils", "equivalent", "parking_lot", "portable-atomic", "smallvec", "tagptr", "uuid", ] [[package]] name = "native-tls" version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" dependencies = [ "libc", "log", "openssl", "openssl-probe", "openssl-sys", "schannel", "security-framework", "security-framework-sys", "tempfile", ] [[package]] name = "nettle" version = "7.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2578a3627c28fefb60f1680e20e85f38bd8c8bf98c288b370489a573b0640907" dependencies = [ "getrandom 0.4.3", "libc", "nettle-sys", "thiserror 2.0.18", "typenum", ] [[package]] name = "nettle-sys" version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f35502358aa77e598570bbf9a79ad19c4985a1bcd157b5d70197688dafca9b48" dependencies = [ "bindgen", "cc", "libc", "pkg-config", "tempfile", "vcpkg", ] [[package]] name = "new_debug_unreachable" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "nibble_vec" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" dependencies = [ "smallvec", ] [[package]] name = "nix" version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ "bitflags 2.13.0", "cfg-if", "cfg_aliases", "libc", ] [[package]] name = "nom" version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", ] [[package]] name = "normalize-line-endings" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" [[package]] name = "normpath" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9985ef7269fa99f3b12437bb698381da2428743ab90f20393f399fa14cab21a" dependencies = [ "windows-sys 0.61.2", ] [[package]] name = "nu-ansi-term" version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ "windows-sys 0.61.2", ] [[package]] name = "num-bigint-dig" version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" dependencies = [ "lazy_static", "libm", "num-integer", "num-iter", "num-traits", "rand 0.8.6", "smallvec", "zeroize", ] [[package]] name = "num-conv" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-integer" version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ "num-traits", ] [[package]] name = "num-iter" version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", "num-traits", ] [[package]] name = "num-traits" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", ] [[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]] name = "ocb3" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c196e0276c471c843dd5777e7543a36a298a4be942a2a688d8111cd43390dedb" dependencies = [ "aead", "cipher", "ctr", "subtle", ] [[package]] name = "once_cell" version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" dependencies = [ "critical-section", "portable-atomic", ] [[package]] name = "once_cell_polyfill" version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "opaque-debug" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openpgp-cert-d" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd47b0b6df1022ca8a9a06791261c3153028abef191fe53aa326b7f443f2d6" dependencies = [ "anyhow", "dirs", "fd-lock", "libc", "sha1collisiondetection", "sha2", "tempfile", "thiserror 2.0.18", "walkdir", ] [[package]] name = "openssl" version = "0.10.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45" dependencies = [ "bitflags 2.13.0", "cfg-if", "foreign-types", "libc", "openssl-macros", "openssl-sys", ] [[package]] name = "openssl-macros" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "openssl-probe" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-sys" version = "0.9.117" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b47e7e6bb2c38cd930d25a23b40fa52e068c10e85f3e03a7f5ba5aaca5713695" dependencies = [ "bindgen", "cc", "libc", "pkg-config", "vcpkg", ] [[package]] name = "option-ext" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "ossl" version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f34df8ca6a2920b0fae969ced913c714b41f23b655a434a45c6a9843a75c019" dependencies = [ "bindgen", "cfg-if", "libc", "openssl-sys", "pkg-config", ] [[package]] name = "p256" version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" dependencies = [ "ecdsa", "elliptic-curve", "primeorder", "sha2", ] [[package]] name = "p384" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" dependencies = [ "ecdsa", "elliptic-curve", "primeorder", "sha2", ] [[package]] name = "p521" version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2" dependencies = [ "base16ct", "ecdsa", "elliptic-curve", "primeorder", "rand_core 0.6.4", "sha2", ] [[package]] name = "parking_lot" version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", ] [[package]] name = "parking_lot_core" version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", "windows-link", ] [[package]] name = "password-hash" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" dependencies = [ "base64ct", "rand_core 0.6.4", "subtle", ] [[package]] name = "paste" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pem-rfc7468" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" dependencies = [ "base64ct", ] [[package]] name = "percent-encoding" version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" version = "2.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47627dd7305c6a2d6c8c6bcd24c5a4c17dbbf425f4f9c5313e724b38fc9782e9" dependencies = [ "memchr", "ucd-trie", ] [[package]] name = "pest_derive" version = "2.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b4254325ecad416ab689e27ba51da03ba01a9632bc6e108f5fe7c3c4ad29d58" dependencies = [ "pest", "pest_generator", ] [[package]] name = "pest_generator" version = "2.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c4c0e91ead7a8f7acecbca6f003fc2e8282b1dbe2dd9c9d2f16aba42995e0a7" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", "syn", ] [[package]] name = "pest_meta" version = "2.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9744bc48116fee06334924bb5f2bad41eed5e89bd26e29b0b799f9a3f82c210" dependencies = [ "pest", ] [[package]] name = "petgraph" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" dependencies = [ "fixedbitset", "indexmap", ] [[package]] name = "phf_shared" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ "siphasher", ] [[package]] name = "pikchr" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13680336a9060974d823f15053decc0ae5380eebf6f82abf17608523a7d71826" dependencies = [ "cc", "libc", ] [[package]] name = "pin-project-lite" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pkcs1" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" dependencies = [ "der", "pkcs8", "spki", ] [[package]] name = "pkcs8" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ "der", "spki", ] [[package]] name = "pkg-config" version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "polyval" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", "cpufeatures 0.2.17", "opaque-debug", "universal-hash", ] [[package]] name = "portable-atomic" version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "portable-atomic-util" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" dependencies = [ "portable-atomic", ] [[package]] name = "potential_utf" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ "zerovec", ] [[package]] name = "powerfmt" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ "zerocopy 0.8.53", ] [[package]] name = "precomputed-hash" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "predicates" version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ada8f2932f28a27ee7b70dd6c1c39ea0675c55a36879ab92f3a715eaa1e63cfe" dependencies = [ "anstyle", "difflib", "float-cmp", "normalize-line-endings", "predicates-core", "regex", ] [[package]] name = "predicates-core" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cad38746f3166b4031b1a0d39ad9f954dd291e7854fcc0eed52ee41a0b50d144" [[package]] name = "predicates-tree" version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0de1b847b39c8131db0467e9df1ff60e6d0562ab8e9a16e568ad0fdb372e2f2" dependencies = [ "predicates-core", "termtree", ] [[package]] name = "prettyplease" version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", "syn", ] [[package]] name = "primeorder" version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" dependencies = [ "elliptic-curve", ] [[package]] name = "proc-macro2" version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "pulldown-cmark" version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9f068eba8e7071c5f9511831b44f32c740d5adf574e990f946ddb53db2f314e" dependencies = [ "bitflags 2.13.0", "getopts", "memchr", "pulldown-cmark-escape", "unicase", ] [[package]] name = "pulldown-cmark-escape" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae" [[package]] name = "quote" version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "r-efi" version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "radium" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "radix_trie" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" dependencies = [ "endian-type", "nibble_vec", ] [[package]] name = "rand" version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.4", ] [[package]] name = "rand" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.5", ] [[package]] name = "rand_chacha" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", "rand_core 0.6.4", ] [[package]] name = "rand_chacha" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", "rand_core 0.9.5", ] [[package]] name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom 0.2.17", ] [[package]] name = "rand_core" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ "getrandom 0.3.4", ] [[package]] name = "rand_core" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] name = "rayon" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" dependencies = [ "either", "rayon-core", ] [[package]] name = "rayon-core" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" dependencies = [ "crossbeam-deque", "crossbeam-utils", ] [[package]] name = "redox_syscall" version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ "bitflags 2.13.0", ] [[package]] name = "redox_users" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom 0.2.17", "libredox", "thiserror 1.0.69", ] [[package]] name = "redox_users" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.17", "libredox", "thiserror 2.0.18", ] [[package]] name = "regex" version = "1.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" dependencies = [ "aho-corasick", "memchr", "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "remove_dir_all" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "808cc0b475acf76adf36f08ca49429b12aad9f678cb56143d5b3cb49b9a1dd08" dependencies = [ "cfg-if", "cvt", "fs_at", "libc", "normpath", "windows-sys 0.59.0", ] [[package]] name = "reqwest" version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64", "bytes", "encoding_rs", "futures-core", "futures-util", "h2", "hickory-resolver 0.25.2", "http", "http-body", "http-body-util", "hyper", "hyper-rustls", "hyper-tls", "hyper-util", "js-sys", "log", "mime", "native-tls", "once_cell", "percent-encoding", "pin-project-lite", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", "tokio", "tokio-native-tls", "tokio-util", "tower", "tower-http", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "wasm-streams", "web-sys", ] [[package]] name = "resolv-conf" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7" [[package]] name = "rfc6979" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ "hmac", "subtle", ] [[package]] name = "ring" version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", "getrandom 0.2.17", "libc", "untrusted", "windows-sys 0.52.0", ] [[package]] name = "ripemd" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" dependencies = [ "digest 0.10.7", ] [[package]] name = "roadmap" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec49775c5134c7e4befdedecaf112bb72964baa9b24bedfc79b54c3ca0ee9f77" dependencies = [ "anyhow", "marked-yaml 0.7.2", "serde", "tempfile", "textwrap", "thiserror 2.0.18", ] [[package]] name = "roff" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88f8660c1ff60292143c98d08fc6e2f654d722db50410e3f3797d40baaf9d8f3" [[package]] name = "rpassword" version = "7.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2da316a15f47e3d053de9cb2c439650bd8fa4aaeb9365f2e5f27f492ff73c196" dependencies = [ "libc", "rtoolbox", "windows-sys 0.61.2", ] [[package]] name = "rsa" version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" dependencies = [ "const-oid", "digest 0.10.7", "num-bigint-dig", "num-integer", "num-traits", "pkcs1", "pkcs8", "rand_core 0.6.4", "signature 2.2.0", "spki", "subtle", "zeroize", ] [[package]] name = "rsqlite-vfs" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c51c9ae4df8a7fba42103df5c621fa3c37eccf3a3c650879e90fc48b11cc192c" dependencies = [ "hashbrown 0.16.1", "thiserror 2.0.18", ] [[package]] name = "rtoolbox" version = "0.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50a0e551c1e27e1731aba276dbeaeac73f53c7cd34d1bda485d02bd1e0f36844" dependencies = [ "libc", "windows-sys 0.59.0", ] [[package]] name = "rusqlite" version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0d2b0146dd9661bf67bb107c0bb2a55064d556eeb3fc314151b957f313bcd4e" dependencies = [ "bitflags 2.13.0", "fallible-iterator", "fallible-streaming-iterator", "hashlink 0.11.1", "libsqlite3-sys", "smallvec", "sqlite-wasm-rs", ] [[package]] name = "rustc-hash" version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" [[package]] name = "rustc_version" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ "bitflags 2.13.0", "errno", "libc", "linux-raw-sys", "windows-sys 0.61.2", ] [[package]] name = "rustls" version = "0.23.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b92b125634d9b795e7beca796cc790df15a7fb38323bf3196fda83292d06b1f" dependencies = [ "once_cell", "rustls-pki-types", "rustls-webpki", "subtle", "zeroize", ] [[package]] name = "rustls-pki-types" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046" dependencies = [ "zeroize", ] [[package]] name = "rustls-webpki" version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ "ring", "rustls-pki-types", "untrusted", ] [[package]] name = "rustversion" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "same-file" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ "winapi-util", ] [[package]] name = "schannel" version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" dependencies = [ "windows-sys 0.61.2", ] [[package]] name = "scoped-tls" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sec1" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der", "generic-array 0.14.7", "pkcs8", "serdect", "subtle", "zeroize", ] [[package]] name = "security-framework" version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ "bitflags 2.13.0", "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", ] [[package]] name = "security-framework-sys" version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" dependencies = [ "core-foundation-sys", "libc", ] [[package]] name = "semver" version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "sequoia-autocrypt" version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d65ff1c8589a3e505d36c8e1919483bf4a2d8d6eb65f84c3922fbdcae6928b" dependencies = [ "base64", "sequoia-openpgp", ] [[package]] name = "sequoia-cert-store" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4e07e420427eb5e0dc3bb61172d181fa3c87afb2a77e8c629e920f54a291a6d" dependencies = [ "anyhow", "crossbeam", "dirs", "gethostname", "num_cpus", "openpgp-cert-d", "rayon", "rusqlite", "sequoia-openpgp", "smallvec", "thiserror 2.0.18", "url", ] [[package]] name = "sequoia-directories" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b01dd48960c5cf8617ab77e5c9f8ebeb55a1d694e3eabf830fa70453ffa637d5" dependencies = [ "anyhow", "directories", "same-file", "tempfile", "thiserror 1.0.69", ] [[package]] name = "sequoia-gpg-agent" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c36b37720b61230507a953d9879eb0dd8c228d86948d37cba53ced942e862a1" dependencies = [ "anyhow", "chrono", "futures", "lalrpop", "lalrpop-util", "libc", "sequoia-ipc", "sequoia-openpgp", "stfu8", "tempfile", "thiserror 2.0.18", "tokio", ] [[package]] name = "sequoia-ipc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0770bf144d96733921b4647cd4b243cbebf032127676a441e3ebe702c0768c54" dependencies = [ "anyhow", "capnp-rpc", "capnpc", "ctor", "dirs", "fs2", "lalrpop", "lalrpop-util", "libc", "memsec", "sequoia-openpgp", "socket2", "tempfile", "thiserror 2.0.18", "tokio", "tokio-util", "winapi", ] [[package]] name = "sequoia-keystore" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50e5887d0c3c5f0df1d1cab937ef7a5c398111ddfd911c714f28c904438f229c" dependencies = [ "anyhow", "async-generic", "capnp", "capnpc", "dirs", "env_logger", "log", "paste", "sequoia-directories", "sequoia-ipc", "sequoia-keystore-backend", "sequoia-keystore-gpg-agent", "sequoia-keystore-softkeys", "sequoia-openpgp", "thiserror 2.0.18", "tokio", "tokio-util", ] [[package]] name = "sequoia-keystore-backend" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c55b047f9b6412c34dc7a26a42f278205cbf1e29516feab1228edccca215f500" dependencies = [ "anyhow", "async-trait", "env_logger", "futures", "log", "sequoia-openpgp", "tempfile", "thiserror 2.0.18", "tokio", ] [[package]] name = "sequoia-keystore-gpg-agent" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ad901f1f1d88b38f5f5738d5bf2b80136ec44e94a40716193be0bbf3314df2b" dependencies = [ "anyhow", "async-trait", "futures", "log", "openpgp-cert-d", "sequoia-gpg-agent", "sequoia-ipc", "sequoia-keystore-backend", "sequoia-openpgp", "tokio", ] [[package]] name = "sequoia-keystore-softkeys" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c4944848f748ce22875020e9cff9e604d52c563aef8e19053f5abe037139e" dependencies = [ "anyhow", "async-trait", "dirs", "futures", "log", "sequoia-keystore-backend", "sequoia-openpgp", ] [[package]] name = "sequoia-man" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "961fa9711d7a1d9ccc13ac55b65482f828399dda12a0be7fa4e059dca410d217" dependencies = [ "anyhow", "clap", "roff", ] [[package]] name = "sequoia-net" version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75c0ea4f555b2b109fb39d6c5ebdb614945d82da0105957591adf4641e9cc3b2" dependencies = [ "anyhow", "base64", "futures-util", "hickory-client", "hickory-resolver 0.24.4", "http", "hyper", "hyper-tls", "libc", "percent-encoding", "reqwest", "sequoia-openpgp", "thiserror 2.0.18", "tokio", "url", "z-base-32", ] [[package]] name = "sequoia-openpgp" version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421679c8175ef4674d913af7fdb8ad0078c8a2599db633ad0b4d02a06b2cb3c" dependencies = [ "aes", "aes-gcm", "anyhow", "argon2", "base64", "block-padding", "blowfish", "botan", "buffered-reader", "bzip2", "camellia", "cast5", "cbc", "cfb-mode", "chrono", "cipher", "cx448", "des", "digest 0.10.7", "dsa", "dyn-clone", "eax", "ecb", "ecdsa", "ed25519", "ed25519-dalek", "flate2", "getrandom 0.2.17", "hkdf", "idea", "idna", "lalrpop", "lalrpop-util", "libc", "md-5", "memsec", "ml-dsa", "ml-kem", "nettle", "num-bigint-dig", "num-integer", "ocb3", "ossl", "p256", "p384", "p521", "rand 0.9.4", "rand_core 0.6.4", "regex", "regex-syntax", "ripemd", "rsa", "sha1collisiondetection", "sha2", "sha3 0.10.9", "slh-dsa", "thiserror 2.0.18", "twofish", "typenum", "win-crypto-ng", "winapi", "x25519-dalek", "xxhash-rust", "zeroize", ] [[package]] name = "sequoia-policy-config" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54ecc2eeefc0ccbba225e6e57ef1cde9df78e55b315e71fd95ebebc5bd1dbbb6" dependencies = [ "anyhow", "chrono", "sequoia-openpgp", "serde", "thiserror 2.0.18", "toml", ] [[package]] name = "sequoia-sq" version = "1.4.0" dependencies = [ "aho-corasick", "anyhow", "assert_cmd", "buffered-reader", "cfg-if", "chrono", "clap", "clap_complete", "clap_lex", "culpa", "dirs", "filetime", "fs_extra", "futures-util", "gethostname", "humantime", "indicatif", "libc", "once_cell", "predicates", "regex", "reqwest", "roff", "rpassword", "rusqlite", "sequoia-autocrypt", "sequoia-cert-store", "sequoia-directories", "sequoia-ipc", "sequoia-keystore", "sequoia-man", "sequoia-net", "sequoia-openpgp", "sequoia-policy-config", "sequoia-wot", "serde", "subplot-build", "subplotlib", "tempfile", "termcolor", "terminal_size", "textwrap", "thiserror 1.0.69", "tokio", "toml_edit", "typenum", ] [[package]] name = "sequoia-wot" version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc825dbf5b5d5d20b16a01e39319a0e4d6368ea8b6ea7e88d12d2bd30532b011" dependencies = [ "anyhow", "chrono", "crossbeam", "num_cpus", "sequoia-cert-store", "sequoia-openpgp", "thiserror 2.0.18", ] [[package]] name = "serde" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", "serde_derive", ] [[package]] name = "serde_core" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_json" version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ "itoa", "memchr", "serde", "serde_core", "zmij", ] [[package]] name = "serde_path_to_error" version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" dependencies = [ "itoa", "serde", "serde_core", ] [[package]] name = "serde_spanned" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" dependencies = [ "serde_core", ] [[package]] name = "serde_urlencoded" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", "itoa", "ryu", "serde", ] [[package]] name = "serdect" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" dependencies = [ "base16ct", "serde", ] [[package]] name = "sha1collisiondetection" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f606421e4a6012877e893c399822a4ed4b089164c5969424e1b9d1e66e6964b" dependencies = [ "const-oid", "digest 0.10.7", "generic-array 1.4.3", ] [[package]] name = "sha2" version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures 0.2.17", "digest 0.10.7", ] [[package]] name = "sha3" version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77fd7028345d415a4034cf8777cd4f8ab1851274233b45f84e3d955502d93874" dependencies = [ "digest 0.10.7", "keccak 0.1.6", ] [[package]] name = "sha3" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be176f1a57ce4e3d31c1a166222d9768de5954f811601fb7ca06fc8203905ce1" dependencies = [ "digest 0.11.3", "keccak 0.2.0", ] [[package]] name = "shake" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09057cb2149ad4cbd2da1e26b351f9a4c354219421229c69c3063e6f61947c4a" dependencies = [ "digest 0.11.3", "keccak 0.2.0", "sponge-cursor", ] [[package]] name = "sharded-slab" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] [[package]] name = "shell-words" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77" [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "shlex" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "signature" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest 0.10.7", "rand_core 0.6.4", ] [[package]] name = "signature" version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d567dcbaf0049cb8ac2608a76cd95ff9e4412e1899d389ee400918ca7537f5" dependencies = [ "digest 0.11.3", ] [[package]] name = "simd-adler32" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" [[package]] name = "siphasher" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" [[package]] name = "slab" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "slh-dsa" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd2f20f4049197e03db1104a6452f4d9e96665d79f880198dce4a7026ba5f267" dependencies = [ "const-oid", "digest 0.10.7", "hmac", "hybrid-array 0.3.1", "pkcs8", "rand_core 0.6.4", "sha2", "sha3 0.10.9", "signature 2.2.0", "typenum", "zerocopy 0.7.35", ] [[package]] name = "slug" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "882a80f72ee45de3cc9a5afeb2da0331d58df69e4e7d8eeb5d3c7784ae67e724" dependencies = [ "deunicode", "wasm-bindgen", ] [[package]] name = "smallvec" version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" [[package]] name = "smawk" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8e2fb0f499abb4d162f2bedad68f5ef91a1682b5a03596ddb67efd37768d100" [[package]] name = "socket2" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" dependencies = [ "libc", "windows-sys 0.61.2", ] [[package]] name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "spki" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", "der", ] [[package]] name = "sponge-cursor" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a0219bd7d979d58245a4f41f695e1ac9f8befdffadd7f61f1bae9e39abc6620" [[package]] name = "sqlite-wasm-rs" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc3efc0da82635d7e1ced0053bbbfa8c7ab9645d0bf36ceb4f7127bb85315d75" dependencies = [ "cc", "js-sys", "rsqlite-vfs", "wasm-bindgen", ] [[package]] name = "stable_deref_trait" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "state" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b8c4a4445d81357df8b1a650d0d0d6fbbbfe99d064aa5e02f3e4022061476d8" dependencies = [ "loom", ] [[package]] name = "stfu8" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51f1e89f093f99e7432c491c382b88a6860a5adbe6bf02574bf0a08efff1978" [[package]] name = "string_cache" version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" dependencies = [ "new_debug_unreachable", "parking_lot", "phf_shared", "precomputed-hash", ] [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "subplot" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2d7d684d11cc4256f675dd026f2999762fdd407dcdfae7ed06005370359dc6" dependencies = [ "anyhow", "base64", "descape", "getopts", "html-escape", "lazy_static", "line-col", "marked-yaml 0.8.0", "pikchr", "pulldown-cmark", "regex", "roadmap", "serde", "serde_json", "slug", "tera", "thiserror 2.0.18", "tracing", "walkdir", ] [[package]] name = "subplot-build" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a1e4b117c4e8177c359b14cbea439ff70c4d8c91f81f1361c49987f8890e8c7" dependencies = [ "subplot", "tracing", ] [[package]] name = "subplotlib" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e975eda1ad88fef962133294b2bfee9e3a586b92e2f57b4d7c7544485199f042" dependencies = [ "base64", "culpa", "filetime", "fs2", "lazy_static", "regex", "remove_dir_all", "shell-words", "state", "subplotlib-derive", "tempfile", "time", ] [[package]] name = "subplotlib-derive" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd444e7bcbeb865f8337901f7266b9d6175b36cd16c4950fe2a49f4dbdbc7785" dependencies = [ "culpa", "proc-macro2", "quote", "subplot", "syn", ] [[package]] name = "subtle" version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" version = "2.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "sync_wrapper" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ "futures-core", ] [[package]] name = "synstructure" version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "system-configuration" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ "bitflags 2.13.0", "core-foundation 0.9.4", "system-configuration-sys", ] [[package]] name = "system-configuration-sys" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" dependencies = [ "core-foundation-sys", "libc", ] [[package]] name = "tagptr" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" [[package]] name = "tap" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", "getrandom 0.4.3", "once_cell", "rustix", "windows-sys 0.61.2", ] [[package]] name = "tera" version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8004bca281f2d32df3bacd59bc67b312cb4c70cea46cbd79dbe8ac5ed206722" dependencies = [ "globwalk", "humansize", "lazy_static", "percent-encoding", "pest", "pest_derive", "rand 0.8.6", "regex", "serde", "serde_json", "slug", "unicode-segmentation", ] [[package]] name = "term" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8c27177b12a6399ffc08b98f76f7c9a1f4fe9fc967c784c5a071fa8d93cf7e1" dependencies = [ "windows-sys 0.61.2", ] [[package]] name = "termcolor" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] [[package]] name = "terminal_size" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" dependencies = [ "rustix", "windows-sys 0.61.2", ] [[package]] name = "termtree" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" [[package]] name = "textwrap" version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" dependencies = [ "smawk", "unicode-linebreak", "unicode-width", ] [[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]] name = "thiserror" version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ "thiserror-impl 2.0.18", ] [[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]] name = "thiserror-impl" version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "thread_local" version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ "cfg-if", ] [[package]] name = "time" version = "0.3.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9e442fc33d7fdb45aa9bfeb312c095964abdf596f7567261062b2a7107aaabd" dependencies = [ "deranged", "num-conv", "powerfmt", "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b36ee98fd31ec7426d599183e8fe26932a8dc1fb76ddb6214d05493377d34ca" [[package]] name = "time-macros" version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e552d1249bf61ac2a52db88179fd0673def1e1ad8243a00d9ec9ed71fee3dd" dependencies = [ "num-conv", "time-core", ] [[package]] name = "tinystr" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "zerovec", ] [[package]] name = "tinyvec" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] [[package]] name = "tinyvec_macros" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ "bytes", "libc", "mio", "pin-project-lite", "socket2", "tokio-macros", "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "tokio-native-tls" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ "native-tls", "tokio", ] [[package]] name = "tokio-rustls" version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ "rustls", "tokio", ] [[package]] name = "tokio-util" version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", "futures-io", "futures-sink", "pin-project-lite", "tokio", ] [[package]] name = "toml" version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" dependencies = [ "indexmap", "serde_core", "serde_spanned", "toml_datetime", "toml_parser", "toml_writer", "winnow", ] [[package]] name = "toml_datetime" version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" dependencies = [ "serde_core", ] [[package]] name = "toml_edit" version = "0.25.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7" dependencies = [ "indexmap", "toml_datetime", "toml_parser", "toml_writer", "winnow", ] [[package]] name = "toml_parser" version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ "winnow", ] [[package]] name = "toml_writer" version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" [[package]] name = "tower" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", "pin-project-lite", "sync_wrapper", "tokio", "tower-layer", "tower-service", ] [[package]] name = "tower-http" version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ "bitflags 2.13.0", "bytes", "futures-util", "http", "http-body", "pin-project-lite", "tower", "tower-layer", "tower-service", "url", ] [[package]] name = "tower-layer" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "pin-project-lite", "tracing-attributes", "tracing-core", ] [[package]] name = "tracing-attributes" version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "tracing-core" version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", ] [[package]] name = "tracing-log" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ "log", "once_cell", "tracing-core", ] [[package]] name = "tracing-subscriber" version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ "matchers", "nu-ansi-term", "once_cell", "regex-automata", "sharded-slab", "smallvec", "thread_local", "tracing", "tracing-core", "tracing-log", ] [[package]] name = "try-lock" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "twofish" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a78e83a30223c757c3947cd144a31014ff04298d8719ae10d03c31c0448c8013" dependencies = [ "cipher", ] [[package]] name = "typenum" version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "ucd-trie" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "unicase" version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-linebreak" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" [[package]] name = "unicode-segmentation" version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" [[package]] name = "unicode-width" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] name = "unicode-xid" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "unit-prefix" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3" [[package]] name = "universal-hash" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ "crypto-common 0.1.7", "subtle", ] [[package]] name = "untrusted" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", "percent-encoding", "serde", ] [[package]] name = "utf8_iter" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "utf8parse" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" version = "1.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf80a72845275afea99e7f2b434723d3bc7e38470fcd1c7ed39a599c73319a53" dependencies = [ "getrandom 0.4.3", "js-sys", "wasm-bindgen", ] [[package]] name = "valuable" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "vcpkg" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wait-timeout" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" dependencies = [ "libc", ] [[package]] name = "walkdir" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", ] [[package]] name = "want" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ "try-lock", ] [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ "wit-bindgen", ] [[package]] name = "wasm-bindgen" version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" version = "0.4.76" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" dependencies = [ "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" dependencies = [ "bumpalo", "proc-macro2", "quote", "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" dependencies = [ "unicode-ident", ] [[package]] name = "wasm-streams" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" dependencies = [ "futures-util", "js-sys", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", ] [[package]] name = "web-sys" version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] name = "web-time" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] name = "widestring" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" [[package]] name = "win-crypto-ng" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99abfb435a71e54ab2971d8d8c32f1a7e006cdbf527f71743b1d45b93517bb92" dependencies = [ "cipher", "doc-comment", "rand_core 0.6.4", "winapi", "zeroize", ] [[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ "windows-sys 0.61.2", ] [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ "windows-targets 0.48.5", ] [[package]] name = "windows-core" version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", "windows-link", "windows-result", "windows-strings", ] [[package]] name = "windows-implement" version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "windows-interface" version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-registry" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" dependencies = [ "windows-link", "windows-result", "windows-strings", ] [[package]] name = "windows-result" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ "windows-link", ] [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ "windows-targets 0.48.5", ] [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ "windows-targets 0.52.6", ] [[package]] name = "windows-sys" version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets 0.52.6", ] [[package]] name = "windows-sys" version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ "windows-link", ] [[package]] name = "windows-targets" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm 0.48.5", "windows_aarch64_msvc 0.48.5", "windows_i686_gnu 0.48.5", "windows_i686_msvc 0.48.5", "windows_x86_64_gnu 0.48.5", "windows_x86_64_gnullvm 0.48.5", "windows_x86_64_msvc 0.48.5", ] [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" dependencies = [ "memchr", ] [[package]] name = "wit-bindgen" version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "writeable" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "wyz" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" dependencies = [ "tap", ] [[package]] name = "x25519-dalek" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" dependencies = [ "curve25519-dalek", "rand_core 0.6.4", "zeroize", ] [[package]] name = "xxhash-rust" version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d93c89cdc2d3a63c3ec48ffe926931bdc069eafa8e4402fe6d8f790c9d1e576" [[package]] name = "yaml-rust2" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a1a1c0bc9823338a3bdf8c61f994f23ac004c6fa32c08cd152984499b445e8d" dependencies = [ "arraydeque", "encoding_rs", "hashlink 0.9.1", ] [[package]] name = "yaml-rust2" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2462ea039c445496d8793d052e13787f2b90e750b833afee748e601c17621ed9" dependencies = [ "arraydeque", "encoding_rs", "hashlink 0.10.0", ] [[package]] name = "yoke" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" dependencies = [ "stable_deref_trait", "yoke-derive", "zerofrom", ] [[package]] name = "yoke-derive" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", "syn", "synstructure", ] [[package]] name = "z-base-32" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44f94003b56f8f812c88dd188d9bafc71d8e3786fd04812c2d8cdb176810ceb4" [[package]] name = "zerocopy" version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "byteorder", "zerocopy-derive 0.7.35", ] [[package]] name = "zerocopy" version = "0.8.53" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75726053136156d419e285b9b7eddaaea9e3fea6ce32eed44a89901f0bd98de1" dependencies = [ "zerocopy-derive 0.8.53", ] [[package]] name = "zerocopy-derive" version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "zerocopy-derive" version = "0.8.53" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4714fd92cf900833d49538023a9b3915155210801d1c1169eba513b2addefd71" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "zerofrom" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", "syn", "synstructure", ] [[package]] name = "zeroize" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "zerotrie" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" dependencies = [ "displaydoc", "yoke", "zerofrom", ] [[package]] name = "zerovec" version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ "yoke", "zerofrom", "zerovec-derive", ] [[package]] name = "zerovec-derive" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "zmij" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" sequoia-sq-1.4.0/Cargo.toml0000644000000170521046102023000111520ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.85" name = "sequoia-sq" version = "1.4.0" authors = [ "Azul ", "Heiko Schaefer ", "Igor Matuszewski ", "Justus Winter ", "Kai Michaelis ", "Lars Wirzenius ", "Neal H. Walfield ", "Nora Widdecke ", "Wiktor Kwapisiewicz ", ] build = "build.rs" autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "Command-line frontends for Sequoia" homepage = "https://sequoia-pgp.org/" documentation = "https://docs.rs/sequoia-sq" readme = "README.md" keywords = [ "cryptography", "openpgp", "pgp", "encryption", "signing", ] categories = [ "cryptography", "authentication", "command-line-utilities", ] license = "LGPL-2.0-or-later" repository = "https://gitlab.com/sequoia-pgp/sequoia-sq" [badges.gitlab] repository = "sequoia-pgp/sequoia-sq" [badges.maintenance] status = "actively-developed" [features] allow-experimental-crypto = ["sequoia-openpgp/allow-experimental-crypto"] allow-variable-time-crypto = ["sequoia-openpgp/allow-variable-time-crypto"] crypto-botan = ["sequoia-openpgp/crypto-botan"] crypto-botan2 = ["sequoia-openpgp/crypto-botan2"] crypto-cng = ["sequoia-openpgp/crypto-cng"] crypto-nettle = ["sequoia-openpgp/crypto-nettle"] crypto-openssl = ["sequoia-openpgp/crypto-openssl"] crypto-rust = ["sequoia-openpgp/crypto-rust"] default = ["crypto-nettle"] subplot = [ "culpa", "subplot-build", "subplotlib", ] [[bin]] name = "sq" path = "src/main.rs" bench = false [[test]] name = "integration" path = "tests/integration.rs" [[test]] name = "sq-subplot" path = "tests/sq-subplot.rs" required-features = ["subplot"] [dependencies.aho-corasick] version = "1" [dependencies.anyhow] version = "1.0.18" [dependencies.buffered-reader] version = "1.4" features = ["compression"] default-features = false [dependencies.chrono] version = "0.4.10" [dependencies.clap] version = "4" features = [ "derive", "env", "string", "wrap_help", ] [dependencies.clap_lex] version = ">=0.7, <2" default-features = false [dependencies.culpa] version = "1" optional = true [dependencies.dirs] version = ">=5, <7" [dependencies.filetime] version = "0.2" [dependencies.fs_extra] version = "1" [dependencies.futures-util] version = "0.3" [dependencies.gethostname] version = ">=0.4, <2" [dependencies.humantime] version = "2" [dependencies.indicatif] version = ">= 0.17, <0.19" [dependencies.libc] version = "0.2" [dependencies.once_cell] version = "1.17" [dependencies.regex] version = "1" [dependencies.reqwest] version = ">=0.12, <0.13" features = [ "hickory-dns", "stream", ] [dependencies.rpassword] version = "7.0" [dependencies.rusqlite] version = ">=0.31, <0.41" [dependencies.sequoia-autocrypt] version = "0.26" default-features = false [dependencies.sequoia-cert-store] version = "0.7" default-features = false [dependencies.sequoia-directories] version = "0.1" [dependencies.sequoia-ipc] version = "0.36" default-features = false [dependencies.sequoia-keystore] version = "0.7" [dependencies.sequoia-net] version = "0.30" default-features = false [dependencies.sequoia-openpgp] version = "2" features = ["compression"] default-features = false [dependencies.sequoia-policy-config] version = "0.8" [dependencies.sequoia-wot] version = "0.15" default-features = false [dependencies.serde] version = "1.0.137" features = ["derive"] [dependencies.subplotlib] version = ">=0.11, <0.14" optional = true [dependencies.tempfile] version = "3.1" [dependencies.termcolor] version = "1.2.0" [dependencies.terminal_size] version = ">=0.2.6, <0.5" [dependencies.textwrap] version = ">=0.15, <0.17" features = [ "smawk", "unicode-width", ] default-features = false [dependencies.thiserror] version = ">=1, <3" [dependencies.tokio] version = "1.13.1" [dependencies.toml_edit] version = ">= 0.22, <0.26" features = [ "display", "parse", ] default-features = false [dependencies.typenum] version = "1" [dev-dependencies.assert_cmd] version = "2" [dev-dependencies.libc] version = "0.2" [dev-dependencies.predicates] version = ">=2, <4" [dev-dependencies.regex] version = "1" [build-dependencies.anyhow] version = "1.0.18" [build-dependencies.buffered-reader] version = "1.4" features = ["compression"] default-features = false [build-dependencies.cfg-if] version = "1" [build-dependencies.chrono] version = "0.4.38" [build-dependencies.clap] version = "4" features = [ "derive", "env", "string", "wrap_help", ] [build-dependencies.clap_complete] version = "4" [build-dependencies.clap_lex] version = ">=0.7, <2" default-features = false [build-dependencies.dirs] version = ">=5, <7" [build-dependencies.roff] version = ">=0.2.1, <2" [build-dependencies.sequoia-directories] version = "0.1" [build-dependencies.sequoia-man] version = "0.3" [build-dependencies.sequoia-net] version = "0.30" default-features = false [build-dependencies.sequoia-openpgp] version = "2" features = ["compression"] default-features = false [build-dependencies.serde] version = "1.0.137" features = ["derive"] [build-dependencies.subplot-build] version = ">=0.11, <0.14" optional = true [build-dependencies.terminal_size] version = ">=0.2.6, <0.5" [build-dependencies.textwrap] version = ">=0.15, <0.17" [build-dependencies.typenum] version = "1" [profile.dev.package.aes] opt-level = 2 [profile.dev.package.aes-gcm] opt-level = 2 [profile.dev.package.argon2] opt-level = 2 [profile.dev.package.blake2] opt-level = 2 [profile.dev.package.block-padding] opt-level = 2 [profile.dev.package.blowfish] opt-level = 2 [profile.dev.package.camellia] opt-level = 2 [profile.dev.package.cast5] opt-level = 2 [profile.dev.package.cfb-mode] opt-level = 2 [profile.dev.package.cipher] opt-level = 2 [profile.dev.package.cx448] opt-level = 2 [profile.dev.package.des] opt-level = 2 [profile.dev.package.digest] opt-level = 2 [profile.dev.package.dsa] opt-level = 2 [profile.dev.package.eax] opt-level = 2 [profile.dev.package.ecb] opt-level = 2 [profile.dev.package.ecdsa] opt-level = 2 [profile.dev.package.ed25519] opt-level = 2 [profile.dev.package.ed25519-dalek] opt-level = 2 [profile.dev.package.idea] opt-level = 2 [profile.dev.package.keccak] opt-level = 2 [profile.dev.package.md-5] opt-level = 2 [profile.dev.package.ml-dsa] opt-level = 2 [profile.dev.package.ml-kem] opt-level = 2 [profile.dev.package.num-bigint-dig] opt-level = 2 [profile.dev.package.num-integer] opt-level = 2 [profile.dev.package.ocb3] opt-level = 2 [profile.dev.package.p256] opt-level = 2 [profile.dev.package.p384] opt-level = 2 [profile.dev.package.p521] opt-level = 2 [profile.dev.package.ripemd] opt-level = 2 [profile.dev.package.rsa] opt-level = 2 [profile.dev.package.sha2] opt-level = 2 [profile.dev.package.sha3] opt-level = 2 [profile.dev.package.slh-dsa] opt-level = 2 [profile.dev.package.twofish] opt-level = 2 [profile.dev.package.x25519-dalek] opt-level = 2 [profile.release] debug = 2 sequoia-sq-1.4.0/Cargo.toml.orig000064400000000000000000000144441046102023000146130ustar 00000000000000[package] name = "sequoia-sq" description = "Command-line frontends for Sequoia" version = "1.4.0" authors = [ "Azul ", "Heiko Schaefer ", "Igor Matuszewski ", "Justus Winter ", "Kai Michaelis ", "Lars Wirzenius ", "Neal H. Walfield ", "Nora Widdecke ", "Wiktor Kwapisiewicz ", ] build = "build.rs" documentation = "https://docs.rs/sequoia-sq" homepage = "https://sequoia-pgp.org/" repository = "https://gitlab.com/sequoia-pgp/sequoia-sq" readme = "README.md" keywords = ["cryptography", "openpgp", "pgp", "encryption", "signing"] categories = ["cryptography", "authentication", "command-line-utilities"] license = "LGPL-2.0-or-later" edition = "2021" rust-version = "1.85" [badges] gitlab = { repository = "sequoia-pgp/sequoia-sq" } maintenance = { status = "actively-developed" } [dependencies] aho-corasick = "1" buffered-reader = { version = "1.4", default-features = false, features = ["compression"] } dirs = ">=5, <7" filetime = "0.2" fs_extra = "1" sequoia-directories = "0.1" sequoia-openpgp = { version = "2", default-features = false, features = ["compression"] } sequoia-autocrypt = { version = "0.26", default-features = false } sequoia-net = { version = "0.30", default-features = false } sequoia-policy-config = "0.8" anyhow = "1.0.18" chrono = "0.4.10" clap = { version = "4", features = ["derive", "env", "string", "wrap_help"] } clap_lex = { version = ">=0.7, <2", default-features = false } futures-util = "0.3" gethostname = { version = ">=0.4, <2" } humantime = "2" libc = "0.2" indicatif = ">= 0.17, <0.19" once_cell = "1.17" reqwest = { version = ">=0.12, <0.13", features = ["hickory-dns", "stream"] } sequoia-cert-store = { version = "0.7", default-features = false } sequoia-ipc = { version = "0.36", default-features = false } sequoia-keystore = { version = "0.7" } sequoia-wot = { version = "0.15", default-features = false } tempfile = "3.1" thiserror = { version = ">=1, <3" } tokio = { version = "1.13.1" } toml_edit = { version = ">= 0.22, <0.26", default-features = false, features = ["display", "parse"] } regex = "1" rpassword = "7.0" rusqlite = ">=0.31, <0.41" serde = { version = "1.0.137", features = ["derive"] } terminal_size = ">=0.2.6, <0.5" termcolor = "1.2.0" textwrap = { version = ">=0.15, <0.17", default-features = false, features = ["smawk", "unicode-width"] } typenum = "1" # This is for subplot only. If you don't enable the subplot feature, # feel free to patch it out. subplotlib = { version = ">=0.11, <0.14", optional = true } culpa = { version = "1", optional = true } [build-dependencies] anyhow = "1.0.18" buffered-reader = { version = "1.4", default-features = false, features = ["compression"] } clap = { version = "4", features = ["derive", "env", "string", "wrap_help"] } clap_complete = "4" clap_lex = { version = ">=0.7, <2", default-features = false } chrono = "0.4.38" dirs = ">=5, <7" roff = ">=0.2.1, <2" serde = { version = "1.0.137", features = ["derive"] } sequoia-directories = "0.1" sequoia-man = "0.3" sequoia-openpgp = { version = "2", default-features = false, features = ["compression"] } sequoia-net = { version = "0.30", default-features = false } textwrap = ">=0.15, <0.17" typenum = "1" cfg-if = "1" terminal_size = ">=0.2.6, <0.5" # This is for subplot only. If you don't enable the subplot feature, # feel free to patch it out. subplot-build = { version = ">=0.11, <0.14", optional = true } [dev-dependencies] assert_cmd = "2" predicates = ">=2, <4" regex = "1" libc = "0.2" [[bin]] name = "sq" path = "src/main.rs" bench = false [[test]] name = "sq-subplot" path = "tests/sq-subplot.rs" required-features = ["subplot"] [features] default = [ "crypto-nettle", ] crypto-nettle = ["sequoia-openpgp/crypto-nettle"] crypto-openssl = ["sequoia-openpgp/crypto-openssl"] crypto-botan = ["sequoia-openpgp/crypto-botan"] crypto-botan2 = ["sequoia-openpgp/crypto-botan2"] crypto-cng = ["sequoia-openpgp/crypto-cng"] crypto-rust = ["sequoia-openpgp/crypto-rust"] allow-experimental-crypto = ["sequoia-openpgp/allow-experimental-crypto"] allow-variable-time-crypto = ["sequoia-openpgp/allow-variable-time-crypto"] subplot = ["culpa", "subplot-build", "subplotlib"] [profile.release] debug = true [workspace.lints.clippy] # default clippy lint levels matching the common-ci environment: # https://gitlab.com/sequoia-pgp/common-ci/-/blob/main/templates/precheck.yml suspicious = { level = "deny", priority = -1 } style = { level = "allow", priority = -1 } complexity = { level = "allow", priority = -1 } # The Rust Crypto crates are *very* slow when compiled without any # optimizations. Turn on some optimizations. [profile.dev.package.aes] opt-level = 2 [profile.dev.package.aes-gcm] opt-level = 2 [profile.dev.package.argon2] opt-level = 2 [profile.dev.package.blake2] opt-level = 2 [profile.dev.package.block-padding] opt-level = 2 [profile.dev.package.blowfish] opt-level = 2 [profile.dev.package.camellia] opt-level = 2 [profile.dev.package.cast5] opt-level = 2 [profile.dev.package.cipher] opt-level = 2 [profile.dev.package.cfb-mode] opt-level = 2 [profile.dev.package.cx448] opt-level = 2 [profile.dev.package.des] opt-level = 2 [profile.dev.package.digest] opt-level = 2 [profile.dev.package.dsa] opt-level = 2 [profile.dev.package.eax] opt-level = 2 [profile.dev.package.ecb] opt-level = 2 [profile.dev.package.ecdsa] opt-level = 2 [profile.dev.package.ed25519] opt-level = 2 [profile.dev.package.ed25519-dalek] opt-level = 2 [profile.dev.package.idea] opt-level = 2 [profile.dev.package.keccak] opt-level = 2 [profile.dev.package.md-5] opt-level = 2 [profile.dev.package.ml-dsa] opt-level = 2 [profile.dev.package.ml-kem] opt-level = 2 [profile.dev.package.num-bigint-dig] opt-level = 2 [profile.dev.package.num-integer] opt-level = 2 [profile.dev.package.ocb3] opt-level = 2 [profile.dev.package.p256] opt-level = 2 [profile.dev.package.p384] opt-level = 2 [profile.dev.package.p521] opt-level = 2 [profile.dev.package.ripemd] opt-level = 2 [profile.dev.package.rsa] opt-level = 2 [profile.dev.package.sha2] opt-level = 2 [profile.dev.package.sha3] opt-level = 2 [profile.dev.package.slh-dsa] opt-level = 2 [profile.dev.package.twofish] opt-level = 2 [profile.dev.package.x25519-dalek] opt-level = 2 sequoia-sq-1.4.0/Containerfile000064400000000000000000000042301046102023000144210ustar 00000000000000# See https://gitlab.com/sequoia-pgp/sequoia/-/blob/main/README.md#debian # for system requirements FROM docker.io/library/debian:trixie AS build # create a sandbox user for the build (in ~builder) and install (in /opt) # give it permissions to the build dir and home # upgrade everything # add dependencies, as specified by the Sequoia README.md file RUN groupadd builder && \ useradd --no-log-init --create-home --gid builder builder && \ apt-get update && \ apt-get upgrade --assume-yes && \ apt-get install --assume-yes --no-install-recommends \ ca-certificates \ capnproto \ cargo \ git \ libclang-dev \ libsqlite3-dev \ libssl-dev \ make \ nettle-dev \ pkg-config \ rustc \ && \ apt-get clean && \ chown builder /opt COPY --chown=builder:builder . /home/builder/sequoia # switch to the sandbox user USER builder # retry build because cargo sometimes segfaults during download (#918854) # # the `build-release` target is used instead of the default because # `install` calls it after anyways RUN cd /home/builder/sequoia && \ CARGO_TARGET_DIR=/tmp/target ASSET_OUT_DIR=/tmp/target/assets cargo build -p sequoia-sq --release && \ install --strip -D --target-directory /opt/usr/local/bin \ /tmp/target/release/sq FROM docker.io/library/debian:trixie-slim AS sq-base RUN apt-get update && \ apt-get upgrade --assume-yes && \ apt-get install -yqq \ bash-completion \ ca-certificates \ libssl3 \ libsqlite3-0 \ man-db && \ apt-get clean && \ rm -fr -- /var/lib/apt/lists/* /var/cache/* FROM sq-base AS sq COPY --from=build /opt/usr/local/bin/sq /usr/local/bin/sq COPY --from=build /etc/ssl/certs /etc/ssl/certs COPY --from=build /tmp/target/assets/shell-completions/sq.bash /etc/bash_completion.d/sq COPY --from=build /tmp/target/assets/man-pages/* /usr/share/man/man1/ ENV SEQUOIA_HOME=/sequoia SEQUOIA_CERT_STORE=/sequoia/certstore SEQUOIA_KEY_STORE=/sequoia/keystore # Set the default workdir to sequoia home directory WORKDIR /sequoia VOLUME /sequoia ENTRYPOINT ["/usr/local/bin/sq"] sequoia-sq-1.4.0/LICENSE.txt000064400000000000000000000627421046102023000135530ustar 00000000000000Sequoia PGP sq is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Sequoia PGP sq is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. --- GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! sequoia-sq-1.4.0/NEWS000064400000000000000000001227061046102023000124240ustar 00000000000000 -*- org -*- #+TITLE: sequoia-sq NEWS – history of user-visible changes #+STARTUP: content hidestars * Changes in 1.4.0 ** New functionality - `sq` now supports post quantum cryptography as defined in RFC 9980. - When directing `sq` to write to a file that already exists, the user had to specify `--overwrite`. This is no longer required for special files (character devices, block devices, FIFOs and Unix domain sockets). - When writing to a file, `sq` would first write to a temporary file in the same directory to avoid writing anything if the command fails. If the command succeeds, it would move the file into place. This would fail when writing to special files (character devices, block devices, FIFOs and Unix domain sockets) like `/dev/null` and when the directory is not writable. In these cases, `sq` now writes to a temporary file in the user's temporary directory (often under `/tmp`) and then copies the file. - If `sq` outputs sensitive content to a regular file like keys or revocation certificates, it restricts the output file's permissions on Unix-like operating systems so that the group permissions and other permissions don't allow access to the data. - You can use `sq key generate --encryption-algorithm` and `sq key generate --signing-algorithm` to specify the precise algorithm that `sq key generate` will use for encryption-capable keys and signing-capable keys, respectively. - Add the cipher suites Cv448, MLDSA65_Ed25519, and MLDSA87_Ed448, which can be used to control what algorithms `sq key generate` and `sq key subkey add` use. - `sq` no longer panics on a broken pipe. Instead it acts like other tools and exits with an exit code of 128 + SIGPIPE. ** Notable fixes - `sq download` no longer freezes if some of the passed URLs return a '404 - not found' error when trying to fetch them. * Changes in 1.3.1 - This is a bugfix release, fixing and improving displayed hints, improving test vectors so that the tests work fine years into the future, improving some documentation. No new functionality. * Changes in 1.3.0 ** New functionality - This release adds support for RFC 9580. * Changes in 1.2.0 ** New functionality - `sq pki vouch list` lists certifications made by a particular certificate or made on a particular certificate. - `sq pki vouch replay` replays the certifications made by one certificate using another certificate. - `sq key rotate` generates a new certificate based on an existing one. It also copies links, recreates certifications, and retires the old certificate. ** Notable fixes - `sq packet dump` no longer duplicates the PKESK or SKESK packet immediately preceding the SEIPD packet. - `sq key export` and `sq key subkey export` no longer export non-exportable signatures and cert components. - `sq --cli-version` was broken. The check was reversed. That is, instead of `sq` 1.1.0 saying that `sq --cli-version 1.0.0` is compatible, it said it is incompatible, and instead of saying that `sq --cli-version 1.2.0` is incompatible, it said that it is compatible. In terms of the API, this should be considered a new feature. - `sq cert lint`, `sq inspect`, `sq packet dump`, and `sq pki link list` didn't check that certificates designated by user ID using e.g., `--cert-email`, are actually authenticated. They are now correctly checked. * Changes in 1.1.0 ** New functionality - New argument `--unusable` for `sq cert list`, `sq pki identify`, `sq pki lookup`, and `sq pki authenticate`. This option causes these commands to also show unusable bindings and certificates (i.e., those that are not valid according to the current policy, are revoked, or are expired). Requires `--gossip`. ** Notable changes - Fix `--gossip`. The `--gossip` option for `sq cert list`, `sq pki identify`, `sq pki lookup`, and `sq pki authenticate` was broken. It is now fixed, and works as documented. In terms of the API, this should be considered a new feature, as although the option was present, it did not work. - `sq cert list --cert FPR` incorrectly failed if all of a certificate's bindings are invalid (i.e., the bindings are invalid according to the cryptographic policy, or the user ID is revoked). `sq cert list --cert FPR` now only considers the validity of the certificate. Note: this command correctly succeeded when the certificate had no bindings. - `sq cert list` showed certificates with no user IDs, but it should only show authenticated bindings. Certificates with no user IDs are no only shown when `--gossip` is provided. * Changes in 1.0.0 ** New functionality - `sq encrypt --for-self` now adds the certs configured under `encrypt.for-self` to the list of recipients. - `sq sign --signer-self` and `sq encrypt --signer-self` now add the keys configured under `sign.signer-self` to the list of signers. - `sq pki vouch add --certifier-self` and `sq pki vouch authorize --certifier-self` now use the key configured under `pki.vouch.certifier-self` as certification key. - `sq` now automatically imports certificates from GnuPG's certificate store. Note: we only do this for the default Sequoia and GnuPG state directories. Further, We don't parse the GnuPG configuration file, we just scan GnuPG's default cert stores. ** Notable changes - `sq pki link add`, `sq pki link authorize`, and `sq pki link retract` gain a new parameter, `--cert-special`, which allows addressing shadow CAs by symbolic names. For instance, `sq pki link authorize --cert-special keys.openpgp.org --all --unconstrained` can be used to fully trust the keys.openpgp.org key server. This also creates the shadow CA if it doesn't exist yet. - `sq sign --signature-file` now takes a value specifying where the signature should be written to. It conflicts with `--output`. - `sq cert list` now takes cert designators, like `--cert-email` instead of `--email`. - `sq encrypt` now requires explicit opt-out for signing in the form of the `--without-signature` flag. - Remove the `--name` argument from `sq key approvals list`, `sq key approvals update`, `sq key userid revoke` and `sq pki path`, and remove the `--name-or-add` argument from `sq key userid revoke`. - The arguments `--userid-or-add`, and `--email-or-add` have respectively been renamed to `--add-userid`, and `--add-email`. - Change `sq pki link add --email` and `sq pki link authorize --email` to use a user ID with just the specified email address, if the email address is part of a self-signed user ID. That is, if the certificate has the self-signed user ID "Alice ", then `--email alice@example.org` would have selected "Alice " to link, but now it selects "". - Add `sq pki link add --userid-by-email`, and `sq pki link authorize --userid-by-email`, which use the self-signed user ID with the specified email address. That is, if the certificate has the self-signed user ID "Alice ", then `--userid-by-email alice@example.org` selects "Alice " to link. - Add `sq pki link retract --userid-by-email`, which selects a self-signed user ID with the specified email address. - Change `sq pki vouch add --email` and `sq pki vouch authorize --email` to use a user ID with just the specified email address, if the email address is part of a self-signed user ID. That is, if the certificate has the self-signed user ID "Alice ", then `--email alice@example.org` would have selected "Alice " for certification, but now it selects "". - Add `sq pki vouch add --userid-by-email`, and `sq pki vouch authorize --userid-by-email`, which use the self-signed user ID with the specified email address. That is, if the certificate has the self-signed user ID "Alice ", then `--userid-by-email alice@example.org` selects "Alice " for certification. - Change `sq key userid revoke --email` to use a user ID with just the specified email address, if the email address is part of a self-signed user ID. That is, if the certificate has the self-signed user ID "Alice ", then `--email alice@example.org` would have selected "Alice " for revocation, but now it selects "". - Add `sq key userid revoke --userid-by-email`, which uses the self-signed user ID with the specified email address. That is, if the certificate has the self-signed user ID "Alice ", then `--userid-by-email alice@example.org` selects "Alice " for revocation. - When writing to a file output, we first write to a temporary file, then rename the file at the end of the operation so that it has its desired name. There are two benefits: no one sees partially written files, and one can safely use the same file as input and output. - `sq download --signature` is now called `sq download --signature-url`. - `sq download` now requires one of `--signature-url`, `--message`, or `--cleartext` like `sq verify`. * Changes in 0.40.0 ** New functionality - New subcommand `sq download`, which downloads a file and a signature file, and then authenticates the file. ** Notable changes - `sq toolbox keyring merge` now supports merging bare revocation certificates. - `sq verify` now deletes the output file on failure. - `sq decrypt` now deletes the output file on failure. - Add a global option, `--policy-as-of`, that selects the cryptographic policy as of the specified time. - `sq key subkey export` takes an additional argument, `--cert`, which is required. The specified keys must be attached to that certificate. This ensures that if a key is attached to multiple certificates, the correct certificate is exported. - Add a new argument, `--cli-version`, which requests a particular semver-compatible version of the CLI. This enables breaking changes to the CLI in the future. - The `help` subcommand has been removed everywhere except at the top-level (`--help` still works). - If designated signers are specified for `sq verify`, `sq decrypt`, and `sq download`, they are now the only certificates that are considered when verifying signatures. If no signers are specified, the certificate store is consulted. - The argument `sq cert lint --list-keys` has been removed. - `sq key list` now has a DWIM search parameter. - The flag `sq sign --detached` is now called `sq sign --signature-file`. - The flag `sq sign --clearsign` is now called `sq sign --cleartext`. - Both `sq sign` and `sq verify` now require an explicit mode, one of `--signature-file`, `--message`, or `--cleartext`. - The flag `sq --no-cert-store` has been replaced with `sq --cert-store=none`. - The flag `sq --no-key-store` has been replaced with `sq --key-store=none`. - Similarly, `sq --home=none` disables all state, unless explicitly re-enabled using `--cert-store` or `--key-store`. - `sq pki link add`, `sq pki link authorize`, `sq pki vouch certify`, and `sq pki vouch authorize` have a `--userid-or-add` flag. Replace it with an `--userid-or-add` argument, and an `--email-or-add` argument. - The `--email` and `--email-or-add` arguments to `sq pki link add`, etc. cannot be used to designate a self-signed user ID, if multiple self-signed user IDs include the specified email address. Previously, the arguments would designate all self-signed user IDs with the specified email address. - The new argument `sq sign --mode` can be used to create text signatures in addition to binary signatures. - The argument `sq network wkd publish --create` has been split into two arguments, `--create` and `--method`, avoiding an ambiguity when parsing the arguments. - `sq key userid revoke` no longer accepts the `--userid-or-add` flag to indicate that a user ID specified using `--userid`, an email specified using `--email`, or a name specified using `--name` should be used even if there is no corresponding self-signed user ID. This functionality is replaced by the `--userid-or-add`, `--email-or-add` and `--name-or-add` arguments. - `sq pki path` previously interpreted the last positional argument as the user ID to authenticate. Make it a named argument instead, `--userid`. - Add `sq pki path --email` and `sq pki path --name` as additional ways to specify the user ID to authenticate. - The argument `sq encrypt --set-metadata-time` has been removed. - The argument `sq encrypt --set-metadata-filename` now takes a string that specifies the file name to be set. - `sq pki authenticate`'s positional argument for specifying the certificate to authenticate must now be specified using a named argument, `--cert`. - `sq pki identify`'s positional argument for specifying the certificate to identify must now be specified using a named argument, `--cert`. - Drop `sq cert list --email`'s flag, and replace it with the `--userid` and `--email` positional arguments, which match on user IDs. - Drop `sq pki authenticate --email`'s flag, and replace it with the `--userid` and `--email` positional arguments, which match on user IDs. - Drop `sq pki lookup --email`'s flag, and replace it with the `--userid` and `--email` positional arguments, which match on user IDs. - `sq toolbox keyring` is now just `sq keyring`. - `sq toolbox packet` is now just `sq packet`. - `sq toolbox armor` is now `sq packet armor`. - `sq toolbox dearmor` is now `sq packet dearmor`. - `sq key userid revoke`, `sq pki link add`, `sq pki link authorize`, `sq pki vouch certify`, and `sq pki vouch authorize` now check that user IDs that are not self-signed are in canonical form. Add a flag, `--allow-non-canonical-userids`, to disable this check. - `sq key approvals update` now requires an action, like `--add-authenticated`. - `sq key approvals --add-authenticated` is now a simple flag, and we always require full authentication. - `sq toolbox strip-userid` has been removed. - All cert designators now use the `--cert-` prefix, e.g. `sq key export --email` has been changed to `sq key export --cert-email` for consistency reasons, and to free `--name`, `--email`, and `--userid` for user ID designators. - The `--binary` argument has been removed from all commands but those that emit signed and or encrypted messages. - The command `sq toolbox extract-cert` has been removed in favor of `sq key delete` and `sq key subkey delete`. - The command `sq packet split` now writes to stdout by default. - The argument `sq packets split --prefix` is now called `--output-prefix`. - `sq pki vouch certify` is now called `sq pki vouch add`. - We now certify newly generated keys with a per-host shadow CA. - The argument `sq encrypt --signature-notation` has been added. - All arguments to add signature notations have been renamed from `--notation` to `--signature-notation`. - When generating keys, either `--own-key` or `--shared-key` has to be given. The former marks the key's user IDs as authenticated and makes it a trusted introducer. The latter marks the key's user IDs as authenticated, and marks the key as a group key. - The argument `sq cert lint --export-secret-keys` has been removed: if a secret key is provided as file input, it will be emitted. - The argument `sq key subkey export --cert-file` has been removed. - `sq` now reads a configuration file that can be used to tweak a number of defaults, like the cipher suite to generate new keys, the set of key servers to query, and the cryptographic policy. - The command `sq keyring filter` is now considered experimental and may change in the future. To acknowledge this, it has to be invoked with the `--experimental` flag. * Changes in 0.39.0 ** Notable changes - Subcommand `sq key userid strip` has been moved to `sq toolbox strip-userid`. - `sq key adopt` supports adopting bare keys (i.e., a primary key without any signatures). - `sq key adopt` add options (`--can-sign`, `--cannot-sign`, `--can-authenticate`, `--cannot-authenticate`, `--can-encrypt`, `--cannot-encrypt`) to allow overriding the key flags. - `sq key adopt` now accepts the option `--creation-time` to allow the user to override the key's creation time. - `sq key adopt` sets the key's creation time to the current time (while respecting `--time`) if `--creation-time` is not specified, and the key's time is the Unix epoch. - To select the type of generated DNS resource records a new switch has been introduced. `sq network dane generate --type generic` replaces the old `--generic` flag. - `sq key adopt` is now called `sq key subkey bind`. - The option to verify a detached signature has been renamed from `--detached` to `--signature-file`: `sq verify --signature-file foo.sig foo.txt`. - `sq key userid revoke` has a new flag `--add-userid` that adds missing user IDs, analogous to the flag in `sq pki certify`. Previously, the global `--force` was used for this. - `sq pki link add` and `sq pki link retract` have a new flag `--recreate` that forces a signature to be created even if it should not be necessary because the parameters did not change. Previously, the global `--force` was used for this. - The global `--force` flag has been renamed to `--overwrite` and now controls whether existing files are overwritten. - The argument `--signer-key` is now just called `--signer`. - The arguments to name recipients for encryption now use the `--for` prefix, as in `sq encrypt --for-email alice@example.org`. Further, `--recipient-cert` is now just called `--for` - The environment variables to override the default cert store and key store location have been renamed from SQ_CERT_STORE to SEQUOIA_CERT_STORE, and SQ_KEY_STORE to SEQUOIA_KEY_STORE, respectively. - `sq toolbox packet split` now requires an explicit output parameter. - `sq pki certify` no longer supports using expired or revoked certificates; the options `--allow-not-alive-certifier` and `--allow-revoked-certifier` have been removed. - `sq toolbox keyring filter --handle` has been made more robust by splitting `--handle` into `--cert` and `--key`, where the former only matches on primary keys, and the latter matches on both primary keys and subkeys. - The argument `sq network keyserver publish --require-all` is the default now and has been removed. - The argument `sq key generate --rev-cert ...` is now mandatory if `--output` has been given. - `sq network fetch` has been renamed to `sq network search` to emphasize that this is key discovery, and may return related or even wrong results. Likewise for the key server, WKD, and DANE methods. - `sq pki certify`'s positional argument for specifying the user ID to certify must now be specified using a named argument, `--userid`, or `--email`. The `--email` argument no longer changes the meaning of how `--userid` is interpreted, but takes an email address. The `--userid` and `--email` arguments may be given multiple times to certify multiple user IDs at once. - `sq pki certify`'s positional argument for specifying the certificate to certify must now be specified using a named argument, `--cert` or `--cert-file`. - Previously `sq pki certify` could create certifications, and mark a certificate as a trusted introducer (when the user set `--depth` to be greater than zero). The latter functionality has been split off to the new subcommand `sq pki authorize`. - Add the `--domain` argument to `sq pki authorize` so the user doesn't have to manually convert a domain to a regular expression. - `sq pki link add`'s positional argument for specifying the certificate to link must now be specified using a named argument, `--cert`. - `sq pki link retract`'s positional argument for specifying the certificate to unlink must now be specified using a named argument, `--cert`. - Removed `sq pki link add`'s positional argument for specifying a user ID directly or by email address. Use the named arguments, `--userid` or `--email` instead. - Add `--add-userid` to `sq pki link add`. This aligns it with `sq pki certify`. - Removed `sq pki link add`'s `--petname` argument. Use `--userid` in conjunction with `--add-userid` instead. - Previously `sq pki link certify` could create certifications, and mark a certificate as a trusted introducer (when the user set `--depth` to be greater than zero). The latter functionality has been split off to the new subcommand `sq pki link authorize`. - Move `sq pki certify` to `sq pki vouch certify`. - Move `sq pki authorize` to `sq pki vouch authorize`. - Move `sq pki list` to `sq cert list`. - Add a new flag `--all` to `sq network wkd publish` and `sq network dane generate` that adds all certificates with a user ID in the target domain that can be authenticated. - The argument `sq verify --signer-cert` is now called `--signer`. - The argument `sq network wkd --rsync` which previously had an optional value argument has been split into two arguments, a boolean `--rsync` to enable the use of rsync, and `--rsync-path`, which implies `--rsync`, to specify a path to the local rsync executable. - When exporting certificates selected by user IDs (i.e. --email, --userid, --domain, or --grep), the bindings are authenticated and only those certificates that can be authenticated are exported. - The do-what-I-mean query parameter has been removed from `sq cert export`. - `sq autocrypt import` has been merged into `sq cert import`. - `sq autocrypt decode` and `sq autocrypt encode-sender` are removed without substitute. - `--cert` now only looks up by primary key fingerprint. - The argument `sq key delete --cert-file` has been renamed to `--file`. - The argument `sq key delete --file` now requires `--output`. - The argument `sq cert lint --cert-file` has been renamed to `--file`. - The argument `sq key password --cert-file` has been renamed to `--file`. - The argument `sq key password --file` now requires `--output`. - The argument `sq key expire --cert-file` has been renamed to `--file`. - The argument `sq key expire --file` now requires `--output`. - The argument `sq key revoke --cert-file` has been renamed to `--file`. - The argument `sq key revoke --file` now requires `--output`. - The argument `sq key userid add --cert-file` now requires `--output`. - The argument `sq key userid revoke --cert-file` now requires `--output`. - The argument `sq key subkey add --cert-file` has been renamed to `--file`. - The argument `sq key subkey add --file` now requires `--output`. - The argument `sq key subkey delete --cert-file` has been renamed to `--file`. - The argument `sq key subkey delete --file` now requires `--output`. - The argument `sq key subkey password --cert-file` has been renamed to `--file`. - The argument `sq key subkey password --file` now requires `--output`. - The argument `sq key subkey expire --cert-file` has been renamed to `--file`. - The argument `sq key subkey expire --file` now requires `--output`. - The argument `sq key subkey revoke --cert-file` has been renamed to `--file`. - The argument `sq key subkey revoke --file` now requires `--output`. - The argument `sq key subkey bind --cert-file` has been renamed to `--file`. - The argument `sq key subkey bind --file` now requires `--output`. - The argument `sq key approvals update --cert-file` now requires `--output`. - The pEp store integration has been removed. - Removed `sq pki path`'s `--gossip` argument, it didn't actually do anything. - Changed `sq key subkey expire`'s expiration argument from a positional argument to a named argument, `--expiration`. - Changed `sq key expire`'s expiration argument from a positional argument to a named argument, `--expiration`. - Changed `sq key revoke`'s reason and message arguments from positional arguments to named arguments, `--reason`, and `--message`, respectively. - Changed `sq key subkey revoke`'s reason and message arguments from positional arguments to named arguments, `--reason`, and `--message`, respectively. - Changed `sq key userid revoke`'s reason and message arguments from positional arguments to named arguments, `--reason`, and `--message`, respectively. - `sq cert import` now supports importing bare revocation certificates. * Changes in 0.38.0 ** Notable changes - New subcommand `sq key subkey delete` to delete secret key material. - New subcommand `sq network wkd publish` that publishes certificates in a WKD over rsync. - Removed now obsolete `sq network wkd generate`. - Removed `sq network wkd url` and `sq network wkd direct-url`. - Renamed subcommand `sq key attest-certifications` to `sq key approvals update` to reflect the new name in the draft, and to make room for introspection commands. - New subcommand `sq key subkey password` to change the password protecting secret key material. - The subcommand `sq network keyserver publish` can now publish certs from the certificate store using the `--cert` parameter. - The subcommands `sq key generate` and `sq key userid add` gained the options `--name` and `--email` as a more user-friendly way to specify user IDs. - All short options with the exception of `-v` have been removed. We will judiciously add some back before releasing 1.0. - The dot output has been removed. Those relying on it can use the standalone sq-wot tool. - New subcommand `sq key subkey export` to export individual keys. This functionality was split off from `sq key export`. - `sq key generate` and `sq key subkey add` now prompt for a password by default. This can be disabled by passing `--without-password`. - New subcommand `sq key approvals list` that lists approved third-party certifications and those pending approval. - Remove `sq cert export`'s `--key` argument. Change `--cert` to match both primary keys and subkeys. * Changes in 0.37.0 ** Notable changes - Remove PKS support. - `sq key userid add` can now use the certificate store and the keystore. - `sq key userid add` no longer accepts positional arguments. The user ID is provided by the `--userid` argument, and the certificate by `--cert` or `--cert-file`. - Drop the `--certificate-file` argument from `sq key revoke`, `sq key subkey revoke`, and `sq key userid revoke` drop the `--certificate-file`. (The certificate can still be specified using `--cert-file`.) - Rename the `--revocation-file` argument to `--revoker-file` in `sq key revoke`, `sq key subkey revoke`, and `sq key userid revoke`. - `sq key revoke --cert-file`, `sq key revoke --revoker-file` `sq key subkey revoke --cert-file`, `sq key subkey revoke --revoker-file`, `sq key userid revoke --cert-file`, and `sq key userid revoke --revoker-file` now accept `-`, which means to read from stdin. - `sq key revoke`, `sq key subkey revoke`, and `sq key userid revoke` now reads from the certificate store when using `--cert` or --revoker`. When `--cert` is used, and `--output` is not specified, the resulting revocation certificate is saved to the certificate store. - The user ID argument to `sq key userid revoke` is no longer a positional argument, but must be specified with `--userid`. - Change `sq cert lint` to not read from stdin by default. - In `sq cert lint`, change the certificate file parameter from a positional parameter to a named parameter, `--cert-file`. - `sq cert lint` can now use the certificate store and the keystore. - In `sq key subkey add`, change the certificate file parameter from a positional parameter to a named parameter, `--cert-file`. - `sq key subkey add` now reads from the certificate store when using `--cert`. When `--cert` is used, and `--output` is not specified, the new subkey is saved to the key store. - In `sq key expire`, change the certificate file parameter from a positional parameter to a named parameter, `--cert-file`. - Split the functionality to update a subkey's expiration time off of `sq key expire` and into `sq key subkey expire`. - Rename `sq key subkey expire`'s `--subkey` argument to `--key`. - `sq key expire` and `sq key subkey expire` can now use the cert store and the key store. - Add the `--password-file` argument to the `sq sign` command to allow the user to prefill the password cache with a password from a file. - In `sq key password`, change the certificate file parameter from a positional parameter to a named parameter, `--cert-file`. - `sq pki certify`'s certifier parameter interprets `-` as meaning it should read the certificate from stdin. - In `sq pki certify`, change the certifier file parameter from a positional parameter to a named parameter, `--certifier-file`. - `sq pki certify` can now use the cert store and the key store. - In `sq key adopt`, change the certificate file parameter from a positional parameter to a named parameter, `--cert-file`. - `sq key adopt` can now use the cert store and the key store. - In `sq key attest-certifications`, change the certificate file parameter from a positional parameter to a named parameter, `--cert-file`. - In `sq key attest-certifications`, don't make `--all` the default, but require the user to specify it (or `--none`) explicitly. - `sq key attest-certifications` can now use the cert store and the key store. - Rename the `--expiry` argument to `--expiration`. - Rename `sq key password`'s `--clear` argument to `--clear-password`. - Add a top-level `--password-file` argument to seed the password cache. Remove `sq key password`'s `--old-password-file`, and `sq sign`'s `--password-file` local arguments in favor of this argument. * Changes in 0.36.0 - Missing * Changes in 0.35.0 - Missing * Changes in 0.34.0 ** Notable changes - `sq` now uses `sequoia-keystore` for secret key operations. When decrypting a message, `sq` will automatically ask the keystore to decrypt the message. `sq sign --signer-key` can be used to specify a signing key managed by the key store. - New top-level option: `sq --no-key-store`: A new switch to disable the use of the key store. - New top-level option: `sq --key-store`: A new option to use an alternate key store. - New subcommand `sq key list` to list keys managed by the key store. - New subcommand `sq key import` to import a key into the key store. - When showing a user ID for a certificate, choose the one that is most authenticated. - `sq network wkd publish` publishes and updates WKD hierarchies via rsync. * Changes in 0.33.0 ** Notable changes - The command line interface has been restructured. Please consult the manual pages and review any code and documents using the interface. Notably: - `sq import` and `sq export` have been moved to `sq cert`. - `sq wot` has been renamed to `sq pki`. - `sq link` and `sq certify` have been moved to `sq pki`. - `sq lookup, `sq keyserver`, `sq wkd`, and `sq dane` have been moved to `sq network`. - All commands retrieving certificates from network services are now called `fetch`, e.g. `sq network fetch` and `sq network dane fetch`. The command for publishing certs on key servers is now called `sq network keyserver publish`. - `sq armor`, `sq dearmor`, and `sq packet` have been moved to `sq toolbox`. - `sq --version` is now `sq version`, and `sq output-versions` has been integrated with that command. - The manual page generation has been improved, and manual pages and shell completions are generated during the build process. To write the assets to a predictable location, set the environment variable `ASSET_OUT_DIR` to a suitable location. * Changes in 0.32.0 ** New functionality - Support for password-encrypted keys has been improved. For example, a newly generated subkey can be password protected. - When encrypting a message with a password, or creating a new password-protected key or subkey, or changing passwords on a key, sq now prompts you to repeat the password to catch typos. - Literal data metadata can now be set using `--set-metadata-filename` and `--set-metadata-time`. - sq now reads the file /etc/crypto-policies/back-ends/sequoia.config to configure its cryptographic policy. The file to load can be overridden using the SEQUOIA_CRYPTO_POLICY environment variable. For more information on the format, see: https://docs.rs/sequoia-policy-config/latest/sequoia_policy_config/#format - New subcommand: `sq dane generate`. Generates DANE records for the given domain and certificates. DANE is a way to distribute OpenPGP certificates via DNS. https://www.rfc-editor.org/rfc/rfc7929.html - When querying network resources via `sq keyserver get`, `sq wkd get`, or `sq dane get`, multiple queries can be given that are executed simultaneously. - When querying key servers via `sq keyserver get` or `sq keyserver send`, multiple servers are queried simultaneously. - There are now four default keyservers: - hkps://keys.openpgp.org - hkps://mail-api.proton.me - hkps://keys.mailvelope.com - hkps://keyserver.ubuntu.com - New subcommand: `sq lookup`. Searches for certificates using all supported network services. ** Notable changes - Padding has been disabled to increase compatibility with other implementations. The padding method we previously used relies on a compressed data packet to pad the message. However, some implementations do not gracefully process these padded encryption containers, so until we get proper padding support from the next revision of OpenPGP, we disable padding. - Message notarization has been disabled. Message notarization and their semantics are not well defined, and there is no consensus on how to do that. - When doing a userid, subkey, or third-party certificate revocation, with the cert given to --certificate-file containing secret key material, we previously emitted a revocation certificate containing secret key material. This has been fixed, and tests have been added to ensure secret key material is only emitted where we expect it to be. * Changes in 0.31.0 ** New functionality - `sq key subkey add` allows to create and add a new subkey to an existing certificate. - The functionality of `sq-keyring-linter` is now available as `sq keyring lint`. - The new subcommands `sq key revoke`, `sq key subkey revoke` and `sq key userid revoke`, allow writing to a file using the `--output` option. ** Notable changes - The `--keyring` option is now global and can be specified anywhere when calling `sq`. ** Deprecated functionality - The `--expires` and `--expires-in` options used in various subcommands are deprecated in favor of the unifying `--expiry`. - `sq key generate --export FILE` is deprecated in favor of the more generic `sq key generate --output FILE`. - The `sq revoke certificate` command has been renamed to `sq key revoke`. - The `sq revoke subkey` command has been renamed to `sq key subkey revoke`. - The `sq revoke userid` command has been renamed to `sq key userid revoke`. * Changes in 0.30.1 ** Notable changes - The `crypto-botan` feature now selects Botan's v3 interface. Use the new `crypto-botan2` feature to continue using Botan's v2 interface. ** Notable fixes - Several parser bugs were fixed in sequoia-openpgp 1.16.0 and buffered-reader 1.2.0. These are all low-severity as Rust correctly detects the out of bounds access and panics. Update Cargo.lock to make sure we use these versions. * Changes in 0.30 ** New functionality - `sq key adopt` now honors `--time`. - Add `sq key adopt --expire` to allow setting an adopted key's expiration time. - Add support for using pEp's certificate store. A pEp certificate store can be used by specifying `sq --pep-cert-store PATH` or setting the environment variable `PEP_CERT_STORE`. * Changes in 0.29 ** New functionality - `sq` now supports and implicitly uses a certificate store. By default, `sq` uses the standard OpenPGP certificate directory. This is located at `$HOME/.local/share/pgp.cert.d` on XDG compliant systems. - `sq --no-cert-store`: A new switch to disable the use of the certificate store. - `sq --cert-store`: A new option to use an alternate certificate store. Currently, only OpenPGP certificate directories are supported. - `sq import`: A new command to import certificates into the certificate store. - `sq export`: A new command to export certificates from the certificate store. - `sq encrypt --recipient-cert`: A new option to specify a recipient's certificate by fingerprint or key ID, which is then looked up in the certificate store. - `sq verify --signer-cert`: A new option to specify a signer's certificate by fingerprint or key ID, which is then looked up in the certificate store. - `sq verify` now also implicitly looks for missing certificates in the certificate store. But, unless they are explicitly named using `--signer-cert`, they are not considered authenticated and the verification will always fail. - `sq certify`: If the certificate to certify is a fingerprint or Key ID, then the corresponding certificate is looked up in the certificate store. - Add a global option, `--time`, to set the reference time. This option replaces the various subcommand's `--time` argument as well as `sq key generate` and `sq key userid add`'s `--creation-time` arguments. - Add top-level option, `--trust-root`, to allow the user to specify trust roots. - Extend `sq encrypt` to allow addressing recipients by User ID (`--recipient-userid`) or email address (`--recipient-email`). Only User IDs that can be fully authenticated are considered. - Extend `sq verify` to verify certificates looked up from the certificate store using the web of trust. If the signature includes a Signer's User ID packet, and the binding can be fully authenticated, consider the signature to be authenticated. If there is no Signer's User ID packet, consider the signature to be authenticated if any binding can fully be authenticated. - Add `sq link add`, which uses the local trust root to certify the specified bindings. - Add `sq link retract`, which retracts certifications made by the local trust root on the specified bindings. - Add `sq link list`, which lists the links. - Add a top-level option, `--keyring`, to allow the user to specify additional keyrings to search for certificates. - Import web of trust subcommands from sq-wot. Specifically, add: - `sq wot authenticate` to authenticate a binding. - `sq wot lookup` to find a certificate with a particular User ID. - `sq wot identify` to list authenticated bindings for a certificate. - `sq wot list` to list authenticated bindings. - `sq wot path` to authenticate and lint a path in a web of trust. - `sq keyserver get`, `sq wkd get`, and `sq dane get` now import any certificates into the certificate store by default instead of exporting them on stdout. It is still possible to export them using the `--output` option. - When `sq keyserver get` (for verifying key servers), `sq wkd get`, or `sq dane get` saves a certificate to the local certificate store, `sq` certifies the validated User IDs (all returned User IDs in the case of verifying key servers; User IDs that contain the looked up email address in the case of WKD and DANE) using a local service-specific proxy CA. If the proxy key doesn't exist, it is created, and certified as a minimally trusted CA (trust amount 1 of 120) by the local trust root. The proxy certificates can be managed in the usual way using `sq link add` and `sq link retract`. - Extend `sq inspect` to inspect certificates from the certificate store using the `--cert` option. ** Deprecated functionality - `sq key generate --creation-time TIME` is deprecated in favor of `sq key generate --time TIME`. - `sq key user id --creation-time TIME` is deprecated in favor of `sq user id --time TIME`. * Started the NEWS file. sequoia-sq-1.4.0/README.md000064400000000000000000000064171046102023000132040ustar 00000000000000# sq, the Sequoia-PGP command line tool [Sequoia-PGP][] is an implementation of OpenPGP in Rust. It includes a suite of library crates, which are meant to be used from applications. This crate provides the `sq` command line application. `sq` is aimed at command line users as a way to use OpenPGP conveniently from the command line. See the [sq user documentation][] for instructions. The program also has built-in help, using the `--help` option and `help` subcommand: ~~~sh $ sq help ... ~~~ You can also browse the [manual pages][], look at our [acceptance criteria][], and browse the [rustdoc output][] if you want to learn about the implementation. [Sequoia-PGP]: https://sequoia-pgp.org/ [sq user documentation]: https://sequoia-pgp.gitlab.io/user-documentation [manual pages]: https://sequoia-pgp.gitlab.io/sequoia-sq/man/ [acceptance criteria]: https://sequoia-pgp.gitlab.io/sequoia-sq/subplot/ [rustdoc output]: https://sequoia-pgp.gitlab.io/sequoia-sq/impl/ ## Installing The `sq` tool can be installed using cargo: ```sh cargo install sequoia-sq ``` Please see [sequoia-openpgp's README] for how to install build dependencies on your system. [sequoia-openpgp's README]: https://gitlab.com/sequoia-pgp/sequoia#requirements-and-msrv ## Building from source This crate can be built from a source checkout using the standard `cargo` toolchain: ```sh cargo build ``` The above creates the `sq` executable, the manual pages, and its shell completions. By default, the manual pages and shell completions are put into the `cargo` target directory, but the exact location is unpredictable. To write the assets to a predictable location, set the environment variable `ASSET_OUT_DIR` to a suitable location. ## Using a Container (Docker, Podman, etc.) The command line tool `sq` can also be built using an OCI compatible image builder, eg. podman or docker: ```shell $ podman build -f Containerfile -t sq . $ podman run --rm -i sq --help ``` You can then use sq in the container. For example searching for a certificate: ```shell $ podman run --rm -i sq network search 653909A2F0E37C106F5FAF546C8857E0D8E8F074 ``` All sq state is stored under `/sequoia` inside of the container, thus if you would like to persist the state between container runs you may bind mount the directory on the host. ```shell $ mkdir sq-container # create a directory on the host where you will mount the working dir from the container $ podman run --rm -i -v $PWD/sq-container:/sequoia sq network search 653909A2F0E37C106F5FAF546C8857E0D8E8F074 $ podman run --rm -i -v $PWD/sq-container:/sequoia sq inspect --cert 653909A2F0E37C106F5FAF546C8857E0D8E8F074 ``` The container environment has sq manpages and bash completion configured. By default the container will run sq as its "entrypoint", so if you would like to be dropped into a shell then override the entrypoint as follows. ```shell # Note the "-t"; Necessary for the allocation of a pseudo-TTY. $ podman run --rm -t -i --entrypoint bash sq ``` A current build of the container image is available from the gitlab registry. Rename it to `sq` locally so that it matches the above commands and for convenience. ```shell $ podman pull registry.gitlab.com/sequoia-pgp/sequoia-sq:latest $ podman tag registry.gitlab.com/sequoia-pgp/sequoia-sq:latest sq $ podman run --rm -i sq --help ``` sequoia-sq-1.4.0/build.rs000064400000000000000000000111301046102023000133560ustar 00000000000000use clap::ValueEnum; use clap_complete::Shell; use anyhow::Result; use sequoia_man::asset_out_dir; pub mod cli { #![allow(unused_macros)] include!("src/macros.rs"); include!("src/cli/mod.rs"); } fn main() { println!("cargo:rerun-if-changed=build.rs"); // Generate subplot tests. #[cfg(feature = "subplot")] subplot_build::codegen("sq.subplot") .expect("failed to generate code with Subplot"); let mut sq = cli::build(false); generate_shell_completions(&mut sq).unwrap(); generate_man_pages(&mut sq).expect("can generate man pages"); lint_help_texts(&sq).unwrap(); } /// Generates shell completions. fn generate_shell_completions(sq: &mut clap::Command) -> Result<()> { let path = asset_out_dir("shell-completions")?; for shell in Shell::value_variants() { clap_complete::generate_to(*shell, sq, "sq", &path)?; }; println!("cargo:warning=shell completions written to {}", path.display()); Ok(()) } /// Generates man pages. fn generate_man_pages(cli: &mut clap::Command) -> Result<()> { let version = env!("CARGO_PKG_VERSION"); let mut builder = sequoia_man::man::Builder::new(cli, version, None); builder.see_also( &[ "For the full documentation see ." ]); let man_pages = asset_out_dir("man-pages")?; sequoia_man::generate_man_pages(&man_pages, &builder).unwrap(); Ok(()) } /// Lints the help texts. fn lint_help_texts(sq: &clap::Command) -> Result<()> { let mut lints = Vec::new(); walk(&mut Vec::new(), sq, &mut |path: &[&str], c: &clap::Command| { let top_level = path.len() == 1; let path = path.join(" "); lint_short_long(&mut lints, &path, c.get_about(), c.get_long_about()); for arg in c.get_arguments() .filter(|a| a.get_id().as_str() != "help") .filter(|a| ! a.is_global_set() || top_level) { let slug = format!("{} {}", path, if let Some(l) = arg.get_long() { format!("--{}", l) } else if let Some(s) = arg.get_short() { format!("-{}", s) } else { arg.get_id().as_str().to_string() }); lint_short_long(&mut lints, &slug, arg.get_help(), arg.get_long_help()); } Ok(()) }, &mut |_, _, _| Ok(()))?; if lints.is_empty() { Ok(()) } else { println!("cargo:warning=Linting help texts found {} issues", lints.len()); println!("cargo:warning="); for lint in lints { println!("cargo:warning=lint: {}", lint); } Err(anyhow::anyhow!("linting help texts failed")) } } use clap::builder::StyledStr; /// Lints short and long about and help texts. fn lint_short_long(lints: &mut Vec, slug: &str, short: Option<&StyledStr>, long: Option<&StyledStr>) { let short = if let Some(short) = short { short.to_string() } else { lints.push(format!("{}: no short help", slug)); return; }; if short.contains(". ") { lints.push(format!("{}: short contains more than one sentence", slug)); } if short.ends_with(".") { lints.push(format!("{}: short ends in period", slug)); } let long = if let Some(long) = long { long.to_string() } else { return; }; if ! long.starts_with(&format!("{}\n\n", short)) { lints.push(format!("\ {}: long help doesn't start with subject (short help + \\n\\n) long help: {} short help: {}", slug, long, short)); } if long.split("\n").count() == 1 { lints.push(format!("{}: long help consists of a single line", slug)); } } fn walk<'sq, F, G, R>(path: &mut Vec<&'sq str>, c: &'sq clap::Command, fun0: &mut F, fun1: &mut G) -> Result where F: FnMut(&[&str], &clap::Command) -> Result<()>, G: FnMut(&[&str], &clap::Command, &[R]) -> Result, { path.push(c.get_name()); (fun0)(&path, c)?; let mut r = Vec::new(); for s in c.get_subcommands().filter(|cmd| cmd.get_name() != "help") { r.push(walk(path, s, fun0, fun1)?); } let r = (fun1)(&path, c, &r)?; path.pop(); Ok(r) } sequoia-sq-1.4.0/clippy.toml000064400000000000000000000004171046102023000141140ustar 00000000000000ignore-interior-mutability = [ # interior mutability is only used for cached properties # which are not considered by PartialEq and Hash impls "sequoia_openpgp::packet::Key", "sequoia_openpgp::packet::Signature", "sequoia_openpgp::packet::UserID", ] sequoia-sq-1.4.0/openpgp-policy.toml000064400000000000000000004025351046102023000155700ustar 00000000000000version = 0 commit_goodlist = [] [authorization."Alexander Kjäll"] sign_commit = true keyring = """ -----BEGIN PGP PUBLIC KEY BLOCK----- Comment: 7E06 8070 D5EF 794B 00C8 A9D9 1D10 8E6C 07CB C406 Comment: Alexander Kjäll xjMEXkLj2xYJKwYBBAHaRw8BAQdAHUsNSgCBZ9wSRCyVciyLF/dT+mf9ezwXY0RA 9PAb3L3NLEFsZXhhbmRlciBLasOkbGwgPGFsZXhhbmRlci5ramFsbEBnbWFpbC5j b20+wpYEExYKAD4CGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AWIQR+BoBw1e95 SwDIqdkdEI5sB8vEBgUCZcpRMwUJC0nUWAAKCRAdEI5sB8vEBl3SAQDbtYe+X6Y9 lbNE1RsEYCLQXchSPDAZHIN70QDoSYQs3wD7BMSNcAi1dVpjbYoyMT4CfwxYFbjS OGU1UGbV8Nh4uAHClgQTFgoAPgIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgBYh BH4GgHDV73lLAMip2R0QjmwHy8QGBQJiBoyrBQkHhg/QAAoJEB0QjmwHy8QGH54A /jzaCsEdQg4QuuezCClRuXQJRkPyPdF8Q/zAjVRhg8dBAP4krUwY7KS8g+fp64lQ IknH0U0dETYVVH0F37dLOuaIBcKWBBMWCAA+AhsDBQsJCAcCBhUKCQgLAgQWAgMB Ah4BAheAFiEEfgaAcNXveUsAyKnZHRCObAfLxAYFAl5DAWcFCQPChIwACgkQHRCO bAfLxAavyAEAoENjrYxz9LCSswCaFJeb57CFiNGlvBWUjlM3StGIg6sA/A2FtNXw Iphqyhk/oRyHsYoYpMdbcURDqVTEt7PGS7IF =JRvp -----END PGP PUBLIC KEY BLOCK----- """ [authorization.dvn] sign_commit = true keyring = """ -----BEGIN PGP PUBLIC KEY BLOCK----- Comment: 0CC0 11A7 C3DC 6EB4 7567 9BC9 AC0A BA31 866A 7E76 Comment: Devan Carpenter Comment: dvn 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 =2GFA -----END PGP PUBLIC KEY BLOCK----- """ [authorization.justus] sign_commit = true keyring = """ -----BEGIN PGP PUBLIC KEY BLOCK----- Comment: D2F2 C5D4 5BE9 FDE6 A4EE 0AAF 3185 5247 6038 31FD Comment: Justus Winter (Code Signing Key) Comment: Justus Winter Comment: Justus Winter Comment: Justus Winter Comment: Justus Winter Comment: Justus Winter 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 GNLnNS2c13ota/HZo1jjyOOIhJ3wkyUY5s8ugtxIwO4gE34rgdxXe1w7w2dy3DKq zWOHKs7wca8m6ufk75MQGk7TPL6nXZM+1F6OBo+moEaW/X8hn4meXikLE/6p4PxG wclL3/+FbwlJpMjPunedyDa+CVL5yCf7vww8mW52YiIWHNvmSJ5szWgc276uMk0T 1+ckzQ1KdXN0dXMgV2ludGVywsHhBBMBCgCZBYJofiMXBYkQ8B+PAwsJBwkQm33U M/JUkEpHFAAAAAAAHgAgc2FsdEBub3RhdGlvbnMuc2VxdW9pYS1wZ3Aub3Jndceh oMOXCdcGEK5NieaTCfHICdd30Ek4k7Ypxe002Z0FFQoOCAwCFgACF4ACGwECHgkW IQTLzY8DBYhlPu3X4mWbfdQz8lSQSg0nCQIJAQkDBwIHAQcDAABY9g/gnj/02oHg NDdYg7P3fWZAkABu8Gj0uH68dpFCIL8wCc5AL9l6WVSBmdxFmoNMD7TsKfiBRVg1 9IUWitxb0bcmm/OzzkvGgk1SG8gcJE46oA4sumfNh/7CnHUAvKL4ALIPMMXUDkz3 KhmUaqnZdzpQYsGRvujgOaKCia0xVNCSh2t1wGPPyIP0QLCrC6Ntcm/HD0tEQlU7 0GxLMNAzsD6ag4iqZI8X1/qilbbtiIYdoiT+bU9CWuv/fBx/nK43O4+t/G168vfh mseTAhI/q8ObbrQJB9aJJW7gbF2Qs2wC6yrtb8BYaKpfSzNXAlKH+YQbFdouq8m1 NPNoUbU27dMEG9KPeQXAiv74N4upkNpUju1IieJ80fat4QWx3pstlbCU2dfS7/8n FqbW74QFjy6eR/Mt81exw1+rxW4CMRVLnGeTxvMYWVJvj34F/dHOjGk/CNkeMvDK T+PggTHT1O/54wEgdURUKD9L0VOaBlVFIawmqfmKdXd3qks2mtakPv29vR6CnKPQ M59DSU3hE7XjWXndgjjT70d2GYcDEybBB37sy6h4dh0kc8+BWTwJztMDn2ffhUD7 XwKlTpFBhHwPcS3q+SbDApKxrOhYoSmdzez92lwG7748Cu/WZIB2u65kvzm+l4ov vuUuGcyOf7rSalLjGz+J4n7IywWz/cLB4QQTAQoAmQWCZ9gwBgWJDwBWzQMLCQcJ EJt91DPyVJBKRxQAAAAAAB4AIHNhbHRAbm90YXRpb25zLnNlcXVvaWEtcGdwLm9y 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 tHKhU4JgfYfj3/ZkxE7B8rTAgDZ/l7ax+ppDmWU17OqhIVx7RFBxLEEg90569zT4 cvYROmoHhr7CweEEEwEKAJkFgmfYMAoFiQ8AVs0DCwkHCRCbfdQz8lSQSkcUAAAA AAAeACBzYWx0QG5vdGF0aW9ucy5zZXF1b2lhLXBncC5vcmdVuzGVhHnLLB+JWAgd MQStKDJtRcLwGgcPL1i8xDel+QUVCg4IDAIWAAIXgAIbAQIeCRYhBMvNjwMFiGU+ 7dfiZZt91DPyVJBKDScJAgkBCQMHAgcBBwMAANgKD90amXbCcheJIIlYxu6w+CI8 u+fBK5wzvAsBus+lPiiHIMwwcOiWM5cSY1zHWmrHT7UvIJ64TEJbyyIYtvy5/LPV O0b+m95MeVHWTEyqY0TylIqyjKBJeQdUmZiJERWXOCOhqOCxT+VSZ15k3KYP/jIH byldOvjpsWRcTwaJq2lvTPBUbJ9hzPNkuTdIFrmqPMJypgfBm+HwsIbH1XAEUKEq GpofsAh5NSGDZVWOT8ZHtpHiA8fAN1iTsM8hjd6EQ9UzR2BuRv964e+5cVFLmSnU kCHxUM1vyjciFq6pv6Zxhzdb8DEBvcABBwtyihFvKdNd8sKUyjKvB7Fo3Qaz/8xC dEJSHdqCJGJCO1DWHP3L+L59D4g2MKu3YAlOQDx2izEafJfRVQhwYLvlswzaeV93 aaM5gNEHRIayHaOOOR2xcZR27Vc/iL7z6vHUSw8GTUcQjm9uA5VWegR1dHIDC4ok is43nNBinP1lp1o4jNe5cQSpOalRrgprr8ow7YuEe07MmqvC1q6udYGNf3YZVgfW KiBWSU2N0JEVCCjD4Ae2+0d6qph6BWwjbKQtTQ8Rv5OMFJtlKKHVMXLBYfkI2gMy YPgTT0Vc0D3wqrqeSHPxwGIeWF83e5dMIE3Wnme9NOChQkFCWAH40YMhNutrG3dR AJM8WExkMyAL0gmzwsGNBBMBCgA7AhsBCAsJCAcNDAsKBRUKCQgLAh4BAheAFiEE y82PAwWIZT7t1+Jlm33UM/JUkEoFAmaOrBwFCQ8AVs0ACgkQm33UM/JUkEr2rA/g sXbm0JtEbE/gzxoLlI71WhZFvXWwZehWpNnxWuBgnxHyCAiB6Ulf0wqlfTyRUirI o6pcL9Gadj6y4V5sxa8NLH6Zvv2KeLelNjMTSx3VPAbSprhzLQXvO25wubmfI8wP 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 wocIA3yDQ/POwE0EWW+JnwEIALljGLPt+4QNsRcqLgzAVXsgTpDeYQmtdZh3otmM vMU76/cM+Ez9iBA50jvD7x5imuwVpQ+1gAsXLhtH/lQUaP0zTRGTe2CVXd0LTlCI cbNpEaAbVbTgfmFxC4bUOJNcyuABfOVklTBceRplK0iWRs1zXf/K8Qrz/Ujv7W5p w+WckeFKH30Pg8wlMt/yLZZTHTsxUhGh4gP35oXvfmFxb2si7obPUfSywmSzVk/U 8WVhx7IMJPMb9iJnPCIB/AecM+mUC8rIyhjHQsZB22/5akyiGFpJ10ve92MOKrzU fessmj4YK1rjY1wDSsMFf9bPt4sNZ8o96ajZWma+zMn9lhcAEQEAAcLC9gQYAQoA eAWCaH4jlwWJEPAfNwkQm33UM/JUkEpHFAAAAAAAHgAgc2FsdEBub3RhdGlvbnMu c2VxdW9pYS1wZ3Aub3Jnw2NNWQrZUBaUYYLV8LDmEeEG76wn6pJcMlxZVZw5Y7oC GwIWIQTLzY8DBYhlPu3X4mWbfdQz8lSQSgE2wHQgBBkBCgAdFiEEJWpOVeSnLZet JGjniNx+MzhfeR0FAllviZ8ACgkQiNx+MzhfeR3XZgf/ViFPa4G4HdY7X9GrinjD /GYvQnHeQl/NsY4lIEzR5/8GptxbeMTF0kjGGX6snU+oCshPSUibcd09eBIWZ+B1 KJcUosvxvvEIuegA+t8Yb61QWzj+GDzc8az/+atr8fM4a6Y6Y3KQojCCy2+ouZ9D LZRHLNHpZx5uwBN6/zzr+CuNCkLIY5XWZYIKPaoscRCuXqxEYCkO9zZFvvHSZatt s8sBZJkpgVlT7GdGwpqw55phJGZi/qSFXi3U52BCli5t/r4jJ2KfpO/lnCkfupSQ 5nIJA8+TlsOksz0DY3Mlti9PtLV9YbgNkOO2eSOcl3mmrgJXy2jh+0qOGG28WpkE AJSnD+CKo2jppMFmS0YmIT6UVVsoYvWnUmDJ5SCSnJR/GMBwSfKD/SfWxQAPLWzn 5onVRlyFCpBEaEqj3xb6d8Dr/3K0EZ6kdF89SW4spO/a3VDlfAJQ5oYNtlg+FW+k hUb6q4sEYp1tNUGfWwqDCjuSugqLfgpqZaO1nq55bMl3nEL3BndDp97GrSZx6I/P Cfzmwsuny/61tjCAY+NQBGAtc8zgiEM1xoIDJgBF27DDFRPpR9pwQLjlKro0AVhW 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 =N5EW -----END PGP PUBLIC KEY BLOCK----- """ [authorization.neal] sign_commit = true keyring = """ -----BEGIN PGP PUBLIC KEY BLOCK----- Comment: F717 3B3C 7C68 5CD9 ECC4 191B 74E4 45BA 0E15 C957 Comment: Neal H. Walfield (Code Signing Key) Comment: Neal H. Walfield Comment: Neal H. Walfield Comment: Neal H. Walfield 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 =k8pO -----END PGP PUBLIC KEY BLOCK----- """ sequoia-sq-1.4.0/sq-subplot.md000064400000000000000000001471111046102023000143550ustar 00000000000000--- title: "Sequoia-PGP sq" subtitle: "integration tests, requirements, acceptance criteria" authors: "The Sequoia-PGP project" bindings: - subplot/sq-subplot.yaml - lib/files.yaml - lib/runcmd.yaml impls: rust: - subplot/sq-subplot.rs classes: - json ... # Introduction The [Sequoia-PGP][] project is an implementation of the [OpenPGP][] standard for encryption and digital signatures. Sequoia itself is a library for the Rust programming language, as well as the `sq` command line tool for people to use directly. This document captures the requirements and acceptance criteria for the `sq` tool and how they are verified, and at the same time acts as an integration test for the tool. [Sequoia-PGP]: https://sequoia-pgp.org/ [OpenPGP]: https://en.wikipedia.org/wiki/Pretty_Good_Privacy#OpenPGP ## Testing approach for sq This document explicitly only covers integration and acceptance testing of the `sq` command line tool. It does not try to verify that the underlying library implements OpenPGP correctly: the library has its own test suite for that. Instead, this document concentrates on making sure the `sq` command line tool behaves as it should from an end-user's point of view. We make the following simplifying assumption: we know the `sq` developers as competent developers, and assume that they don't entangle unrelated functionality. By this we mean that we feel we can assume that the code in `sq` that reads input files is separate from the code that compresses it, which in turn is independent of the code that writes output as text or binary data. Thus, we verify each such functionality independently of each other. This drastically cuts down the number of feature combinations we need to test. If this assumption turns out to be incorrect, we will rethink and revise the testing approach as needed. We also know, by inspection, that `sq` uses the well-known, well-respected Rust library `clap` for parsing the command line. Because of this we feel it's not necessary to verify that, for example, `sq` notices that a required argument is missing from the command line, or that it notices that there are extra arguments present. We will concentrate on testing that when invoked with valid arguments results in expected output. ## Using Subplot and this document The acceptance criteria and requirements are explained in prose and when they can be verified in an automated way, that is done using _test scenarios_. Both the prose and the scenarios are meant to be understood and agreed to by all stakeholders in the project. The [Subplot][] tool is used to render this document into human-readable form (HTML or PDF), and to generate a test program that executes the scenarios and checks they all pass. To achieve this, run the following commands: ~~~sh $ git clone https://gitlab.com/sequoia-pgp/sequoia-sq.git $ cd sequoia-sq $ subplot docgen sq-subplot.md -o sq-subplot.html $ subplot docgen sq-subplot.md -o sq-subplot.pdf $ cargo test ~~~ If you only care about generating and running tests, you only need to run `cargo test`. All the dependencies for that are automatically handled via `Cargo.toml`. To generate typeset documents (HTML and PDF), you need the following software installed: * [Subplot][], via cargo install or a Debian package (see its website) * Pandoc * Parts of TeX Live (for PDF) * Graphviz On a Debian system, that means the following packages: > `subplot pandoc pandoc-citeproc lmodern librsvg2-bin graphviz > texlive-latex-base texlive-latex-recommended > texlive-fonts-recommended plantuml` [Subplot]: https://subplot.liw.fi/ # Smoke test _Requirement: We must be able to invoke `sq` at all._ This scenario verifies that we can run `sq` in the simplest possible case: we ask the program for its version. If this works, then we know that the executable program exists, can be invoked, and at least some of its command line parsing code works. If this scenario doesn't work, then we can't expect anything else to work either. ~~~scenario given an installed sq when I run sq version then exit code is 0 then stderr matches regex ^sq \d+\.\d+\.\d+ ~~~ # Key management: `sq key` This chapter covers all key management functionality: the `sq key` subcommands. ## Key generation: `sq key generate` This section covers key generation with `sq`. Keys are somewhat complicated: it is possible to have keys for specify that they can only used for specific operations, or the time period when they are valid. Different cryptographic algorithms have different kinds of keys. We verify these by varying what kind keys we generate and that they look as expected, when inspected. ### Generate a key with defaults _Requirement: We must be able to generate new encryption keys and corresponding certificates._ This scenario generates a new key with `sq` using default settings and inspects it to see if it looks at least vaguely correct. Note that in this scenario we don't verify that the key works, other scenarios take care of that. Here we merely verify that the new key looks OK. ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --userid Alice --output key.pgp --rev-cert key.pgp.rev when I run sq inspect key.pgp then stdout contains "Alice" then stdout contains "Expiration time: 20" then stdout contains "Key flags: certification" then stdout contains "Key flags: signing" then stdout contains "Key flags: authentication" then stdout contains "Key flags: transport encryption, data-at-rest encryption" ~~~ ### Generate key without user identifiers _Requirement: We must be able to generate new encryption keys without any user identifiers._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev then file key.pgp contains "-----BEGIN PGP PRIVATE KEY BLOCK-----" ~~~ ### Generate key with more than one user identifier _Requirement: We must be able to generate new encryption keys with more than one user identifier._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --userid Alice --userid '' --output key.pgp --rev-cert key.pgp.rev then file key.pgp contains "Comment: Alice" then file key.pgp contains "Comment: " ~~~ ### Generate a key for certification only _Requirement: We must be able to generate a key that can only be used for certification, and can't be used for signing, encryption or authentication._ Note that `sq` always creates a key usable for certification. ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev --cannot-sign --cannot-authenticate --cannot-encrypt when I run sq inspect key.pgp then stdout contains "Key flags: certification" then stdout doesn't contain "Key flags: signing" then stdout doesn't contain "Key flags: authentication" then stdout doesn't contain "Key flags: transport encryption, data-at-rest encryption" ~~~ ### Generate a key for encryption only _Requirement: We must be able to generate a key that can only be used for encryption, and can't be used for signing or authentication._ Note that `sq` always creates a key usable for certification. ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev --cannot-sign --cannot-authenticate when I run sq inspect key.pgp then stdout contains "Key flags: certification" then stdout doesn't contain "Key flags: signing" then stdout doesn't contain "Key flags: authentication" then stdout contains "Key flags: transport encryption, data-at-rest encryption" ~~~ ### Generate a key for storage encryption only _Requirement: We must be able to generate a key that can only be used for at-rest (storage) encryption._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev --can-encrypt=storage when I run sq inspect key.pgp then stdout contains "Key flags: certification" then stdout doesn't contain "transport encryption" then stdout contains "Key flags: data-at-rest encryption" ~~~ ### Generate a key for transport encryption only _Requirement: We must be able to generate a key that can only be used for transport encryption._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev --can-encrypt=transport when I run sq inspect key.pgp then stdout contains "Key flags: certification" then stdout contains "Key flags: transport encryption" then stdout doesn't contain "data-at-rest encryption" ~~~ ### Generate a key for signing only _Requirement: We must be able to generate a key that can only be used for signing, and can't be used for encryption._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev --cannot-encrypt --cannot-authenticate when I run sq inspect key.pgp then stdout contains "Key flags: certification" then stdout contains "Key flags: signing" then stdout doesn't contain "Key flags: transport encryption, data-at-rest encryption" then stdout doesn't contain "Key flags: authentication" ~~~ ### Generate a key for authentication only _Requirement: We must be able to generate a key that can only be used for authentication, and can't be used for encryption or signing._ Note that `sq` always creates a key usable for certification. ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev --can-authenticate --cannot-sign --cannot-encrypt when I run sq inspect key.pgp then stdout contains "Key flags: certification" then stdout contains "Key flags: authentication" then stdout doesn't contain "Key flags: signing" then stdout doesn't contain "Key flags: transport encryption, data-at-rest encryption" ~~~ ### Generate a key for encryption and authentication _Requirement: We must be able to generate a key that can only be used for encryption and authentication, and can't be used for signing._ Note that `sq` always creates a key usable for certification. ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev --cannot-sign when I run sq inspect key.pgp then stdout contains "Key flags: certification" then stdout contains "Key flags: authentication" then stdout contains "Key flags: transport encryption, data-at-rest encryption" then stdout doesn't contain "Key flags: signing" ~~~ ### Generate a key for encryption and signing _Requirement: We must be able to generate a key that can only be used for encryption and signing, and can't be used for authentication._ Note that `sq` always creates a key usable for certification. ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev --cannot-authenticate when I run sq inspect key.pgp then stdout contains "Key flags: certification" then stdout contains "Key flags: transport encryption, data-at-rest encryption" then stdout contains "Key flags: signing" then stdout doesn't contain "Key flags: authentication" ~~~ ### Generate a key for signing and authentication _Requirement: We must be able to generate a key that can only be used for signing and authentication, and can't be used for encryption._ Note that `sq` always creates a key usable for certification. ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev --cannot-encrypt when I run sq inspect key.pgp then stdout contains "Key flags: certification" then stdout doesn't contain "Key flags: transport encryption, data-at-rest encryption" then stdout contains "Key flags: signing" then stdout contains "Key flags: authentication" ~~~ ### Generate a key for encryption, authentication and signing _Requirement: We must be able to generate a key that can be used for encryption, authentication and signing._ Note that `sq` always creates a key usable for certification. ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev when I run sq inspect key.pgp then stdout contains "Key flags: certification" then stdout contains "Key flags: authentication" then stdout contains "Key flags: transport encryption, data-at-rest encryption" then stdout contains "Key flags: signing" ~~~ ### Generate a version four elliptic curve key _Requirement: We must be able to generate a v4 Curve25519 key_ This is currently the default key, but we check it separately in case the default ever changes. ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev --cipher-suite=cv25519 --profile=rfc4880 when I run sq inspect key.pgp then stdout contains "Public-key algo: EdDSA" then stdout contains "Public-key size: 256 bits" ~~~ ### Generate a version six elliptic curve key _Requirement: We must be able to generate a v6 Curve25519 key_ This is currently the default key, but we check it separately in case the default ever changes. ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev --cipher-suite=cv25519 --profile=rfc9580 when I run sq inspect key.pgp then stdout contains "Public-key algo: Ed25519" then stdout contains "Public-key size: 256 bits" ~~~ ### Generate a three kilobit RSA key _Requirement: We must be able to generate a 3072-bit RSA key._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev --cipher-suite=rsa3k when I run sq inspect key.pgp then stdout contains "Public-key algo: RSA" then stdout contains "Public-key size: 3072 bits" ~~~ ### Generate four kilobit RSA key _Requirement: We must be able to generate a 4096-bit RSA key._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev --cipher-suite=rsa4k when I run sq inspect key.pgp then stdout contains "Public-key algo: RSA" then stdout contains "Public-key size: 4096 bits" ~~~ ### Generate a key with revocation certificate _Requirement: We must be able to specify where the revocation certificate is store._ When `sq` generates a key, it also generates a revocation certificate. By default, this is written to a file next to the key file. However, we need to able to specify where it goes. This scenario tests various cases. ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev then file key.pgp.rev contains "Comment: Revocation certificate for" when I run sq key generate --own-key --without-password --no-userids --output key2.pgp --rev-cert rev.pgp then file rev.pgp contains "Comment: Revocation certificate for" ~~~ ### Generate a key with default duration _Requirement: By default, generated key expire._ We generate a key with defaults, and check the key expires. ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev when I run sq inspect key.pgp then stdout contains "Expiration time: 20" ~~~ The check for expiration time assumes the scenario is run the 21st century, and will need to be amended in the 2090s or by time travellers running it before about the year 2000. ### Generate a key that expires at a given moment _Requirement: We must be able to generate a key that expires._ Note that the timestamp given to `--expire` is the first second when the key is no longer valid, not the last second it's valid. The inspect output is the last second of validity. ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev --expiration=2038-01-19T03:14:07+00:00 when I run sq inspect key.pgp then stdout contains "Expiration time: 2038-01-19 03:14" when I run sq inspect --time 2038-01-20T00:00:00+00:00 key.pgp then stdout contains "Invalid: The primary key is not live" ~~~ ### Generate a key with a given duration _Requirement: We must be able to generate a key that expires in a given time._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev --expiration=1y when I run sq inspect key.pgp then stdout contains "Expiration time: 20" ~~~ ### Generate a key without password _Requirement: We must be able to generate a that doesn't have a password._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev when I run sq inspect key.pgp then stdout contains "Secret key: Unencrypted" ~~~ ### Generate a key with a password _Requirement: We must be able to generate a that does have a password._ ~~~scenario given an installed sq given file password.txt when I run sq key generate --own-key --no-userids --output key.pgp --rev-cert key.pgp.rev --new-password-file password.txt when I run sq inspect key.pgp then stdout contains "Secret key: Encrypted" ~~~ ### Update a key by adding User IDs _Requirement: We must be able to generate a key and add User IDs to it._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev when I run sq key userid add --cert-file key.pgp --name Juliet --email juliet@example.org --output new.pgp when I run sq inspect new.pgp then stdout contains "UserID: Juliet" then stdout contains "UserID: " ~~~ ## Certificate extraction: `sq key delete` This section covers extraction of certificates from keys: the `sq key delete` subcommand and its variations. ### Extract certificate to the standard output _Requirement: We must be able to extract a certificate to standard output._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev when I run sq key delete --cert-file key.pgp --output - then stdout contains "-----BEGIN PGP PUBLIC KEY BLOCK-----" then stdout contains "-----END PGP PUBLIC KEY BLOCK-----" ~~~ ### Extract certificate to a file _Requirement: We must be able to extract a certificate to a named file._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --output key.pgp --rev-cert key.pgp.rev --userid Alice when I run sq key delete --cert-file key.pgp --output cert.pgp when I run sq inspect cert.pgp then stdout contains "OpenPGP Certificate." then stdout contains "Alice" ~~~ # Keyring management: `sq keyring` This chapter verifies that the various subcommands to manage keyring files work: subcommands of the `sq keyring` command. ## Joining keys into a keyring: `sq keyring merge` The scenarios in this section verify that various ways of joining keys into a keyring work. ### Join two keys into a textual keyring to stdout _Requirement: we can join two keys into a keyring, and have it written to stdout._ This is for secret keys, with the output going to stdout in text form. ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --userid Alice --output alice.pgp --rev-cert alice.pgp.rev when I run sq key generate --own-key --without-password --userid Bob --output bob.pgp --rev-cert bob.pgp.rev when I run sq keyring merge alice.pgp bob.pgp --output ring.pgp when I run sq keyring list ring.pgp then stdout contains "Alice" then stdout contains "Bob" ~~~ ### Join two keys into a textual keyring to a named file _Requirement: we can join two keys into a keyring, and have it written to a named file._ This is for secret keys, with the output going to a file in text form. ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --userid Alice --output alice.pgp --rev-cert alice.pgp.rev when I run sq key generate --own-key --without-password --userid Bob --output bob.pgp --rev-cert bob.pgp.rev when I run sq keyring merge alice.pgp bob.pgp --output ring.pgp then file ring.pgp contains "-----BEGIN PGP PRIVATE KEY BLOCK-----" then file ring.pgp contains "-----END PGP PRIVATE KEY BLOCK-----" when I run sq inspect ring.pgp then stdout contains "Transferable Secret Key." then stdout contains "Alice" then stdout contains "Bob" ~~~ ### Join two keys into a keyring _Requirement: we can join two keys into a keyring form._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --userid Alice --output alice.pgp --rev-cert alice.pgp.rev when I run sq key generate --own-key --without-password --userid Bob --output bob.pgp --rev-cert bob.pgp.rev when I run sq keyring merge alice.pgp bob.pgp --output ring.pgp when I run sq inspect ring.pgp then stdout contains "Transferable Secret Key." then stdout contains "Alice" then stdout contains "Bob" ~~~ ### Join two certificates into a keyring _Requirement: we can join two certificates into a keyring._ This scenario writes the keyring to a named file. We assume the writing operation is independent of the types of items in the keyring, so we don't change writing to stdout separately. ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --userid Alice --output alice.pgp --rev-cert alice.pgp.rev when I run sq key generate --own-key --without-password --userid Bob --output bob.pgp --rev-cert bob.pgp.rev when I run sq key delete --cert-file alice.pgp --output alice-cert.pgp when I run sq key delete --cert-file bob.pgp --output bob-cert.pgp when I run sq keyring merge alice-cert.pgp bob-cert.pgp --output ring.pgp when I run cat ring.pgp then stdout contains "-----BEGIN PGP PUBLIC KEY BLOCK-----" then stdout contains "-----END PGP PUBLIC KEY BLOCK-----" when I run sq inspect ring.pgp then stdout doesn't contain "Transferable Secret Key." then stdout contains "OpenPGP Certificate." then stdout contains "Alice" then stdout contains "Bob" ~~~ ## Filter a keyring: `sq keyring filter` The scenarios in this section verify that various ways of filtering the contents of a keyring work: the `sq keyring filter` subcommand variants. ### We can extract only certificates to named file _Requirement: we can remove private keys from a keyring, leaving only certificates._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --userid Alice --output alice.pgp --rev-cert alice.pgp.rev when I run sq key generate --own-key --without-password --userid Bob --output bob.pgp --rev-cert bob.pgp.rev when I run sq keyring merge alice.pgp bob.pgp --output ring.pgp when I run sq keyring filter --experimental --to-cert ring.pgp --output filtered.pgp when I run sq inspect filtered.pgp then stdout contains "OpenPGP Certificate." then stdout doesn't contain "Transferable Secret Key." then stdout contains "Alice" then stdout contains "Bob" ~~~ ### We can filter to stdout _Requirement: we can get filter output to stdout instead of a named file._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --userid Alice --output alice.pgp --rev-cert alice.pgp.rev when I run sq key generate --own-key --without-password --userid Bob --output bob.pgp --rev-cert bob.pgp.rev when I run sq keyring merge alice.pgp bob.pgp --output ring.pgp when I run sq keyring filter --experimental --to-cert ring.pgp then stdout contains "-----BEGIN PGP PUBLIC KEY BLOCK-----" then stdout contains "-----END PGP PUBLIC KEY BLOCK-----" ~~~ ### We can keep only matching certificates _Requirement: we can remove certificates that don't match filter criteria._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --userid Alice --userid Bob --output alice.pgp --rev-cert alice.pgp.rev when I run sq keyring filter --experimental --prune-certs --name Alice alice.pgp --output filtered.pgp when I run sq inspect filtered.pgp then stdout contains "Alice" then stdout doesn't contain "Bob" ~~~ ### We can filter for specific user id _Requirement: we can extract only keys and certificates with a specific user id._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --userid Alice --output alice.pgp --rev-cert alice.pgp.rev when I run sq key generate --own-key --without-password --userid Bob --output bob.pgp --rev-cert bob.pgp.rev when I run sq keyring merge alice.pgp bob.pgp --output ring.pgp when I run sq keyring filter --experimental --userid Alice ring.pgp --output filtered.pgp when I run sq inspect filtered.pgp then stdout contains "Alice" then stdout doesn't contain "Bob" ~~~ ### We can filter for any of several user ids _Requirement: we can extract only keys and certificates with any of specific user ids._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --userid Alice --output alice.pgp --rev-cert alice.pgp.rev when I run sq key generate --own-key --without-password --userid Bob --output bob.pgp --rev-cert bob.pgp.rev when I run sq keyring merge alice.pgp bob.pgp --output ring.pgp when I run sq keyring filter --experimental --userid Alice --userid Bob ring.pgp --output filtered.pgp when I run sq inspect filtered.pgp then stdout contains "Alice" then stdout contains "Bob" ~~~ ### We can filter for a name _Requirement: we can extract only keys and certificates with a name as part of a user ids._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --userid 'Alice ' --output alice.pgp --rev-cert alice.pgp.rev when I run sq key generate --own-key --without-password --userid 'Bob ' --output bob.pgp --rev-cert bob.pgp.rev when I run sq keyring merge alice.pgp bob.pgp --output ring.pgp when I run sq keyring filter --experimental --name Alice ring.pgp --output filtered.pgp when I run sq inspect filtered.pgp then stdout contains "Alice" then stdout doesn't contain "Bob" ~~~ ### We can filter for several names _Requirement: we can extract only keys and certificates with any of several names as part of the user id._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --userid 'Alice ' --output alice.pgp --rev-cert alice.pgp.rev when I run sq key generate --own-key --without-password --userid 'Bob ' --output bob.pgp --rev-cert bob.pgp.rev when I run sq keyring merge alice.pgp bob.pgp --output ring.pgp when I run sq keyring filter --experimental --name Alice --name Bob ring.pgp --output filtered.pgp when I run sq inspect filtered.pgp then stdout contains "Alice" then stdout contains "Bob" ~~~ ### We can filter for a domain _Requirement: we can extract only keys and certificates with a name as part of a user ids._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --userid 'Alice ' --output alice.pgp --rev-cert alice.pgp.rev when I run sq key generate --own-key --without-password --userid 'Bob ' --output bob.pgp --rev-cert bob.pgp.rev when I run sq keyring merge alice.pgp bob.pgp --output ring.pgp when I run sq keyring filter --experimental --domain example.com ring.pgp --output filtered.pgp when I run sq inspect filtered.pgp then stdout contains "Alice" then stdout doesn't contain "Bob" ~~~ ### We can filter for several domains _Requirement: we can extract only keys and certificates with any of several names as part of the user id._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --userid 'Alice ' --output alice.pgp --rev-cert alice.pgp.rev when I run sq key generate --own-key --without-password --userid 'Bob ' --output bob.pgp --rev-cert bob.pgp.rev when I run sq keyring merge alice.pgp bob.pgp --output ring.pgp when I run sq keyring filter --experimental --domain example.com --domain sequoia-pgp.org ring.pgp --output filtered.pgp when I run sq inspect filtered.pgp then stdout contains "Alice" then stdout contains "Bob" ~~~ ## Listing contents of a keyring: `sq keyring list` The scenarios in this section verify the contents of a keyring can be listed. ### List keys in a keyring _Requirement: we can list the keys in a keyring._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --userid Alice --output alice.pgp --rev-cert alice.pgp.rev when I run sq key generate --own-key --without-password --userid Bob --output bob.pgp --rev-cert bob.pgp.rev when I run sq keyring merge alice.pgp bob.pgp --output ring.pgp when I run sq keyring list ring.pgp then stdout contains "Alice" then stdout contains "Bob" ~~~ ### List keys in a key file _Requirement: we can list the keys in a key file._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --userid Alice --output alice.pgp --rev-cert alice.pgp.rev when I run sq keyring list alice.pgp then stdout contains "Alice" then stdout doesn't contain "Bob" ~~~ ### List all user ids in a key file _Requirement: we can list all user ids._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --userid Alice --userid Bob --output alice.pgp --rev-cert alice.pgp.rev when I run sq keyring list alice.pgp --all-userids then stdout contains "Alice" then stdout contains "Bob" ~~~ ### List keys in keyring read from stdin _Requirement: we can list keys in a keyring that we read from stdin._ This isn't implemented yet, because Subplot needs to add support for redirecting stdin to come from a file first. ## Split a keyring: `sq keyring split` The scenarios in this section verify that splitting a keyring into individual files, one per key: the `sq keyring split` subcommand. Or rather, there will be such scenarios here when Subplot provides tools for dealing with randomly named files. Until then, this section is a placeholder. ~~~ given an installed sq when I run sq key generate --own-key --without-password --userid Alice --output alice.pgp --rev-cert alice.pgp.rev when I run sq key generate --own-key --without-password --userid Bob --output bob.pgp --rev-cert bob.pgp.rev when I run sq keyring merge alice.pgp bob.pgp --output ring.pgp when I run sq keyring split ring.pgp then the resulting files match alice,pgp and bob.pgp ~~~ # Encryption and decryption: `sq encrypt` and `sq decrypt` This chapter has scenarios for verifying that encryption and decryption work. The overall approach is to do round trips: we encrypt, then decrypt, and is the result is identical to the input, all good. ## Encrypt to stdout as ASCII armored _Requirement: We must be able to encrypt a file using a certificate, with output going to stdout. We also verify that the encrypted output doesn't contain the message in cleartext, just in case. ~~~scenario given an installed sq given file hello.txt when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev when I run sq key delete --cert-file key.pgp --output cert.pgp when I run sq encrypt --without-signature --for-file cert.pgp hello.txt then stdout contains "-----BEGIN PGP MESSAGE-----" then stdout doesn't contain "hello, world" ~~~ ## Encrypt to stdout as binary _Requirement: We must be able to encrypt a file using a certificate, with output going to stdout. We also verify that the encrypted output doesn't contain the message in cleartext, just in case. ~~~scenario given an installed sq given file hello.txt when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev when I run sq key delete --cert-file key.pgp --output cert.pgp when I run sq encrypt --without-signature --binary --for-file cert.pgp hello.txt then stdout doesn't contain "-----BEGIN PGP MESSAGE-----" then stdout doesn't contain "hello, world" ~~~ ## Encrypt and decrypt using asymmetric encryption _Requirement: We must be able to encrypt a file using a certificate, and then decrypt it using the corresponding key._ This scenario creates a plain text file, generates a key, encrypts and then decrypts the file. The resulting output must be identical to the original plain text input file. This is a very simplistic scenario and does not even try to test harder cases (binary files, very large files, etc). ~~~scenario given an installed sq given file hello.txt when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev when I run sq key delete --cert-file key.pgp --output cert.pgp when I run sq encrypt --without-signature --output x.pgp --for-file cert.pgp hello.txt when I run sq decrypt --output output.txt --recipient-file key.pgp x.pgp then files hello.txt and output.txt match ~~~ ## Encrypt for multiple recipients _Requirement: We must be able to encrypt a message for multiple recipients at a time._ ~~~scenario given an installed sq given file hello.txt when I run sq key generate --own-key --without-password --no-userids --output alice.pgp --rev-cert alice.pgp.rev when I run sq key delete --cert-file alice.pgp --output alice-cert.pgp when I run sq key generate --own-key --without-password --no-userids --output bob.pgp --rev-cert bob.pgp.rev when I run sq key delete --cert-file bob.pgp --output bob-cert.pgp when I run sq encrypt --without-signature --for-file alice-cert.pgp --for-file bob-cert.pgp hello.txt --output x.pgp when I run sq decrypt --recipient-file alice.pgp --output alice.txt x.pgp then files hello.txt and alice.txt match when I run sq decrypt --recipient-file bob.pgp --output bob.txt x.pgp then files hello.txt and bob.txt match ~~~ ## Encrypt and sign at the same time _Requirement: We must be able to sign and encrypt a message at the same time._ ~~~scenario given an installed sq given file hello.txt when I run sq key generate --own-key --without-password --no-userids --output alice.pgp --rev-cert alice.pgp.rev when I run sq key delete --cert-file alice.pgp --output alice-cert.pgp when I run sq encrypt --for-file alice-cert.pgp --signer-file alice.pgp hello.txt --output x.pgp when I run sq decrypt --recipient-file alice.pgp --output alice.txt x.pgp --signer-file alice-cert.pgp then files hello.txt and alice.txt match ~~~ ## Detect bad signature when decrypting _Requirement: When decrypting a message, if a signature check fails, the output file should be deleted. ~~~scenario given an installed sq given file hello.txt given file empty when I run sq key generate --own-key --without-password --no-userids --output alice.pgp --rev-cert alice.pgp.rev when I run sq key delete --cert-file alice.pgp --output alice-cert.pgp when I run sq key generate --own-key --without-password --no-userids --output bob.pgp --rev-cert bob.pgp.rev when I run sq key delete --cert-file bob.pgp --output bob-cert.pgp when I run sq encrypt --for-file alice-cert.pgp --signer-file alice.pgp hello.txt --output x.pgp when I try to run sq decrypt --recipient-file alice.pgp --output alice.txt x.pgp --signer-file bob-cert.pgp then exit code is 1 then file alice.txt does not exist ~~~ # Certify user identities: `sq pki vouch add` The scenarios in this chapter verify the certification functionality: the subcommand `sq certify` in its various variations. ## Certify an identity as ASCII armor _Requirement: We can certify a user identity on a key._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --userid Alice --output alice.pgp --rev-cert alice.pgp.rev when I run sq key delete --cert-file alice.pgp --output alice-cert.pgp when I run sq key generate --own-key --without-password --userid Bob --output bob.pgp --rev-cert bob.pgp.rev when I run sq key delete --cert-file bob.pgp --output bob-cert.pgp when I run sq inspect bob-cert.pgp then stdout doesn't contain "Certifications:" when I run sq pki vouch add --certifier-file alice.pgp --cert-file bob-cert.pgp --userid Bob --output cert.pgp then file cert.pgp contains "-----BEGIN PGP PUBLIC KEY BLOCK-----" then file cert.pgp contains "-----END PGP PUBLIC KEY BLOCK-----" when I run sq inspect cert.pgp then stdout contains "Certifications: 1," ~~~ ## Certify an identity _Requirement: We can certify a user identity on a key._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --userid Alice --output alice.pgp --rev-cert alice.pgp.rev when I run sq key delete --cert-file alice.pgp --output alice-cert.pgp when I run sq key generate --own-key --without-password --userid Bob --output bob.pgp --rev-cert bob.pgp.rev when I run sq key delete --cert-file bob.pgp --output bob-cert.pgp when I run sq inspect bob-cert.pgp then stdout doesn't contain "Certifications:" when I run sq pki vouch add --certifier-file alice.pgp --cert-file bob-cert.pgp --userid Bob --output cert.pgp when I run sq inspect cert.pgp then stdout contains "Certifications: 1," ~~~ ## Certify an identity matched by email address _Requirement: We can certify a user identity on a cert identified by email address._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --userid "" --output alice.pgp --rev-cert alice.pgp.rev when I run sq key delete --cert-file alice.pgp --output alice-cert.pgp when I run sq key generate --own-key --without-password --userid "" --output bob.pgp --rev-cert bob.pgp.rev when I run sq key delete --cert-file bob.pgp --output bob-cert.pgp when I run sq pki vouch add --certifier-file alice.pgp --cert-file bob-cert.pgp --email bob@example.org --output cert.pgp when I run sq inspect cert.pgp then stdout contains "Certifications: 1," ~~~ ## Certify an identity that is not self-signed _Requirement: We can certify a user identity on a cert, even if that user identity doesn't exist on that cert, and consequently has no self-signature._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --userid Alice --output alice.pgp --rev-cert alice.pgp.rev when I run sq key delete --cert-file alice.pgp --output alice-cert.pgp when I run sq key generate --own-key --without-password --userid Bob --output bob.pgp --rev-cert bob.pgp.rev when I run sq key delete --cert-file bob.pgp --output bob-cert.pgp when I run sq inspect bob-cert.pgp then stdout doesn't contain "Certifications:" when I run sq pki vouch add --certifier-file alice.pgp --cert-file bob-cert.pgp --add-userid "My friend Bob" --output cert.pgp when I run sq inspect cert.pgp then stdout contains "My friend Bob" then stdout contains "Certifications: 1," ~~~ ## Certify an email identity that is not self-signed _Requirement: We can certify an email on a cert, even if that email address doesn't exist on that cert, and consequently has no self-signature._ ~~~scenario given an installed sq when I run sq key generate --own-key --without-password --userid Alice --output alice.pgp --rev-cert alice.pgp.rev when I run sq key delete --cert-file alice.pgp --output alice-cert.pgp when I run sq key generate --own-key --without-password --userid Bob --output bob.pgp --rev-cert bob.pgp.rev when I run sq key delete --cert-file bob.pgp --output bob-cert.pgp when I run sq pki vouch add --certifier-file alice.pgp --cert-file bob-cert.pgp --add-email "bob@example.org" --output cert.pgp when I run sq inspect cert.pgp then stdout contains "" then stdout contains "Certifications: 1," ~~~ # Sign a document and verify the signature: `sq sign` and `sq verify` This chapter verifies that digital signatures work in `sq`. Like with encryption, the verification is based on round trips: we create a signature, and that it matches the signed data. We break this into a number simple cases. ## Create signature to stdout in ASCII armor _Requirement: We can create a signature and have it written to stdout in ASCII armor form._ ~~~scenario given an installed sq given file hello.txt when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev when I run sq sign --message --signer-file key.pgp hello.txt then stdout contains "-----BEGIN PGP MESSAGE-----" then stdout contains "-----END PGP MESSAGE-----" ~~~ ## Create signature to stdout in binary _Requirement: We can create a signature and have it written to stdout in binary form._ ~~~scenario given an installed sq given file hello.txt when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev when I run sq sign --message --signer-file key.pgp --binary hello.txt then stdout doesn't contain "-----BEGIN PGP MESSAGE-----" then stdout doesn't contain "-----END PGP MESSAGE-----" ~~~ ## Create signature to named file _Requirement: We can create a signature and have it written to a named file._ ~~~scenario given an installed sq given file hello.txt when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev when I run sq sign --message --signer-file key.pgp --output signed.pgp hello.txt then file signed.pgp contains "-----BEGIN PGP MESSAGE-----" then file signed.pgp contains "-----END PGP MESSAGE-----" ~~~ ## Signed file can be verified _Requirement: We can sign a file and verify the signature._ ~~~scenario given an installed sq given file hello.txt when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev when I run sq key delete --cert-file key.pgp --output cert.pgp when I run sq sign --message --signer-file key.pgp --output signed.pgp hello.txt when I run sq verify --message --signer-file cert.pgp signed.pgp then stdout contains "hello, world" ~~~ ## File is signed with all required keys _Requirement: We can verify that a file is signed by all required keys._ We verify this by signing a file twice, and verifying there are two signatures. We also verify that if there is only one signature, it's not enough, when we need two. ~~~scenario given an installed sq given file hello.txt when I run sq key generate --own-key --without-password --userid Alice --output alice.pgp --rev-cert alice.pgp.rev when I run sq key delete --cert-file alice.pgp --output alice-cert.pgp when I run sq key generate --own-key --without-password --userid Bob --output bob.pgp --rev-cert bob.pgp.rev when I run sq key delete --cert-file bob.pgp --output bob-cert.pgp when I run sq sign --message --signer-file alice.pgp --output signed1.pgp hello.txt when I try to run sq verify --message --signer-file alice-cert.pgp --signer-file bob-cert.pgp --signatures=2 signed1.pgp then exit code is 1 when I run sq sign --message --append --signer-file bob.pgp --output signed2.pgp signed1.pgp when I run sq verify --message --signer-file alice-cert.pgp --signer-file bob-cert.pgp --signatures=1 signed2.pgp then stdout contains "hello, world" when I run sq verify --message --signer-file alice-cert.pgp --signer-file bob-cert.pgp --signatures=2 signed2.pgp then stdout contains "hello, world" ~~~ ## Signed file cannot be verified if it has been modified _Requirement: We can sign a file and verifying the signature fails if the signed file has been modified._ We modify the signed file by removing the third line of it. The file starts with a line containing "-----BEGIN PGP MESSAGE-----" and then an empty line, and the third line is actual data. If we delete that, the file by definition can't be valid anymore. ~~~scenario given an installed sq given file hello.txt given file sed-in-place when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev when I run sq key delete --cert-file key.pgp --output cert.pgp when I run sq sign --message --signer-file key.pgp --output signed.pgp hello.txt when I run sh sed-in-place 3d signed.pgp when I try to run sq verify --message --signer-file cert.pgp signed.pgp then command fails ~~~ ~~~{#sed-in-place .file .sh} #!/bin/sh set -eu tmp="$(mktemp)" trap 'rm -f "$tmp"' EXIT sed "$1" "$2" > "$tmp" cat "$tmp" > "$2" ~~~ ## Create cleartext signature _Requirement: We can create a signature such that the signed data is included in a readable form._ ~~~scenario given an installed sq given file hello.txt when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev when I run sq key delete --cert-file key.pgp --output cert.pgp when I run sq sign --cleartext --signer-file key.pgp --output signed.txt hello.txt then file signed.txt contains "-----BEGIN PGP SIGNED MESSAGE-----" then file signed.txt contains "hello, world" then file signed.txt contains "-----END PGP SIGNATURE-----" when I run sq verify --cleartext --signer-file cert.pgp signed.txt then stdout contains "hello, world" ~~~ ## Cleartext signature cannot be verified if it has been modified _Requirement: If a cleartext signature is modified, it can't be verified._ ~~~scenario given an installed sq given file hello.txt given file sed-in-place when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev when I run sq key delete --cert-file key.pgp --output cert.pgp when I run sq sign --cleartext --signer-file key.pgp --output signed.txt hello.txt when I run sh sed-in-place s/hello/HELLO/ signed.txt when I try to run sq verify --cleartext --signer-file cert.pgp signed.txt then exit code is 1 ~~~ ## Create a detached signature _Requirement: We can create a signature that is doesn't include the data it signs._ ~~~scenario given an installed sq given file hello.txt when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev when I run sq key delete --cert-file key.pgp --output cert.pgp when I run sq sign --signature-file=hello.txt.sig --signer-file key.pgp hello.txt then file hello.txt.sig contains "-----BEGIN PGP SIGNATURE-----" then file hello.txt.sig contains "-----END PGP SIGNATURE-----" when I run sq verify --signature-file=hello.txt.sig --signer-file=cert.pgp hello.txt then stdout doesn't contain "hello, world" then exit code is 0 ~~~ ## Detached signature cannot be verified if the data has been modified _Requirement: If the file that is signed using a detached signature is modified, the signature can't be verified._ ~~~scenario given an installed sq given file hello.txt given file sed-in-place when I run sq key generate --own-key --without-password --no-userids --output key.pgp --rev-cert key.pgp.rev when I run sq key delete --cert-file key.pgp --output cert.pgp when I run sq sign --signature-file=hello.txt.sig --signer-file key.pgp hello.txt when I run sh sed-in-place s/hello/HELLO/ hello.txt when I try to run sq verify --signature-file=hello.txt.sig --signer-file=cert.pgp hello.txt then exit code is 1 ~~~ ## Append signature to already signed message _Requirement: We must be able to add a signature to an already signed message._ ~~~scenario given an installed sq given file hello.txt when I run sq key generate --own-key --without-password --userid Alice --output alice.pgp --rev-cert alice.pgp.rev when I run sq key delete --cert-file alice.pgp --output alice-cert.pgp when I run sq key generate --own-key --without-password --userid Bob --output bob.pgp --rev-cert bob.pgp.rev when I run sq key delete --cert-file bob.pgp --output bob-cert.pgp when I run sq sign --message --signer-file alice.pgp --output signed1.pgp hello.txt when I run sq sign --message --append --signer-file bob.pgp --output signed2.pgp signed1.pgp when I run sq verify --message signed2.pgp --signer-file alice-cert.pgp --signer-file bob-cert.pgp then stdout contains "hello, world" then stderr matches regex 2.authenticated signatures ~~~ ## Merge signed files _Requirement: We must be able to merge signatures of a file signed twice separately._ ~~~scenario given an installed sq given file hello.txt when I run sq key generate --own-key --without-password --userid Alice --output alice.pgp --rev-cert alice.pgp.rev when I run sq key delete --cert-file alice.pgp --output alice-cert.pgp when I run sq key generate --own-key --without-password --userid Bob --output bob.pgp --rev-cert bob.pgp.rev when I run sq key delete --cert-file bob.pgp --output bob-cert.pgp when I run sq sign --message --signer-file alice.pgp --output signed1.pgp hello.txt when I run sq sign --message --signer-file bob.pgp --output signed2.pgp hello.txt when I run sq sign --message --output merged.pgp --merge=signed2.pgp signed1.pgp when I run sq verify --message --signer-file alice-cert.pgp --signer-file bob-cert.pgp merged.pgp then stdout contains "hello, world" then stderr matches regex 2.authenticated signatures ~~~ # ASCII Armor data representation: `sq packet armor` and `sq packet dearmor` The scenarios in this chapter verify that `sq` can convert data into the "ASCII Armor" representation and back. ## Convert data file to armored format to stdout _Requirement: We must be able to convert a file to armored format to stdout._ ~~~scenario given an installed sq given file hello.txt when I run sq packet armor hello.txt then stdout contains "-----BEGIN PGP ARMORED FILE-----" then stdout contains "-----END PGP ARMORED FILE-----" ~~~ ## Convert data file to armored format to file _Requirement: We must be able to convert a file to armored format to a named file._ ~~~scenario given an installed sq given file hello.txt given file hello.asc when I run sq packet armor hello.txt --output hello.out then files hello.asc and hello.out match ~~~ ## Convert data file to armored format with desired label _Requirement: We must be able to convert a file to armored format with the label we choose._ ~~~scenario given an installed sq given file hello.txt when I run sq packet armor hello.txt --label auto then stdout contains "-----BEGIN PGP ARMORED FILE-----" when I run sq packet armor hello.txt --label message then stdout contains "-----BEGIN PGP MESSAGE-----" when I run sq packet armor hello.txt --label cert then stdout contains "-----BEGIN PGP PUBLIC KEY BLOCK-----" when I run sq packet armor hello.txt --label key then stdout contains "-----BEGIN PGP PRIVATE KEY BLOCK-----" when I run sq packet armor hello.txt --label sig then stdout contains "-----BEGIN PGP SIGNATURE-----" when I run sq packet armor hello.txt --label file then stdout contains "-----BEGIN PGP ARMORED FILE-----" ~~~ ## Convert data file from armored format to stdout _Requirement: We must be able to convert a file from armored format to stdout._ ~~~scenario given an installed sq given file hello.asc when I run sq packet dearmor hello.asc then stdout contains "hello, world" ~~~ ## Convert data file from armored format to file _Requirement: We must be able to convert a file from armored format to a named file._ ~~~scenario given an installed sq given file hello.txt given file hello.asc when I run sq packet dearmor hello.asc --output hello.out then files hello.txt and hello.out match ~~~ ## Armor round trip _Requirement: We must be able to convert data to armored format and back._ ~~~scenario given an installed sq given file hello.txt when I run sq packet armor hello.txt --output hello.tmp when I run sq packet dearmor hello.tmp --output hello.out then files hello.txt and hello.out match ~~~ # Web key directory (WKD) support [Web Key Directory]: https://wiki.gnupg.org/WKD [Internet Draft 14 for WKD]: https://www.ietf.org/archive/id/draft-koch-openpgp-webkey-service-14.html [Web Key Directory][] (WKD) specifies how to locate a certificate for a given email address by constructing HTTPS URLs from the email address. It is specified in [Internet Draft 14 for WKD][]. # Test data file We use this file as an input file in the tests. It is a very short file, and a text file, but this is enough for the current set of requirements and scenarios. ~~~{#hello.txt .file} hello, world ~~~ This is the same content, but in ASCII armored representation. ~~~{#hello.asc .file} -----BEGIN PGP ARMORED FILE----- aGVsbG8sIHdvcmxkCg== =FOuc -----END PGP ARMORED FILE----- ~~~ This is an empty file. ~~~{#empty .file add-newline=no} ~~~ This is a file containing a password. ~~~{#password.txt .file} hunter2 ~~~ sequoia-sq-1.4.0/sq.subplot000064400000000000000000000004311046102023000137500ustar 00000000000000title: "Sequoia-PGP sq" subtitle: "integration tests, requirements, acceptance criteria" authors: - "The Sequoia-PGP project" markdowns: - sq-subplot.md bindings: - subplot/sq-subplot.yaml - lib/files.yaml - lib/runcmd.yaml impls: rust: - subplot/sq-subplot.rs classes: - json sequoia-sq-1.4.0/src/cli/cert/export.rs000064400000000000000000000072211046102023000161010ustar 00000000000000use clap::ArgGroup; use clap::Parser; use crate::cli::types::*; use crate::cli::types::cert_designator::CertUserIDEmailDomainGrepArgs; use crate::cli::types::cert_designator::CertPrefix; use crate::cli::types::cert_designator::OptionalValue; use crate::cli::examples::*; const EXAMPLES: Actions = Actions { actions: &[ Action::setup().command(&[ "sq", "pki", "link", "add", "--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--userid=Alice ", ]).build(), Action::setup().command(&[ "sq", "pki", "link", "add", "--cert=511257EBBF077B7AEDAE5D093F68CB84CE537C9A", "--userid=Bob ", ]).build(), Action::example().comment( "Export certificates with a User ID containing the \ email address." ).command(&[ "sq", "cert", "export", "--cert-email=alice@example.org", ]).build(), Action::example().comment( "Export certificates that contain a User ID with *either* \ (not both!) email address." ).command(&[ "sq", "cert", "export", "--cert-email=alice@example.org", "--cert-email=bob@example.org", ]).build(), Action::example().comment( "Export all certificates." ).command(&[ "sq", "cert", "export", "--all", ]).build(), ], }; test_examples!(sq_cert_export, EXAMPLES); #[derive(Parser, Debug)] #[clap( name = "export", about = "Export certificates from the local certificate store", long_about = "Export certificates from the local certificate store If multiple predicates are specified a certificate is returned if \ at least one of them matches. This does not check the authenticity of the certificates in anyway. \ Before using the certificates, be sure to validate and authenticate \ them. When matching on subkeys or User IDs, the component must have a valid \ self signature according to the policy. Fails if search criteria are specified and none of them matches any \ certificates. Note: this means if the certificate store is empty and \ no search criteria are specified, then this will return success. ", after_help = EXAMPLES, )] #[clap(group(ArgGroup::new("some-designator") .args(&["cert", "cert-userid", "cert-email", "cert-domain", "cert-grep", "all"]) .required(true) .multiple(true)))] pub struct Command { #[clap( default_value_t = FileOrStdout::default(), help = FileOrStdout::HELP_OPTIONAL, long, value_name = FileOrStdout::VALUE_NAME, )] pub output: FileOrStdout, #[clap( long = "local", help = "Export local (non-exportable) signatures", long_help = "\ Export local (non-exportable) signatures By default, non-exportable signatures are not emitted when exporting \ certificates, certificate components that are only bound by \ non-exportable signatures are not emitted, and certificates consisting \ of only non-exportable components are not emitted. This flag enables exporting of non-exportable signatures, components, \ and certs. This is useful for synchronization between ones devices, \ for example.", )] pub local: bool, #[clap( long, conflicts_with_all = [ "cert", "cert-userid", "cert-email", "cert-domain", "cert-grep", ], help = "Export all certificates", )] pub all: bool, #[command(flatten)] pub certs: CertDesignators, } sequoia-sq-1.4.0/src/cli/cert/import.rs000064400000000000000000000012311046102023000160650ustar 00000000000000use std::path::PathBuf; use clap::Parser; use crate::cli::examples; use examples::Action; use examples::Actions; const EXAMPLES: Actions = Actions { actions: &[ Action::example().comment( "Import a certificate." ).command(&[ "sq", "cert", "import", "juliet.pgp", ]).build(), ] }; test_examples!(sq_cert_import, EXAMPLES); #[derive(Parser, Debug)] #[clap( name = "import", about = "Import certificates into the local certificate store", after_help = EXAMPLES, )] pub struct Command { #[clap(value_name = "FILE", help = "Read from FILE or stdin if omitted")] pub input: Vec, } sequoia-sq-1.4.0/src/cli/cert/lint.rs000064400000000000000000000062011046102023000155230ustar 00000000000000//! Command-line parser for `sq cert lint`. use clap::Args; use crate::cli::examples::*; use crate::cli::types::ClapData; use crate::cli::types::FileOrStdout; use crate::cli::types::cert_designator::*; /// Checks for and optionally repairs OpenPGP certificates that use /// SHA-1. #[derive(Debug, Args)] #[clap( about = "Check certificates for issues", long_about = "Check certificates for issues `sq cert lint` checks the supplied certificates for the following \ SHA-1-related issues: - Whether a certificate revocation uses SHA-1. - Whether the current self signature for a non-revoked User ID uses \ SHA-1. - Whether the current subkey binding signature for a non-revoked, \ live subkey uses SHA-1. - Whether a primary key binding signature (\"backsig\") for a \ non-revoked, live subkey uses SHA-1. Diagnostics are printed to stderr. At the end, some statistics are \ shown. This is useful when examining a keyring. If `--fix` is \ specified and at least one issue could be fixed, the fixed \ certificates are printed to stdout. This tool does not currently support smart cards. But, if only the \ subkeys are on a smart card, this tool may still be able to partially \ repair the certificate. In particular, it will be able to fix any \ issues with User ID self signatures and subkey binding signatures for \ encryption-capable subkeys, but it will not be able to generate new \ primary key binding signatures for any signing-capable subkeys. ", after_help = EXAMPLES, )] pub struct Command { /// Attempts to fix certificates, when possible. #[arg(long)] pub fix: bool, #[command(flatten)] pub certs: CertDesignators, #[clap( long, value_name = FileOrStdout::VALUE_NAME, help = "Write to the specified FILE", long_help = "Write to the specified FILE If not specified, and the \ certificate was read from the certificate store, imports the \ modified certificate into the cert store. If not specified, \ and the certificate was read from a file, writes the modified \ certificate to stdout.", )] pub output: Option, } const EXAMPLES: Actions = Actions { actions: &[ Action::setup().command(&[ "sq", "keyring", "merge", "--output=certs.pgp", "bob.pgp", "romeo.pgp", ]).build(), Action::setup().command(&[ "sq", "key", "import", "alice-secret.pgp", ]).build(), Action::example().comment( " Gather statistics on the certificates in a keyring." ).command (&[ "sq", "cert", "lint", "--cert-file", "certs.pgp", ]).build(), Action::example().comment( "Fix a key with known problems." ).command (&[ "sq", "key", "export", "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "|", "sq", "cert", "lint", "--fix", "--cert-file=-", "|", "sq", "cert", "import" ]).build(), ], }; test_examples!(sq_cert_lint, EXAMPLES); sequoia-sq-1.4.0/src/cli/cert/list.rs000064400000000000000000000127261046102023000155410ustar 00000000000000//! Command-line parser for `sq cert list`. use clap::Parser; use crate::cli::examples::Action; use crate::cli::examples::Actions; use crate::cli::pki::CertificationNetworkArg; use crate::cli::pki::GossipArg; use crate::cli::pki::RequiredTrustAmountArg; use crate::cli::pki::ShowPathsArg; use crate::cli::pki::UnusableArg; use crate::cli::types::cert_designator::*; const EXAMPLES: Actions = Actions { actions: &[ Action::setup().command(&[ "sq", "pki", "link", "add", "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--all", ]).build(), Action::example().comment( "List all bindings for user IDs containing an email address from \ example.org, and that can be authenticated." ).command (&[ "sq", "cert", "list", "@example.org", ]).build(), Action::example().comment( "List all authenticated bindings for User IDs containing a specific email address." ).command (&[ "sq", "cert", "list", "--cert-email=alice@example.org", ]).build(), Action::example().comment( "List all paths to certificates containing a specific email address." ).command (&[ "sq", "cert", "list", "--gossip", "--show-paths", "--cert-email=alice@example.org", ]).build(), ] }; test_examples!(sq_cert_list, EXAMPLES); /// List certificates and user IDs /// /// List certificates and user IDs that match a query, are usable, and /// can be authenticated. By default, bindings (certificate and user /// ID pairs) must be fully authenticated. If no certificates or /// bindings match a query, then the command returns a non-zero exit /// code. /// /// If no queries are provided, then all bindings that are usable, and /// can be authenticated are listed. If there are no such bindings, /// the command still succeeds. /// /// By default, unusable certificates, i.e., those that are not valid /// according to the policy, are revoked, or are not live, are /// skipped. Likewise, user ID self signatures and certifications /// that are not valid according to the policy, and user IDs that are /// revoked are skipped. #[derive(Parser, Debug)] #[clap( name = "list", after_help = EXAMPLES, )] pub struct Command { #[command(flatten)] pub certs: CertDesignators, #[clap( value_name = "FINGERPRINT|KEYID|PATTERN", help = "List certs that match the pattern", long_help = "\ List certs that match the pattern If the pattern appears to be a fingerprint or key ID, it is treated as \ if it were passed to `--cert`, which matches on the certificate's \ fingerprint. Otherwise, it is treated as if it were passed to \ `--cert-grep`, which matches on user IDs.", conflicts_with_all = &["cert", "cert-userid", "cert-email", "cert-domain", "cert-grep"], )] pub pattern: Option, #[command(flatten)] pub show_paths: ShowPathsArg, #[command(flatten)] pub gossip: GossipArg, #[command(flatten)] pub unusable: UnusableArg, #[command(flatten)] pub certification_network: CertificationNetworkArg, #[command(flatten)] pub trust_amount: RequiredTrustAmountArg, } /// Documentation for the cert designators for the cert list. pub struct ListCertDoc {} impl AdditionalDocs for ListCertDoc { fn help(arg: &'static str, _help: &'static str) -> clap::builder::StyledStr { match arg { "cert" => "\ List certificates with the specified fingerprint or key ID".into(), "userid" => "\ List bindings with the specified user ID".into(), "email" => "\ List bindings with user IDs that contain the specified email address".into(), "domain" => "\ List bindings with user IDs that contain an email address in the \ specified domain".into(), "grep" => "\ List bindings with a user ID that contains the pattern".into(), _ => unreachable!(), } } fn long_help(arg: &'static str, _help: &'static str) -> Option { match arg { "cert" => Some(format!("\ {} Note: fingerprints and key IDs are self-authenticating identifiers. As \ such, a certificate with the specified fingerprint or key ID is \ considered authenticated; no user IDs have to be authenticated.", Self::help(arg, "")).into()), "userid" => Some(format!("\ {} The user ID must match exactly.", Self::help(arg, "")).into()), "email" => Some(format!("\ {} Email addresses are first normalized by doing puny-code normalization on \ the domain, and lower casing the local part in the so-called empty \ locale.", Self::help(arg, "")).into()), "domain" => Some(format!("\ {} A user ID's domain is extracted from the email address, if any, and is \ normalized by doing puny-code normalization.", Self::help(arg, "")).into()), "grep" => Some(format!("\ {} Performs a case-insensitive substring search. Case-folding is done in \ the empty locale.", Self::help(arg, "")).into()), _ => { None } } } } sequoia-sq-1.4.0/src/cli/cert.rs000064400000000000000000000016461046102023000145650ustar 00000000000000//! Command-line parser for `sq cert`. use clap::{Parser, Subcommand}; pub mod export; pub mod import; pub mod lint; pub mod list; #[derive(Parser, Debug)] #[clap( name = "cert", about = "Manage certificates", long_about = "Manage certificates We use the term \"certificate\", or \"cert\" for short, to refer to \ OpenPGP keys that do not contain secrets. This subcommand provides \ primitives to generate and otherwise manipulate certs. Conversely, we use the term \"key\" to refer to OpenPGP keys that do \ contain secrets. See `sq key` for operations on keys. ", subcommand_required = true, arg_required_else_help = true, disable_help_subcommand = true, )] pub struct Command { #[clap(subcommand)] pub subcommand: Subcommands, } #[derive(Debug, Subcommand)] pub enum Subcommands { Import(import::Command), Export(export::Command), List(list::Command), Lint(lint::Command), } sequoia-sq-1.4.0/src/cli/config/get.rs000064400000000000000000000021271046102023000156470ustar 00000000000000//! Command-line parser for `sq config get`. use clap::Args; use crate::cli::examples::*; #[derive(Debug, Args)] #[clap( name = "get", about = "Get configuration options", long_about = "\ Get configuration options Retrieves the configuration with the given key. Use `sq config get` \ to see all available options and their values.", after_help = GET_EXAMPLES, )] pub struct Command { #[clap( value_name = "NAME", help = "Get the value of the configuration NAME", )] pub name: Option, } const GET_EXAMPLES: Actions = Actions { actions: &[ Action::Example(Example { comment: "\ List all configuration options.", command: &[ "sq", "config", "get", ], hide: &[], }), Action::Example(Example { comment: "\ Get the default cipher suite for key generation.", command: &[ "sq", "config", "get", "key.generate.cipher-suite", ], hide: &[], }), ] }; test_examples!(sq_config_get, GET_EXAMPLES); sequoia-sq-1.4.0/src/cli/config/inspect/network.rs000064400000000000000000000013611046102023000202250ustar 00000000000000//! Command-line parser for `sq config inspect network`. use clap::Args; use crate::cli::examples::*; #[derive(Debug, Args)] #[clap( name = "network", about = "Inspect the network configuration", long_about = "\ Inspect the network configuration Prints the network configuration. This can be used to gauge the \ metadata leakage resulting from network operations. ", after_help = EXAMPLES, )] pub struct Command { } const EXAMPLES: Actions = Actions { actions: &[ Action::example() .comment("Inspect the network configuration.") .command(&[ "sq", "config", "inspect", "network", ]) .build(), ], }; test_examples!(sq_config_inspect_network, EXAMPLES); sequoia-sq-1.4.0/src/cli/config/inspect/paths.rs000064400000000000000000000013501046102023000176510ustar 00000000000000//! Command-line parser for `sq config inspect paths`. use clap::Args; use crate::cli::examples::*; #[derive(Debug, Args)] #[clap( name = "paths", about = "Inspect relevant paths", long_about = "\ Inspect relevant paths Prints paths that are used by sq, such as the location of the home \ directory, the configuration file, the certificate store, the key \ store, etc. \ ", after_help = EXAMPLES, )] pub struct Command { } const EXAMPLES: Actions = Actions { actions: &[ Action::example() .comment("Inspect relevant paths.") .command(&[ "sq", "config", "inspect", "paths", ]) .build(), ], }; test_examples!(sq_config_inspect_paths, EXAMPLES); sequoia-sq-1.4.0/src/cli/config/inspect/policy.rs000064400000000000000000000014111046102023000200270ustar 00000000000000//! Command-line parser for `sq config inspect policy`. use clap::Args; use crate::cli::examples::*; #[derive(Debug, Args)] #[clap( name = "policy", about = "Inspect the cryptographic policy", long_about = "\ Inspect the cryptographic policy Explains the cryptographic policy that Sequoia uses to \ either accept or reject algorithms and packets outright, \ or at a configured point in time. ", after_help = EXAMPLES, )] pub struct Command { } const EXAMPLES: Actions = Actions { actions: &[ Action::example() .comment("Inspect the cryptographic policy.") .command(&[ "sq", "config", "inspect", "policy", ]) .build(), ], }; test_examples!(sq_config_inspect_policy, EXAMPLES); sequoia-sq-1.4.0/src/cli/config/inspect.rs000064400000000000000000000015141046102023000165340ustar 00000000000000//! Command-line parser for `sq config inspect`. use clap::{ Parser, Subcommand, }; pub mod network; pub mod paths; pub mod policy; #[derive(Debug, Parser)] #[clap( name = "inspect", about = "Inspect effective configuration details", long_about = "\ Inspect effective configuration details This subcommand can be used to inspect various aspects of the \ effective configuration, such as various relevant paths, \ the cryptographic policy, the network configuration, etc. ", subcommand_required = true, arg_required_else_help = true, disable_help_subcommand = true, )] pub struct Command { #[clap(subcommand)] pub subcommand: Subcommands, } #[derive(Debug, Subcommand)] #[non_exhaustive] pub enum Subcommands { Paths(paths::Command), Network(network::Command), Policy(policy::Command), } sequoia-sq-1.4.0/src/cli/config/set.rs000064400000000000000000000046131046102023000156650ustar 00000000000000//! Command-line parser for `sq config`. use clap::Args; use crate::cli::examples::*; // XXX: We don't currently expose the set command. #[derive(Debug, Args)] #[clap( name = "set", about = "Set configuration options", long_about = "\ Set configuration options Changes the configuration with the given key. Use `sq config get` \ to see all existing options and their values. ", after_help = SET_EXAMPLES, )] // XXX: value and delete should be in an argument group, but doing // that messes up the usage: // // Usage: sq config set // // Note how VALUE comes first. I believe this is tracked upstream as // https://github.com/clap-rs/clap/issues/1794 // // For now, we do the validation in the command handler. // //#[clap(group(ArgGroup::new("action").args(&["value", "delete"]).required(true)))] pub struct Command { #[clap( value_name = "NAME", help = "Set the value of the configuration NAME", )] pub name: String, #[clap( value_name = "VALUE", help = "New value for the configuration item", )] pub value: Option, #[clap( long = "delete", help = "Delete the configuration item", conflicts_with = "value", )] pub delete: bool, #[clap( long = "add", help = "Add an item to a list of items", conflicts_with = "delete", )] pub add: bool, } const SET_EXAMPLES: Actions = Actions { actions: &[ Action::Example(Example { comment: "\ Set the default cipher suite for key generation.", command: &[ "sq", "config", "set", "key.generate.cipher-suite", "rsa3k", ], hide: &[], }), Action::Example(Example { comment: "\ Delete the default cipher suite for key generation.", command: &[ "sq", "config", "set", "key.generate.cipher-suite", "--delete", ], hide: &[], }), Action::Example(Example { comment: "\ Add a default key server for network queries.", command: &[ "sq", "config", "set", "network.keyservers", "--add", "hkps://keys.example.org", ], hide: &[], }), ] }; // XXX: We don't currently expose the set command. //test_examples!(sq_config_set, SET_EXAMPLES); sequoia-sq-1.4.0/src/cli/config/template.rs000064400000000000000000000020401046102023000166750ustar 00000000000000//! Command-line parser for `sq config template`. use clap::Args; use crate::cli::{ examples::*, types::{ClapData, FileOrStdout}, }; #[derive(Debug, Args)] #[clap( name = "template", about = "Write a template configuration file", long_about = "\ Write a template configuration file Writes a template containing the default values to the given file or stdout. \ This can be used as a starting point to tweak the configuration.", after_help = TEMPLATE_EXAMPLES, )] pub struct Command { #[clap( long, value_name = FileOrStdout::VALUE_NAME, default_value_t = FileOrStdout::default(), help = FileOrStdout::HELP_OPTIONAL, )] pub output: FileOrStdout, } const TEMPLATE_EXAMPLES: Actions = Actions { actions: &[ Action::Example(Example { comment: "\ Write a template configuration.", command: &[ "sq", "config", "template", ], hide: &[], }), ] }; test_examples!(sq_config_template, TEMPLATE_EXAMPLES); sequoia-sq-1.4.0/src/cli/config.rs000064400000000000000000000110231046102023000150630ustar 00000000000000//! Command-line parser for `sq config`. use std::{ collections::BTreeMap, ffi::OsStr, path::PathBuf, sync::OnceLock, }; use clap::{ Parser, Subcommand, }; use clap_lex::OsStrExt; use sequoia_directories::Home; pub mod get; pub mod inspect; pub mod set; pub mod template; /// Computes the path to the config file even if argument parsing /// failed. /// /// This happens notably if `--help` is given. pub fn find_home() -> Option { let args = std::env::args_os().collect::>(); for (i, arg) in args.iter().enumerate() { if arg == "--" { break; } if arg.starts_with("--home=") { return handle(arg.strip_prefix("--home=")); } if arg == "--home" { if let Some(home) = args.get(i + 1) { return handle(Some(home.as_os_str())); } } } /// Handle the argument to `--home`. fn handle(arg: Option<&OsStr>) -> Option { if let Some(arg) = arg { match arg.to_str() { Some("default") => Home::default().cloned(), Some("none") => None, _ => Home::new(Some(PathBuf::from(arg))).ok(), } } else { // No argument to `--home` is a syntax error. None } } // No `--home` argument, select the default, possibly overridden // by SEQUOIA_HOME. Home::new(None).ok() } /// Values read from the config file to be included in help messages. pub type Augmentations = BTreeMap<&'static str, String>; /// Includes values from the config file in help messages. pub fn augment_help(key: &'static str, text: &str) -> String { if let Some(a) = get_augmentation(key) { format!("{}\n\ \n\ The default can be changed in the configuration \ file using the setting `{}`. \n\ [config: {}] (overrides default)", text.trim_end(), key, a) } else { format!("{}\n\ \n\ The default can be changed in the configuration \ file using the setting `{}`.", text.trim_end(), key) } } /// Returns the value of an augmentation, if any. pub fn get_augmentation(key: &str) -> Option<&str> { AUGMENTATIONS.get().and_then(|a| a.get(key).map(|v| v.as_str())) } /// Includes values from the config file in help messages. pub fn set_augmentations(augmentations: Augmentations) { AUGMENTATIONS.set(augmentations) .expect("augmentations must only be set once"); } /// Values read from the config file to be included in help messages. static AUGMENTATIONS: OnceLock = OnceLock::new(); #[derive(Debug, Parser)] #[clap( name = "config", about = "Query, inspect, and create the configuration file", long_about = format!("\ Query, inspect, and create the configuration file This subcommand can be used to query and inspect the configuration \ file{}, and to create a template that can be edited to your liking. Configuration file: {} ", sequoia_directories::Home::default() .map(|home| { let p = home.config_dir(sequoia_directories::Component::Sq); let p = p.join("config.toml"); let p = p.display().to_string(); if let Some(home) = dirs::home_dir() { let home = home.display().to_string(); if let Some(rest) = p.strip_prefix(&home) { return format!(" (default location: $HOME{})", rest); } } format!(" (default location: {})", p) }) .unwrap_or("".to_string()), find_home() .map(|home| { let p = home.config_dir(sequoia_directories::Component::Sq); let p = p.join("config.toml"); let p = p.display().to_string(); if let Some(home) = dirs::home_dir() { let home = home.display().to_string(); if let Some(rest) = p.strip_prefix(&home) { return format!("$HOME{}", rest); } } p }) .unwrap_or("".to_string())), subcommand_required = true, arg_required_else_help = true, disable_help_subcommand = true, )] pub struct Command { #[clap(subcommand)] pub subcommand: Subcommands, } #[derive(Debug, Subcommand)] #[non_exhaustive] pub enum Subcommands { Get(get::Command), Inspect(inspect::Command), Template(template::Command), } sequoia-sq-1.4.0/src/cli/decrypt.rs000064400000000000000000000074011046102023000152750ustar 00000000000000//! Command-line parser for `sq decrypt`. use std::path::PathBuf; use clap::Parser; use super::types::ClapData; use super::types::FileOrStdin; use super::types::FileOrStdout; use super::types::SessionKey; use super::types::cert_designator::*; use crate::cli::examples; use examples::Action; use examples::Actions; const DECRYPT_EXAMPLES: Actions = Actions { actions: &[ Action::example().comment( "Decrypt a file using a secret key", ).command(&[ "sq", "decrypt", "--recipient-file", "juliet-secret.pgp", "ciphertext.pgp", ]).build(), Action::example().comment( "Decrypt a file verifying signatures", ).command(&[ "sq", "decrypt", "--recipient-file", "juliet-secret.pgp", "--signer-file", "romeo.pgp", "ciphertext.pgp" ]).build(), Action::setup().command(&[ "sq", "key", "import", "juliet-secret.pgp", ]).build(), Action::example().comment( "decrypt a file using the key store", ).command(&[ "sq", "decrypt", "ciphertext.pgp", ]).build(), ], }; test_examples!(sq_decrypt, DECRYPT_EXAMPLES); #[derive(Parser, Debug)] #[clap( name = "decrypt", about = "Decrypt a message", long_about = "Decrypt a message Decrypt a message using either supplied keys, or by prompting for a \ password. If message tampering is detected, an error is returned. \ See below for details. If certificates are supplied using the `--signer-file` option, any \ signatures that are found are checked using these certificates. \ Verification is only successful if there is no bad signature, and the \ number of successfully verified signatures reaches the threshold \ configured with the `--signatures` parameter. If the signature verification fails, or if message tampering is \ detected, the program terminates with an exit status indicating \ failure. and the output file is deleted. If the output was sent \ to stdout, then the last 25 MiB of the message are withheld \ (consequently, if the message is smaller than 25 MiB, no output \ is produced). The converse operation is `sq encrypt`. ", after_help = DECRYPT_EXAMPLES, )] // TODO use usize pub struct Command { #[clap( default_value_t = FileOrStdin::default(), help = FileOrStdin::HELP_OPTIONAL, value_name = FileOrStdin::VALUE_NAME, )] pub input: FileOrStdin, #[clap( default_value_t = FileOrStdout::default(), help = FileOrStdout::HELP_OPTIONAL, long, value_name = FileOrStdout::VALUE_NAME, )] pub output: FileOrStdout, #[clap( long = "signatures", value_name = "N", help = "Set the threshold of valid signatures to N", long_help = "Set the threshold of valid signatures to N The message will only be considered \ verified if this threshold is reached. \ [default: 1 if at least one signer cert file is given, 0 otherwise]", )] pub signatures: Option, #[command(flatten)] pub signers: CertDesignators, #[clap( long = "recipient-file", value_name = "KEY_FILE", help = "Decrypt the message using the key in KEY_FILE", )] pub secret_key_file: Vec, #[clap( long = "dump-session-key", help = "Print the session key to stderr", )] pub dump_session_key: bool, #[clap( long = "session-key", value_name = "SESSION-KEY", help = "Decrypt an encrypted message using SESSION-KEY", )] pub session_key: Vec, } sequoia-sq-1.4.0/src/cli/download.rs000064400000000000000000000054521046102023000154360ustar 00000000000000//! Command-line parser for `sq download`. use clap::{ArgGroup, Parser}; use crate::cli::examples; use examples::Action; use examples::Actions; use super::types::ClapData; use super::types::cert_designator::*; use crate::cli::types::FileOrStdout; const EXAMPLES: Actions = Actions { actions: &[ Action::setup().command(&[ "sq", "cert", "import", "debian/debian-cd-signing-key.pgp", ]).build(), Action::example().comment( "Download and verify the Debian 12 checksum file.", ).command(&[ "sq", "download", "--url=file://debian/SHA512SUMS", "--signature-url=file://debian/SHA512SUMS.sign", "--signer=DF9B9C49EAA9298432589D76DA87E80D6294BE9B", "--output=SHA512SUMS", ]).build(), ], }; test_examples!(sq_download, EXAMPLES); #[derive(Parser, Debug)] #[clap( name = "download", about = "Download and authenticate the data", long_about = "Download and authenticate the data This command downloads the data from the specified URL, checks the signature, and then authenticates the signer. If the signer cannot be authenticated, the data is deleted, if possible. ", after_help = EXAMPLES, )] #[clap(group(ArgGroup::new("kind") .args(&["detached", "message", "cleartext"]).required(true)))] pub struct Command { #[clap( long = "url", value_name = "URL", help = "The data to download", )] pub url: String, #[clap( long = "signature-url", value_name = "URL", help = "URL of the signature", long_help = "\ URL of the signature Use this when the signature is detached from the data. If no signature is specified, then the signature is assumed to be \ inline. ", )] pub detached: Option, #[clap( long = "message", value_name = "SIG", help = "Verify an inline signed message" )] pub message: bool, #[clap( long = "cleartext", value_name = "SIG", help = "Verify a cleartext-signed message" )] pub cleartext: bool, #[command(flatten)] pub signers: CertDesignators, #[clap( long = "signatures", value_name = "N", default_value_t = 1, help = "Set the threshold of valid signatures to N", long_help = "Set the threshold of valid signatures to N If this threshold is not reached, the message \ will not be considered verified.", )] pub signatures: usize, #[clap( help = FileOrStdout::HELP_REQUIRED, long, value_name = FileOrStdout::VALUE_NAME, )] pub output: FileOrStdout, } sequoia-sq-1.4.0/src/cli/encrypt.rs000064400000000000000000000143441046102023000153130ustar 00000000000000//! Command-line parser for `sq encrypt`. use clap::{ValueEnum, Parser}; use super::types::ClapData; use super::types::EncryptPurpose; use super::types::FileOrStdin; use super::types::FileOrStdout; use crate::cli::config; use crate::cli::types::CertDesignators; use crate::cli::types::cert_designator::*; use crate::cli::types::Profile; use crate::cli::examples; use examples::*; /// Key for the help augmentation. pub const ENCRYPT_FOR_SELF: &str = "encrypt.for-self"; const ENCRYPT_EXAMPLES: Actions = Actions { actions: &[ Action::setup().command(&[ "sq", "pki", "link", "add", "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--email", "alice@example.org", ]).build(), Action::setup().command(&[ "sq", "key", "import", "juliet-secret.pgp", ]).build(), Action::setup().command(&[ "sq", "pki", "link", "add", "--cert=7A58B15E3B9459483D9FFA8D40E299AC5F2B0872", "--email=juliet@example.org", ]).build(), Action::example().comment( "Encrypt a file for a recipient given by fingerprint.", ).command(&[ "sq", "encrypt", "--for=EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--signer-email=juliet@example.org", "document.txt", ]).build(), Action::example().comment( "Encrypt a file for a recipient given by email.", ).command(&[ "sq", "encrypt", "--for-email=alice@example.org", "--signer-email=juliet@example.org", "document.txt", ]).build(), ] }; test_examples!(sq_encrypt, ENCRYPT_EXAMPLES); #[derive(Parser, Debug)] #[clap( name = "encrypt", about = "Encrypt a message", long_about = "Encrypt a message Encrypt a message for any number of recipients and with any number of \ passwords, optionally signing the message in the process. The converse operation is `sq decrypt`. `sq encrypt` respects the reference time set by the top-level \ `--time` argument. It uses the reference time when selecting \ encryption keys, and it sets the signature's creation time to the \ reference time. ", after_help = ENCRYPT_EXAMPLES, )] pub struct Command { #[clap( default_value_t = FileOrStdin::default(), help = FileOrStdin::HELP_OPTIONAL, value_name = FileOrStdin::VALUE_NAME, )] pub input: FileOrStdin, #[clap( default_value_t = FileOrStdout::default(), help = FileOrStdout::HELP_OPTIONAL, long, value_name = FileOrStdout::VALUE_NAME, )] pub output: FileOrStdout, #[clap( long, help = "Emit binary data", )] pub binary: bool, #[command(flatten)] pub recipients: CertDesignators, #[clap( help = "Set the filename of the encrypted file as metadata", long = "set-metadata-filename", long_help = "Set the filename of the encrypted file as metadata Do note, that this metadata is not signed and as such relying on \ it - on sender or receiver side - is generally considered \ dangerous.", )] pub set_metadata_filename: Option, #[command(flatten)] pub signers: CertDesignators, #[command(flatten)] pub signature_notations: crate::cli::types::SignatureNotationsArg, #[clap( long = "encrypt-for", value_name = "PURPOSE", default_value_t = EncryptPurpose::Universal, help = "Select what kind of keys are considered for encryption", value_enum, )] pub mode: EncryptPurpose, #[clap( long = "compression", value_name = "KIND", default_value_t = CompressionMode::Pad, help = "Select compression scheme to use", value_enum, )] pub compression: CompressionMode, #[clap( long = "use-expired-subkey", help = "Fall back to expired encryption subkeys", long_help = "Fall back to expired encryption subkeys If a certificate has only expired \ encryption-capable subkeys, fall back \ to using the one that expired last", )] pub use_expired_subkey: bool, #[clap( long = "profile", value_name = "PROFILE", default_value_t = Default::default(), help = "Select the default OpenPGP standard for the encryption container", long_help = config::augment_help( "key.generate.profile", "Select the default OpenPGP standard for the encryption container When encrypting for certificates, the encryption container is selected \ based on the stated preferences of the recipients. However, if there \ is no guidance, for example because the message is encrypted only with \ passwords, sq falls back to this profile. As OpenPGP evolves, new versions will become available. This option \ selects the version of OpenPGP to use for encrypting messages if the \ version can not be inferred otherwise. Currently, sq supports two profiles: RFC9580 and RFC4880. Currently, \ the default is RFC4880. However, once support for RFC9580 is rolled \ out further, the default will change in a future version of sq."), value_enum, )] pub profile: Profile, /// Workaround for https://github.com/clap-rs/clap/issues/3846 #[clap(skip)] pub profile_source: Option, } /// Documentation for signer arguments. pub struct SignerDoc {} impl AdditionalDocs for SignerDoc { fn help(arg: &'static str, help: &'static str) -> clap::builder::StyledStr { match arg { "file" => "Sign the message using the key read from PATH" .into(), _ => { debug_assert!(help.starts_with("Use certificates")); help.replace("Use certificates", "Sign the message using the key") .into() }, } } } #[derive(ValueEnum, Debug, Clone)] pub enum CompressionMode { None, Pad, Zip, Zlib, Bzip2 } sequoia-sq-1.4.0/src/cli/examples.rs000064400000000000000000000337011046102023000154430ustar 00000000000000//! A framework to format and check examples. //! //! The help text for subcommands includes examples. That's great. //! But, it is even better when they are tested. This module defines //! data structures to describe the examples, mechanisms to format the //! examples, and infrastructure to execute the examples. use std::collections::BTreeMap; use clap::builder::IntoResettable; use clap::builder::Resettable; /// A command that is executed by the integration test, but not shown /// in the manual pages. pub struct Setup<'a> { pub command: &'a [ &'a str ], } /// Builds up setup actions in an extensible way. pub struct SetupBuilder<'a> { setup: Setup<'a>, } impl<'a> SetupBuilder<'a> { /// Returns a new setup builder. const fn new() -> Self { SetupBuilder { setup: Setup { command: &[], } } } /// Provides the command as slice. /// /// It'd be nice to provide a per-argument interface, but that /// requires some ingenuity for it to stay const. pub const fn command(mut self, command: &'a [&'a str]) -> Self { self.setup.command = command; self } /// Finishes building the setup action. pub const fn build(self) -> Action<'a> { assert!(! self.setup.command.is_empty()); Action::Setup(self.setup) } } /// A command that is executed by the integration test, and shown in /// the manual pages. pub struct Example<'a> { // A human-readable comment. pub comment: &'a str, pub command: &'a [ &'a str ], pub hide: &'a [ &'a str ], } /// Builds up example actions in an extensible way. pub struct ExampleBuilder<'a> { example: Example<'a>, } impl<'a> ExampleBuilder<'a> { /// Returns a new example builder. const fn new() -> Self { ExampleBuilder { example: Example { comment: "", command: &[], hide: &[], }, } } /// Provides the comment. /// /// It'd be nice to provide a per-argument interface, but that /// requires some ingenuity for it to stay const. pub const fn comment(mut self, comment: &'a str) -> Self { self.example.comment = comment; self } /// Provides the command as slice. /// /// It'd be nice to provide a per-argument interface, but that /// requires some ingenuity for it to stay const. pub const fn command(mut self, command: &'a [&'a str]) -> Self { self.example.command = command; self } /// Hides the parameters in the output /// /// Skip these parameters when generating human readable output #[allow(unused)] pub const fn hide(mut self, hide: &'a [&'a str]) -> Self { self.example.hide = hide; self } /// Finishes building the example action. /// /// The example will be executed by the test. pub const fn build(self) -> Action<'a> { assert!(! self.example.comment.is_empty()); assert!(! self.example.command.is_empty()); Action::Example(self.example) } /// Finishes building the example action, marking it for syntax /// checking only. /// /// The example will not be executed by the test, but the syntax /// will be checked using our command line parser. pub const fn syntax_check(self) -> Action<'a> { assert!(! self.example.comment.is_empty()); assert!(! self.example.command.is_empty()); Action::SyntaxCheck(self.example) } } /// An action to execute. #[allow(dead_code)] pub enum Action<'a> { /// A command that is executed by the integration test, but not /// shown in the manual pages. Setup(Setup<'a>), /// A command that is syntax check (but not run) by the /// integration test, and shown in the manual pages. SyntaxCheck(Example<'a>), /// A command that is executed by the integration test, and shown /// in the manual pages. Example(Example<'a>), } impl<'a> Action<'a> { /// Creates a setup action. pub const fn setup() -> SetupBuilder<'a> { SetupBuilder::new() } /// Creates an example action. pub const fn example() -> ExampleBuilder<'a> { ExampleBuilder::new() } /// Return the action's command, if any. #[allow(dead_code)] pub fn command(&self) -> Option<&'a [ &'a str ]> { match self { Action::Setup(Setup { command, .. }) => Some(command), Action::SyntaxCheck(Example { command, .. }) => Some(command), Action::Example(Example { command, .. }) => Some(command), } } } /// A sequence of actions to execute. pub struct Actions<'a> { pub actions: &'a [Action<'a>], } impl<'a> IntoResettable for Actions<'a> { fn into_resettable(self) -> Resettable { // Default width when we aren't connected to a terminal. let default_width = 72; // We prefix lines with either `# `, `$ `, or ` `. const PREFIX_WIDTH: usize = 2; let terminal_size = terminal_size::terminal_size(); let width = if let Some((width, _height)) = terminal_size { let width = width.0 as usize; if width < 40 { // If the terminal is too narrow, then give up and use // the default. default_width } else { std::cmp::max(40, width - PREFIX_WIDTH) } } else { default_width }; let mut lines = vec![ "Examples:".to_string() ]; lines.extend(self.actions .iter() .filter_map(|action| { let example = match action { Action::SyntaxCheck(example) => example, Action::Example(example) => example, // Don't show it. Action::Setup(_) => return None, }; let comment = textwrap::indent( &textwrap::wrap(example.comment, width).join("\n"), "# "); // Our manpage generate complains if an // example is too long: // // warning: Command in example exceeds 64 chars: // // or // // warning: Continuation in example exceeds 57 chars: let command = wrap_command(&example.command, &example.hide, "", width.min(64), " ", width.min(57)); Some(format!("{}\n{}", comment, command)) })); let text = lines.join("\n\n").into(); Resettable::Value(text) } } /// Wraps the given command to width, adding continuation backslashes. /// /// The first line is prefixed with `indent` and wrapped `to_width`, /// any continuations are prefixed with `continuation_indent` and /// wrapped to `continuation_width`. pub fn wrap_command>(command: &[S], hide: &[S], indent: &str, to_width: usize, continuation_indent: &str, continuation_width: usize) -> String { let prompt = platform! { unix => { "$" }, windows => { ">" }, }; let mut hide = BTreeMap::from_iter(hide.iter().map(|s| (s.as_ref(), false))); let result = command .iter() .filter(|&item| { // Remove all of the items in command which are also in // hide. if let Some(used) = hide.get_mut(item.as_ref()) { *used = true; // Don't show it. false } else { // Show it. true } }) .fold(vec![format!("{}{}", indent, prompt)], |mut s, arg| { let first = s.len() == 1; let arg = arg.as_ref(); if arg == "|" { let last = s.last_mut().expect("have one"); *last = format!("{} \\", last); s.push(format!(" {}", arg)); return s; } // Quote the argument, if necessary. let quote = |arg: &str| -> String { if arg.contains(&[ '\"', ]) { format!("'{}'", arg) } else if arg.chars().any(char::is_whitespace) || arg.contains(&[ '`', '#', '$', '&', '*', '(', ')', '\\', '|', '[', ']', '{', '}', ';', '\'', '<', '>', '?', '!', ]) { format!("\"{}\"", arg) } else { arg.to_string() } }; // If we have --foo=bar, then only but bar in quotes. let mut quoted = None; if arg.starts_with("--") { if let Some(i) = arg.find('=') { if arg[0..i].chars().all(|c| { c.is_alphanumeric() || c == '-' }) { quoted = Some(format!("{}={}", &arg[..i], quote(&arg[i + 1..]))); } } } let arg = if let Some(quoted) = quoted { quoted } else { quote(arg) }; let last = s.last_mut().expect("have one"); let last_chars = last.chars().count(); let arg_chars = arg.chars().count(); let max_width = if first { to_width } else { continuation_width }; if last_chars + 1 + arg_chars <= max_width { *last = format!("{} {}", last, arg); } else { *last = format!("{} \\", last); s.push(format!("{}{}", continuation_indent, arg)); } s }) .join("\n"); #[cfg(debug_assertions)] for (arg, used) in hide.into_iter() { if ! used { panic!("Example `{}` includes an argument to hide (`{}`), but the \ argument wasn't used by the example!", command.iter() .map(|arg| arg.as_ref().to_string()) .collect::>() .join(" "), arg); } } result } macro_rules! test_examples { ($ident:ident, $actions:expr) => { #[test] fn $ident() { use std::path::PathBuf; use tempfile::TempDir; use assert_cmd::Command; let fixtures = PathBuf::from(concat!( env!("CARGO_MANIFEST_DIR"), "/tests/data/examples")); let tmp_dir = TempDir::new().unwrap(); let options = fs_extra::dir::CopyOptions::new() .content_only(true); fs_extra::dir::copy(&fixtures, &tmp_dir, &options) .expect(&format!("Copying {:?} to {:?}", fixtures, &tmp_dir)); // Create an empty policy configuration file. We use this // instead of the system-wide policy configuration file, // which might be more strict than what our test vectors // expect. let policy = tmp_dir.path().join("empty-policy.toml"); std::fs::write(&policy, "").unwrap(); let home = tmp_dir.path().join("home"); let cert_store = tmp_dir.path().join("cert-store"); let key_store = tmp_dir.path().join("key-store"); eprintln!("Testing example from {}:{}", file!(), line!()); for (i, action) in $actions.actions.into_iter().enumerate() { let command = if let Some(command) = action.command() { command } else { continue; }; if let Action::SyntaxCheck(_) = &action { // Just syntax check it. eprintln!("Syntax checking: {:?}", command); use clap::Parser; if let Err(err) = $crate::cli::SqCommand::try_parse_from(command.iter()) { eprintln!("example:{}:{}: checking example #{}: {}", file!(), line!(), i + 1, err); panic!("syntax checking example failed"); } continue; } // Handle pipelines by tracking intermediate results. let mut intermediate = None; for command in command.split(|p| *p == "|") { eprintln!("Executing: {:?}", command); let mut cmd = Command::cargo_bin(command[0]).unwrap(); cmd.current_dir(&tmp_dir) .env("RUST_BACKTRACE", "1") .env("RUST_LOG", "trace") .env("SEQUOIA_CRYPTO_POLICY", &policy) .env("SEQUOIA_HOME", &home) .env("SEQUOIA_CERT_STORE", &cert_store) .env("SEQUOIA_KEY_STORE", &key_store) .arg("--batch") .args(&command[1..]); if let Some(prev) = intermediate { cmd.write_stdin(prev); } let res = cmd.assert(); intermediate = Some(res.get_output().stdout.clone()); if let Err(err) = res.try_success() { eprintln!("example:{}:{}: executing example #{}: {}", file!(), line!(), i + 1, err); panic!("executing example failed"); } } } } }; } sequoia-sq-1.4.0/src/cli/inspect.rs000064400000000000000000000055231046102023000152730ustar 00000000000000//! Command-line parser for `sq inspect`. use clap::Parser; use super::types::ClapData; use super::types::FileOrStdin; use super::types::cert_designator::*; use crate::cli::examples; use examples::Action; use examples::Actions; const INSPECT_EXAMPLES: Actions = Actions { actions: &[ Action::example().comment( "Inspect a certificate.", ).command(&[ "sq", "inspect", "juliet.pgp", ]).build(), Action::example().comment( "Show how the certificate looked on July 21, 2013.", ).command(&[ "sq", "inspect", "--time", "20130721", "juliet.pgp", ]).build(), Action::example().comment( "Inspect an encrypted message.", ).command(&[ "sq", "inspect", "message.pgp", ]).build(), Action::example().comment( "Inspect a detached signature.", ).command(&[ "sq", "inspect", "document.sig", ]).build(), ], }; test_examples!(sq_inspect, INSPECT_EXAMPLES); #[derive(Parser, Debug)] #[clap( name = "inspect", about = "Inspect data, like file(1)", long_about = "Inspect data, like file(1) It is often difficult to tell from cursory inspection using cat(1) or \ file(1) what kind of OpenPGP one is looking at. This subcommand \ inspects the data and provides a meaningful human-readable description \ of it. `sq inspect` respects the reference time set by the top-level \ `--time` argument. It uses the reference time when determining what \ binding signatures are active. ", after_help = INSPECT_EXAMPLES, )] pub struct Command { #[clap( default_value_t = FileOrStdin::default(), help = FileOrStdin::HELP_OPTIONAL, value_name = FileOrStdin::VALUE_NAME, conflicts_with_all = ["cert-file", "cert", "cert-userid", "cert-email", "cert-domain", "cert-grep"], )] pub input: FileOrStdin, #[command(flatten)] pub certs: CertDesignators, #[clap( long = "certifications", help = "Print third-party certifications", )] pub certifications: bool, #[clap( long = "dump-bad-signatures", help = "Dump signatures that are definitively bad", )] pub dump_bad_signatures: bool, } /// Documentation for the cert designators for `--inspect`. pub struct ToInspectDoc {} impl AdditionalDocs for ToInspectDoc { fn help(arg: &'static str, help: &'static str) -> clap::builder::StyledStr { let help = help.replace("Use", "Inspect"); match arg { "cert" | "file" => help, _ => format!( "{} (note: User IDs are not authenticated)", help), }.into() } } sequoia-sq-1.4.0/src/cli/key/approvals.rs000064400000000000000000000232731046102023000164270ustar 00000000000000//! Command-line parser for `sq key expire`. use clap::{ Args, ArgGroup, Subcommand, }; use sequoia_openpgp as openpgp; use openpgp::KeyHandle; use crate::cli::types::ClapData; use crate::cli::types::FileOrStdout; use crate::cli::examples::*; use crate::cli::types::cert_designator::*; use crate::cli::types::UserIDDesignators; use crate::cli::types::userid_designator; #[derive(Debug, Subcommand)] #[clap( name = "approvals", about = "Manages certification approvals", long_about = "\ Manages certification approvals Key holders may approve of third-party certifications associated with \ their certificate. This subcommand manages the approvals. To prevent certificate flooding attacks, modern key servers prevent \ uncontrolled distribution of third-party certifications on \ certificates. To allow the key holder to control what information is \ distributed with their certificate, these key servers only distribute \ third-party certifications that the key holder has explicitly \ approved. ", subcommand_required = true, arg_required_else_help = true, disable_help_subcommand = true, )] #[non_exhaustive] pub enum Command { List(ListCommand), Update(UpdateCommand), } const LIST_EXAMPLES: Actions = Actions { actions: &[ Action::Example(Example { comment: "\ Lists the approved certifications on all the user IDs.", command: &[ "sq", "key", "approvals", "list", "--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0", ], hide: &[], }), Action::Example(Example { comment: "\ Lists the unapproved certifications on all the user IDs.", command: &[ "sq", "key", "approvals", "list", "--pending", "--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0", ], hide: &[], }), Action::Example(Example { comment: "\ Lists all unapproved certifications on a given user ID.", command: &[ "sq", "key", "approvals", "list", "--pending", "--email=alice@example.org", "--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0", ], hide: &[], }), ] }; test_examples!(sq_key_approvals_list, LIST_EXAMPLES); #[derive(Debug, Args)] #[clap( name = "list", about = "Lists third-party certifications and their approval status", long_about = "\ Lists third-party certifications and their approval status To prevent certificate flooding attacks, modern key servers prevent \ uncontrolled distribution of third-party certifications on \ certificates. To allow the key holder to control what information is \ distributed with their certificate, these key servers only distribute \ third-party certifications that the key holder has explicitly \ approved. ", after_help = LIST_EXAMPLES, )] pub struct ListCommand { #[command(flatten)] pub cert: CertDesignators, #[command(flatten)] pub userids: UserIDDesignators< userid_designator::PlainByArgs, userid_designator::OptionalValue>, #[clap( long = "pending", help = "List unapproved certifications", )] pub pending: bool, } /// Documentation for the cert designators for the key approvals list /// command. pub struct ApprovalsListDoc {} impl AdditionalDocs for ApprovalsListDoc { fn help(arg: &'static str, help: &'static str) -> clap::builder::StyledStr { match arg { "file" => "List the approvals on the certificate read from PATH" .into(), _ => { debug_assert!(help.starts_with("Use certificates")); help.replace("Use certificates", "List the approvals on the certificate") .into() }, } } } const UPDATE_EXAMPLES: Actions = Actions { actions: &[ Action::setup().command(&[ "sq", "key", "import", "alice-secret.pgp", ]).build(), Action::setup().command(&[ "sq", "key", "import", "bob-secret.pgp", ]).build(), Action::setup().command(&[ "sq", "pki", "vouch", "add", "--certifier=511257EBBF077B7AEDAE5D093F68CB84CE537C9A", "--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--email=alice@example.org", ]).build(), Action::setup().command(&[ "sq", "pki", "link", "add", "--cert=511257EBBF077B7AEDAE5D093F68CB84CE537C9A", "--email=bob@example.org", ]).build(), Action::example().comment("\ Approve of all of the certifications on all of Alice's user IDs." ).command(&[ "sq", "key", "approvals", "update", "--add-all", "--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0", ]).build(), Action::example().comment("\ Approve of all of the certifications on all of Alice's user IDs made by Bob, \ discarding all prior approvals first." ).command(&[ "sq", "key", "approvals", "update", "--remove-all", "--add-by=511257EBBF077B7AEDAE5D093F68CB84CE537C9A", "--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0", ]).build(), Action::example().comment("\ Approve of all of the certifications on a specific user ID by certifiers that \ can be authenticated, discarding all prior approvals first." ).command(&[ "sq", "key", "approvals", "update", "--remove-all", "--add-authenticated", "--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--userid=Alice ", ]).build(), Action::example().comment("\ Remove the approval of Bob's certification on all of Alice's user IDs." ).command(&[ "sq", "key", "approvals", "update", "--remove-by=511257EBBF077B7AEDAE5D093F68CB84CE537C9A", "--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0", ]).build(), ] }; test_examples!(sq_key_approvals_update, UPDATE_EXAMPLES); #[derive(Debug, Args)] #[clap( name = "update", about = "Approves of third-party certifications allowing for their distribution", long_about = "\ Approves of third-party certifications allowing for their distribution To prevent certificate flooding attacks, modern key servers prevent \ uncontrolled distribution of third-party certifications on \ certificates. To allow the key holder to control what information is \ distributed with their certificate, these key servers only distribute \ third-party certifications that the key holder has explicitly \ approved. By default, all user IDs are considered, but if at least one `--name`, \ `--email`, or `--userid` argument is given, only the matching user IDs \ are considered. After the approvals have been changed, the certificate has to be \ distributed, e.g. by uploading it to a key server. ", after_help = UPDATE_EXAMPLES, )] #[clap(group( ArgGroup::new("action") .args(&[ "remove_all", "remove_by", "add_all", "add_by", "add_authenticated", ]) .required(true) .multiple(true)))] pub struct UpdateCommand { #[command(flatten)] pub cert: CertDesignators, #[command(flatten)] pub userids: UserIDDesignators< userid_designator::PlainByArgs, userid_designator::OptionalValue>, #[clap( long = "remove-all", help = "Remove all prior approvals", conflicts_with = "add_all", long_help = "\ Remove all prior approvals By default, this command adds to the set of already approved certifications. If this flag is given, the existing approvals are disregarded, and only the newly selected certifications are approved, if any. ", )] pub remove_all: bool, #[clap( long = "remove-by", value_name = "FINGERPRINT|KEYID", help = "Remove all prior approvals of certifications by this certifier", conflicts_with = "remove_all", )] pub remove_by: Vec, #[clap( long = "add-all", help = "Approve of all pending certifications", conflicts_with_all = ["remove_all", "remove_by"], )] pub add_all: bool, #[clap( long = "add-by", value_name = "FINGERPRINT|KEYID", help = "Approve of all certifications by this certifier", conflicts_with = "add_all", )] pub add_by: Vec, #[clap( long = "add-authenticated", value_name = "AMOUNT", help = "Approve of all certifications by authenticated certifiers", long_help = "\ Approve of all certifications by authenticated certifiers For all pending approvals, try to authenticate any user ID on the certifier, and if any can be authenticated, approve of the certification.", conflicts_with = "add_all", )] pub add_authenticated: bool, #[clap( long, value_name = FileOrStdout::VALUE_NAME, help = "Write to the specified FILE", long_help = "\ Write to the specified FILE If not specified, and the certificate was read from the certificate \ store, imports the modified certificate into the cert store. If not \ specified, and the certificate was read from a file, writes the \ modified certificate to stdout.", )] pub output: Option, } sequoia-sq-1.4.0/src/cli/key/delete.rs000064400000000000000000000045331046102023000156600ustar 00000000000000//! Command-line parser for `sq key delete`. use clap::Args; use crate::cli::types::*; use crate::cli::examples::*; use crate::cli::types::cert_designator::*; #[derive(Debug, Args)] #[clap( name = "delete", about = "Delete a certificate's secret key material", after_help = EXAMPLES, )] pub struct Command { #[command(flatten)] pub cert: CertDesignators, #[clap( long, value_name = FileOrStdout::VALUE_NAME, conflicts_with = "cert", help = "Write the stripped certificate to the specified file", )] pub output: Option, } const EXAMPLES: Actions = Actions { actions: &[ Action::setup().command(&[ "sq", "key", "import", "alice-secret.pgp", ]).build(), Action::example().comment("\ Delete any secret key associated with Alice's certificate." ).command(&[ "sq", "key", "delete", "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", ]).build(), Action::setup().command(&[ "sq", "key", "import", "alice-secret.pgp", ]).build(), Action::setup().command(&[ "sq", "pki", "link", "add", "--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--userid=Alice ", ]).build(), Action::example().comment("\ Delete any secret key associated with Alice's certificate \ selected by user ID." ).command(&[ "sq", "key", "delete", "--cert-email=alice@example.org", ]).build(), ] }; test_examples!(sq_key_delete, EXAMPLES); /// Documentation for the cert designators for the key delete. pub struct DeleteKeyDoc {} impl AdditionalDocs for DeleteKeyDoc { fn help(arg: &'static str, help: &'static str) -> clap::builder::StyledStr { match arg { "file" => "Delete the secret key material from the key read from PATH" .into(), _ => { debug_assert!(help.starts_with("Use certificates")); help.replace("Use certificates", "Delete secret key material from the key") }, }.into() } } sequoia-sq-1.4.0/src/cli/key/expire.rs000064400000000000000000000046751046102023000157210ustar 00000000000000//! Command-line parser for `sq key expire`. use clap::Args; use crate::cli::types::ClapData; use crate::cli::types::ExpirationArg; use crate::cli::types::FileOrStdout; use crate::cli::examples::*; use crate::cli::types::cert_designator::*; const EXAMPLES: Actions = Actions { actions: &[ Action::setup().command(&[ "sq", "key", "import", "alice-secret.pgp", ]).build(), Action::example().comment( "Change Alice's certificate to expire in a year." ).command(&[ "sq", "key", "expire", "--expiration", "1y", "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", ]).build(), Action::example().comment( "Change Alice's certificate to never expire." ).command(&[ "sq", "key", "expire", "--expiration", "never", "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", ]).build(), ], }; test_examples!(sq_key_expire, EXAMPLES); #[derive(Debug, Args)] #[clap( name = "expire", about = "Change a certificate's expiration time", long_about = "Change a certificate's expiration time This subcommand changes a certificate's expiration time. To change \ the expiration time of an individual subkey, use the `sq key subkey \ expire` subcommand. ", after_help = EXAMPLES, )] #[clap(mut_arg("expiration", |arg| { arg.required(true) }))] pub struct Command { #[command(flatten)] pub cert: CertDesignators, #[clap( help = FileOrStdout::HELP_OPTIONAL, long, value_name = FileOrStdout::VALUE_NAME, )] pub output: Option, #[clap(flatten)] pub expiration: ExpirationArg, } /// Documentation for the cert designators for the key expire. pub struct KeyExpireDoc {} impl AdditionalDocs for KeyExpireDoc { fn help(arg: &'static str, help: &'static str) -> clap::builder::StyledStr { match arg { "file" => "Change the expiration of the key \ read from PATH" .into(), _ => { debug_assert!(help.starts_with("Use certificates")); help.replace("Use certificates", "Change the expiration of the key") }, }.into() } } sequoia-sq-1.4.0/src/cli/key/export.rs000064400000000000000000000051311046102023000157320ustar 00000000000000//! Command-line parser for `sq key list`. use clap::Args; use crate::cli::examples::*; use crate::cli::types::*; use crate::cli::types::cert_designator::*; #[derive(Debug, Args)] #[clap( about = "Export keys from the key store", long_about = "\ Export keys from the key store Exports the secret key material associated with a certificate. Note \ that even if secret key material is available, it may not be \ exportable. For instance, secret key material stored on a hardware \ security module usually cannot be exported from the device. Iterate over all of the specified certificates and export \ any keys (primary key and subkeys) with secret key material. \ An error is returned if any specified certificate does not \ contain any secret key material. If you only want to export a particular key and not all keys associate \ with a certificate, use `sq key subkey export`. ", after_help = EXAMPLES, )] pub struct Command { #[command(flatten)] pub certs: CertDesignators, #[clap( default_value_t = FileOrStdout::default(), help = FileOrStdout::HELP_OPTIONAL, long, value_name = FileOrStdout::VALUE_NAME, )] pub output: FileOrStdout, } const EXAMPLES: Actions = Actions { actions: &[ Action::setup().command(&[ "sq", "key", "import", "alice-secret.pgp", ]).build(), Action::setup().command(&[ "sq", "pki", "link", "add", "--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--userid=Alice ", ]).build(), Action::example().comment("\ Export Alice's certificate with all available secret key material." ).command(&[ "sq", "key", "export", "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", ]).build(), Action::example().comment("\ Export Alice's certificate with all available secret key material \ identified by email address." ).command(&[ "sq", "key", "export", "--cert-email", "alice@example.org", ]).build(), ] }; test_examples!(sq_key_export, EXAMPLES); /// Documentation for the cert designators for the key export. pub struct ExportKeyDoc {} impl AdditionalDocs for ExportKeyDoc { fn help(_arg: &'static str, help: &'static str) -> clap::builder::StyledStr { debug_assert!(help.starts_with("Use certificates")); help.replace("Use certificates", "Export keys").into() } } sequoia-sq-1.4.0/src/cli/key/generate.rs000064400000000000000000000253031046102023000162060ustar 00000000000000use std::path::PathBuf; use clap::{ArgGroup, Args}; use sequoia_openpgp as openpgp; use openpgp::packet::UserID; use crate::cli::KEY_VALIDITY_DURATION; use crate::cli::KEY_VALIDITY_IN_YEARS; use crate::cli::config; use crate::cli::types::ClapData; use crate::cli::types::EncryptPurpose; use crate::cli::types::EncryptionAlgorithm; use crate::cli::types::Expiration; use crate::cli::types::ExpirationArg; use crate::cli::types::FileOrStdout; use crate::cli::types::Profile; use crate::cli::types::SigningAlgorithm; use crate::cli::examples::*; use crate::cli::key::CipherSuite; #[derive(Debug, Args)] #[clap( about = "Generate a new key", long_about = format!( "Generate a new key Generating a key is the prerequisite to receiving encrypted messages \ and creating signatures. There are a few parameters to this process, \ but we provide reasonable defaults for most users. When generating a key, we also generate an emergency revocation \ certificate. This can be used in case the key is lost or compromised. \ It is saved alongside the key. This can be changed using the \ `--rev-cert` argument. By default a key expires after {} years. This can be changed using \ the `--expiration` argument. `sq key generate` respects the reference time set by the top-level \ `--time` argument. It sets the creation time of the primary key, any \ subkeys, and the binding signatures to the reference time. ", KEY_VALIDITY_IN_YEARS, ), after_help = GENERATE_EXAMPLES, )] #[clap(group(ArgGroup::new("cap-sign").args(&["can_sign", "cannot_sign"])))] #[clap(group(ArgGroup::new("cap-authenticate").args(&["can_authenticate", "cannot_authenticate"])))] #[clap(group(ArgGroup::new("cap-encrypt").args(&["can_encrypt", "cannot_encrypt"])))] #[clap(group(ArgGroup::new("cert-userid").args(&["names", "emails", "userid", "no_userids"]).required(true).multiple(true)))] #[clap(group(ArgGroup::new("key-owner") .args(&["own_key", "shared_key"]) .required(true)))] #[clap(mut_arg("expiration", |arg| { arg.default_value(Expiration::from_duration(KEY_VALIDITY_DURATION)) }))] pub struct Command { #[clap( long = "own-key", help = "Mark the key as one's own key", long_help = "Mark the key as one's own key The newly generated key with all of its user IDs will be marked as \ authenticated and as a fully trusted introducer.", )] pub own_key: bool, #[clap( long = "shared-key", help = "Mark the key as a shared key", long_help = "Mark the key as a shared key The newly generated key with all of its user IDs will be marked as \ authenticated, but not as a trusted introducer. Further, the key \ metadata will indicate that this is a shared key. Use this option if you plan to share this key with other people. \ Normally, you shouldn't share keys material. An example of where you \ might want to do this is a shared mailbox." )] pub shared_key: bool, #[clap( long = "name", value_name = "NAME", help = "Add a name as user ID to the key" )] pub names: Vec, #[clap( long = "email", value_name = "ADDRESS", help = "Add an email address as user ID to the key" )] pub emails: Vec, #[clap( long = "userid", value_name = "USERID", help = "Add a user ID to the key", long_help = "\ Add a user ID to the key This user ID can combine name and email address, can optionally \ contain a comment, or even be free-form if \ `--allow-non-canonical-userids` is given. However, user IDs that \ include different information such as name and email address are more \ difficult to reason about, so using distinct user IDs for name and \ email address is preferred nowadays. In doubt, prefer `--name` and `--email`. ", )] pub userid: Vec, #[clap( long = "allow-non-canonical-userids", help = "Don't reject user IDs that are not in canonical form", long_help = "\ Don't reject user IDs that are not in canonical form Canonical user IDs are of the form `Name (Comment) \ `.", )] pub allow_non_canonical_userids: bool, #[clap( long = "no-userids", help = "Create a key without any user IDs", conflicts_with_all = ["names", "emails", "userid"], )] pub no_userids: bool, #[clap( long = "cipher-suite", value_name = "CIPHER-SUITE", default_value_t = Default::default(), help = "Select the cryptographic algorithms for the key", long_help = config::augment_help( "key.generate.cipher-suite", "Select the cryptographic algorithms for the key"), value_enum, )] pub cipher_suite: CipherSuite, /// Workaround for https://github.com/clap-rs/clap/issues/3846 #[clap(skip)] pub cipher_suite_source: Option, #[clap( long = "encryption-algorithm", value_name = "ALGORITHM", help = "Select the cryptographic algorithm for encryption keys", long_help = "Select the cryptographic algorithm for encryption keys When set, the algorithm is used for encryption-capable keys. This \ parameter overrides the cipher suite parameter.", value_enum, )] pub encryption_algorithm: Option, #[clap( long = "signing-algorithm", value_name = "ALGORITHM", help = "Select the cryptographic algorithm for signing keys", long_help = "Select the cryptographic algorithm for signing keys When set, the algorithm is used for keys used for signing. This \ includes keys with the signing, authentication, and the certification \ capability. This parameter overrides the cipher suite parameter.", value_enum, )] pub signing_algorithm: Option, #[clap( long = "profile", value_name = "PROFILE", default_value_t = Default::default(), help = "Select the OpenPGP standard for the key", long_help = config::augment_help( "key.generate.profile", "Select the OpenPGP standard for the key As OpenPGP evolves, new versions will become available. This option \ selects the version of OpenPGP to use for the newly generated key. Currently, sq supports two profiles: RFC9580 and RFC4880. Currently, \ the default is RFC4880. However, once support for RFC9580 is rolled \ out further, the default will change in a future version of sq."), value_enum, )] pub profile: Profile, /// Workaround for https://github.com/clap-rs/clap/issues/3846 #[clap(skip)] pub profile_source: Option, #[clap( long = "new-password-file", value_name = "PASSWORD_FILE", help = "\ File containing password to encrypt the secret key material", long_help = "\ File containing password to encrypt the secret key material Note that the entire key file will be used as the password including \ any surrounding whitespace like a trailing newline.", conflicts_with = "without_password", )] pub new_password_file: Option, #[clap( long = "without-password", help = "Don't protect the secret key material with a password", )] pub without_password: bool, #[command(flatten)] pub expiration: ExpirationArg, #[clap( long = "can-sign", help ="Add a signing-capable subkey (default)", )] pub can_sign: bool, #[clap( long = "cannot-sign", help = "Don't add a signing-capable subkey", )] pub cannot_sign: bool, #[clap( long = "can-authenticate", help = "Add an authentication-capable subkey (default)", )] pub can_authenticate: bool, #[clap( long = "cannot-authenticate", help = "Don't add an authentication-capable subkey", )] pub cannot_authenticate: bool, #[clap( long = "can-encrypt", value_name = "PURPOSE", help = "Add an encryption-capable subkey [default: universal]", long_help = "\ Add an encryption-capable subkey [default: universal] Encryption-capable subkeys can be marked as suitable for transport \ encryption, storage encryption, or both, i.e., universal.", value_enum, )] pub can_encrypt: Option, #[clap( long = "cannot-encrypt", help = "Don't add an encryption-capable subkey", )] pub cannot_encrypt: bool, #[clap( long, value_name = FileOrStdout::VALUE_NAME, help = "Write the key to the specified file", long_help = "\ Write the key to the specified file When not specified, the key is saved on the key store.", requires = "rev_cert", )] pub output: Option, #[clap( long = "rev-cert", value_name = "FILE", help = "Write the emergency revocation certificate to FILE", long_help = format!("\ Write the emergency revocation certificate to FILE When the key is stored on the key store, the revocation certificate is \ stored in {} by default. When `--output` is specified, the revocation certificate is written to \ the file specified by `--rev-cert`. If `--output` is `-`, then this option must not also be `-`.", sequoia_directories::Home::default() .map(|home| { let p = home.data_dir(sequoia_directories::Component::Other( "revocation-certificates".into())); let p = p.display().to_string(); if let Some(home) = dirs::home_dir() { let home = home.display().to_string(); if let Some(rest) = p.strip_prefix(&home) { return format!("$HOME{}", rest); } } p }) .unwrap_or("".to_string())) )] pub rev_cert: Option } const GENERATE_EXAMPLES: Actions = Actions { actions: &[ Action::example().comment("\ Generate a key, and save it on the key store." ).command(&[ "sq", "key", "generate", "--own-key", "--without-password", "--name", "Alice", "--email", "alice@example.org", ]) .hide(&["--without-password"]).build(), Action::example().comment("\ Generate a key, and save it in a file instead of in the key store." ).command(&[ "sq", "key", "generate", "--own-key", "--without-password", "--name", "Alice", "--email", "alice@example.org", "--output", "alice-priv.pgp", "--rev-cert", "alice-priv.rev", ]) .hide(&["--without-password"]).build(), ] }; test_examples!(sq_key_generate, GENERATE_EXAMPLES); sequoia-sq-1.4.0/src/cli/key/import.rs000064400000000000000000000012501046102023000157210ustar 00000000000000//! Command-line parser for `sq key import`. use std::path::PathBuf; use clap::Args; use crate::cli::examples::*; #[derive(Debug, Args)] #[clap( about = "Import keys into the key store", after_help = IMPORT_EXAMPLES, )] pub struct Command { #[clap( value_name = "KEY_FILE", help = "Read from KEY_FILE or stdin if omitted", )] pub input: Vec, } const IMPORT_EXAMPLES: Actions = Actions { actions: &[ Action::example().comment("\ Import the keys into the key store." ).command(&[ "sq", "key", "import", "alice-secret.pgp", ]).build(), ] }; test_examples!(sq_key_import, IMPORT_EXAMPLES); sequoia-sq-1.4.0/src/cli/key/list.rs000064400000000000000000000043061046102023000153670ustar 00000000000000//! Command-line parser for `sq key list`. use clap::Args; use crate::cli::examples::*; use crate::cli::types::cert_designator::*; #[derive(Debug, Args)] #[clap( about = "List keys managed by the key store", after_help = EXAMPLES, )] pub struct Command { #[command(flatten)] pub certs: CertDesignators, #[clap( value_name = "FINGERPRINT|KEYID|PATTERN", help = "A pattern to filter the displayed certificates", long_help = "\ A pattern to filter the displayed certificates If the pattern appears to be a fingerprint or key ID, it is treated as \ if it were passed to `--cert`, and matches on the certificate's \ fingerprint. Otherwise, it is treated as if it were passed via \ `--cert-grep`, and matches on user IDs. ", conflicts_with_all = &["cert", "cert-userid", "cert-email", "cert-domain", "cert-grep"], )] pub pattern: Option, } const EXAMPLES: Actions = Actions { actions: &[ Action::setup().command(&[ "sq", "key", "import", "alice-secret.pgp" ]).build(), Action::setup().command(&[ "sq", "pki", "link", "add", "--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--userid=Alice ", ]).build(), Action::example().comment("\ List the keys managed by the keystore server." ).command(&[ "sq", "key", "list", ]).build(), Action::example().comment("\ List the keys managed by the keystore server \ with a user ID in example.org." ).command(&[ "sq", "key", "list", "--cert-domain=example.org", ]).build(), ] }; test_examples!(sq_key_list, EXAMPLES); /// Documentation for the cert designators for the key list. pub struct ListKeyDoc {} impl AdditionalDocs for ListKeyDoc { fn help(_: &'static str, help: &'static str) -> clap::builder::StyledStr { debug_assert!(help.starts_with("Use certificates")); help.replace("Use certificates", "List keys").into() } } sequoia-sq-1.4.0/src/cli/key/password.rs000064400000000000000000000065211046102023000162570ustar 00000000000000//! Command-line parser for `sq key password`. use std::path::PathBuf; use clap::Args; use crate::cli::types::*; use crate::cli::examples::*; use crate::cli::types::cert_designator::*; #[derive(Debug, Args)] #[clap( name = "password", about = "Change the password protecting secret key material", long_about = "\ Change the password protecting secret key material Secret key material can be protected by a password. This subcommand \ changes or clears the password. To strip the password either use `--clear` or supply a zero-length \ password when prompted for the new password. If a key is password protected, and the correct password was not \ supplied using the `--password-file` argument, the user is \ prompted for the password. Likewise, if the new password isn't \ provided, the user is prompted. ", after_help = EXAMPLES, )] pub struct Command { #[command(flatten)] pub cert: CertDesignators, #[clap( long = "new-password-file", value_name = "PASSWORD_FILE", help = "\ File containing password to encrypt the secret key material", long_help = "\ File containing password to encrypt the secret key material Note that the entire key file will be used as the password including \ any surrounding whitespace like a trailing newline." )] pub new_password_file: Option, #[clap( long, help = "Clear the password protecting the secret key material", )] pub clear_password: bool, #[clap( help = FileOrStdout::HELP_OPTIONAL, long, value_name = FileOrStdout::VALUE_NAME, )] pub output: Option, } const EXAMPLES: Actions = Actions { actions: &[ Action::setup().command(&[ "sq", "key", "import", "alice-secret.pgp" ]).build(), Action::example().comment("\ Change the password for all of Alice's keys to the password in the \ specified file." ).command(&[ "sq", "key", "password", "--new-password-file", "password-file.txt", "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0" ]).build(), Action::example().comment("\ Clear the password protection for all of Alice's keys." ).command(&[ "sq", "key", "password", "--password-file", "password-file.txt", "--clear-password", "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0" ]).build(), ] }; test_examples!(sq_key_password, EXAMPLES); /// Documentation for the cert designators for the key password. pub struct KeyPasswordDoc {} impl AdditionalDocs for KeyPasswordDoc { fn help(arg: &'static str, help: &'static str) -> clap::builder::StyledStr { match arg { "file" => "Change the password for the secret key material from the key \ read from PATH" .into(), _ => { debug_assert!(help.starts_with("Use certificates")); help.replace("Use certificates", "Change the password for the secret key material \ from the key") }, }.into() } } sequoia-sq-1.4.0/src/cli/key/revoke.rs000064400000000000000000000125501046102023000157070ustar 00000000000000//! Command-line parser for `sq key revoke`. use clap::Args; use crate::cli::types::ClapData; use crate::cli::types::FileOrStdout; use crate::cli::examples::*; use crate::cli::key::KeyReasonForRevocation; use crate::cli::types::cert_designator::*; const REVOKE_EXAMPLES: Actions = Actions { actions: &[ Action::setup().command(&[ "sq", "key", "import", "alice-secret.pgp" ]).build(), Action::example().comment("\ Revoke Alice's key, indicating that there is a new certificate." ).command(&[ "sq", "key", "revoke", "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--reason", "superseded", "--message", "My new cert is C5999E8191BF7B503653BE958B1F7910D01F86E5", ]).build(), Action::example().comment("\ Revoke the key, indicating that the secret key material was \ compromised." ).command(&[ "sq", "key", "revoke", "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--reason", "compromised", "--message", "Computer attacked, secret key material compromised", ]).build(), ] }; test_examples!(sq_key_revoke, REVOKE_EXAMPLES); #[derive(Debug, Args)] #[clap( about = "Revoke a certificate", long_about = "\ Revoke a certificate Creates a revocation certificate for a certificate. If `--revoker` or `--revoker-file` is provided, then that key is used \ to create the revocation certificate. If that key is different from \ the certificate that is being revoked, this results in a third-party \ revocation. This is normally only useful if the owner of the \ certificate designated the key to be a designated revoker. `sq key revoke` respects the reference time set by the top-level \ `--time` argument. When set, it uses the specified time instead of \ the current time when determining what keys are valid, and it sets \ the revocation certificate's creation time to the reference time \ instead of the current time. ", after_help = REVOKE_EXAMPLES, )] pub struct Command { #[command(flatten)] pub cert: CertDesignators, #[command(flatten)] pub revoker: CertDesignators, #[clap( long, value_name = "REASON", required = true, help = "The reason for the revocation", long_help = "\ The reason for the revocation If the reason happened in the past, you should specify that using the \ `--time` argument. This allows OpenPGP implementations to more \ accurately reason about artifacts whose validity depends on the validity \ of the certificate.", value_enum, )] pub reason: KeyReasonForRevocation, #[clap( long, value_name = "MESSAGE", required = true, help = "A short, explanatory text", long_help = "\ A short, explanatory text The text is shown to a viewer of the revocation certificate, and \ explains why the certificate has been revoked. For instance, if Alice \ has created a new key, she would generate a `superseded` revocation \ certificate for her old key, and might include the message `I've \ created a new certificate, $FINGERPRINT, please use that in the \ future.`", )] pub message: String, #[command(flatten)] pub signature_notations: crate::cli::types::SignatureNotationsArg, #[clap( long, value_name = FileOrStdout::VALUE_NAME, help = "Write to the specified FILE", long_help = "\ Write to the specified FILE If not specified, and the certificate was read from the certificate \ store, imports the modified certificate into the cert store. If not \ specified, and the certificate was read from a file, writes the \ modified certificate to stdout.", )] pub output: Option, } /// Documentation for the cert designators for the key revoke. pub struct KeyRevokeCertDoc {} impl AdditionalDocs for KeyRevokeCertDoc { fn help(arg: &'static str, help: &'static str) -> clap::builder::StyledStr { match arg { "file" => "Revoke the key read from PATH" .into(), _ => { debug_assert!(help.starts_with("Use certificates")); help.replace("Use certificates", "Revoke the key") }, }.into() } } /// Documentation for the revoker designators for the key revoke. pub struct KeyRevokeRevokerDoc {} impl AdditionalDocs for KeyRevokeRevokerDoc { fn help(_: &'static str, help: &'static str) -> clap::builder::StyledStr { format!("{} to create the revocation certificate", help.replace("certificates", "key")).into() } fn long_help(_: &'static str, help: &'static str) -> Option { Some(format!("{} to create the revocation certificate Sign the revocation certificate using the specified key. By default, \ the certificate being revoked is used. Using this option, it is \ possible to create a third-party revocation.", help.replace("certificates", "key")).into()) } } sequoia-sq-1.4.0/src/cli/key/rotate.rs000064400000000000000000000221731046102023000157140ustar 00000000000000use std::path::PathBuf; use clap::{ArgGroup, Args}; use crate::cli::KEY_ROTATE_RETIRE_IN_DURATION; use crate::cli::KEY_ROTATE_RETIRE_IN_IN_DAYS; use crate::cli::KEY_VALIDITY_DURATION; use crate::cli::KEY_VALIDITY_IN_YEARS; use crate::cli::config; use crate::cli::types::ClapData; use crate::cli::types::EncryptPurpose; use crate::cli::types::Expiration; use crate::cli::types::ExpirationArg; use crate::cli::types::FileOrStdout; use crate::cli::types::Profile; use crate::cli::types::expiration::RetireInKind; use crate::cli::types::CertDesignators; use crate::cli::types::cert_designator; use crate::cli::examples::*; use crate::cli::key::CipherSuite; #[derive(Debug, Args)] #[clap( about = "Rotate a certificate", long_about = format!( "Rotate a certificate Generates a new certificate to replace an existing one. The new certificate will have the same capabilities as the old \ certificate. This can be overridden using the `--can-sign`, \ `--cannot-sign`, etc., arguments. Note: the new certificate may have \ a different shape from the old certificate. For instance, if the old \ certificate's primary key is marked as both certification and signing \ capable, the new certificate's primary key will be certification \ capable, and it will have a signing subkey. By default the certificate expires after {} years. This can be changed \ using the `--expiration` argument. The new certificate will have the same self-signed user IDs as the old \ certificate. Revoked user IDs are ignored. The new certificate and the old certificate will cross certify each \ other as unconstrained trusted introducers. The new certificate will be linked in the same way as the old \ certificate. This can be overridden using the `--own-key`, or \ the `--shared-key` argument. The new certificate will certify the same certificates as the old \ certificate. That is, the old certificate's certifications will be \ replayed. See `sq pki vouch replay` for more information. A revocation certificate indicating that the old certificate is \ retired, and that the new certificate should be instead used will be \ issued. By default, it will go into effect in {} days. This can be \ changed or suppressed using the `--retire-in` argument. When using `--output`, the new certificate as well as all of the \ other updated certificates are written to the specified file. Stable since 1.2.0. ", KEY_VALIDITY_IN_YEARS, KEY_ROTATE_RETIRE_IN_IN_DAYS, ), after_help = ROTATE_EXAMPLES, )] #[clap(group(ArgGroup::new("cap-sign").args(&["can_sign", "cannot_sign"])))] #[clap(group(ArgGroup::new("cap-authenticate").args(&["can_authenticate", "cannot_authenticate"])))] #[clap(group(ArgGroup::new("cap-encrypt").args(&["can_encrypt", "cannot_encrypt"])))] #[clap(mut_arg("expiration", |arg| { arg.default_value(Expiration::from_duration(KEY_VALIDITY_DURATION)) }))] #[clap(mut_arg("retire-in", |arg| { arg.default_value(Expiration::from_duration(KEY_ROTATE_RETIRE_IN_DURATION)) }))] pub struct Command { #[command(flatten)] pub cert: CertDesignators, #[clap( long = "own-key", help = "Mark the key as one's own key", long_help = "Mark the key as one's own key The newly generated key with all of its user IDs will be marked as \ authenticated and as a fully trusted introducer.", )] pub own_key: bool, #[clap( long = "shared-key", help = "Mark the key as a shared key", long_help = "Mark the key as a shared key The newly generated key with all of its user IDs will be marked as \ authenticated, but not as a trusted introducer. Further, the key \ metadata will indicate that this is a shared key. Use this option if you plan to share this key with other people. \ Normally, you shouldn't share keys material. An example of where you \ might want to do this is a shared mailbox." )] pub shared_key: bool, #[clap( long = "cipher-suite", value_name = "CIPHER-SUITE", default_value_t = Default::default(), help = "Select the cryptographic algorithms for the key", long_help = config::augment_help( "key.generate.cipher-suite", "Select the cryptographic algorithms for the key"), value_enum, )] pub cipher_suite: CipherSuite, /// Workaround for https://github.com/clap-rs/clap/issues/3846 #[clap(skip)] pub cipher_suite_source: Option, #[clap( long = "profile", value_name = "PROFILE", default_value_t = Default::default(), help = "Select the OpenPGP standard for the key", long_help = config::augment_help( "key.generate.profile", "Select the OpenPGP standard for the key As OpenPGP evolves, new versions will become available. This option \ selects the version of OpenPGP to use for the newly generated key. Currently, sq supports only one version: RFC4880. Consequently, this \ is the default. However, there is already a newer version of the \ standard: RFC9580. And, the default will change in a future version of \ sq."), value_enum, )] pub profile: Profile, /// Workaround for https://github.com/clap-rs/clap/issues/3846 #[clap(skip)] pub profile_source: Option, #[clap( long = "new-password-file", value_name = "PASSWORD_FILE", help = "\ File containing password to encrypt the secret key material", long_help = "\ File containing password to encrypt the secret key material Note that the entire key file will be used as the password including \ any surrounding whitespace like a trailing newline.", conflicts_with = "without_password", )] pub new_password_file: Option, #[clap( long = "without-password", help = "Don't protect the secret key material with a password", )] pub without_password: bool, #[command(flatten)] pub expiration: ExpirationArg, #[command(flatten)] pub retire_in: ExpirationArg, #[clap( long = "can-sign", help ="Add a signing-capable subkey", )] pub can_sign: bool, #[clap( long = "cannot-sign", help = "Don't add a signing-capable subkey", )] pub cannot_sign: bool, #[clap( long = "can-authenticate", help = "Add an authentication-capable subkey", )] pub can_authenticate: bool, #[clap( long = "cannot-authenticate", help = "Don't add an authentication-capable subkey", )] pub cannot_authenticate: bool, #[clap( long = "can-encrypt", value_name = "PURPOSE", help = "Add an encryption-capable subkey", long_help = "\ Add an encryption-capable subkey Encryption-capable subkeys can be marked as suitable for transport \ encryption, storage encryption, or both, i.e., universal.", value_enum, )] pub can_encrypt: Option, #[clap( long = "cannot-encrypt", help = "Don't add an encryption-capable subkey", )] pub cannot_encrypt: bool, #[clap( long, value_name = FileOrStdout::VALUE_NAME, help = "Write the key to the specified file", long_help = "\ Write the key to the specified file When not specified, the key is saved on the key store.", requires = "rev_cert", )] pub output: Option, #[clap( long = "rev-cert", value_name = "FILE", help = "Write the emergency revocation certificate to FILE", long_help = format!("\ Write the emergency revocation certificate to FILE When the key is stored on the key store, the revocation certificate is \ stored in {} by default. When `--output` is specified, the revocation certificate is written to \ the file specified by `--rev-cert`. If `--output` is `-`, then this option must not also be `-`.", sequoia_directories::Home::default() .map(|home| { let p = home.data_dir(sequoia_directories::Component::Other( "revocation-certificates".into())); let p = p.display().to_string(); if let Some(home) = dirs::home_dir() { let home = home.display().to_string(); if let Some(rest) = p.strip_prefix(&home) { return format!("$HOME{}", rest); } } p }) .unwrap_or("".to_string())) )] pub rev_cert: Option } const ROTATE_EXAMPLES: Actions = Actions { actions: &[ Action::setup().command(&[ "sq", "key", "import", "alice-secret.pgp", ]).build(), Action::example().comment("\ Rotates Alice's certificate." ).command(&[ "sq", "key", "rotate", "--without-password", "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", ]) .hide(&["--without-password"]).build(), ], }; test_examples!(sq_key_rotate, ROTATE_EXAMPLES); sequoia-sq-1.4.0/src/cli/key/subkey/add.rs000064400000000000000000000140011046102023000164370ustar 00000000000000use std::path::PathBuf; use clap::Args; use clap::ArgGroup; use crate::cli::examples; use examples::Action; use examples::Actions; use crate::cli::config; use crate::cli::key::CipherSuite; use crate::cli::types::CertDesignators; use crate::cli::types::ClapData; use crate::cli::types::EncryptPurpose; use crate::cli::types::ExpirationArg; use crate::cli::types::FileOrStdout; use crate::cli::types::cert_designator; pub struct AdditionalDocs {} impl cert_designator::AdditionalDocs for AdditionalDocs { fn help(arg: &'static str, help: &'static str) -> clap::builder::StyledStr { match arg { "file" => "Add a subkey to the key read from PATH" .into(), _ => { debug_assert!(help.starts_with("Use certificates")); help.replace("Use certificates", "Add a subkey to the key") .into() }, } } } #[derive(Debug, Args)] #[clap( about = "Add a new subkey to a certificate", long_about = "\ Add a new subkey to a certificate A subkey has one or more capabilities. `--can-sign` sets the signing capability, and means that the key may \ be used for signing. `--can-authenticate` sets the authentication \ capability, and means that the key may be used for authentication \ (e.g., as an SSH key). `--can-certify` sets the certificate \ capability, and means that the key may be used to make third-party \ certifications. These capabilities may be combined. `--can-encrypt=storage` sets the storage encryption capability, and \ means that the key may be used for storage \ encryption. `--can-encrypt=transport` sets the transport encryption \ capability, and means that the key may be used for transport \ encryption. `--can-encrypt=universal` sets both the storage and the \ transport encryption capability, and means that the key may be used \ for both storage and transport encryption. The encryption \ capabilities must not be combined with the signing or authentication \ capability. Normally, `sq` prompts the user for a password to use to encrypt the \ secret key material. The password for the new subkey may be different \ from the other keys. When using `--without-password`, `sq` doesn't \ prompt for a password, and doesn't password-protect the subkey. By default a new subkey doesn't expire on its own. However, its \ validity period is limited by that of the certificate. Using the \ `--expiration` argument allows setting a different expiration time. `sq key subkey add` respects the reference time set by the top-level \ `--time` argument. It sets the creation time of the subkey to the specified \ time. ", after_help = EXAMPLES, )] #[clap(group(ArgGroup::new("authentication-group").args(&["can_authenticate", "can_encrypt"])))] #[clap(group(ArgGroup::new("sign-group").args(&["can_sign", "can_encrypt"])))] #[clap(group(ArgGroup::new("required-group").args(&["can_authenticate", "can_sign", "can_encrypt"]).required(true)))] pub struct Command { #[command(flatten)] pub cert: CertDesignators< cert_designator::CertUserIDEmailFileArgs, cert_designator::CertPrefix, cert_designator::OneValueAndFileRequiresOutput, AdditionalDocs>, #[clap( long, value_name = "CIPHER-SUITE", default_value_t = CipherSuite::Cv25519, help = "Select the cryptographic algorithms for the subkey", long_help = config::augment_help( "key.generate.cipher-suite", "Select the cryptographic algorithms for the subkey"), value_enum, )] pub cipher_suite: CipherSuite, /// Workaround for https://github.com/clap-rs/clap/issues/3846 #[clap(skip)] pub cipher_suite_source: Option, #[command(flatten)] pub expiration: ExpirationArg, #[clap( long, help = "Add a signing-capable subkey", )] pub can_sign: bool, #[clap( long, help = "Add an authentication-capable subkey", )] pub can_authenticate: bool, #[clap( long, value_name = "PURPOSE", help = "Add an encryption-capable subkey [default: universal]", long_help = "\ Add an encryption-capable subkey [default: universal] Encryption-capable subkeys can be marked as suitable for transport \ encryption, storage encryption, or both, i.e., universal.", value_enum, )] pub can_encrypt: Option, #[clap( long = "new-password-file", value_name = "PASSWORD_FILE", help = "\ File containing password to encrypt the secret key material", long_help = "\ File containing password to encrypt the secret key material Note that the entire key file will be used as the password including \ any surrounding whitespace like a trailing newline.", conflicts_with = "without_password", )] pub new_password_file: Option, #[clap( long, help = "Don't protect the subkey's secret key material with a password", )] pub without_password: bool, #[clap( long, value_name = FileOrStdout::VALUE_NAME, help = "Write to the specified FILE", long_help = "\ Write to the specified FILE If not specified, and the certificate was read from the certificate \ store, imports the modified certificate into the key store. If not \ specified, and the certificate was read from a file, writes the \ modified certificate to stdout.", )] pub output: Option, } const EXAMPLES: Actions = Actions { actions: &[ Action::setup().command(&[ "sq", "key", "import", "alice-secret.pgp", ]).build(), Action::example().comment("\ Add a new signing-capable subkey to Alice's key." ).command(&[ "sq", "key", "subkey", "add", "--without-password", "--can-sign", "--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0", ]) .hide(&["--without-password"]).build(), ] }; test_examples!(sq_key_subkey_add, EXAMPLES); sequoia-sq-1.4.0/src/cli/key/subkey/bind.rs000064400000000000000000000140551046102023000166340ustar 00000000000000use clap::Args; use clap::ArgGroup; use sequoia_openpgp as openpgp; use openpgp::KeyHandle; use crate::cli::examples; use examples::Action; use examples::Actions; use crate::cli::types::CertDesignators; use crate::cli::types::ClapData; use crate::cli::types::EncryptPurpose; use crate::cli::types::ExpirationArg; use crate::cli::types::FileOrStdout; use crate::cli::types::Time; use crate::cli::types::cert_designator; pub struct AdditionalDocs {} impl cert_designator::AdditionalDocs for AdditionalDocs { fn help(arg: &'static str, help: &'static str) -> clap::builder::StyledStr { match arg { "file" => "Add the specified subkeys to the key read from PATH" .into(), _ => { debug_assert!(help.starts_with("Use certificates")); help.replace("Use certificates", "Add the specified subkeys on the key") .into() }, } } } #[derive(Debug, Args)] #[clap( name = "bind", about = "Bind keys from one certificate to another", long_about = "\ Bind keys from one certificate to another This command allows the user to attach a primary key or a subkey \ attached to one certificate to another certificate. Say you want to \ transition to a new certificate, but have an authentication subkey on \ your current certificate that you want to keep because it allows access \ a server and updating its configuration is not feasible. This command \ makes it easy to attach the subkey to the new certificate. After the operation, the key is bound both to the old certificate and to \ the new one. To remove secret key material from the old certificate, use \ `sq key subkey delete` or `sq key delete`, as appropriate. To revoke the \ old subkey or key, use `sq key subkey revoke` or `sq key revoke`, \ respectively. ", after_help = EXAMPLES, )] #[clap(group(ArgGroup::new("cap-sign").args(&["can_sign", "cannot_sign"])))] #[clap(group(ArgGroup::new("cap-authenticate").args(&["can_authenticate", "cannot_authenticate"])))] #[clap(group(ArgGroup::new("cap-encrypt").args(&["can_encrypt", "cannot_encrypt"])))] pub struct Command { #[command(flatten)] pub cert: CertDesignators< cert_designator::CertUserIDEmailFileArgs, cert_designator::CertPrefix, cert_designator::OneValueAndFileRequiresOutput, AdditionalDocs>, #[clap( long, value_name = "KEY", required(true), help = "Add the key or subkey KEY to the certificate", )] pub key: Vec, #[clap( long, allow_hyphen_values = true, value_name = "CREATION_TIME", help = "Make bound subkeys have the specified creation time", long_help = "\ Make bound subkeys have the specified creation time Normally, the key's creation time is preserved. The exception is if \ the key's creation time is the Unix epoch. In that case, the current \ time is used. This option allows setting the key's creation time to a specified value. \ Note: changing a key's creation time also changes its fingerprint. \ Changing the fingerprint will make it impossible to look up the key for \ the purpose of signature verification, for example.", )] pub creation_time: Option