sequoia-keyring-linter-0.5.0/.cargo_vcs_info.json0000644000000001121376713204300155030ustar { "git": { "sha1": "2f3125952bc274caede4ca17b574c9379c35365f" } } sequoia-keyring-linter-0.5.0/.gitignore010064400017500001750000000000211376713201600162730ustar 00000000000000Cargo.lock targetsequoia-keyring-linter-0.5.0/Cargo.lock0000644000001112721376713204400134710ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] name = "addr2line" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c0929d69e78dd9bf5408269919fcbcaeb2e35e5d43e5815517cdc6a8e11a423" dependencies = [ "gimli", ] [[package]] name = "adler" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" [[package]] name = "aead" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331" dependencies = [ "generic-array 0.14.4", ] [[package]] name = "aho-corasick" version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" dependencies = [ "memchr", ] [[package]] name = "ansi_term" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" dependencies = [ "winapi", ] [[package]] name = "ansi_term" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" dependencies = [ "winapi", ] [[package]] name = "anyhow" version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c0df63cb2955042487fad3aefd2c6e3ae7389ac5dc1beb28921de0b69f779d4" [[package]] name = "arrayref" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" [[package]] name = "arrayvec" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "ascii-canvas" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff8eb72df928aafb99fe5d37b383f2fe25bd2a765e3e5f7c365916b6f2463a29" dependencies = [ "term", ] [[package]] name = "assert_cmd" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dc1679af9a1ab4bea16f228b05d18f8363f8327b1fa8db00d2760cfafc6b61e" dependencies = [ "doc-comment", "predicates", "predicates-core", "predicates-tree", "wait-timeout", ] [[package]] name = "atty" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi", "libc", "winapi", ] [[package]] name = "autocfg" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" [[package]] name = "autocfg" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "backtrace" version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef5140344c85b01f9bbb4d4b7288a8aa4b3287ccef913a14bcc78a1063623598" dependencies = [ "addr2line", "cfg-if 1.0.0", "libc", "miniz_oxide", "object", "rustc-demangle", ] [[package]] name = "base64" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "bindgen" version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebd71393f1ec0509b553aa012b9b58e81dadbdff7130bd3b8cba576e69b32f75" dependencies = [ "bitflags", "cexpr", "cfg-if 0.1.10", "clang-sys", "lazy_static", "peeking_take_while", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", ] [[package]] name = "bit-set" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de" dependencies = [ "bit-vec", ] [[package]] name = "bit-vec" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" [[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "blake2b_simd" version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" dependencies = [ "arrayref", "arrayvec", "constant_time_eq", ] [[package]] name = "block-buffer" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" dependencies = [ "block-padding", "byte-tools", "byteorder", "generic-array 0.12.3", ] [[package]] name = "block-buffer" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ "generic-array 0.14.4", ] [[package]] name = "block-padding" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" dependencies = [ "byte-tools", ] [[package]] name = "buffered-reader" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5711ccfa79a8167779ad2176d3334078f03b1579ddf8f42aa556196eba60a42" dependencies = [ "libc", ] [[package]] name = "byte-tools" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "byteorder" version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" [[package]] name = "cc" version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48" [[package]] name = "cexpr" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fce5b5fb86b0c57c20c834c1b412fd09c77c8a59b9473f86272709e78874cd1d" dependencies = [ "nom", ] [[package]] name = "cfg-if" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" dependencies = [ "num-integer", "num-traits", ] [[package]] name = "cipher" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" dependencies = [ "generic-array 0.14.4", ] [[package]] name = "clang-sys" version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81de550971c976f176130da4b2978d3b524eaa0fd9ac31f3ceb5ae1231fb4853" dependencies = [ "glob", "libc", "libloading", ] [[package]] name = "clap" version = "2.33.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" dependencies = [ "ansi_term 0.11.0", "atty", "bitflags", "strsim 0.8.0", "textwrap", "unicode-width", "vec_map", ] [[package]] name = "cmac" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73d4de4f7724e5fe70addfb2bd37c2abd2f95084a429d7773b0b9645499b4272" dependencies = [ "crypto-mac", "dbl", ] [[package]] name = "constant_time_eq" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "cpuid-bool" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634" [[package]] name = "crossbeam-utils" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d" dependencies = [ "autocfg 1.0.1", "cfg-if 1.0.0", "lazy_static", ] [[package]] name = "crypto-mac" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4857fd85a0c34b3c3297875b747c1e02e06b6a0ea32dd892d8192b9ce0813ea6" dependencies = [ "cipher", "generic-array 0.14.4", "subtle", ] [[package]] name = "ctr" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb4a30d54f7443bf3d6191dcd486aca19e67cb3c49fa7a06a319966346707e7f" dependencies = [ "cipher", ] [[package]] name = "curve25519-dalek" version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8492de420e9e60bc9a1d66e2dbb91825390b738a388606600663fc529b4b307" dependencies = [ "byteorder", "digest 0.9.0", "rand_core", "subtle", "zeroize", ] [[package]] name = "dbl" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2735145c3b9ba15f2d7a3ae8cdafcbc8c98a7bef7f62afe9d08bd99fbf7130de" dependencies = [ "generic-array 0.14.4", ] [[package]] name = "diff" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499" [[package]] name = "difference" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" [[package]] name = "digest" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" dependencies = [ "generic-array 0.12.3", ] [[package]] name = "digest" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ "generic-array 0.14.4", ] [[package]] name = "dirs" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" dependencies = [ "libc", "redox_users", "winapi", ] [[package]] name = "doc-comment" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "docopt" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f525a586d310c87df72ebcd98009e57f1cc030c8c268305287a476beb653969" dependencies = [ "lazy_static", "regex", "serde", "strsim 0.9.3", ] [[package]] name = "dyn-clone" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d55796afa1b20c2945ca8eabfc421839f2b766619209f1ede813cf2484f31804" [[package]] name = "eax" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1f76e7a5e594b299a0fa9a99de627530725e341df41376aa342aecb2c5eb76e" dependencies = [ "aead", "cipher", "cmac", "ctr", "subtle", ] [[package]] name = "ed25519" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37c66a534cbb46ab4ea03477eae19d5c22c01da8258030280b7bd9d8433fb6ef" dependencies = [ "signature", ] [[package]] name = "ed25519-dalek" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" dependencies = [ "curve25519-dalek", "ed25519", "rand", "sha2 0.9.2", "zeroize", ] [[package]] name = "either" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "ena" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3" dependencies = [ "log", ] [[package]] name = "fake-simd" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "fixedbitset" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" [[package]] name = "float-cmp" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1267f4ac4f343772758f7b1bdcbe767c218bbab93bb432acbf5162bbf85a6c4" dependencies = [ "num-traits", ] [[package]] name = "generic-array" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" dependencies = [ "typenum", ] [[package]] name = "generic-array" version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" dependencies = [ "typenum", "version_check 0.9.2", ] [[package]] name = "getrandom" version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" dependencies = [ "cfg-if 0.1.10", "libc", "wasi", ] [[package]] name = "gimli" version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" [[package]] name = "glob" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "hashbrown" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" [[package]] name = "heck" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" dependencies = [ "unicode-segmentation", ] [[package]] name = "hermit-abi" version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8" dependencies = [ "libc", ] [[package]] name = "idna" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" dependencies = [ "matches", "unicode-bidi", "unicode-normalization", ] [[package]] name = "indexmap" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b" dependencies = [ "autocfg 1.0.1", "hashbrown", ] [[package]] name = "itertools" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" dependencies = [ "either", ] [[package]] name = "lalrpop" version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60fb56191fb8ed5311597e5750debe6779c9fdb487dbaa5ff302592897d7a2c8" dependencies = [ "ascii-canvas", "atty", "bit-set", "diff", "docopt", "ena", "itertools", "lalrpop-util", "petgraph", "regex", "regex-syntax", "serde", "serde_derive", "sha2 0.8.2", "string_cache", "term", "unicode-xid", ] [[package]] name = "lalrpop-util" version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6771161eff561647fad8bb7e745e002c304864fb8f436b52b30acda51fca4408" [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" dependencies = [ "spin", ] [[package]] name = "libc" version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" [[package]] name = "libloading" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" dependencies = [ "cc", "winapi", ] [[package]] name = "libm" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" [[package]] name = "log" version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" dependencies = [ "cfg-if 0.1.10", ] [[package]] name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" [[package]] name = "memchr" version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" [[package]] name = "memsec" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2af4f95d8737f4ffafbd1fb3c703cdc898868a244a59786793cba0520ebdcbdd" [[package]] name = "miniz_oxide" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" dependencies = [ "adler", "autocfg 1.0.1", ] [[package]] name = "nettle" version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1afae85450b829ad720f2827e3b07d78e06b5521cfe5ed72808a9f593e7cdd8" dependencies = [ "getrandom", "libc", "nettle-sys", "thiserror", ] [[package]] name = "nettle-sys" version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8629333ff5f3b74d251dae253e383cda9242410fac4244a4fe855469be101fb" dependencies = [ "bindgen", "pkg-config", ] [[package]] name = "new_debug_unreachable" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" [[package]] name = "nom" version = "4.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" dependencies = [ "memchr", "version_check 0.1.5", ] [[package]] name = "normalize-line-endings" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" [[package]] name = "num-bigint-dig" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d51546d704f52ef14b3c962b5776e53d5b862e5790e40a350d366c209bd7f7a" dependencies = [ "autocfg 0.1.7", "byteorder", "lazy_static", "libm", "num-integer", "num-iter", "num-traits", "smallvec", ] [[package]] name = "num-integer" version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" dependencies = [ "autocfg 1.0.1", "num-traits", ] [[package]] name = "num-iter" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" dependencies = [ "autocfg 1.0.1", "num-integer", "num-traits", ] [[package]] name = "num-traits" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" dependencies = [ "autocfg 1.0.1", ] [[package]] name = "object" version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" [[package]] name = "opaque-debug" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "opaque-debug" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "peeking_take_while" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "petgraph" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" dependencies = [ "fixedbitset", "indexmap", ] [[package]] name = "phf_shared" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" dependencies = [ "siphasher", ] [[package]] name = "pkg-config" version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" [[package]] name = "ppv-lite86" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "precomputed-hash" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "predicates" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96bfead12e90dccead362d62bb2c90a5f6fc4584963645bc7f71a735e0b0735a" dependencies = [ "difference", "float-cmp", "normalize-line-endings", "predicates-core", "regex", ] [[package]] name = "predicates-core" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06075c3a3e92559ff8929e7a280684489ea27fe44805174c3ebd9328dcb37178" [[package]] name = "predicates-tree" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e63c4859013b38a76eca2414c64911fba30def9e3202ac461a2d22831220124" dependencies = [ "predicates-core", "treeline", ] [[package]] name = "proc-macro-error" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", "syn", "version_check 0.9.2", ] [[package]] name = "proc-macro-error-attr" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ "proc-macro2", "quote", "version_check 0.9.2", ] [[package]] name = "proc-macro2" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" dependencies = [ "unicode-xid", ] [[package]] name = "quote" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" dependencies = [ "proc-macro2", ] [[package]] name = "rand" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ "rand_chacha", "rand_core", "rand_hc", ] [[package]] name = "rand_chacha" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" dependencies = [ "ppv-lite86", "rand_core", ] [[package]] name = "rand_core" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" [[package]] name = "rand_hc" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" dependencies = [ "rand_core", ] [[package]] name = "redox_syscall" version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "redox_users" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" dependencies = [ "getrandom", "redox_syscall", "rust-argon2", ] [[package]] name = "regex" version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c" dependencies = [ "aho-corasick", "memchr", "regex-syntax", "thread_local", ] [[package]] name = "regex-syntax" version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189" [[package]] name = "rpassword" version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d755237fc0f99d98641540e66abac8bc46a0652f19148ac9e21de2da06b326c9" dependencies = [ "libc", "winapi", ] [[package]] name = "rust-argon2" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" dependencies = [ "base64", "blake2b_simd", "constant_time_eq", "crossbeam-utils", ] [[package]] name = "rustc-demangle" version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232" [[package]] name = "rustc-hash" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "sequoia-keyring-linter" version = "0.5.0" dependencies = [ "ansi_term 0.12.1", "anyhow", "assert_cmd", "atty", "predicates", "rpassword", "sequoia-openpgp", "structopt", "thiserror", ] [[package]] name = "sequoia-openpgp" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "664de0a9388e38d0f350547056f18fcc03f78d85e5a49fa4fa8927ca6aea1424" dependencies = [ "anyhow", "backtrace", "base64", "buffered-reader", "chrono", "dyn-clone", "eax", "ed25519-dalek", "idna", "lalrpop", "lalrpop-util", "lazy_static", "libc", "memsec", "nettle", "num-bigint-dig", "regex", "sha1collisiondetection", "thiserror", "unicode-normalization", "win-crypto-ng", "winapi", ] [[package]] name = "serde" version = "1.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "sha1collisiondetection" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7a6cf187c4059b3e63de2358b7e2f9a2261b6f3fd8ef4e7342308d0863ed082" dependencies = [ "digest 0.9.0", "generic-array 0.14.4", "libc", ] [[package]] name = "sha2" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" dependencies = [ "block-buffer 0.7.3", "digest 0.8.1", "fake-simd", "opaque-debug 0.2.3", ] [[package]] name = "sha2" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e7aab86fe2149bad8c507606bdb3f4ef5e7b2380eb92350f56122cca72a42a8" dependencies = [ "block-buffer 0.9.0", "cfg-if 1.0.0", "cpuid-bool", "digest 0.9.0", "opaque-debug 0.3.0", ] [[package]] name = "shlex" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" [[package]] name = "signature" version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29f060a7d147e33490ec10da418795238fd7545bba241504d6b31a409f2e6210" [[package]] name = "siphasher" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa8f3741c7372e75519bd9346068370c9cdaabcc1f9599cbcf2a2719352286b7" [[package]] name = "smallvec" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae524f056d7d770e174287294f562e95044c68e88dec909a00d2094805db9d75" [[package]] name = "spin" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "string_cache" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ddb1139b5353f96e429e1a5e19fbaf663bddedaa06d1dbd49f82e352601209a" dependencies = [ "lazy_static", "new_debug_unreachable", "phf_shared", "precomputed-hash", "serde", ] [[package]] name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "strsim" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" [[package]] name = "structopt" version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5277acd7ee46e63e5168a80734c9f6ee81b1367a7d8772a2d765df2a3705d28c" dependencies = [ "clap", "lazy_static", "structopt-derive", ] [[package]] name = "structopt-derive" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ba9cdfda491b814720b6b06e0cac513d922fc407582032e8706e9f137976f90" dependencies = [ "heck", "proc-macro-error", "proc-macro2", "quote", "syn", ] [[package]] name = "subtle" version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" [[package]] name = "syn" version = "1.0.54" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2af957a63d6bd42255c359c93d9bfdb97076bd3b820897ce55ffbfbf107f44" dependencies = [ "proc-macro2", "quote", "unicode-xid", ] [[package]] name = "synstructure" version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ "proc-macro2", "quote", "syn", "unicode-xid", ] [[package]] name = "term" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42" dependencies = [ "byteorder", "dirs", "winapi", ] [[package]] name = "textwrap" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ "unicode-width", ] [[package]] name = "thiserror" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e9ae34b84616eedaaf1e9dd6026dbe00dcafa92aa0c8077cb69df1fcfe5e53e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ba20f23e85b10754cd195504aebf6a27e2e6cbe28c17778a0c930724628dd56" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "thread_local" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" dependencies = [ "lazy_static", ] [[package]] name = "tinyvec" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf8dbc19eb42fba10e8feaaec282fb50e2c14b2726d6301dbfeed0f73306a6f" dependencies = [ "tinyvec_macros", ] [[package]] name = "tinyvec_macros" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "treeline" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" [[package]] name = "typenum" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" [[package]] name = "unicode-bidi" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" dependencies = [ "matches", ] [[package]] name = "unicode-normalization" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a13e63ab62dbe32aeee58d1c5408d35c36c392bba5d9d3142287219721afe606" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" [[package]] name = "unicode-width" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" [[package]] name = "unicode-xid" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] name = "vec_map" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" [[package]] name = "version_check" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" [[package]] name = "wait-timeout" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" dependencies = [ "libc", ] [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "win-crypto-ng" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24cf92e98e8f4ade45b5140795415a0f256fd9b69a1919248dcda11ba5d6466c" dependencies = [ "cipher", "doc-comment", "rand_core", "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-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "zeroize" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81a974bcdd357f0dca4d41677db03436324d45a4c9ed2d0b873a5a360ce41c36" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f369ddb18862aba61aa49bf31e74d29f0f162dec753063200e1dc084345d16" dependencies = [ "proc-macro2", "quote", "syn", "synstructure", ] sequoia-keyring-linter-0.5.0/Cargo.toml0000644000000032241376713204400135110ustar # 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 believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] edition = "2018" name = "sequoia-keyring-linter" version = "0.5.0" authors = ["Neal Walfield "] description = "A linter for keyrings" homepage = "https://sequoia-pgp.org/" readme = "README.md" keywords = ["cryptography", "openpgp", "pgp", "keyring", "linter"] categories = ["cryptography", "command-line-utilities"] license = "GPL-2.0-or-later" repository = "https://gitlab.com/sequoia-pgp/keyring-linter" [[bin]] name = "sq-keyring-linter" path = "src/keyring-linter.rs" [dependencies.ansi_term] version = "0.12" [dependencies.anyhow] version = "1" [dependencies.atty] version = "0.2" [dependencies.rpassword] version = "5.0" [dependencies.sequoia-openpgp] version = "1.0" default-features = false [dependencies.structopt] version = "0.3" [dependencies.thiserror] version = "1" [dev-dependencies.assert_cmd] version = "1.0.1" [dev-dependencies.predicates] version = "1.0.5" [features] crypto-cng = ["sequoia-openpgp/crypto-cng"] crypto-nettle = ["sequoia-openpgp/crypto-nettle"] default = ["crypto-nettle"] [badges.gitlab] repository = "sequoia-pgp/keyring-linter" [badges.maintenance] status = "actively-developed" sequoia-keyring-linter-0.5.0/Cargo.toml.orig010064400017500001750000000017461376713201600172110ustar 00000000000000[package] name = "sequoia-keyring-linter" description = "A linter for keyrings" version = "0.5.0" authors = [ "Neal Walfield ", ] homepage = "https://sequoia-pgp.org/" repository = "https://gitlab.com/sequoia-pgp/keyring-linter" readme = "README.md" keywords = ["cryptography", "openpgp", "pgp", "keyring", "linter"] categories = ["cryptography", "command-line-utilities"] license = "GPL-2.0-or-later" edition = "2018" [badges] gitlab = { repository = "sequoia-pgp/keyring-linter" } maintenance = { status = "actively-developed" } [dependencies] ansi_term = "0.12" anyhow = "1" atty = "0.2" rpassword = "5.0" sequoia-openpgp = { version = "1.0", default-features = false } structopt = "0.3" thiserror = "1" [dev-dependencies] assert_cmd = "1.0.1" predicates = "1.0.5" [[bin]] name = "sq-keyring-linter" path = "src/keyring-linter.rs" [features] default = ["crypto-nettle"] crypto-nettle = ["sequoia-openpgp/crypto-nettle"] crypto-cng = ["sequoia-openpgp/crypto-cng"] sequoia-keyring-linter-0.5.0/Makefile010064400017500001750000000002551376713201600157540ustar 00000000000000sq-keyring-linter.1: src/keyring-linter.rs src/cli.rs Makefile help2man --output=$@ --name=sq-keyring-linter --no-info $${CARGO_TARGET_DIR:-target}/debug/sq-keyring-linter sequoia-keyring-linter-0.5.0/README.md010064400017500001750000000131001376713201600155640ustar 00000000000000An OpenPGP certificate linter. This program checks for and can fix issues with OpenPGP certificates. The current focus is on the use of SHA-1, which has been [successfully attacked], and was [deprecated by NIST] in **2011**: > Since 2005 SHA-1 has not been considered secure against > well-funded opponents, as of 2010 many organizations have > recommended its replacement. NIST formally deprecated use > of SHA-1 in 2011 and disallowed its use for digital > signatures in 2013. As of 2020, attacks against SHA-1 are > as practical as against MD5; as such, it is recommended to > remove SHA-1 from products as soon as possible and use > instead SHA-256 or SHA-3. Replacing SHA-1 is urgent where > it's used for signatures. [successfully attacked]: https://sha-mbles.github.io/ [deprecated by NIST]: https://en.wikipedia.org/wiki/SHA-1 This program checks for the following issues: - Certificate revocations that use SHA-1. - Whether a User ID's current self signature uses SHA-1; - Whether a subkey's current binding signature uses SHA-1; and, - Whether a signing-capable subkey's current backsig uses SHA-1. `sq-keyring-linter` can fix all of these issues in a straightforward manner: ``` $ gpg --export-secret-key 4BE50C526C743502 | cargo run -- --fix | gpg --import Certificate 4BE50C526C743502 is not valid under the standard policy: No binding signature at time 2020-11-26T22:32:12Z Certificate 4BE50C526C743502 contains a User ID ("SHA1 User ID, SHA256 Subkeys ") protected by SHA-1 Certificate 4BE50C526C743502, key CC6387BFA4D9263D uses a SHA-1-protected binding signature. Examined 1 certificate. 0 certificates are invalid and were not linted. (GOOD) 1 certificate was linted. 1 of the 1 certificates (100%) has at least one issue. (BAD) 0 of the linted certificates were revoked. 0 of the 0 certificates has revocation certificates that are weaker than the certificate and should be recreated. (GOOD) 0 of the linted certificates were expired. 1 of the non-revoked linted certificate has at least one non-revoked User ID: 1 has at least one User ID protected by SHA-1. (BAD) 1 has all User IDs protected by SHA-1. (BAD) 1 of the non-revoked linted certificates has at least one non-revoked, live subkey: 1 has at least one non-revoked, live subkey with a binding signature that uses SHA-1. (BAD) 1 of the non-revoked linted certificates has at least one non-revoked, live, signing-capable subkey: 0 certificates have at least one non-revoked, live, signing-capable subkey with a strong binding signature, but a backsig that uses SHA-1. (GOOD) gpg: key 4BE50C526C743502: "SHA1 User ID, SHA256 Subkeys " 2 new signatures gpg: Total number processed: 1 gpg: new signatures: 2 ``` (The diagnostics and the summary are printed to `stderr`; any fixed keys are printed to `stdout` and encoded using ASCII Armor.) If you run it again, no issues will be detected: ``` $ gpg --export-secret-key 4BE50C526C743502 | cargo run -- --fix | gpg --import Examined 1 certificate. No issues found (see `/tmp/keyring-linter/debug/sq-keyring-linter --help` for a list of issues that are checked for). gpg: no valid OpenPGP data found. gpg: Total number processed: 0 ``` You can examine the signatures that `sq-keyring-linter` creates using, for instance, `pgpdump`: ``` $ gpg --export-secret-key 4BE50C526C743502 | cargo run -- --fix | pgpdump ... ``` In our experience, Sequoia's output is a bit more readable. You can either use `sq packet dump` or [https://dump.sequoia-pgp.org/](https://dump.sequoia-pgp.org/). Note: by default `sq-keyring-linter` does not export secret key material as this is usually not needed. You can override this by passing `--export-secret-keys`. You can check whether one or more OpenPGP certificates have issues as follows: ``` $ dpkg -l debian-keyring ... ii debian-keyring 2020.09.24 $ cargo run -- /usr/share/keyrings/debian-keyring.gpg ... Examined 885 certificates. 1 certificate is invalid and was not linted. (BAD) 884 certificates were linted. 203 of the 885 certificates (22%) have at least one issue. (BAD) 0 of the linted certificates were revoked. 0 of the 0 certificates has revocation certificates that are weaker than the certificate and should be recreated. (GOOD) 26 of the linted certificates were expired. 858 of the non-revoked linted certificates have at least one non-revoked User ID: 165 have at least one User ID protected by SHA-1. (BAD) 102 have all User IDs protected by SHA-1. (BAD) 834 of the non-revoked linted certificates have at least one non-revoked, live subkey: 160 have at least one non-revoked, live subkey with a binding signature that uses SHA-1. (BAD) 228 of the non-revoked linted certificates have at least one non-revoked, live, signing-capable subkey: 10 certificates have at least one non-revoked, live, signing-capable subkey with a strong binding signature, but a backsig that uses SHA-1. (BAD) ``` From the above output, we can see that the current Debian keyring has 885 certificates. One certificate is considered invalid by Sequoia and was skipped. Of the rest, 203 (22%) use SHA-1 in some way. These should be fixed. You shouldn't screen scrape the above output. If you want to programatically identify which certificates have an issue, use the `--list-keys` option, which prints the fingerprint of each certificate with an issue to stdout and like `--quiet` suppresses the diagnostics and statistics: ``` $ cargo run -- --list-keys /usr/share/keyrings/debian-keyring.gpg 124124BD3B4862AF7A0A42F100B45EBD4CA7BABE 7733B328D2795F5BE2325ADD01509D5CAB4AFD3F ... ``` sequoia-keyring-linter-0.5.0/sq-keyring-linter.1010064400017500001750000000065001376713201600177610ustar 00000000000000.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.8. .TH SQ-KEYRING-LINTER "1" "November 2020" "sq-keyring-linter 0.4.0" "User Commands" .SH NAME sq-keyring-linter \- sq-keyring-linter .SH DESCRIPTION sq\-keyring\-linter 0.4.0 .PP `sq\-keyring\-linter' checks for and optionally repairs OpenPGP certificates that use SHA\-1. .SS "USAGE:" .IP sq\-keyring\-linter [FLAGS] [OPTIONS] [\-\-] [inputs]... .SS "FLAGS:" .HP \fB\-e\fR, \fB\-\-export\-secret\-keys\fR .IP When fixing a certificate, the fixed certificate is exported without any secret key material. Using this switch causes any secret key material to also be exported .HP \fB\-f\fR, \fB\-\-fix\fR .IP Attempts to fix certificates, when possible .HP \fB\-h\fR, \fB\-\-help\fR .IP Prints help information .HP \fB\-k\fR, \fB\-\-list\-keys\fR .IP If set, outputs a list of fingerprints, one per line, of certificates that have issues. This output is intended for use by scripts. .IP This option implies `\-\-quiet'. If you also specify `\-\-fix', errors will still be printed to stderr, and fixed certificates will still be emitted to stdout. .HP \fB\-q\fR, \fB\-\-quiet\fR .IP Quiet; does not output any diagnostics .HP \fB\-V\fR, \fB\-\-version\fR .IP Prints version information .SS "OPTIONS:" .HP \fB\-p\fR, \fB\-\-password\fR ... .TP A key's password. Normally this is not needed: if stdin is .IP connected to a tty, the linter will ask for a password when needed .SS "ARGS:" .IP ... .TP A list of OpenPGP keyrings to process. If none are .IP specified, a keyring is read from stdin .PP `sq\-keyring\-linter' checks the supplied certificates for the following SHA\-1\-related issues: .IP \- Whether a certificate revocation uses SHA\-1. .IP \- Whether the current self signature for a non\-revoked User ID uses .IP SHA\-1. .IP \- Whether the current subkey binding signature for a non\-revoked, .IP live subkey uses SHA\-1. .IP \- Whether a primary key binding signature (a `backsig') for a .IP non\-revoked, live subkey uses SHA\-1. .PP 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. .PP 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. .SH "EXIT STATUS" If `\-\-fix' is not specified, then the exit status is 2, if any issues are found, and 0 otherwise. If `\-\-fix' is specified, then the exit status is 3, if any issues could not be fixed, and 0 if there were no issues or all issues were fixed. .SH EXAMPLES To gather statistics, simply run: .IP \f(CW$ sq-keyring-linter keyring.pgp\fR .PP To fix a key: .IP \f(CW$ gpg --export-secret-keys FPR | sq-keyring-linter --fix -p passw0rd\fR .PP \-p password123 | gpg \-\-import .PP To get a list of keys with issues: .IP \f(CW$ sq-keyring-linter --list-keys keyring.pgp | while read FPR; do\fR .PP something; done .SH "SEE ALSO" sq\-keyring\-linter's homepage: sequoia-keyring-linter-0.5.0/src/cli.rs010064400017500001750000000065171376713201600162270ustar 00000000000000use std::ffi::OsString; use structopt::StructOpt; #[derive(StructOpt)] #[structopt(name="sq-keyring-linter", set_term_width=72, about="\n\ `sq-keyring-linter' checks for and optionally repairs OpenPGP certificates that use SHA-1.", after_help="\ `sq-keyring-linter' 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 (a `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. *Exit status* If `--fix' is not specified, then the exit status is 2, if any issues are found, and 0 otherwise. If `--fix' is specified, then the exit status is 3, if any issues could not be fixed, and 0 if there were no issues or all issues were fixed. *Examples* To gather statistics, simply run: $ sq-keyring-linter keyring.pgp To fix a key: $ gpg --export-secret-keys FPR | sq-keyring-linter --fix -p passw0rd -p password123 | gpg --import To get a list of keys with issues: $ sq-keyring-linter --list-keys keyring.pgp | while read FPR; do something; done *See also* sq-keyring-linter's homepage: ")] pub struct Linter { // (progn (make-local-variable 'fill-column) (setq fill-column 70)) /// Quiet; does not output any diagnostics. #[structopt(short, long)] pub quiet: bool, /// Attempts to fix certificates, when possible. #[structopt(short, long)] pub fix: bool, /// When fixing a certificate, the fixed certificate is exported /// without any secret key material. Using this switch causes any /// secret key material to also be exported. #[structopt(short, long)] pub export_secret_keys: bool, /// A key's password. Normally this is not needed: if stdin is /// connected to a tty, the linter will ask for a password when /// needed. #[structopt(short, long, number_of_values = 1, multiple = true)] pub password: Vec, /// If set, outputs a list of fingerprints, one per line, of /// certificates that have issues. This output is intended for /// use by scripts. /// /// This option implies `--quiet'. If you also specify `--fix', /// errors will still be printed to stderr, and fixed certificates /// will still be emitted to stdout. #[structopt(short="k", long)] pub list_keys: bool, /// A list of OpenPGP keyrings to process. If none are specified, /// a keyring is read from stdin. #[structopt(parse(from_os_str))] pub inputs: Vec, } sequoia-keyring-linter-0.5.0/src/errors.rs010064400017500001750000000003151376713201600167620ustar 00000000000000/// Prints the error and causes, if any. pub fn print_error_chain(err: &anyhow::Error) { eprintln!(" {}", err); err.chain().skip(1).for_each(|cause| eprintln!(" because: {}", cause)); } sequoia-keyring-linter-0.5.0/src/keyring-linter.rs010064400017500001750000001077651376713201600204320ustar 00000000000000use std::env; use std::ffi::OsString; use std::cmp::Ordering; use std::process::exit; #[macro_use] extern crate anyhow; use sequoia_openpgp as openpgp; use openpgp::Result; use openpgp::armor; use openpgp::cert::prelude::*; use openpgp::crypto::Password; use openpgp::parse::Parse; use openpgp::packet::prelude::*; use openpgp::policy::Policy; use openpgp::policy::StandardPolicy; use openpgp::serialize::Serialize; use openpgp::serialize::stream::{Message, Armorer}; use openpgp::types::HashAlgorithm; use openpgp::types::KeyFlags; use openpgp::types::RevocationStatus; use openpgp::types::SignatureType; use openpgp::types::SymmetricAlgorithm; use structopt::StructOpt; use atty::Stream; use ansi_term::Colour::{Red, Green}; mod cli; mod errors; fn decrypt_key(key: Key, passwords: &mut Vec) -> Result> where R: key::KeyRole + Clone { let key = key.parts_as_secret()?; match key.secret() { SecretKeyMaterial::Unencrypted(_) => { Ok(key.clone()) } SecretKeyMaterial::Encrypted(_) => { for p in passwords.iter() { if let Ok(key) = key.clone().decrypt_secret(&Password::from(&p[..])) { return Ok(key); } } if atty::is(Stream::Stdin) { let mut first = true; loop { // Prompt the user. match rpassword::read_password_from_tty( Some(&format!( "{}Enter password to unlock {} (blank to skip): ", if first { "" } else { "Invalid password. " }, key.keyid().to_hex()))) { Ok(p) => { first = false; if p == "" { // Give up. break; } if let Ok(key) = key .clone() .decrypt_secret(&Password::from(&p[..])) { passwords.push(p); return Ok(key); } } Err(err) => { eprintln!("While reading password: {}", err); break; } } } } Err(anyhow!("Key {}: Unable to decrypt secret key material", key.keyid().to_hex())) } } } fn update_cert_revocation(cert: &Cert, rev: &Signature, passwords: &mut Vec) -> Result { assert_eq!(rev.typ(), SignatureType::KeyRevocation); let pk = cert.primary_key().key(); // Derive a signer. let mut signer = decrypt_key( pk.clone().parts_into_secret()?, passwords)? .into_keypair()?; let sig = SignatureBuilder::from(rev.clone()) .set_hash_algo(HashAlgorithm::SHA256) .preserve_signature_creation_time()? .sign_direct_key(&mut signer, pk)?; Ok(sig) } const GOOD_HASHES: &[ HashAlgorithm ] = &[ HashAlgorithm::SHA256, HashAlgorithm::SHA512, ]; // Update the binding signature for ua. // // ua is using a weak policy. fn update_user_id_binding(ua: &ValidUserIDAmalgamation, passwords: &mut Vec) -> Result { let pk = ua.cert().primary_key().key(); // Derive a signer. let mut signer = decrypt_key( pk.clone().parts_into_secret()?, passwords)? .into_keypair()?; let sym = &[ SymmetricAlgorithm::AES128, SymmetricAlgorithm::AES192, SymmetricAlgorithm::AES256, SymmetricAlgorithm::Twofish, SymmetricAlgorithm::Camellia128, SymmetricAlgorithm::Camellia192, SymmetricAlgorithm::Camellia256, ]; // Update the signature. let sig = ua.binding_signature(); let mut sig = SignatureBuilder::from(sig.clone()) .set_hash_algo(GOOD_HASHES[0]) .set_preferred_hash_algorithms( sig.preferred_hash_algorithms() .unwrap_or(&[ HashAlgorithm::SHA512, HashAlgorithm::SHA256 ]) .iter() .map(|h| h.clone()) .filter(|a| GOOD_HASHES.contains(&a)) .collect())? .set_preferred_symmetric_algorithms( sig.preferred_symmetric_algorithms() .unwrap_or(&[ SymmetricAlgorithm::AES128, SymmetricAlgorithm::AES256, ]) .iter() .map(|h| h.clone()) .filter(|a| sym.contains(&a)) .collect())? .sign_userid_binding(&mut signer, pk, ua.userid())?; // Verify it. assert!(sig.verify_userid_binding(signer.public(), pk, ua.userid()) .is_ok()); // Make sure the signature is integrated. assert!(ua.cert().cert().clone() .insert_packets(Packet::from(sig.clone())).unwrap() .into_packets() .any(|p| { if let Packet::Signature(s) = p { s == sig } else { false } })); Ok(sig) } // Update the subkey binding signature for ka. // // ka is using a weak policy. fn update_subkey_binding

(ka: &ValidSubordinateKeyAmalgamation

, passwords: &mut Vec) -> Result where P: key::KeyParts + Clone { let pk = ka.cert().primary_key().key(); // Derive a signer. let mut signer = decrypt_key( pk.clone().parts_into_secret()?, passwords)? .into_keypair()?; // Update the signature. let sig = ka.binding_signature(); let mut builder = SignatureBuilder::from(sig.clone()) .set_hash_algo(HashAlgorithm::SHA256); // If there is a valid backsig, recreate it. if let Some(backsig) = sig.embedded_signatures() .filter(|backsig| { (*backsig).clone().verify_primary_key_binding( &ka.cert().cert().primary_key(), ka.key()).is_ok() }) .nth(0) { // Derive a signer. let mut subkey_signer = decrypt_key( ka.key().clone().parts_into_secret()?, passwords)? .into_keypair()?; let backsig = SignatureBuilder::from(backsig.clone()) .set_hash_algo(HashAlgorithm::SHA256) .sign_primary_key_binding(&mut subkey_signer, pk, ka.key())?; builder = builder.set_embedded_signature(backsig)?; } let mut sig = builder.sign_subkey_binding(&mut signer, pk, ka.key())?; // Verify it. assert!(sig.verify_subkey_binding(signer.public(), pk, ka.key()) .is_ok()); // Make sure the signature is integrated. assert!(ka.cert().cert().clone() .insert_packets(Packet::from(sig.clone())).unwrap() .into_packets() .any(|p| { if let Packet::Signature(s) = p { s == sig } else { false } })); Ok(sig) } fn main() { match real_main() { Ok(()) => (), Err(e) => { errors::print_error_chain(&e); exit(1); }, } } fn real_main() -> Result<()> { // Number of certs that have issues. let mut certs_with_issues = 0; // Whether we were unable to fix at least one issue. let mut unfixed_issue = 0; // Standard policy that unconditionally rejects SHA-1: this is // where we want to be. let mut sp = StandardPolicy::new(); sp.reject_hash(HashAlgorithm::SHA1); let sp = &sp; // A standard policy that also accepts SHA-1. let mut sp_sha1 = StandardPolicy::new(); sp_sha1.accept_hash(HashAlgorithm::SHA1); let sp_sha1 = &sp_sha1; // The number of valid and invalid certificates (according to // SP+SHA-1). let mut certs_valid = 0; let mut certs_invalid = 0; // Certificates that are revoked. let mut certs_revoked = 0; let mut certs_with_inadequota_revocations = 0; let mut certs_expired = 0; // Certificates that are valid and have a valid User ID. let mut certs_sp_sha1_userids = 0; let mut certs_with_a_sha1_protected_userid = 0; let mut certs_with_only_sha1_protected_userids = 0; // Subkeys. let mut certs_with_subkeys = 0; let mut certs_with_a_sha1_protected_binding_sig = 0; let mut certs_with_signing_subkeys = 0; let mut certs_with_sha1_protected_backsig = 0; let mut args = cli::Linter::from_args(); if args.list_keys { args.quiet = true; } let mut passwords: Vec = args.password; let inputs: Vec = if args.inputs.len() == 0 { vec![ "/dev/stdin".into() ] } else { args.inputs }; let mut out = Armorer::new(Message::new(std::io::stdout())) .kind(armor::Kind::SecretKey) .build()?; for input in inputs { let filename = if input == "-" { "/dev/stdin".into() } else { input }; let certp = CertParser::from_file(filename)?; 'next_cert: for certo in certp { match certo { Ok(cert) => { // Whether we found at least one issue. let mut found_issue = false; macro_rules! diag { ($($arg:tt)*) => {{ // found_issue may appear to be unused if // diag is immediately followed by a // continue or break. #[allow(unused_assignments)] { if ! found_issue { certs_with_issues += 1; found_issue = true; if args.list_keys { println!("{}", cert.fingerprint().to_hex()); } } if ! args.quiet { eprintln!($($arg)*); } } }}; } let mut updates: Vec = Vec::new(); macro_rules! next_cert { () => {{ if updates.len() > 0 { let cert = cert.insert_packets(updates)?; if args.export_secret_keys { cert.as_tsk().serialize(&mut out)?; } else { cert.serialize(&mut out)?; } } continue 'next_cert; }} } let sp_vc = cert.with_policy(sp, None); let sp_sha1_vc = cert.with_policy(sp_sha1, None); if let Err(ref err) = sp_sha1_vc { diag!("Certificate {} is not valid under \ the standard policy + SHA-1: {}", cert.keyid().to_hex(), err); certs_invalid += 1; unfixed_issue += 1; continue; } let sp_sha1_vc = sp_sha1_vc.unwrap(); certs_valid += 1; // Check if the certificate is revoked. // // There are four cases to consider: // // 1. SHA1 certificate, SHA1 revocation certificate // 2. SHA1 certificate, SHA256 revocation certificate // 3. SHA256 certificate, SHA1 revocation certificate // 4. SHA256 certificate, SHA256 revocation certificate // // When the revocation certificate uses SHA256, // there is nothing to do even if something else // relies on SHA1: the certificate should be // ignore, because it is revoked! // // In the case that we have a SHA1 certificate and // a SHA1 revocation certificate, we also don't // have to do anything: either the whole // certificate will be considered invalid or // implementation accepts SHA1 and it will be // considered revoked. // // So, the only case that we have to fix is when // the certificate uses SHA256, but the revocation // certificate uses SHA1. In this case, we need // to upgrade the revocation certificate. if let RevocationStatus::Revoked(mut revs) = sp_sha1_vc.revocation_status() { certs_revoked += 1; if sp_vc.is_err() { // Cases #1 and #2. Nothing to do. next_cert!(); } // Dedup based on creation time and the reason // for revocation. Prefer revocations that do // not use SHA-1. let cmp = |a: &&Signature, b: &&Signature| -> Ordering { a.signature_creation_time() .cmp(&b.signature_creation_time()) .then(a.reason_for_revocation() .cmp(&b.reason_for_revocation())) }; revs.sort_by(cmp); revs.dedup_by( |a: &mut &Signature, b: &mut &Signature| -> bool { let x = cmp(a, b); if x != Ordering::Equal { return false; } // Prefer the non-SHA-1 variant. // Recall: if the elements are // considered equal, a is removed and // b is kept. if GOOD_HASHES.contains(&a.hash_algo()) && b.hash_algo() == HashAlgorithm::SHA1 { *b = *a; } true }); // See what revocation certificates need to be // fixed. let mut inadequate_revocation = false; for rev in revs { if rev.hash_algo() == HashAlgorithm::SHA1 { if ! inadequate_revocation { inadequate_revocation = true; certs_with_inadequota_revocations += 1; } diag!("Certificate {}: Revocation certificate \ {:02X}{:02X} uses SHA-1.", cert.keyid().to_hex(), rev.digest_prefix()[0], rev.digest_prefix()[1]); if args.fix { match update_cert_revocation( &cert, rev, &mut passwords) { Ok(sig) => { updates.push(sig); } Err(err) => { unfixed_issue += 1; eprintln!("Certificate {}: \ Failed to update \ revocation certificate \ {:02X}{:02X}: {}", cert.keyid().to_hex(), rev.digest_prefix()[0], rev.digest_prefix()[1], err); } } } } continue; } next_cert!(); } // Check if the certificate is alive. match (sp_sha1_vc.alive(), sp_vc.as_ref().map(|vc| vc.alive())) { (Err(_), Err(_)) => { // SP+SHA1: Not alive, SP: Invalid // // It only uses SHA1, and under SP+SHA1, // it is expired. Invalid or expired, we // don't need to fix it. certs_expired += 1; next_cert!(); } (Err(_), Ok(Err(_))) => { // SP+SHA1: Not alive, SP: Not alive. // // However you look at it, it's expired. certs_expired += 1; next_cert!(); } (Err(_), Ok(Ok(_))) => { // SP+SHA1: Not alive, SP: Alive // // Impossible. panic!(); } (Ok(_), Err(_)) => { // SP+SHA1: Alive, SP: Invalid. // // The certificate only uses SHA-1. Lint // it as usual. () } (Ok(_), Ok(Err(_))) => { // SP+SHA1: Alive, SP: Not alive. // // We have a binding signature using SHA1 // that says the certificate does not // expire, and a newer binding signature // using SHA2+ that is expired. // // Linting should(tm) fix this. diag!("Certificate {} is live under SP+SHA1, \ but expire under SP.", cert.keyid().to_hex()); } (Ok(_), Ok(Ok(_))) => { // SP+SHA1: Alive, SP: Alive. Lint it as // usual. () } } if let Err(ref err) = sp_vc { diag!("Certificate {} is not valid under \ the standard policy: {}", cert.keyid().to_hex(), err); } // User IDs that are not revoked, and valid under // the standard policy + SHA-1. let mut a_userid = false; let mut sha1_protected_userid = false; let mut not_sha1_protected_userid = false; let not_revoked = |ua: &ValidUserIDAmalgamation| -> bool { if let RevocationStatus::Revoked(_) = ua.revocation_status() { false } else { true } }; for ua in sp_sha1_vc.userids().filter(not_revoked) { if ! a_userid { a_userid = true; certs_sp_sha1_userids += 1; } let sig = ua.binding_signature(); if sig.hash_algo() == HashAlgorithm::SHA1 { diag!("Certificate {} contains a \ User ID ({:?}) protected by SHA-1", cert.keyid().to_hex(), String::from_utf8_lossy(ua.value())); if !sha1_protected_userid { sha1_protected_userid = true; certs_with_a_sha1_protected_userid += 1; } if args.fix { match update_user_id_binding( &ua, &mut passwords) { Ok(sig) => { updates.push(sig); } Err(err) => { unfixed_issue += 1; eprintln!("Certificate {}: User ID {}: \ Failed to update \ binding signature: {}", cert.keyid().to_hex(), String::from_utf8_lossy( ua.value()), err); } } } } else { if !not_sha1_protected_userid { not_sha1_protected_userid = true; } } } if sha1_protected_userid && ! not_sha1_protected_userid { certs_with_only_sha1_protected_userids += 1; } let sha1_subkeys: Vec<_> = sp_sha1_vc .keys().subkeys() .revoked(false).alive() .collect(); if sha1_subkeys.len() > 0 { certs_with_subkeys += 1; // Does this certificate have any subkeys whose // binding signatures use SHA-1? let mut uses_sha1_protected_binding_sig = false; let mut uses_certs_with_signing_subkeys = false; let mut uses_sha1_protected_backsig = false; for ka in sha1_subkeys.into_iter() { let sig = ka.binding_signature(); if sig.hash_algo() == HashAlgorithm::SHA1 { diag!("Certificate {}, key {} uses a \ SHA-1-protected binding signature.", cert.keyid().to_hex(), ka.keyid().to_hex()); if ! uses_sha1_protected_binding_sig { uses_sha1_protected_binding_sig = true; certs_with_a_sha1_protected_binding_sig += 1; } if args.fix { match update_subkey_binding( &ka, &mut passwords) { Ok(sig) => updates.push(sig), Err(err) => { unfixed_issue += 1; eprintln!("Certificate {}, key {}: \ Failed to update \ binding signature: {}", cert.keyid().to_hex(), ka.keyid().to_hex(), err); } } } continue; } // Check if the backsig uses SHA-1. if ! ka.has_any_key_flag( KeyFlags::empty() .set_signing() .set_certification()) { // No backsig required. continue; } if ! uses_certs_with_signing_subkeys { uses_certs_with_signing_subkeys = true; certs_with_signing_subkeys += 1; } // Get the cryptographically valid backsigs. let mut backsigs: Vec<_> = sig.embedded_signatures() .filter(|backsig| { (*backsig).clone().verify_primary_key_binding( &cert.primary_key(), ka.key()).is_ok() }) .collect(); if backsigs.len() == 0 { // We can't get here. If the key is // valid under sp+SHA-1, and requires // a backsig, then it must have a // valid backsig. panic!("Valid signing-capable subkey without \ a valid backsig?"); } backsigs.sort(); backsigs.dedup(); if backsigs.len() > 1 { eprintln!("Warning: multiple cryptographically \ valid backsigs."); } if backsigs .iter() .any(|s| { sp.signature(s, ka.hash_algo_security()) .is_ok() }) { // It's valid under the standard // policy. We're fine. } else if backsigs .iter() .any(|s| { sp_sha1.signature(s, ka.hash_algo_security()) .is_ok() }) { // It's valid under SP+SHA-1 policy. // Update it. diag!("Certificate {}, key {} uses a \ {}-protected binding signature, \ but a SHA-1-protected backsig", cert.keyid().to_hex(), ka.keyid().to_hex(), sig.hash_algo()); if ! uses_sha1_protected_backsig { uses_sha1_protected_backsig = true; certs_with_sha1_protected_backsig += 1; } if args.fix { match update_subkey_binding( &ka, &mut passwords) { Ok(sig) => updates.push(sig), Err(err) => { unfixed_issue += 1; eprintln!("Certificate {}, key: {}: \ Failed to update \ binding signature: {}", cert.keyid().to_hex(), ka.keyid().to_hex(), err); } } } } else { let sig = backsigs[0]; let err = sp_sha1.signature(sig, ka.hash_algo_security()).unwrap_err(); diag!("Cert {}: backsig {:02X}{:02X} for \ {} is not valid under SP+SHA-1: {}. \ Ignoring.", cert.keyid().to_hex(), sig.digest_prefix()[0], sig.digest_prefix()[1], ka.keyid().to_hex(), err); unfixed_issue += 1; } } } if !found_issue { if let Err(err) = sp_vc { diag!("Certificate {} is not valid under \ the standard policy: {}", cert.keyid().to_hex(), err); } } next_cert!(); } Err(err) => panic!("parsing cert #{}: {}", certs_valid + certs_invalid, err), } } } out.finalize()?; let pl = |n, singular, plural| { if n == 1 { singular } else { plural } }; macro_rules! err { ($n:expr, $($arg:tt)*) => {{ eprint!($($arg)*); eprint!(" ("); if $n > 0 { if atty::is(Stream::Stderr) { eprint!("{}", Red.paint("BAD")); } else { eprint!("BAD"); } } else { if atty::is(Stream::Stderr) { eprint!("{}", Green.paint("GOOD")); } else { eprint!("GOOD"); } } eprintln!(")"); }}; } if ! args.quiet { eprintln!("Examined {} {}.", certs_valid + certs_invalid, pl(certs_valid + certs_invalid, "certificate", "certificates")); } if certs_with_issues == 0 { if ! args.quiet { eprintln!("No issues found (see `{} --help` for a list of issues \ that are checked for).", env::args().nth(0).unwrap_or("sq-keyring-linter".into())); } } else { if ! args.quiet { err!(certs_invalid, " {} {} invalid and {} not linted.", certs_invalid, pl(certs_invalid, "certificate is", "certificates are"), pl(certs_invalid, "was", "were")); if certs_valid > 0 { eprintln!(" {} {} linted.", certs_valid, pl(certs_valid, "certificate was", "certificates were")); err!(certs_with_issues, " {} of the {} certificates ({}%) \ {} at least one issue.", certs_with_issues, certs_valid + certs_invalid, certs_with_issues * 100 / (certs_valid + certs_invalid), pl(certs_with_issues, "has", "have")); eprintln!("{} of the linted certificates {} revoked.", certs_revoked, pl(certs_revoked, "was", "were")); err!(certs_with_inadequota_revocations, " {} of the {} certificates has revocation certificates \ that are weaker than the certificate and should be \ recreated.", certs_with_inadequota_revocations, certs_revoked); eprintln!("{} of the linted certificates {} expired.", certs_expired, pl(certs_expired, "was", "were")); eprintln!("{} of the non-revoked linted {} at least one non-revoked User ID:", certs_sp_sha1_userids, pl(certs_sp_sha1_userids, "certificate has", "certificates have")); err!(certs_with_a_sha1_protected_userid, " {} {} at least one User ID protected by SHA-1.", certs_with_a_sha1_protected_userid, pl(certs_with_a_sha1_protected_userid, "has", "have")); err!(certs_with_only_sha1_protected_userids, " {} {} all User IDs protected by SHA-1.", certs_with_only_sha1_protected_userids, pl(certs_with_only_sha1_protected_userids, "has", "have")); eprintln!("{} of the non-revoked linted certificates {} at least one \ non-revoked, live subkey:", certs_with_subkeys, pl(certs_with_subkeys, "has", "have")); err!(certs_with_a_sha1_protected_binding_sig, " {} {} at least one non-revoked, live subkey with \ a binding signature that uses SHA-1.", certs_with_a_sha1_protected_binding_sig, pl(certs_with_a_sha1_protected_binding_sig, "has", "have")); eprintln!("{} of the non-revoked linted certificates {} at least one non-revoked, live, \ signing-capable subkey:", certs_with_signing_subkeys, pl(certs_with_signing_subkeys, "has", "have")); err!(certs_with_sha1_protected_backsig, " {} {} at least one non-revoked, live, signing-capable subkey \ with a strong binding signature, but a backsig \ that uses SHA-1.", certs_with_sha1_protected_backsig, pl(certs_with_sha1_protected_backsig, "certificate has", "certificates have")); } } if args.fix { if unfixed_issue == 0 { exit(0); } else { if ! args.quiet { err!(unfixed_issue, "Failed to fix {} {}.", unfixed_issue, pl(unfixed_issue, "issue", "issues")); } exit(3); } } else { exit(2); } } Ok(()) } sequoia-keyring-linter-0.5.0/tests/data/all-sha1-password-Foobar-priv.pgp010064400017500001750000000050361376713201600245270ustar 00000000000000_KrvNƱ,Cr5*ܢnwwGMPʭIAKqid<ʂX@Gryr2L$ń$mu\U%6^1MeT%a[=:6IUoO+e}8"_   XO S rE̽;Ym.P+@s7a[/](Q _W[GRR Vb IE7[UW{:X=0|'VZuEv Q0Jd݁fn@Ww9># ЕpOj?#7nLiHz] AϽ {w)|z/8* F,J3yNχx@mu7qđ1EEj_Wkbx^ 3ox v)l aAgK4|?DSp'-aUhs6579D.1'I$;WuXJV\̳k9~Z99rڏUG(ܺb E 3R*[$6*g92Ok&Ҏ8 ĠDRYkJkuXw3D=DOE['.<޳EoiϟuV$@#?iAOݖ{}ۀk+imqJ1P{ge[=gV61IgAByAFm-x~vㆫPݴ<'^CW6Hk0]E 2h2B8;DiUcٹOû4 wE-#5G ]dae;Kmu{IQyRe]Te9䍡ol*`iK/K+6<i$Y_ENe΅c 'x.U}ClJ&6$hXZz9-oͫ|Y -ӝMe8"_   XO S rE̽;Ym.P+@s7a[/](Q _W[GRR Vb IE7[UW{:X=0|'VZuEv Q0Jd݁fn@Ww9># ЕpOj?#7nLiHz] AϽ {w)|z/8* F,J3yNχx@mu7qđ1EEj _Wkbx^ 3ox v)l aAgK4|?DSp'-aUhs6579D.1'I$;WuXJV\̳#5G ]dae;Kmu{IQyRe]Te9䍡ol*`iK/K+6<i$Y_ENe΅c 'x.U}ClJ&6$hXZz9-oͫ|Y -ӝMe).B:+p!ůw[ R Xy]s$<2+RRy(kK7>#1|v)pxUJ蟡P&u嘉0,nY.PkCw!E8"vC\CHM|xBe *!CQgP ҙm'1},w=i kwI F30v4ݵ~ֆյAj{6kǓUEk.ćM~P8v(U qk= s`P0ʿB0@!~"@hWGsK5mO%N<u_If>xڍI?A"5Mk-{_]m $Z,[.YDws\V}Rƕq3d5#)qP*6+JhZ*XEdt((ןX@hA;ƫf3[4rN>YW0>8 yy[Ԁ{&t b5w6E:̈́Ȉ̫83э2j<_|B 'DΧajI$CfUaMɓwOj^0c]qXq]2a|ʥX+~`&% XS h7W\f[S!tk(WP&Aa0Kq 6F%ҏ~w']F)hHXcQ Fуsuv'&uCe$RI;wA fbyxM:׬[$ ݞ|a'ers QH"nDCz1+һ9ӥ_M@'K^s_k}*# ?@C jp}^} %GkYwZaX4qBO}"VL}5-ا9Authentication Subkey  >!uRq;Jt`_ g    ;Jt`2 ۧ5@5f_M^֓ K]3z -$K*#tgnʦN!)C 8:c '0s Zk+tJRLtʲ[f$`PHIOcX8XOb_ۃpmzP G-(.¬ΤA=d Ƽ7Z{vHAӂVlDʉz>4c(ZN}zƏK>,t%4RSF=SU8RN!bXig_#peVn={_(@ T7b/a/􈻝n46Z@,UaX*-  XnꇝqR<+>@jrG|`a\ ZM}ϲul{@4#Zt*6J Vz:x ox_;:+(cVbz;x#9t (/{6-:A>ģ{yJ<7(f)2>%׃\NATBăЄIΝrVզ9Vgsz/!ŦTO5/KT_kӯyb %_il :Gbs,R^`" 8{Yvx\KGwE Ǖ/F.Tyz;8Pfw$\xVNk P&Rl J6 hn>vBl0ha$xYNq `D2;JLޅ~&;1! %>\Ggrg\T1H$;~=@ZR4XV#H%spy $\v)L+33Sܟ䨶# h):L{@MB08 ^VuJ jU_N&i=܆"qdQօ4ʬww~9;ƝMg1[&kQ؈Aai>>$r>WeST[&M ?vdwm1FPj.}6nTdLC 59*xlDԠ[#L'$2I -0kޏ TN˲Eޣ>[LP7=B,iD+?#Og|!`klL\"D9lHOr0&:Tpg9Ϳ,mIWۑhZ(.Aƥ?$d[P7 8^fyCvr|ySp*c@p=^ .xC$PtH.h p^dA%ER)Kefk!:. #YOǖ4дə;1#%4Cptث]Wi邳 &!uRq;Jt`_  g ;Jt` A| +J Y˞Zmgw=4 NG7 ưˆָ}fTi +HvB&S{c(~/pfiW"X ؜ ݵ|;{hr1A8GL54t 9Nt`=0X꥖!ˍsz]dBJ`F )N䰕_?#[MSr:DIx/#Rٛ凷T_sof#n/>i>uZJ B6 ѳ̖ہ D -)6\3" vjDl4 }\HEj)\1QbõYRңi$5./*$ TtGTX_ ͢; śA 89_X2t)?o:Q^e䬉>Ps"96M$)x^OLГ~q0e(nU CcK"Jȴ@)ς*6Ua>0u5fx|E0ElJ3d$}w|3f;HOfyM3Gzkā$iUgcc&Cw f:=cBR8zG8c2\m` ?,V -\>թM]K{:ʆbëחZ<$mkG`SHU#aa&PIbVs/vՑ.]IO![Yջ<\,؃%KsY} 7S+݂se5-`pZPMSpii( $gj9WmN")X**!L5Ruq8Wf4tMGkYP:uZL&pI|bĨ8AH֋KA|S91ы>r;]vJ!XjyLXeܑã\}r7*}X] *((%<3`k (t}Aʃ]䈮~4&&'>5Zx=KSt2̐*e.11HGew0ٍ\C;IZ \ x[ز /gD#j|%6$ i㫦Az.o|xjJ/=maBNO"ȩF'"!&ϟπvm &+76}AzC-՚kK@_{`j(6R ǕҘO"/Qvc~+sequoia-keyring-linter-0.5.0/tests/data/authentication-subkey-pub.pgp010064400017500001750000000050721376713201600242040ustar 00000000000000_ ˁkAU32J܋Q˛Qj1Vk;X{j`۸IsQHX=r L0]I]*b Ix4ɻ@kR ? `G!zԀrוAucrp2DgēpPE sX Xa7$#keE1rњ/Q~q&[*?NHfȢ4;v yy_{޻hC2S{6:$CCaT4207Fqr 颚^N(Y~({J7|m%{(4'Z/Ld5E7>).B:+p!ůw[9Authentication Subkey  >!uRq;Jt`_ g    ;Jt`2 ۧ5@5f_M^֓ K]3z -$K*#tgnʦN!)C 8:c '0s Zk+tJRLtʲ[f$`PHIOcX8XOb_ۃpmzP G-(.¬ΤA=d Ƽ7Z{vHAӂVlDʉz>4c(ZN}zƏK>,t%4RSF=SU8RN!bXig_#peVn={_(@ T7b/a/􈻝n46Z@,UaX*-  XnꇝqR<+>@jrG|`a\ ZM}ϲul{@4#Zt*6J Vz:x &!uRq;Jt`_  g ;Jt` A| +J Y˞Zmgw=4 NG7 ưˆָ}fTi +HvB&S{c(~/pfiW"X ؜ ݵ|;{hr1A8GL54t 9Nt`=0X꥖!ˍsz]dBJ`F )N䰕_?#[MSr:DIx/#Rٛ凷T_sof#n/>i>uZJ B6 ѳ̖ہ D -)6\3" vjDl4 }\HEj)\1QbõYRңi$5./*$ TtGT_ ͢; śA 89_X2t)?o:Q^e䬉>Ps"96M$)x^OLГ~q0e(nU CcK"Jȴ@)ς*6Ua>0u5fx|E0ElJ3d$}w|3f;HOfyM3Gzkā$iUgcc&Cw f:=cBR8zG8c2\m` ?,V -\>թM]K{:ʆbëחZ<$mk[ز /gD#j|%6$ i㫦Az.o|xjJ/=maBNO"ȩF'"!&ϟπvm &+76}AzC-՚kK@_{`j(6R ǕҘO"/Qvc~+sequoia-keyring-linter-0.5.0/tests/data/gnupg-ecc-normal-priv.pgp010064400017500001750000000007501376713201600232130ustar 00000000000000X_ +G@p8*6jZ+ӓ`>0-2k`hMʒ(ɷ#]n!GnuPG ECC 8!;DXǫJO6_    XǫJO6 hXx@,5qګ+U>gtES=݈98zKH]%q=AJ+Gc]_ +U@:hRN 2W1hcƎlcZWŒ-P)(]wƄb{!tq>ʼn<#+2x !;DXǫJO6_ XǫJO6{2"Lm—-.INqxb:gF{>HG E OEaY sequoia-keyring-linter-0.5.0/tests/data/gnupg-ecc-normal-pub.pgp010064400017500001750000000006361376713201600230240ustar 000000000000003_ +G@p8*6jZ+ӓ`>0-2k!GnuPG ECC 8!;DXǫJO6_    XǫJO6 hXx@,5qګ+U>gtES=݈98zKH]%q=AJ+Gc8_ +U@:hRN 2W1hcƎlcZWŒ-x !;DXǫJO6_ XǫJO6{2"Lm—-.INqxb:gF{>HG E OEaY sequoia-keyring-linter-0.5.0/tests/data/gnupg-rsa-normal-priv.pgp010064400017500001750000000134551376713201600232540ustar 00000000000000X_F 'qνh'e q:u1X?{k$ & +tO[yY'Φy/1^'(ج47'.xٙsS$d-ΐ wF}華Ӣ BByntd`GފMTڍ)uMh.uJkZ":-ĬYsA, 'ih[ +DHY b͔q[v:yܨ9ahÀ-4s ]āXÚOG[j˔1 9NMA,iͦ&R˹.ph|$_7@Wh,|/Bo^/LKIڗmp^/QhĮp6BhlML꽳F>i] <%SVU3/E=䥝'] 8mjjڜ H(,ۦjf7TܤEt^ru4n[dW%y\a p-/G*kwLC»5-Q2 05a@>.%x=V,}corLu<\ Շp| _ [uEBOv_`*9 ze{m-ERiLǒܶ5X PHE=rbB:Fb*(^@'JWxS0|8:M"X#oe Q=ME|07Z^N *놝`U9߳h|0G#邧&$e^z3XTVssJFMz %n-@5(T0xzxSV.Rk^nг<w#d-'&W)]zjo>r,Dmet,G q\giF.b蔴D4-XXgsd/@e&D߿YWęR?VxMa9vEAH2qd}qM5xjto0!]}3|'gQdV1YOoޕң&}0JfVQ㿴!GnuPG RSA  8!Uqˆz _F     MF $cA{ S@1>X $J5PjKZQNrG ITAc-q5 9]m*#ѩRayGg r5Vfn:``Wa>k/<ܖ۬t9t:Ā\hx=9/u+X_W bT[xl(n`> D;DGA=Qhʥ)W[t?{: ǺHܱ0TFGt߇˼NE0$sji*=1>g%*L*[j[` )M0S Z &IN#Wbxc?KUTUkFzU75nH%w:FTi7'V#+f@jtZ/*hq7nQz.bѣ3j?°D麔n VH~>υ+޳1 z|{b&T/ÕBWs/DI%d+w, .sǯN]_mox ryGyB!Wah8[lSIYS-J _ U*ybB`E#y ӑZX?hv"0d:5*=6r.LӘTh Q' ȂDCg-NͼՇGϵq1N+P0NgF"g9XTz&G&墂wLY"oV۵4u9_' nÊ GnM_nt,gÇ0qH۝eoW &, BVdT %J JUAَ&~)5]|18VޟCǾ Vf’ YZŖ9l-,^;dɛ xfXQS ?? ry\mH=+Ό<)Y J 3Qcv#7tcX18K&d͂} Z}?_QV^CeH%sV0>bȦ-yP0TuM ¦e7q3"VBsaWª X~P9b;$"#%3NuR^$%ĉI}o: " O8l{p%l !Uqˆz _W    !.Q惩Ʃ1:IB_W :IBg qۻC0{q]R4hw:S{e6BFLl"D(L0<š _d@gFF;jMpx(mXJ0iM v<S߰c h1:3}Н<nIk)d@M%HBtei풅f+gf1ӆz|B9:JټޖA&w%K>-hѦ3=2oKYAH{-R-,k"m2t˃W+%E߼S\JsU퇰lj}Z"OL+GQ9KB"K8'ndݑ)LHQJN ObeYmiuw|!ȴ߽A&H>X_ ihAY^KF΍1Ȍf0d.j?0/)JP#{BWqLn|hP9=50\K(Ƿ &!Q҂t`CAӂr?F2=)&ސOy'$] Y=AcC6lItlCV,L}MxXi^%%qByc+'%˦/TIV]V;,,~5["HM\az"|c]knJ3`{+|7ÿURl&5Zr09 a`sm:wO,D ĉ/x#$3HHNJ; e"C>#(aƝ:8":ߥ #tNi Etmg-ǐvͣ9 ]3Dci{} MT-WUzIv0D3XRJ2)NJ4TD,Ś]t^0q-d0iFv. 7!nmTR$8{c!/AhP]wy|7OK%9plaf 2o2lbܟ-9ۗ,DMZ u8H*z$!JWk'P#1PHIRqMaqkIJ3O|&B5 q߾Ƶ!Sc{1wq}A0 {{BjSҾ&IAS@*3 ޼ۂl%{ʝq@n72؝"hMd&īe\9WC ?4b bsOd?8G QoσV{78Ϡv'd(]җ2#ZH{J_G:1 }o?T'Kv, Z>߳tAR: ="~Ҽg6L;C.ף,~“ɩx8$.59Gsx'Nu՚XTެ%$~LjMfuQ-&o(}/U |Z*O2تuV(Ǿh>cN&ktl0uFߙ4`t] Ч AWfVuLYU- \S7!|9D uj&JTPY ? ɻ5ۭ؞;ak @nI~1ѾIע ZmE3B*""}[4wTF}[6IZPk!8mD\ΈIg5$9sGfc>@: uOAVyꮉ !Uqˆz _  0S Nگ;7F˭qt9N8Ox9 sAx.=Y#tm.JvzB0ŭN.XP8=a t c+X-(pS Q/NlXim֧I)6 VHbbsX;⑀z9,N} '/ŋTT{mKȞj2CDD#LDàYtK&#SIh.nr p DBQBcNVSQ/)GDSEq,H&4{r$IF3zC*= $)k eoͶO9#^0)i_E2ݨt ¶g{4sequoia-keyring-linter-0.5.0/tests/data/gnupg-rsa-normal-pub.pgp010064400017500001750000000057141376713201600230610ustar 00000000000000_F 'qνh'e q:u1X?{k$ & +tO[yY'Φy/1^'(ج47'.xٙsS$d-ΐ wF}華Ӣ BByntd`GފMTڍ)uMh.uJkZ":-ĬYsA,!GnuPG RSA  8!Uqˆz _F     MF $cA{ S@1>X $J5PjKZQNrG ITAc-q5 9]m*#ѩRayGg r5Vfn:``Wa>k/<ܖ۬t9t:Ā\hx=9/u+_W bT[xl(n`> D;DGA=Qhʥ)W[t?{: ǺHܱ0TFGt߇˼NE0$sji*=1>g%*L*[j[` )M0S Z &IN#Wbxc?KUTUkFzU75nH%w:FTi7'V#+f@jtZ/*hq7nQz.bѣ3j?°D麔n VH~>υ+޳1l !Uqˆz _W    !.Q惩Ʃ1:IB_W :IBg qۻC0{q]R4hw:S{e6BFLl"D(L0<š _d@gFF;jMpx(mXJ0iM v<S߰c h1:3}Н<nIk)d@M%HBtei풅f+gf1ӆz|B9:JټޖA&w%K>-hѦ3=2oKYAH{-R-,k"m2t˃W+%E߼S\JsU퇰lj}Z"OL+GQ9KB"K8'ndݑ)LHQJN ObeYmiuw|!ȴ߽A&H>_ ihAY^KF΍1Ȍf0d.j?0/)JP#{BWqLn|hP9=50\K(Ƿ &!Q҂t`CAӂr?F2=)&ސOy'$] Y=AcC6lItlCV,L}MxXi^%%qByc+'%˦/TIV]V;,,~5["HM\az"|c]knJ3`{+|7ÿURl&5Zr09 a`sm:wO,D ĉ/x#$3HHNJ; e"C>#(aƝ:8":ߥ !Uqˆz _  0S Nگ;7F˭qt9N8Ox9 sAx.=Y#tm.JvzB0ŭN.XP8=a t c+X-(pS Q/NlXim֧I)6 VHbbsX;⑀z9,N} '/ŋTT{mKȞj2CDD#LDàYtK&#SIh.nr p DBQBcNVSQ/)GDSEq,H&4{r$IF3zC*= $)k eoͶO9#^0)i_E2ݨt ¶g{4sequoia-keyring-linter-0.5.0/tests/data/multiple-passwords-priv.pgp010064400017500001750000000124311376713201600237320ustar 00000000000000_ށ*[g':в˱[g-n0^aC>\ z1hNj} Tv $98i[ZWrRR!dRBJDY_X ?ȠEճ 9-_br|QZI2mWiT%Oi JzLҲ95eIsH.fXP`˙nީoG/D/SUu0f 3Ӄpmf8mcq`Ԁ>5{\FRNĊԽIl3YA>㯣kr0/{@TBGxzAO/OerTo?9,Qۈ䔸>8$s^`t;,?:`qlVYa6HEl= ܒM `i_3ڶT&8`9f/`_]ӂ.h_536W߉'h =B8BFy_[@\mǰUd;VGQrr%Dt=5 :yfH@〰 9XSB\eQDq,)o@$B5Jc\vJ$-vE2bT뵴3Multiple Passwords 8"_   0KU$ҍgdC/%K*':͝O{8 O(gahL0Ӌ[~zŀߜ_;M6R~3Nn}sg8Y0C\\UU}+FacNw".Woqb R"n D;\t$$EROT0 >mP,zOGNb^yise >Kb'lCTzJ#ddɩ5}*)@&2064_3C>6]U@F J{3ϹZVqJP3} L~02 VSN[xO/u=.͚p/Gh`8\`X75\$!qs4˻ω#4+ sf*9בDKH;6|8nF1QW O!+}ۄȎQ8^CI0L'ԩfQ>\YSXFޡǑY~f8mcq`UP@]^6Cy(BO}8:ְ Θz!H/O)dZ8)$UVNVm9`c@<7z3 a w:.Z>\臨]Gk7{!!\ֵYHŧ@/QuU"0*험ƺK\?1u_iAZkA: otiZ7YwӮ=Ml4|BucyKrl䓴lyA-G`ޱ1X+}Ew\i1[;H c ) _ 0KH^:FioI^^ eouz#& -įs{Pv_9ހ,iq!M8g0oʨÒr>tOT[9sh *Xpd6%Hr\??F?z˿DW55UoJ(~vaYAwB۳OP0aFa!03D 3Bn$Q#) VGTN{z* xa?7h򐤁r_ us96V {X*xlED%?1Zq,pIHpۍ,nLk*$6o |8˕֒"$,XD#g sSX`h'iOf6YoOtAqwGVe˯?ſD)P:Ȋ{G[9:GwyFSڞ]lN:F2i3_68Czbt=h22 MjCU>x}[bڤ I W`xŪRoK^.g7d-hcጹ%e5~:%B+|U jзl¢[5E Woҡxw+ vbݰGbHTOZ4pTLNJ:ˇŦg|G=.]t.:ea4:dFW(ZfZsS]]%*!"!7-q8 Mg蓴+?T5Nm3kZ ZGh6N(3j [Py5$;{B4|.𒭕98co!0ܵK]o106+e-ܲB>Q FuR^/J.t!\H _ 0KEh r†3M.h nPpetfq[Dq!ɾmȗF{.\aZ By%٤L1eFc?ou{#T}ͻpۭ??5ɹya|!l^vӬޞ6ha>{TS=0[;ڰ0wb嬕\\LMe)i27Rb`X;3kJtQEk9A:sJ CPמy olf`dkm746Bp~ ]]Ks,fY Ifhf𹄧S* k{Jdp#SxjAL-K4%_el2rF(HHu;(/,-p[f<|crn 7g4`G!p;i,Hȱg9}sȏO iy ̾t5ه]b9Kj/1'iacg<_'xLR=jqN>8ՄvrET)4I#r,!wVC^ KK]=dhٵPl޷z҄ MD]V^_D 8j.G?xB_:ŅL> _9) 0K] _9 RNx& ,W_&u SzAy%GDi)2utu$\0~eY(T *..msĒ[MЛm8m  PTy4Ü_t];r0b>QMnގ7V="H 0 >}{|'7Mt8p: 2C`vCzZ-sJ5kU)̍E"2sequoia-keyring-linter-0.5.0/tests/data/multiple-passwords-pub.pgp010064400017500001750000000050651376713201600235450ustar 00000000000000 _ށ*[g':в˱[g-n0^aC>\ z1hNj} Tv $98i[ZWrRR!dRBJDY_X ?ȠEճ 9-_br|QZI2mWiT%Oi JzLҲ95eIsH.fXP`˙nީoG/D/SUu0f 3Ӄpm3Multiple Passwords 8"_   0KU$ҍgdC/%K*':͝O{8 O(gahL0Ӌ[~zŀߜ_;M6R~3Nn}sg8Y0C\\UU}+FacNw".Woqb R"n D;\t$$EROT0 >mP,zOGNb^yise >Kb'lCTzJ#ddɩ5}*)@&2064 _3C>6]U@F J{3ϹZVqJP3} L~02 VSN[xO/u=.͚p/Gh`8\`X75\$!qs4˻ω#4+ sf*9בDKH;6|8nF1QW O!+}ۄȎQ8^CI0L'ԩfQ>\YSXFޡǑY~ _ 0KH^:FioI^^ eouz#& -įs{Pv_9ހ,iq!M8g0oʨÒr>tOT[9sh *Xpd6%Hr\??F?z˿DW55UoJ(~vaYAwB۳OP0aFa!03D 3Bn$Q#) VGTN{z* xa?7h򐤁r _ us96V {X*xlED%?1Zq,pIHpۍ,nLk*$6o |8˕֒"$,XD#g sSX`h'iOf6YoOtAqwGVe˯?ſD)P:Ȋ{G[9:GwyFSڞ]lN:F2i3_68Czbt=h22 MjCU>x}[bڤ _ 0KEh r†3M.h nPpetfq[Dq!ɾmȗF{.\aZ By%٤L1eFc?ou{#T}ͻpۭ??5ɹya|!l^vӬޞ6ha>{T _9) 0K] _9 RNx& ,W_&u SzAy%GDi)2utu$\0~eY(T *..msĒ[MЛm8m  PTy4Ü_t];r0b>QMnގ7V="H 0 >}{|'7Mt8p: 2C`vCzZ-sJ5kU)̍E"2sequoia-keyring-linter-0.5.0/tests/data/no-backsig-priv.pgp010064400017500001750000000071431376713201600220750ustar 00000000000000X] pOB Lˡ/o\4m=r~whǎ^q7Nq[m0 A88oܵxO鬍T7֓+7s[cm!|QBi%7CuvP W/i- ?j*`ɡ%tO-AhƱ*[kq ^pw_7):.]iYn7^Kcp&`3-JiY,Y"K"S/+qSNe/nyU$(..k{s'"ǜgt_~Y =_zyA>F^R&ڈ9FZSHe뗖L:wD|hV~`ֈ0+l U!@k|0kt +!}= jl" rb_TaMdpeˏx¦us cޑզOp+d%c0 2[$(_f`H7aneFmCg ٜG~Z}f%H2YI ,80r&E pNL3M 0,a]TKeRMR6_nl>Or蜶ᒸ#"@0rwcD'5@dn'l5xVzE.n gs\-UB[%⣺z2)"0HƲTq ~`﹅CK &*:(TUO~ЏH ` mԸg?mD'2̦c\A:}dh+TW`4f搚ȅ. -k.罸>S]qXl?$Tj{XY(Yx(ef3u~ hw\CT S)c uDE)\=Z{]D`qfmz֙aNeڝ<éN犙'U ֎B#3zyͲ#!iflV̇MNDZ\~Ke])Zj;ڢ!Bob Babbage  8   !Ѧn#ɘx*^s0] *^s0ol T=ѮÝ_aTHg\/ƿ.;lYdJN4{Ԡ(ZP<wT5ze* 3The]'wÈ~=532oId#&FX] 0\lc+]_[4 Nͤt`cуmGYlI{ B 9 ]Ɗt!:巡az7sB4vH."`>S;k: 3W?Ѡ)Mg1uC뼋ь2Z~j*X5-`?V7f"AA'[o^ٹQ?iPZnU{֖ܱF<-uDX#gsZ,TARyhI]fbiB.gMOM~xOk<&'GP*'MzGm\+|>M=$5{19Qı!\31 `4J8u3[ހٍ踀]G ЭI{)Io"x]#J-rhW%B:f6$a8W7I[ϵGY;7aM$i>;MGmps˹OT-cщJ [svExwGeK, AFlSne);+x<Yr›P5,X[34hfm(G釲ߺ|A(Ӂ ԞGhzWNt;M@.ࠨ9B)f uQ@,>͆@v>'raO}sYlV=Ԋ7"A[Hks/JrP1#)r0NitIܕ JV 5Rcߩ,Au-g ;|BEk6TCi#\\5)vtsoexecϢ{˧4I/ɀce/"}i- MZ) ucbl_Z,B-?Hӌt?̊ҹ|yٲ3dߘ҉`.O)c{ۿeFY5, n-%(m,E.NUc]&״o1&&ɕIny%ϳ']4 fJ o|2ٹ Ncנ*H{Wi?&\K`pϕR1,i}D#Opme:]Wé 9RBmaq\4K| eJւ&IqklK=n_?H^? a-^^3M^LcJtP _aYs'kNl6'X=gCoE#f|>O!y۬wE@Clq j *^! *^s0!Ѧn#ɘx*^s0! qQ|UYhX%m/"[S0Cyqh&;*/B͛R[-NH+t&HLexZ ɥ8⭪ a wx콽YqNȴȥnz=-*dNm8{Ufv噂)Q A *wvcc@}ҭ%k:JPN Lfbur^L;!@!YD'u`zC 䡵ƔHZ l\#8Bb%p]p:Upڳ8ջhNs5PBu s/vK=;e9yFx4-őgB4 7M~bsequoia-keyring-linter-0.5.0/tests/data/no-backsig-pub.pgp010064400017500001750000000032771376713201600217070ustar 00000000000000] pOB Lˡ/o\4m=r~whǎ^q7Nq[m0 A88oܵxO鬍T7֓+7s[cm!|QBi%7CuvP W/i- ?j*`ɡ%tO-AhƱ*[kq ^pw_7):.]iYn7^Kcp&`3-JiY,Y"K"S/+qSNe/nyU$(..k{s'"ǜgt_~Y =_zyA>F^R&ڈ9FZSHe뗖L:wD|hV~`ֈ0+l U!@k|0kt +!}=!Bob Babbage  4^! *^s0 !Ѧn#ɘx*^s0@ "'_] /*56pfAY=\ aTKmcWtw${5xڥLyY A%hKz{mJ+M zI uml#y@eF>,񡤲jzYG_~7} &ᣜ{bUt9B*}*_qHi"o1!eOPʤqHև&3UkBB]rU]u^Qeͳ'bcN nߝTUu"YSO_ʖHo P6޷#CGZ<-E6$ݸg{gaS;k: 3W?Ѡ)Mg1uC뼋ь2Z~j*X5-`?V7f"AA'[o^ٹQ?iPZnU{֖ܱF<-uDX#gsZ,TARyhI]fbiB.gMOM~xOk<&'GP*'MzGm\+|>M=$5{19Qı!\31 *^! *^s0!Ѧn#ɘx*^s0! qQ|UYhX%m/"[S0Cyqh&;*/B͛R[-NH+t&HLexZ ɥ8⭪ a wx콽YqNȴȥnz=-*dNm8{Ufv噂)Q A *wvcc@}ҭ%k:JPN Lfbur^L;!@!YD'u`zC 䡵ƔHZ l\#8Bb%p]p:Upڳ8ջhNs5PBu s/vK=;e9yFx4-őgB4 7M~bsequoia-keyring-linter-0.5.0/tests/data/only-md5-priv.pgp010064400017500001750000000047001376713201600215200ustar 00000000000000_14#@vهAc8VK6ȷn*jdNeodi+ ؽ.Hz@6-}4s&IFA>C.ݣ4T N .l:9g(NEEI<8 o@E-:ȟ0&QYZ8}?Vxkޠ5}\R~y@[TW +c^T*WWIfVADrtrg QP'%-wĴ$nYmk@.m=̓IHLWvAJ,W;nFS?L*M]!;+Ӳ#TWC49̸l[3TMPma4\)@iXU(l/kd Mk$a/'t_ }M\NONN[X#E"& Pvsj*2 >}D9JPP s|%me".6ѳc.pdL x}(CmN:'4f3ث,H]dm8-$"d8GB/ {Vg{[,m=ix%g_ֳ^Ff-2^;iqeřhyH$]fL0n\$ӝƦL SZ<_/s13"qԭyekYs*(32+MD5 All Around 8"_   {SRé\YQ tayi  {H x _TQCgIZÉE H~CBȺ:K҄MNBaWY7%, 35M={'n[a$RٲGGWJLq_#pHۛ;N^x<_Vp0. }CCu)2&)6Hm\:)~'yIƐ Įf\ʬ;eѿZ)K"oN;V/_H;eq|WfҲЎvˌ[|YCxstar y9[# z*, W"hpQtbIeC٢c(J. x42хXWZ_%6ZtBX-O`Eeadhs)_ÅI itcϪ_$)7E?$x&D} uo w 6叫;.[ko7S ;C7KL/6 _ {SRߴ)75IQa ɥ,7>)^bG',' $b >6)F e4D2-:𛄸m!7Y!p~51' af5~u~R^ѵKвLPgtCQٝWgpѭ=Ё1}Miut5^m{p}+:FDȓQ}jHa@J+.oɋR2\ ٞ$sequoia-keyring-linter-0.5.0/tests/data/only-md5-pub.pgp010064400017500001750000000022521376713201600213260ustar 00000000000000 _14#@vهAc8VK6ȷn*jdNeodi+ ؽ.Hz@6-}4s&IFA>C.ݣ4T N .l:9g(NEEI<8 o@E-:ȟ0&QYZ8}?Vxkޠ5}\R~y@[TW +c^T*WWIfVADrtrg QP'+MD5 All Around 8"_   {SRé\YQ tayi  {H x _TQCgIZÉE H~CBȺ:K҄MNBaWY7%, 35M={'n[a$RٲGGWJLq_#pHۛ;N^x<_Vp0. }CCu)2&)6Hm\:)~'yIƐ Įf\ʬ;eѿZ))^bG',' $b >6)F e4D2-:𛄸m!7Y!p~51' af5~u~R^ѵKвLPgtCQٝWgpѭ=Ё1}Miut5^m{p}+:FDȓQ}jHa@J+.oɋR2\ ٞ$sequoia-keyring-linter-0.5.0/tests/data/only-sha1-priv.pgp010064400017500001750000000046741376713201600217010ustar 00000000000000_y 8e.nNf2bT/ <ʆQ3m1ܛʚTNă3J%0;$0'Vod J_/킭w_UwxP~V7wT<:~A0c򩻚}pNǛeD4W@kΜGs 9JV>Ek&YύOE[2EpL3ˢFPzUPk[V*6XJ|?]YvS:U|}{N*pU@:kU5kt"@p#pCgkݱ_F?u_4Ky=P/-fWߣ5ҕX#Hf ?0Y&Ic ,:*E'SHA1 All Around 8"_   k[2(Xчx+i.^c+$~؅><~jn jz¶́EFЮnI-hwi%'w/HPa%ؓ$Xw:e $\x,?_~4}o~tNL١$ =~7AQ%UH.PSD`"eX K>80>)5-6}N hu -?51#oW-i_ٸN^s|&y1C9] hicK) _ibTI*=L]yMG Px&͘POLQS '%ܣF~6*BDR8 |bҌ]Pqˇmn'쨹]́=Gv^0I IZ`nN ;@+ǃicuu9MK?M|t#"پH{CF7 Tk39IM(7_6' ~u0 6餉%݈{&VwVKDɠQNسÐ~t7H{# uou$!K\ұ!bCR$i.*5C]}xB?Iv~_NSc?ds?,+ N-. Ssh%UَCLk00t?,)PJh~bkjD+(|'\OmJvAzpU<]&T˳T}l9؅4V$θ6g-BL֓P1[mw%ﺿ5&w^-eg8[L-!^+%y/1^~~PӶjc~1<[;xR_QSZ7M/;ՇUE4#$N-L+ T:w9{rF:Vn6w'\oN$e2U®Gh$NZdz{n 'l(X?yC _ k[2PT{Bð̎r|e^:,eCC ڈ/Nf0LY6,LZp|3o{~n8^&X/1揗ǤƲU\U ՊqQz d؋#/79!H`V 3:EDEAPƃIlG* IB Iua50 ' untS=}7 ٷdWȥk9D^~sequoia-keyring-linter-0.5.0/tests/data/only-sha1-pub.pgp010064400017500001750000000022461376713201600215000ustar 00000000000000 _y 8e.nNf2bT/ <ʆQ3m1ܛʚTNă3J%0;$0'Vod J_/킭w_UwxP~V7wT<:~A0c򩻚}pNǛeD4W@kΜGs 9JV>Ek&Y8"_   k[2(Xчx+i.^c+$~؅><~jn jz¶́EFЮnI-hwi%'w/HPa%ؓ$Xw:e $\x,?_~4}o~tNL١$ =~7AQ%UH.PSD`"eX K>80>)5-6}N hu -?51#oW-i _ٸN^s|&y1C9] hicK) _ibTI*=L]yMG Px&͘POLQS '%ܣF~6*BDR8 |bҌ]Pqˇmn'쨹]́=Gv^0I IZ`nN ;@+ǃicuu9MK?M|t#"پH{CF7 Tk39I _ k[2PT{Bð̎r|e^:,eCC ڈ/Nf0LY6,LZp|3o{~n8^&X/1揗ǤƲU\U ՊqQz d؋#/79!H`V 3:EDEAPƃIlG* IB Iua50 ' untS=}7 ٷdWȥk9D^~sequoia-keyring-linter-0.5.0/tests/data/sha1-authentication-subkey-priv.pgp010064400017500001750000000117451376713201600252340ustar 00000000000000X_Q fcGDLvG5+Q[".Éjw逘*H<}Gn <вx#fu%[<.(+i"amJQV2Fߞ+LuM ozY!U^EKsڨSV::P 4JbTun޵ĉd7TK}(1t\AILDF#󟕟>0u@rK{x_k٨WkȠ4)g^L!Ucsbu9;F|M@p9TW7nnkQ*xTJ.2~d9jzk޷4bhx!_+?t,JC d*$$L/$aMrJpMeH] [:wcTkV SDEpZaǗ.+, x|sW4qaf/pzcM7ȭ0 ~ɻ(;P|O ~g,R:5F?6myroFvb_Laoٺf!DrFRX@wG6 H 9jȳ$%p¶[P ցK=4i?٨?fYߒXVI@gPåilz;[(⻿C) m叟X lG =%n:9hM`@zg_|HhZ=t|8aCSHA1 Authentication Subkey >!KoF,T_i?Fi _Q g    Fi D CהEY"!n_XVlmUUrXxyr, Zu[Avm! uZ.{xҋiwzt$4u#? hm+kr2' "רgZ2<=3&autp9R5m vkU"BWiLしִ\ݳ10t' ,l>,IdB4Ί<(wf=xfRj뀒3r遅:nnK"b^. H*^}t*=zFtVYS@˙Jb{qDh8Wf( b-]R/Yq+"Dt61:-ǛX_Q x.jm\`;IxVE,=%oC5u] ̮t+k^,0fMW(d6[K]RyQC \'Y4٧WiQ^VO(욧4Uu+}4~F 8/:\loP (2mRӑJ@3Cyo-*iGqh(,T.THN@Yj<Ds=̛P!΄w &Wz-v*nI^% V/ .n|fHpe\_7z6?>/ tn6cӆ)K~[Re۫W/9 p3:if;#R ~ $Rwͽ!Ba+-t9bN8a*荌 F<<߶ MIcUr Lsq::9w]0{N-]ec.ԫTOs:ͫqW6Zs heV9Z>hVl 4 aqq?n`(1“f|k%|e@پ)ݞ*.Z`~**K: @̑V~_X!])Sۣ(œԟkȬk`;,sjڻrjgDzorISѼ!=Rx)9>T]`NuڄHϚjA }aƚ5h ,x +4+@A*mDl\G:p5 A}B\zіN$r)؊̹#3 ջU`i$fW0O'%fD}+Ոj߁z"_Cg[Wt`D @mWc tr%aϴ2h ?~\X/<%?RjKF J#OքJ(ᔫ@a1FE7h_[InZ"N*0DҥظQ;Z5kg5jg &z:~O+_))LBZRƪf zcuPU.gC:4ŵZl&"7x-Ʋ[7ZN99w:waPy$)4R]\Z>Ma(A&fV(ukJ&:q0 y #[|LptL_?2dy66춉&!KoF,T_i?Fi _Q  g Fi D ekRLz9`ff4d \7OLoLm=e ǖr9hT㐋+0 0~7eS,WŤ媟2Ip~7B hU,9Zo`3Cq{ UFa_Z4vhţ,wl$Obg ʖ ;ǛewLY'hD 6M_ݟ#y28X0%c7#zL|3t8r1D\>z .Y>ΐ ."P?0&˪o9C_,M|RV9͐aTbD V4;v ]tk6S4aoe d__,J)~x"֘]͌z.y3$bB [[icJ-~Zd&HV ,t[a#I{?WR7]w5B yIO 6+?2 Tlǂ~T9K,%1( WILDPg\5&Dx&nrx1+,yݺʷ>)eܔ^}L2.&oS[l% Ofg *q\ewW,5a 7j7؅5{S oׇDT);jE}J)޼-;l6\4 QTE3L ϨpqvYq2n|C+6KR,V5]w9d">Ϻ2^:0_?FAHŸnvYߕ@#  ⇌+sqcPx]nxSRDkB m/k(4I:MlD9/!1> :Ur B-?2FQqr[m+)Qi"F|Mep03fݟ oKsᝫ2&q6 ijQ%ww;5 2I3*+CvծV-*6^$Ksequoia-keyring-linter-0.5.0/tests/data/sha1-authentication-subkey-pub.pgp010064400017500001750000000047041376713201600250370ustar 00000000000000_Q fcGDLvG5+Q[".Éjw逘*H<>!KoF,T_i?Fi _Q g    Fi D CהEY"!n_XVlmUUrXxyr, Zu[Avm! uZ.{xҋiwzt$4u#? hm+kr2' "רgZ2<=3&autp9R5m vkU"BWiLしִ\ݳ10t' ,l>,IdB4Ί<(wf=xfRj뀒3r遅:nnK"b^. H*^}t*=zFtVYS@˙Jb{qDh8Wf( b-]R/Yq+"Dt61:-Ǜ_Q x.jm\`;IxVE,=%oC5u] ̮t+k^,0fMW(d6[K]RyQC \'Y4٧WiQ^VO(욧4Uu+}4~F 8/:\loP (2mRӑJ@3Cyo-*iGqh(,T.THN@Yj<Ds=̛P!΄w &Wz-v*nI^% V/ .n|fHpe\_7z6?>/ tn6cӆ)K~[Re۫W/9 p3:if;#R ~&!KoF,T_i?Fi _Q  g Fi D ekRLz9`ff4d \7OLoLm=e ǖr9hT㐋+0 0~7eS,WŤ媟2Ip~7B hU,9Zo`3Cq{ UFa_Z4vhţ,wl$Obg ʖ ;ǛewLY'hD 6M_ݟ#y28X0%c7#zL|3t8r1D\>z .Y>ΐ ."P?0&˪o9C_,M|RV9͐aTbD V4;v ]tk6S4aoe d_ _,J)~x"֘]͌z.y3$bB [[icJ-~Zd&HV ,t[a#I{?WR7]w5B yIO 6+?2 Tlǂ~T9K,%1( WILDPg\5&Dx&nrx1+,yݺʷ>)eܔ^}L2.&oS[l% Ofg *q\ewW,5a 7j7؅5{ !KoF,T_i?Fi _, Fi  ejF_Kv_Sr}$bGԗPg7v!LJ~p  cXń=EqÊ Wg:YKBVƶ}_a֐O;I(E~e$wԮ5R^Y=:)8}!0B /9Aj*(,Q`:x %TL-DB yP'w"ց!58mWo 혟#wD[bLZ-K 'D$ -ԴtB]2 d?>ijQ%ww;5 2I3*+CvծV-*6^$Ksequoia-keyring-linter-0.5.0/tests/data/sha1-backsig-signing-subkey-priv.pgp010064400017500001750000000077031376713201600252530ustar 00000000000000_Sn WGyzE+N駍H$~W\4#C1vòMY.pbͱy 7&rʼP_gG\gSY CtB*xAŊLtZclr|OH6.Y2ۮ}͒NTC׷}6`,2&5u_k#͜qA.ۗ4__TjtXamsxVxޡվȑ0lipli6 рz0JHاEܢp ع"7sgn|XRCCJʁ+z3jY;bBgD6[(B2YԽefڎGO3ѸB=cE QO\T %(Eŏjqv uE ۆӾEX~1`MىHz'65F@鈵 4@>nt_r`Et<'Z-5TJa&P3%)FxM}ba^ GknAI4 Ӟ3&SSoyIA-s1D:HG2Zo_PWLx߅&ρxq qNj-\dfy  !o.[e[]YP0݌gS8Rgev:E$tv2.3,on`w$X˰FH ?E5SHA1 Signing Subkey 8"_S   z熳 ҃ùu\S<]}(NA ICsc6[\q%.Hq=9)ٓ٩.ڡ]qTˆHȟ|hLScy>+ & la0P$Z-?z 2Qc G`jjMߌr[Ԉ}p;]Hva)>@Jبc*Y'/O&ϺaCKҸ\ݻ5Olȧ 47gOOa[}iؿ !+Jnb^-@ nsBNި㻖ZD;C~Q*t0ڥbs-i\* L9zOR B=9HVܖoqԟ }#Ye W]y1(]nƍԑ<||>Au|ҫX:S K[ WaL۞ +d4&;:EO9PmbRfN !,Hn8F}#.$G0^,]F5baO^<ɰl7h<{8QGp9 UKU.)KN+#M3WDG*~ ]㕿bC1Og:9kmE>> o<ϭF`qZVӚK,_aXf+J$Xad[J˶:W@xPNp< '!.9D aO nߕ. +m9h,'ZeiU.Qj8 tP{Aj.٥8޸ǞW=E _S z熿5Y!%l`9!:^JrrSrI{ m%+yUra0E ĕc58>LQF7#ܜ-:c ZDX_r8L #bOJۙ^B&ѲPMoqi.Дx7L(} -pN<jX:2k~Nz.o8Q #/8Zݲ ֛Cޛu*ƪ)ulўUV b4#'_fi@H@E/P1Q,*v$O X6EFSC fHı 6e#|nW|g3a-TͺTdlD:q+$agqye.D.(7[ʟd'yrpMXu-9]Fa{I{ .JH' k==bcVYƿpN|4*m0LO,%f"n7o}aBޕqw1 xi, TOfX.Ҽd} ;r6äe`|9ۇ5r{jƗ,i!k 'LkV<6"hf4>~/~FKAM8іt/JE#Y@*vpҎ5_FᗄӊB./Ѱ-NrK~%M 'wҬnuB$s: mTw]nI#p_ϫ5gtM*)sem;{xVC|~Ž"-YBOJ%|a M&_C-%\_+ <LKcDxpyJ0--~J\dtmřPΛl^"WmZCA#L[M"ۧh1U#-,]1Y7OV.^rb2%|#s1-;I ߬O- a'N[W8s^͸n{ shd&8ϲy&p;3Xb.OZh`tKxv9d@ٞP5I*W"}.L4BxUL l+Fޮlżɪᆠ2kP*VN>[ &! ȁ@%z_ <&p)] _f _˔~ulʖ"Y=R &7mJ d*їa]-k-oVQ"W5%4n\9x_ߛyqˉIv3 E2$r_}8Pn[?=I5S/ܰ DB/Zo>Zۻ7A'ϐ b@<hAj$j}.uغLf-vTE.lY{'˝A\ODcd` z熙+vq{HiY4PG`׳G&3,q((6'&eL`a\,DQR$98.yVՉA'±) PZffۙ":u^0~sQZ78m;.:9>9.Y`Gq*^\cP Si=xt߿DRB޽r 3n)A,R7̘b:LM3ۗisequoia-keyring-linter-0.5.0/tests/data/sha1-backsig-signing-subkey-pub.pgp010064400017500001750000000040421376713201600250520ustar 00000000000000 _Sn WGyzE+N駍H$~W\4#C1vòMY.pbͱy 7&rʼP_gG\gSY CtB*xAŊLtZclr|OH6.Y2ۮ}͒NTC׷}6`,2&5u_k#͜qA.ۗ4__TjtXamsxVxޡվȑ0lipli6 рz0JHا5SHA1 Signing Subkey 8"_S   z熳 ҃ùu\S<]}(NA ICsc6[\q%.Hq=9)ٓ٩.ڡ]qTˆHȟ|hLScy>+ & la0P$Z-?z 2Qc G`jjMߌr[Ԉ}p;]Hva)>@Jبc*Y'/O&ϺaC _S z熿5Y!%l`9!:^JrrSrI{ m%+yUra0E ĕc58>LQF7#ܜ-:c ZDX_r8L #bOJۙ^B&ѲPMoqi.Дx7L(} -pN<jX:2k~Nz.o8Q #/8Zݲ ֛Cޛu*ƪ)ulўUV b4#' _fi@H@E/P1Q,*v$O X6EFSC fHı 6e#|nW|g3a-TͺTdlD:q+$agqye.D.(7[ʟd'yrpMXu-9]Fa{I{ .JH' k==bcVYƿpN|4*m0LO,%f"n7o}aBޕqw1 xi[ &! ȁ@%z_ <&p)] _f _˔~ulʖ"Y=R &7mJ d*їa]-k-oVQ"W5%4n\9x_ߛyqˉIv3 E2$r_}8Pn[?=I5S/ܰ DB/Zo>Zۻ7A'ϐ b@<hAj$j}.uغLf-vTE.lY{'˝A\ODcd` z熙+vq{HiY4PG`׳G&3,q((6'&eL`a\,DQR$98.yVՉA'±) PZffۙ":u^0~sQZ78m;.:9>9.Y`Gq*^\cP Si=xt߿DRB޽r 3n)A,R7̘b:LM3ۗisequoia-keyring-linter-0.5.0/tests/data/sha1-cert-sha1-revocation-priv.pgp010064400017500001750000000054021376713201600246440ustar 00000000000000_;)W='L߆sgv 8w:D7ްsr>_N#U'GR_Db4B2lI uRg%={NWۅkq" l,zXtn L{l#tg!2t,R>r‚F. + i ]) pYϮ^?l'LEdjh\;0Z~UeRߐ;X,}8BYCm};=Ųr%?^_n,ۋ.HLP8Yh5RD0A߱duT* 0FMȔo}&Ji;G_LvVl,"vnqۍ!#La0 z RN 2c,q5Ԟ |REf(TGh6kj|&LWc)8WAƼ+@%6to;e.T~Imsa>SRqL"ܩ=85vB׉( _;G Moved on. {[V;6PydT|d@%,F?KIEsZZħ5/Wl`7[C*DjUpv1pMQe^ڏC '9W/+q#-_0>I8߈q(TҀ0dϴS1/(C'3V|8"_;   {[V(?vjSuDZn'`*c6^jĊǴXCnQ6?ܻƻ 6-~c8grS}8:-I/Ce|^eE5()V9%4T%s]`(UdM\2+Wy;d1Y3S}Yicz0g*9V낹7Njpn&z!(Y[I&fg{;Bu%8-`3/)|LBͽ}ZOc?O4ʢO~YmdgQ}lo_#BjN,O\h/OkWN-`0gM;+fuު,Pi'F)Cc wQ/f[e{knc;mdMaWD0i'/!ZT0#D:mhfrV)o되}lYu6M_gD?L) WW5/10$uIY-YI=T ItM숱]j [6wZ'] >'}%Rg%\!)/_>tdyRc.)Y^au~3orGՏ$3۷$H,M .na W][\Lz/q.0Zy&07i7O!Y`y)TK.1X&dPFCyPp!4@:E%I/KK>Qry>s{cJr<9\_T 2eLdF~w4;/0F9B _; {[Vv .sliEq Q^@`1)ĨNv/.8?$Ept~Wg?\䱼!"]dpSԾ*uIf Ļ,na38aáj,yJ&Fƹojo{%o5#HRlJ {7휜b]ΣL߻wkCPz66²YܦRŶz4W;ݯ?@}W~: !>LCsequoia-keyring-linter-0.5.0/tests/data/sha1-cert-sha1-revocation-pub.pgp010064400017500001750000000027541376713201600244610ustar 00000000000000 _;)W='L߆sgv 8w:D7ްsr>_N#U'GR_Db4B2lI uRg%={NWۅkq" l,z( _;G Moved on. {[V;6PydT|d@%,F?KIEsZZħ5/Wl`7[C*DjUpv1pMQe^ڏC '9W/+q#-_0>I8߈q(TҀ0dϴS1/(C'3V|8"_;   {[V(?vjSuDZn'`*c6^jĊǴXCnQ6?ܻƻ 6-~c8grS}8:-I/Ce|^eE5()V9%4T%s]`(UdM\2+Wy;d1Y3S}Yicz0g*9V낹7Njpn&z!(Y[I&fg{;Bu%8-`3/)|LBͽ}Z _; {[Vv .sliEq Q^@`1)ĨNv/.8?$Ept~Wg?\䱼!"]dpSԾ*uIf Ļ,na38aáj,yJ&Fƹojo{%o5#HRlJ {7휜b]ΣL߻wkCPz66²YܦRŶz4W;ݯ?@}W~: !>LCsequoia-keyring-linter-0.5.0/tests/data/sha1-cert-sha256-revocation-priv.pgp010064400017500001750000000054551376713201600250300ustar 00000000000000_l'˕BZ,j!z$B1J^U sq L#pz'@o+;3zM?"05&EQ<]NiJҬ7OnZPXd'ęڧ3̢'&ܽexϛTEN.=\$%ݾi aE7g9J1y 7hdcʲלVd*5 bl* Hw8&>:.N_ׅXkH]&džݳ3 Ɓ/O|}`E{=q"(dLjtnQݼeQ- 1Ⲓ/> X3Orl7_D]9&ff1T޶8m{h݁ ZXfH3݈ޫX]!J=\)&CQK}N9M;dUJAPr<*C&D8> W@GHAg@˷-hjXmc`pRC?h2iDr"6)Y-ImPfrۑO@&&wB{{U8Z;cOvs8%p*nʵ ce%ԎQ]3*GvA +_la$Left example.org for beispiel.org. 6ss[ϺAWe= {5#nꫮz\=4\|0XOm6@(A>oV WĂ/KsqҨ<1O([+4а_?W" {=pEޓoh ^UA}UU3[QA:7ZkXwЄ9/|eoAKɎP2R{o\R~w^f T7lٴ|$ @Z?/c[4ŗL TSHA1 Certificate, SHA256 Revocation 8"_l'   6ss[ϺKs#p[+uð \˄!=j =QBmMUϦݷ<ۗ DPJGDuAh5GpUQ*h YDW@gm?|{Lr&?  onC/<& AļTF3*$83Κ>R}0Bɟ)}%$ML,1͑$ 0QDHKTI Rc:޵v;$:CYbK(M2?q '#q<[3(CHo#rTzo4[!UTJ{tQ-CfM cפ7XT$iϔ5 ̙bPN|^jvp?湸L$=7?/Gˤ R$En iv}.ЂAn!mjhi_;xԧ'^lB1<NFet2.덕Q&ѐ%yw`BzR 댣Ξ|5 6d~K4(ʟ|Nx^zCJGHi~Hj'A%>+]u<6'ݶ (5=iK給)k(:ZΦ&pTL̳<:Tl<\ÙQINs?Smi b䜋|<@D!xSp"Ya{wٚ:C Wwk 5VsY4voЉ0_?'΋/'E3sr\dvo *R?hEyx9;3s(\`tqiɡfǧ5iJ3yΡ2 Y4֖>X\m~2CCNG ?{] p:RVi H[NsФEP͆?{jgo,3L _l' 6ss[ϺkH)'*N(R7Mjl#q)#/y6dz1'}&a+;3zM?"05&EQA +_la$Left example.org for beispiel.org. 6ss[ϺAWe= {5#nꫮz\=4\|0XOm6@(A>oV WĂ/KsqҨ<1O([+4а_?W" {=pEޓoh ^UA}UU3[QA:7ZkXwЄ9/|eoAKɎP2R{o\R~w^f T7lٴ|$ @Z?/c[4ŗL TSHA1 Certificate, SHA256 Revocation 8"_l'   6ss[ϺKs#p[+uð \˄!=j =QBmMUϦݷ<ۗ DPJGDuAh5GpUQ*h YDW@gm?|{Lr&?  onC/<& AļTF3*$83Κ>R}0Bɟ)}%$ML,1͑$ 0QDHKTI Rc:޵v;$:CYbK(M2?q '#q<[3(CHo#rTzo4[!UTJ{tQ-CfM _l' 6ss[ϺkH)'*N(R7Mjl#q)#/y6dz1'}&a4Be[>pe=UG%.Ks%Խ_|N ;L^fTsh ep0PX'ZU=kOY6 LZ.-dm '{B!sQі`0zS($Zu-']*WKI'p) A&*Æ Zp<3`X.)e*w_,F3?8mzR3hj$Cd`GDZ34Z΁k}+4aR˭քu"FC1c_~V)b(Ǒ7I巁TIXdƄc}Z\:\X7ʲݙn3cbk?lЅ|o$->"+k-uܟ_iք${UD #e.b|B\y df c%>ȔZ B0gRZ3|% pס`vS1/L6 U|p@_[rOçրt<{DЄH >eW975UTS,GnJK^TVSACRhjbQ[xXpAe ԅ59rWHU,B: fju"-$e4b>6DvYb@,3;SHA1 Encryption Subkey 8"_   2h*S:ȳoaS5c7ߩ>M)C7p*rX5%GmyT,USG<>hEjtex"^޸S;|Ie!VnW'|#@5vIƵEYNk=X (dI-4t~xsX>X߮L\fS;с)|VD=Rdy*Q',,fsV·`fҠ2đF̢\o_85wSUj?ΪX>9 w6-^f柔;qt7)+TjuÞ,!LZ]^>S\j[}Y;QtfON[7ӈ ۦCZNA#R_~lORsp2:` hCTv#2s~^KS "8tSc"S ,,nTt<d%K/. *Zw6g S$l]n1@VJTr5<|Ň_(RSiI (4[/2 rC›V6#4>j]zHՁ1)"^Zs}a$ )ρizjWh9Hbxr=~NA wj`h^J3YB7R7qyFF!봊uy& DA/Qbx  ʿԱYlwz * |-*PLf[n8m[h^[=ߎ/Dk=Ւ&GܳںYri[=uL>lcOd+ qѓr eLF1At-T.9w9*'O%S9_#e;겪j ,( 4%k&޿.1_=V(fF]Mf@c@A.ĖlVFo )y[͞{wG4tr1 '|>zQN؉.dP,*SظG0mm0g\nIzo,@VEVe:aXo{.Fܸ^9% _ 2h* O |@wDם_F JܢTЯt?=o3^=Ӣ#).@mU_,=k#ܿbx"aQ@#Qmt Lb9+c|(N*0`v|B_f+:z!9QKT*j](<,O$xaӫd)'`">صk)=9NfU[SL l伴ߝJGeBeW)iY!oGX5BcZ6aI񕹱0mq'O)q&*"_ٺ~mzC14tx~mvkSF=2OZ"6wMutL*(G)#!8͛0Պ_!XL7:YK(epQMry&XD*QA' %\4GC@#zV.%ȇJiuq)}UrY| 0;D  郵+3G=jK_eܩZP? \X aȫ5$Jƀmsgg ⚻0;ּ쀙vdWQڮ$^>Xo >%, y|vU:zDT )wha"kYڇW95l.I>{ 0 Z ^Aejt$oQ7dWsrGZtOmeQ7g%faNJ*J.c6 !(v=,@cgu J8`X_O5e_ZKބ Rz/1+WIѪ}7!ҍ2AbV[H7{NEڡ2^yuS~jRvhm'>lGt).G o~!92O1?ް#b n988 _F 2h*CT9Jb V+Vp\T[']DQ(6.K.&v»&I SjaNU>k 4pxjKI>rQ,W }2&a7yСeP*%m}5M%2%{CyT ̑h_lP qA Ƴ%C鍎 p_xnA94|ǯVf|ݯ[?=(T8eYsequoia-keyring-linter-0.5.0/tests/data/sha1-encryption-subkey-pub.pgp010064400017500001750000000033541376713201600242120ustar 00000000000000 _>4Be[>pe=UG%.Ks%Խ_|N ;L^fTsh ep0PX'ZU=kOY6 LZ.-dm '{8"_   2h*S:ȳoaS5c7ߩ>M)C7p*rX5%GmyT,USG<>hEjtex"^޸S;|Ie!VnW'|#@5vIƵEYNk=X (dI-4t~xsX>X߮L\fS;с)|VD=Rdy*Q',,fsV·`fҠ2đF̢\o _85wSUj?ΪX>9 w6-^f柔;qt7)+TjuÞ,!LZ]^>S\j[}Y;QtfON[7ӈ ۦCZNA#R_~lORsp2:` hCTv#2s~^KS "8tSc"S ,,nTt<d%K/. *Zw6g _ 2h* O |@wD׹ _F JܢTЯt?=o3^=Ӣ#).@mU_,=k#ܿbx"aQ@#Qmt Lb9+c|(N*0`v|B_f+:z!9QKT*j](<,O$xaӫd)'`">صk)=9NfU[SL l伴ߝJGeBeW)iY!oGX5BcZ6aI񕹱0mq _F 2h*CT9Jb V+Vp\T[']DQ(6.K.&v»&I SjaNU>k 4pxjKI>rQ,W }2&a7yСeP*%m}5M%2%{CyT ̑h_lP qA Ƴ%C鍎 p_xnA94|ǯVf|ݯ[?=(T8eYsequoia-keyring-linter-0.5.0/tests/data/sha1-expired-priv.pgp010064400017500001750000000047101376713201600223470ustar 00000000000000_x,~6䉢L1jnDث4f|- ;<+Vq}8\v"R>:Y*W8i/TsE?9W8[_gkNn°M.o#i\㾉-G(jU*NXYWq\iMHIߟ}j3{g^Pk<P/qpmR Z3Ƚ#2?m,4aTF'FDrHU@Qe=ڸjmZ+2,w؎<׵_KeCXr ,DX~w~8&"2;5֋KBG_s=n+xh_Ok-h SsmPatRzq$4qrOD} }0M cN ]fNJvÇ/F!G_ a|P#Cwsӗy+侠F*Q;qᴞgz:#64 6iۄޚG~-nPFWO0sG_<Py=0}J] ~`?|p::i@1vD, :xfTfs[c |acއzbk%% 9(n]h)y60^~l@ɂwO"]KM״o)%JJfl :@3ET}IVғDDWrxceC؟=[ NN6d S?wCݞ^6sNæߡ*Zv_ptPzD+d sUT[ظ{Syxy?>˴F)2X?8u<7'SHA1 Expired >(_x, Q   "}#҅WR#,|4ZYNYdas6+T8 +({^qkR`̷lDSZLh}&?:\:Tv:PTՄC_x,Ē"J:!L]IwK q l,,#>TGpMc|b$ߘ=brak~`M,9=|&kp!ogho/u|zuW){R gX>d̙]8@4{6.qeXĕʻnPb{GݮmĹNLj$MfkeiuK 41Ӓ\Nxۚ7#'I`7(8%#F cERtT敖:™+$DYKXܚ#|͸y?^ʶJz3Ρ.ݛtʸhT 'iJY쓲#VLP T!PNZ:A3omeNV2.!![qcyeT% qJ(~a;.4q|z֙nGeTr H1w'Nx& _0ۏė2ƩˀFƧ\րYFG^^֟*J%У]#OR{ʺJ@`W'tt73bԬ`ͤay[{}d4Biy89yہh/ڮQTF,(=B tϩ '0wpS9]0RvYOg iw oUR! -Yw֊dsبQ* v:e![esS;R2kln5iZ*Cp/Y-jI] M*/@Ip & f:6 Ņgs78Nq 1SԵC Ml5_?ꎋhX doU>Z%_x,  Q "}#u^>黻e`/ۇa >W}PQp0$s9UpՍ&E ]Hg%T-,PMtЫf ޜ)KG<6*%ڤ` D"UfWUЦ*.g'uӳ~7 i Tϊuolڔ+fTIc) ykU&/ 2G] LFqZ}AVi85 (H=HGe:Q2q-[;_ypsequoia-keyring-linter-0.5.0/tests/data/sha1-expired-pub.pgp010064400017500001750000000022621376713201600221550ustar 00000000000000 _x,~6䉢L1jnDث4f|- ;<+Vq}8\v"R>:Y*W8i/TsE?9W8[_gkNn°M.o#i\㾉-G(jU*NXYWq\iMHIߟ}j3{g^Pk<P/qpmR Z3Ƚ#2?m,4aTF'FDr'SHA1 Expired >(_x, Q   "}#҅WR#,|4ZYNYdas6+T8 +({^qkR`̷lDSZLh}&?:\:Tv:PTՄC _x,Ē"J:!L]IwK q l,,#>TGpMc|b$ߘ=brak~`M,9=|&kp!ogho/u|zuW){R gX>d̙]8@4{6.qeXĕʻnPb{GݮmĹNLj$MfkeiuK 41Ӓ\Nxۚ7#'I`%_x,  Q "}#u^>黻e`/ۇa >W}PQp0$s9UpՍ&E ]Hg%T-,PMtЫf ޜ)KG<6*%ڤ` D"UfWUЦ*.g'uӳ~7 i Tϊuolڔ+fTIc) ykU&/ 2G] LFqZ}AVi85 (H=HGe:Q2q-[;_ypsequoia-keyring-linter-0.5.0/tests/data/sha1-offline-subkeys-offline.pgp010064400017500001750000000053041376713201600244560ustar 00000000000000_0 AdS1Z"ڀ!*j4epsT?x~v^tgE%y.C-|^% M&@,K)θp9BsW3oE+g JXA )ǯ,6}\S{iq:иAV=ڜsH5\9:] 8>`Kփ VQp+=xjral[% Ae~r"b9kF@̈́[6+y*Mgןsg`LwCgvͳ56hN *%ln[B [dA cZhxm?k:栽MM׍\,C~PCB,gݔoob Ķi۸XnU/eEfa{j E?^Pg0d%8GiׯYZDwrO8i[G(j!'-hw#U3Ofeއ #Էf(,E1Cƾ7؋5)̖mBr@4Klo)ǘif%5-_Ԙ}Fc/EmhN;P84+ O9 rΪ)w)3v4W;`{Rҋ2m3 CDզC+ݨ6#<$kO 8ƹ@,'Ku;{`QcOz;rv5V u`7vdt@g ?٨^ҸRo2MmoƊ\|y;`3vÀܦd kJe$@J5Z;JE7SHA1 Offline Subkeys 8"_   a$ۋxQ̍L *ٻ#Ћokwq{/uZ=<õ3ԧ5 Hu>DGjG*HD'5qJa`%mȉ2\, h1Qhx| N2;%ސ (%hA g ٲ-cY8]dGρV\^l?̆}ae޽+QJA V!)-ta2{Y1lHH1 mQk'I޶WLfh(WwnMeGNUv$- _ a$^zϥ s$Ф~3J 7_td煻 (uGaPw# tvNhi9w_!rij|boKrǮ]sJ^%bO!1 gL,֢j#[c]U|Q L4}Ҟ+|辕]?_8m Ϋ_VnKݥʈ0Kw ΄`|u@'÷&_#)G747=ܣ3gZc%e94w;ś#~!"@& Xи v']+<([*ϗIiǿUtD|DIO\qnGHeGNUv$-> _) a$] _ Pɹ9rي+#c>K=70ˡpw2>G87z(,!#rZQ"qqħTW^"{@:$K˅||f˔0AA_ ~ { rMa1 ZyuTêVxvH;bj ܑiRgKPlf='^i⍸pº[IaWtSi H 65U:aGAg t}Y e`p'nuuJzD G/_Dx/s\#ECxoZs[F-I6z=|>m]y PLEP]Zќb#&k*t4.F]. GSXT6<ہ iՙ(1(y""\(Pwx_f/aId̤W劆iYV΃Vߨa) @9$%C~ <ӢOS"} rvWkpQ^w!!`u%V ÞJ1jvݢsequoia-keyring-linter-0.5.0/tests/data/sha1-offline-subkeys-priv.pgp010064400017500001750000000076501376713201600240220ustar 00000000000000_0 AdS1Z"ڀ!*j4epsT?x~v^tgE%y.C-|^% M&@,K)θp9BsW3oE+g JXA )ǯ,6}\S{iq:иAV=ڜsH5\9:] 8>`Kփ VQp+=xjral[% Ae~r"b9kF@̈́[6+y*Mgןsg`LwCgvͳ56hN *%ln[B [dA cZhxm?k:栽MM׍\,C~PCB,gݔoob Ķi۸XnU/eEfa{j E?^Pg0d%8GiׯYZDwrO8i[G(j!'-hw#U3Ofeއ #Էf(,E1Cƾ7؋5)̖mBr@4Klo)ǘif%5-_Ԙ}Fc/EmhN;P84+ O9 rΪ)w)3v4W;`{Rҋ2m3 CDզC+ݨ6#<$kO 8ƹ@,'Ku;{`QcOz;rv5V u`7vdt@g ?٨^ҸRo2MmoƊ\|y;`3vÀܦd kJe$@J5Z;JE7SHA1 Offline Subkeys 8"_   a$ۋxQ̍L *ٻ#Ћokwq{/uZ=<õ3ԧ5 Hu>DGjG*HD'5qJa`%mȉ2\, h1Qhx| N2;%ސ (%hA g ٲ-cY8]dGρV\^l?̆}ae޽+QJA V!)-ta2{Y1lHH1 mQk'I޶WLfh(WwnM#Yđ&,YBz` 8%KÑZqwDiԾp〄%dq/Bv_z*C)UvBpYoDq#ٳ;%5pshEΤ>Cپ# ?*XZ}!Rlu.7 IWJ3o*kaCiF 5~US_L4;~3#*C0D629 p#t f> uBg 4n JA)Os_=rC%A6i 厊P(nYȫh4yU2` Ra+ N+VCn<|E%GB#|^tE;{ḁt֭вh>*{aՁtR*{NkZؼ8'~W o^AcXYI"0øPKVk<& 4Y^D(WzQ FD8K;qh*v[4HNZ !GĖ/66z O-{7~&V@6[ӼrhJzW_uyVpWVQ8 kh? ^gBLKk<&G#v,57o _ a$^zϥ s$Ф~3J 7_td煻 (uGaPw# tvNhi9w_!rij|boKrǮ]sJ^%bO!1 gL,֢j#[c]U|Q L4}Ҟ+|辕]?_8m Ϋ_VnKݥʈ0Kw ΄`|u@'÷_#)G747=ܣ3gZc%e94w;ś#~!"@& Xи v']+<([*ϗIiǿUtD|DIO\qnGH;r W=Fy|)+>‘YQx2|y&m)xy-r!gr.|=ܣ\GI=>VӛEÁ3bqag,Vn%Xnف36S@ei0pWա49ɸAr, p^y˪R|ލxJ?lί,՟~as3ȥ?:m F fã2/ hAn{ 5Dn**2%WR))a|332j4VDo֬mىЪf4^v ,"񴐗q(mBgұ7PLЌnQqxhii[ Za (\;Ѿx(eG$#CFJ?+Rt dQ߂oW72ItymOloV~l1m"8&V*A0vM~-B)5׋/6c L!!cfRV|0i. _) a$] _ Pɹ9rي+#c>K=70ˡpw2>G87z(,!#rZQ"qqħTW^"{@:$K˅||f˔0AA_ ~ { rMa1 ZyuTêVxvH;bj ܑiRgKPlf='^i⍸pº[IaWtSi H 65U:aGAg t}Y e`p'nuuJzD G/_Dx/s\#ECxoZs[F-I6z=|>m]y PLEP]Zќb#&k*t4.F]. GSXT6<ہ iՙ(1(y""\(Pwx_f/aId̤W劆iYV΃Vߨa) @9$%C~ <ӢOS"} rvWkpQ^w!!`u%V ÞJ1jvݢsequoia-keyring-linter-0.5.0/tests/data/sha1-offline-subkeys-pub.pgp010064400017500001750000000040071376713201600236210ustar 00000000000000 _0 AdS1Z"ڀ!*j4epsT?x~v^tgE%y.C-|^% M&@,K)θp9BsW3oE+g JXA )ǯ,6}\S{iq:иAV=ڜsH5\9:] 8>`Kփ VQp+=xjral[% Ae~7SHA1 Offline Subkeys 8"_   a$ۋxQ̍L *ٻ#Ћokwq{/uZ=<õ3ԧ5 Hu>DGjG*HD'5qJa`%mȉ2\, h1Qhx| N2;%ސ (%hA g ٲ-cY8]dGρV\^l?̆}ae޽+QJA V!)-ta2{Y1lHH1 mQk'I޶WLfh(WwnM _ a$^zϥ s$Ф~3J 7_td煻 (uGaPw# tvNhi9w_!rij|boKrǮ]sJ^%bO!1 gL,֢j#[c]U|Q L4}Ҟ+|辕]?_8m Ϋ_VnKݥʈ0Kw ΄`|u@'÷ _#)G747=ܣ3gZc%e94w;ś#~!"@& Xи v']+<([*ϗIiǿUtD|DIO\qnGH> _) a$] _ Pɹ9rي+#c>K=70ˡpw2>G87z(,!#rZQ"qqħTW^"{@:$K˅||f˔0AA_ ~ { rMa1 ZyuTêVxvH;bj ܑiRgKPlf='^i⍸pº[IaWtSi H 65U:aGAg t}Y e`p'nuuJzD G/_Dx/s\#ECxoZs[F-I6z=|>m]y PLEP]Zќb#&k*t4.F]. GSXT6<ہ iՙ(1(y""\(Pwx_f/aId̤W劆iYV΃Vߨa) @9$%C~ <ӢOS"} rvWkpQ^w!!`u%V ÞJ1jvݢsequoia-keyring-linter-0.5.0/tests/data/sha1-signing-subkey-priv.pgp010064400017500001750000000076461376713201600236600ustar 00000000000000_Sn WGyzE+N駍H$~W\4#C1vòMY.pbͱy 7&rʼP_gG\gSY CtB*xAŊLtZclr|OH6.Y2ۮ}͒NTC׷}6`,2&5u_k#͜qA.ۗ4__TjtXamsxVxޡվȑ0lipli6 рz0JHاEܢp ع"7sgn|XRCCJʁ+z3jY;bBgD6[(B2YԽefڎGO3ѸB=cE QO\T %(Eŏjqv uE ۆӾEX~1`MىHz'65F@鈵 4@>nt_r`Et<'Z-5TJa&P3%)FxM}ba^ GknAI4 Ӟ3&SSoyIA-s1D:HG2Zo_PWLx߅&ρxq qNj-\dfy  !o.[e[]YP0݌gS8Rgev:E$tv2.3,on`w$X˰FH ?E5SHA1 Signing Subkey 8"_S   z熳 ҃ùu\S<]}(NA ICsc6[\q%.Hq=9)ٓ٩.ڡ]qTˆHȟ|hLScy>+ & la0P$Z-?z 2Qc G`jjMߌr[Ԉ}p;]Hva)>@Jبc*Y'/O&ϺaCKҸ\ݻ5Olȧ 47gOOa[}iؿ !+Jnb^-@ nsBNި㻖ZD;C~Q*t0ڥbs-i\* L9zOR B=9HVܖoqԟ }#Ye W]y1(]nƍԑ<||>Au|ҫX:S K[ WaL۞ +d4&;:EO9PmbRfN !,Hn8F}#.$G0^,]F5baO^<ɰl7h<{8QGp9 UKU.)KN+#M3WDG*~ ]㕿bC1Og:9kmE>> o<ϭF`qZVӚK,_aXf+J$Xad[J˶:W@xPNp< '!.9D aO nߕ. +m9h,'ZeiU.Qj8 tP{Aj.٥8޸ǞW=E _S z熿5Y!%l`9!:^JrrSrI{ m%+yUra0E ĕc58>LQF7#ܜ-:c ZDX_r8L #bOJۙ^B&ѲPMoqi.Дx7L(} -pN<jX:2k~Nz.o8Q #/8Zݲ ֛Cޛu*ƪ)ulўUV b4#'_fi@H@E/P1Q,*v$O X6EFSC fHı 6e#|nW|g3a-TͺTdlD:q+$agqye.D.(7[ʟd'yrpMXu-9]Fa{I{ .JH' k==bcVYƿpN|4*m0LO,%f"n7o}aBޕqw1 xi, TOfX.Ҽd} ;r6äe`|9ۇ5r{jƗ,i!k 'LkV<6"hf4>~/~FKAM8іt/JE#Y@*vpҎ5_FᗄӊB./Ѱ-NrK~%M 'wҬnuB$s: mTw]nI#p_ϫ5gtM*)sem;{xVC|~Ž"-YBOJ%|a M&_C-%\_+ <LKcDxpyJ0--~J\dtmřPΛl^"WmZCA#L[M"ۧh1U#-,]1Y7OV.^rb2%|#s1-;I ߬O- a'N[W8s^͸n{ shd&8ϲy&p;3Xb.OZh`tKxv9d@ٞP5I*W"}.L4BxUL l+Fޮlżɪᆠ2kP*VN>> _f) z] _f _˔~ulʖ"Y=R &7mJ d*їa]-k-oVQ"W5%4n\9x_ߛyqˉIv3 E2$r_}8Pn[?=I5S/ܰ DB/Zo>Zۻ7A'ϐ b@<hAj$j}.uغLf-vTE.lY{'˝A\ODcd`RVg$[:&0롱{K:y5yj]G[6g*c',IUD`NC|86BBJ)KQ E aF zha}&3WAzi_L4[d wUȐY8"_S   z熳 ҃ùu\S<]}(NA ICsc6[\q%.Hq=9)ٓ٩.ڡ]qTˆHȟ|hLScy>+ & la0P$Z-?z 2Qc G`jjMߌr[Ԉ}p;]Hva)>@Jبc*Y'/O&ϺaC _S z熿5Y!%l`9!:^JrrSrI{ m%+yUra0E ĕc58>LQF7#ܜ-:c ZDX_r8L #bOJۙ^B&ѲPMoqi.Дx7L(} -pN<jX:2k~Nz.o8Q #/8Zݲ ֛Cޛu*ƪ)ulўUV b4#' _fi@H@E/P1Q,*v$O X6EFSC fHı 6e#|nW|g3a-TͺTdlD:q+$agqye.D.(7[ʟd'yrpMXu-9]Fa{I{ .JH' k==bcVYƿpN|4*m0LO,%f"n7o}aBޕqw1 xi> _f) z] _f _˔~ulʖ"Y=R &7mJ d*їa]-k-oVQ"W5%4n\9x_ߛyqˉIv3 E2$r_}8Pn[?=I5S/ܰ DB/Zo>Zۻ7A'ϐ b@<hAj$j}.uغLf-vTE.lY{'˝A\ODcd`RVg$[:&0롱{K:y5yj]G[6g*c',IUD`NC|86BBJ)KQ E aF zha}&3WAzi_L4[d wUȐY=^-IVf63|/g$Sd% FO%g,|R2⏛5߼O2T]ĂsDcbz‘}o` Dj*U%^ A!`J#xUxЄ*%©Ng=Q]ά(7-0TfIf̋ʅ$֕B0H '}R3Jr3g V:ߞO2yWsXz8"_-   Z/qt{xL-TsYQYANtlb/1VȬ 65>{ LҾ4/ߝ?%bsVu?ڨ BsW'?eXA-:ƚo'F#'7J.p0O2"OϦ-& UZ8=!vCv b"\kxT_3糮 LX(rlCy4CvBSHA1 User ID 8"_a   Z/qdu[RMf5qȵtpЖ p|GN$^:O?H˽ :Ǘ"!,Ѣ j~m^/[^#C.TUBp%.n0~x/6G%"S 7:9#} A?ɘ8(#7 T}ш&ڛBF\Jl7M^wpE執HTg}s@`*AnsRry}Æ /}"2p0vOs֊ePg ,wu6p >ڎܛ| _fQMPIPGhvJG[t_@ShYkq넅;M|)Gf3½t􂮵«W.zܑL;d(a/1 $_$#պGyUl ㎃9 4b%9҈lL4uV~`vҎnT!ug& HHX YcbG>n& Rܛր3OkpHCQZIQ5ܝ4q {3K`ܱcų3}͛&Tے"iz]>oIӒ!ϥIKl^=( .]/`rϜp;b2ق)үM'Cg缮%ːeR#J$%!7fч Cy* 2ݧZl\xOs-[>T??[L-T7S.y]9͉ _- Z/qkgx_>E;r6ҺFQPveKD3DE3@v>ojbjYfb_sޮݷfi&Cͣjx Id?y4_n J?(c-QhJzL$f1*ϳL&^jNlq[#r۔N#eoׅG+_ p!snKֲp/Ai.aRI[)wVM~Hsequoia-keyring-linter-0.5.0/tests/data/sha1-userid-pub.pgp010064400017500001750000000027761376713201600220220ustar 00000000000000 _-XD;p`:v‭d/WFbWQc sg;虢Tڂ+(z3=^-I#SHA256 User ID 8"_-   Z/qt{xL-TsYQYANtlb/1VȬ 65>{ LҾ4/ߝ?%bsVu?ڨ BsW'?eXA-:ƚo'F#'7J.p0O2"OϦ-& UZ8=!vCv b"\kxT_3糮 LX(rlCy4CvBSHA1 User ID 8"_a   Z/qdu[RMf5qȵtpЖ p|GN$^:O?H˽ :Ǘ"!,Ѣ j~m^/[^#C.TUBp%.n0~x/6G%"S 7:9# _- Z/qkgx_>E;r6ҺFQPveKD3DE3@v>ojbjYfb_sޮݷfi&Cͣjx Id?y4_n J?(c-QhJzL$f1*ϳL&^jNlq[#r۔N#eoׅG+_ p!snKֲp/Ai.aRI[)wVM~Hsequoia-keyring-linter-0.5.0/tests/data/sha1-userid-revoked-priv.pgp010064400017500001750000000061141376713201600236370ustar 00000000000000_-XD;p`:v‭d/WFbWQc sg;虢Tڂ+(z3=^-IVf63|/g$Sd% FO%g,|R2⏛5߼O2T]ĂsDcbz‘}o` Dj*U%^ A!`J#xUxЄ*%©Ng=Q]ά(7-0TfIf̋ʅ$֕B0H '}R3Jr3g V:ߞO2yWsXz60 !c/$3Vݟ@ͫ)YwKR\/q 67[µ8"_a   Z/qdu[RMf5qȵtpЖ p|GN$^:O?H˽ :Ǘ"!,Ѣ j~m^/[^#C.TUBp%.n0~x/6G%"S8"_-   Z/qt{xL-TsYQYANtlb/1VȬ 65>{ LҾ4/ߝ?%bsVu?ڨ BsW'?eXA-:ƚo'F#'7J.p0O2"OϦ-& UZ8=!vCv b"\kxT_3糮 LX(rlCy4CvB_-Fϑ㊊}6NP÷Ӿ1=q0LJ&.꬝œRAECO=9jX["Qf%XfANMMl{*N|*Fbxp`b.P=k++l"P65sZķD3/ ]b}Q Jk*J򝶻IWLخԿW][65)ǒih)/۰Q%|g;Q:> 7:9#} A?ɘ8(#7 T}ш&ڛBF\Jl7M^wpE執HTg}s@`*AnsRry}Æ /}"2p0vOs֊ePg ,wu6p >ڎܛ| _fQMPIPGhvJG[t_@ShYkq넅;M|)Gf3½t􂮵«W.zܑL;d(a/1 $_$#պGyUl ㎃9 4b%9҈lL4uV~`vҎnT!ug& HHX YcbG>n& Rܛր3OkpHCQZIQ5ܝ4q {3K`ܱcų3}͛&Tے"iz]>oIӒ!ϥIKl^=( .]/`rϜp;b2ق)үM'Cg缮%ːeR#J$%!7fч Cy* 2ݧZl\xOs-[>T??[L-T7S.y]9͉ _- Z/qkgx_>E;r6ҺFQPveKD3DE3@v>ojbjYfb_sޮݷfi&Cͣjx Id?y4_n J?(c-QhJzL$f1*ϳL&^jNlq[#r۔N#eoׅG+_ p!snKֲp/Ai.aRI[)wVM~Hsequoia-keyring-linter-0.5.0/tests/data/sha1-userid-revoked-pub.pgp010064400017500001750000000034671376713201600234550ustar 00000000000000 _-XD;p`:v‭d/WFbWQc sg;虢Tڂ+(z3=^-ISHA1 User ID 60 !c/$3Vݟ@ͫ)YwKR\/q 67[µ8"_a   Z/qdu[RMf5qȵtpЖ p|GN$^:O?H˽ :Ǘ"!,Ѣ j~m^/[^#C.TUBp%.n0~x/6G%"S8"_-   Z/qt{xL-TsYQYANtlb/1VȬ 65>{ LҾ4/ߝ?%bsVu?ڨ BsW'?eXA-:ƚo'F#'7J.p0O2"OϦ-& UZ8=!vCv b"\kxT_3糮 LX(rlCy4CvB _-Fϑ㊊}6NP÷Ӿ1=q0LJ&.꬝œRAECO=9jX["Qf%XfANMMl{*N|*Fbxp`b.P=k++l"P65sZķD3/ ]b}Q Jk*J򝶻IWLخԿW][65)ǒih)/۰Q%|g;Q:> 7:9# _- Z/qkgx_>E;r6ҺFQPveKD3DE3@v>ojbjYfb_sޮݷfi&Cͣjx Id?y4_n J?(c-QhJzL$f1*ϳL&^jNlq[#r۔N#eoׅG+_ p!snKֲp/Ai.aRI[)wVM~Hsequoia-keyring-linter-0.5.0/tests/data/sha1-userid-sha256-subkeys-priv.pgp010064400017500001750000000121641376713201600246750ustar 00000000000000_/s\*N^˳'J >2,Ѽ#o|pm3F ̯:wc19ipX=`q]? 6SV+QPVc3ER]!.E'upw7J|AYa&$ (KAG}ϼ ؂o5dIRl\X2#eo`IJUCENU;oS3ī_uӕKk#' S✤&M9YdȤzX1 G <;{=12Ov:;ÀI$㳾9^ahp{9qC Vɡ =rL%L{;q#E\`ȝQyAjq=085-L ]0RbLhêY"!.anoUFQ{ t) -ݷ@D!Ke=GVH,n3*sUa N\TQoI8Bjmi*N,+ 2Jn@O}XʸA'Qrul)J);?1iįG:| aҏUi͗(A/!Ț= 7 }x?l\7 HZϲǿgpImf<7\tox :)״FSHA1 User ID, SHA256 Subkeys 8"_   K Rlt5$#‰aft%1UR M 5 a7 ?Arli e3x E{`d`a[T8n1FbwLey<;uPs 8`9cU эЎ I|AW\]Sn+ K >~CNB}!V}#wF<9v {E0fhHnvp=}μ{'c0EBڛOfusTu+p@; &嚃Yw[Y%p&ׁvx%!/i9JP* *Mk"@ _ K Rlt5h*h 'K7| rߡ͍tX7{]idf4Ah:K۳u|OyKI9>Dbj:|[nDlk>?pJ?|NsLjUVi}$ըd*|TtQ):%ux%N*OЊLg)xsB!_)$uZzhkV,9hPZLA@ "p-G|َ2.-( Mzڴp $_i.Yf"j5({! /3B4&^|iDc,mͬG(,$Fխ쌂qx~oBz-  <95ղ; 1U_D˂Tl7+|\>du֎`*z}ׇL߸f 0uæX; yc=Db<ۓF=K' %4*P.TMA} fq@nO7( BPb'nS8_܀4tkƅ¯͓ttTxAs$z)ЛY1;^({q] _) K Rlt5] _ A%D"CH/4w_%D%%lCT1>9.3t-π>BD5;. a/i{Ӛ4Acd?xZz:7J>^;$cV+%<5R\|!Ӱ?w4SN *ЃznQ0畮Jzz{!'_$ddg:cNvrk z60M~\aF#=ʗwP04j\pRO@%oM HjlF>W/RGH(Pؘt wߞ7!@HcB+_ګ} HZ| ߜ++|H1su!8b|[8H\V@mj͟JUkD.V(xU6`sh7Y3<~e;~\z͊B ;[VЬ0 y% =/ u4N$T'ǷkyF.89ZH,W,jh)F(A6p'zq˸ 8m8[K}toM-iъ%ѝν*h9t mb6딀Qlݹz>ŧF]ɢlnHXA^ ֿW/{*) h&<a /6c.8sRN55W/xG EѫdBC i-jWQ1?@T8y!xp?ލIһ+u ?Bx8&9鍩7S=0R(G 'bdhtᜑhr6򀃓0'=^QC?2,Ѽ#o|pm3F ̯:wc19ipX=`q]? 6SV+QPVc3ER]!.E'upw7J|AYa&$ (KAG}ϼ ؂o5dIRl\X2#eo`IJUCENU;oS3ī_uӕKFSHA1 User ID, SHA256 Subkeys 8"_   K Rlt5$#‰aft%1UR M 5 a7 ?Arli e3Dbj:|[nDlk>?pJ?|NsLjUVi}$ըd*|TtQ):%ux%N*OЊLg)xsB!_)$uZzhkV,9hPZLA@ "p-G|َ2.-( Mzڴp $ _i.Yf"j5({! /3B4&^|iDc,mͬG(,$Fխ쌂qx~oBz-  <95ղ; 1U_D˂Tl7+|\>du֎`*z}ׇL߸f 0uæX; yc=Db<ۓF=K' %4*P.TMA} fq@nO7( BPb> _) K Rlt5] _ A%D"CH/4w_%D%%lCT1>9.3t-π>BD5;. a/i{Ӛ4Acd?xZz:7J>^;$cV+%<5R\|!Ӱ?w4SN *ЃznQ0畮Jzz{!'_$ddg:cNvrk z60M~\aF#=ʗwP04j\pRO@%oM HjlF>W/RGH(Pؘt wߞ7!@HcB+_ګ} _  K Rlt5.d1ҍQV6품Pj5Mjp^2jXS_nM,uQSDvęSź:kI9mvHdrL& /J/֗0qub*,|IWMSpUfU4 $Guw=Η{dd#/Źmܵ҅>v;W1ZXõ i}IKCP&y%_y2u!jH-*`-5Eф1a#4TRBJC٥_Xԋv zSy ' NRIKI ٦ ۩@q'?К41 1*lhe\C5Bv("Ϣʓ{OE#Le[(28{^~HoN=x6 @0z23nEJe-MKyc)/8rA_A4fg No/鞓WT79t:-Bڴ̌c5ӘOJҸ\K½hRvzto]s;٩>*N]Y]\Q_y$nIܪaA.d_&"n ُL$W6YhIpOƧh?ZbuB  _mk )Js\mĽhs8)1N. {']Bc906>M[ Վo0ba5W)p[&7shyiTUK JTQŃg()xAc0J O1\Q9:2ODOrV6EnPK¥Ǹ)]M1.&,fĢ)ڳ4{&.!LqYEќfGCArrQSHA256 Certificate, SHA256 Revocation 8"_mQ   )Js"T&ptw oP~Ft`Vt@vGMӱƙlsC.uxH>D,n ~' DXN!V;v2=l^^mq j{\Qr(97MۘĤ6C'` >#Gk5 ڑ-کG4j8rik5kCu)r$>I/f A5<f"duV_mQKϛ7'{Kt"3NdS꒩82Mxq5ed_F"ּ|k-4ꭞ h@9"GaÛ򭡊}7m^/دqm3?fhoӽҫ?6B3 K_ D_5 z `rjm*MU0.H^QOԃB2QrQ6E;'ƘƳΪ7c\p>sߢ0WBl ]ģ^kP_u>{On\ȉ!N¤xB}aם9a%\u&n>/~IavS!]?t9@L8h37fF7ww/$خ'9UA8E๮B1q‘6ם!i֘#^Z=-`T(1y ͮ3QxE1 =Tp~&+C 7N.ji4D`7,̤b}vG|2 z.VHR0ntɳK4hK QA;xo-ہpC8aBEXh#=T'(@[DE,bo}l1|U+O:ȗC!G9paj&q$j~BprAePi\[_ Sez1R4 FJiV%ҲĶ0L~:2P(YIH I8 teqWOǸ0.郍SG:r})?8j" HuG!7Y)>5yƠiAm _mQ )Js{sy[sB gPn7JaN57\6, HN]A9~B Cm CAZcgǯ 􋪣VK(O̭jE4;/C)OǚB $Af{xua>#ItEei绦8UO&'Mhyio褠d;0J+pnok^'w1σ@u"1/_mu&(XۏƟ);"?gAxbNsJ-Ddwb`mTee 5~f/P@Mt-鴲5Bm2Ɋ;LWENy` j$"5&L4mE/&RwgcpM؈1?lNY?/P,<׳vn:#x1haQ!ASL/S-nw.g(qK$JzlH,dyKdA-lŅ'Q y,-!5Srk҅&R9C]"voˋټ\FPm9 A&Fa{V<l'%чMO=W)yO[Ow$uΦ`c_q2H -/kvƲ #DxB3WVO "D^B짥d*Ò q#w¨!^5q&X3]:#xۄ3\)/`ZJA\%iLk.u&.~1yNw c~K>ܰ*xye }]I!~XW\DH$;=+ڏ@&YyΙ>s v:g2AZ9 2hWڶ]hRPW۝d'ȮMֆqYtX-X|T|FqH2"vAʌ.&N@='9]> _m) )Js] _m 4i{8S9Cc[XF⾜A%^vI'GuI-Ha/4P}TCOY"p{4(T&:&|WqfεÛ,((h]:B|tOt}ЦyZ240#d|%gn5>#ɲxnR湤ЈV\9#nm}pc#JR^}kBJOb|3v))sy^/ gXΑy0xrVt܀9/c_^ 萳wAD0`ȏ?mꮷoĄ- J[`V_T2yI>?PihY0.s3NՁm KKZ7\]zyC49t- w|ꔷk xژi5y྇)REEfG#w5tFaٰy%3 SzY2ђ*sequoia-keyring-linter-0.5.0/tests/data/sha256-cert-sha256-revocation-pub.pgp010064400017500001750000000045031376713201600250030ustar 00000000000000 _mQGdO.;8VdW& [j&kv|y͐ z`5-CB^ȶƴ^À+)"{94w@M*Fh$f3gv0]I@Ļzˮ89`=D-'/.d6zG! ;t^r*^#y$iM[ Վo0ba5W)p[&7shyiTUK JTQŃg()xAc0J O1\Q9:2ODOrV6EnPK¥Ǹ)]M1.&,fĢ)ڳ4{&.!LqYEќfGCArrQSHA256 Certificate, SHA256 Revocation 8"_mQ   )Js"T&ptw oP~Ft`Vt@vGMӱƙlsC.uxH>D,n ~' DXN!V;v2=l^^mq j{\Qr(97MۘĤ6C'` >#Gk5 ڑ-کG4j8rik5kCu)r$>I/f A5<f"duV _mQKϛ7'{Kt"3NdS꒩82Mxq5ed_F"ּ|k-4ꭞ h@9"GaÛ򭡊}7m^/دqm3?fhoӽҫ?6B3 K_ D_5 z `rjm*MU0.H^QOԃB2QrQ6E; _mQ )Js{sy[sB gPn7JaN57\6, HN]A9~B Cm CAZcgǯ 􋪣VK(O̭jE4;/C)OǚB $Af{xua>#ItEei绦8UO&'Mhyio褠d;0J+pnok^'w1σ@u"1/ _mu&(XۏƟ);"?gAxbNsJ-Ddwb`mTee 5~f/P@Mt-鴲5Bm2Ɋ;LWENy` j$"5&L4mE/&RwgcpM؈1?lNY?/P,<׳vn:#x1haQ!ASL/S-nw.g(qK$Jz> _m) )Js] _m 4i{8S9Cc[XF⾜A%^vI'GuI-Ha/4P}TCOY"p{4(T&:&|WqfεÛ,((h]:B|tOt}ЦyZ240#d|%gn5>#ɲxnR湤ЈV\9#nm}pc#JR^}kBJOb|3v))sy^/ gXΑy0xrVt܀9/c_^ 萳wAD0`ȏ?mꮷoĄ- J[`V_T2yI>?PihY0.s3NՁm KKZ7\]zyC49t- w|ꔷk xژi5y྇)REEfG#w5tFaٰy%3 SzY2ђ*sequoia-keyring-linter-0.5.0/tests/data/sha256-expired-priv.pgp010064400017500001750000000047141376713201600225270ustar 00000000000000_ze` _-(jgts0aYufc5롢ےRĹ?!D@$=g-jRpr TrH`1*%dY#9F)>\႒Sό߸Mj\F9_$uAH8Z'DS{"0fo$r' n s\iKTXN]XM|BuQ 2S(tBU(1~T1'ed\Z;X?xԷ-<ӸEjTt,*n#*+'3ro 6s <xМOSK[ Yb]ۛR3"&õڤg%+Bj7k}@hf$x[kec7PPo\5՘eǦoXAOd M0Sd2M=rzTIi#8,V Mq&*:tU}x8] (͑Q,fY1Ww X$&F`]\!k&Kg 5|sjQG M nZ6Ezⶉkf Gg:C D֒-#-wh6G!4cU\?/{z7=P^{hw5m;: zM}!¹]- !ti0Ne'PQpjÉ35]m`lz>b#~I,3w)4뒥ջ{''jcB ;Tq6kBV{?RJrPiiˌki荠O;-;#b&A Ք،Y5byӕ'/3Ф ooͷ չt"k<+SHA256 Expired >(_z Q   5{_!C&Ь$dLc_>u gMD۫dm!$@f3D #`ѵS-Z9q4}=Hj&"B Ƣ9QėoVc[o%$7 6]3f9d ,1"dpf؂XБm'/v)Sjp@ͶOa烙!㥗i$Snzt) /zۦ%]d K[kj  'm:f_zߚi]u^YOʳPqUE3株K :MKCtflȎ<ZlxWd^_8m|{Iν}O%مh29U3I~Qmn/7KπC| a0l[^\C:ugKA06Rv3!vΙdvwA Dfxvb8iqXB']+De?@T waHQŹu٦3Z?J>[''$*[eOI_}MڍX-(!ʼn eŋڍ*[jgTxzRZe5Ł7K2d:\;8%j^)v_S"hk :,,r9>dDü9Rk^(ș7gZL1aMni޻#U![7FLDŽچ86!  9>tED;1QUBuw|㍥ 1m:VG f?DUW!Ñ u$e$an3~|!TR8S1īXU߉~*rT(tBH\Io$CZ\)u+$ kj#xҁ6z@C*vq(.| lPLQ9syjK3t@Kwܞ r0[ SxbGW #vJ"< }t2)&8>( õi@:M2t&Aj^=X1q!\Y gֆvFTsЊݛV[/ k88=a6!嬄qU;13(h00g`UUG=b.ȅ4lj%_z  Q 5{_!C R5c6m~3E<0M퐙hoRV `|3BG B`,^sh5@di%.S鶔S"d~~ei }4P|O8 G?TnoF dDg&A \႒Sό߸Mj\F9_$uAH8Z'DS{"0fo$r' n s\iKTXN]XM|BuQ 2S(tBU(+SHA256 Expired >(_z Q   5{_!C&Ь$dLc_>u gMD۫dm!$@f3D #`ѵS-Z9q4}=Hj&"B Ƣ9QėoVc[o%$7 6]3f9d ,1"dpf؂XБm'/v)Sjp@ͶOa烙!㥗i$Snzt) /zۦ%]d K[kj  'm:f _zߚi]u^YOʳPqUE3株K :MKCtflȎ<ZlxWd^_8m|{Iν}O%مh29U3I~Qmn/7KπC| a0l[^\C:ugKA06Rv3!vΙdvwA Dfxvb8iqXB']+De?@T waHQŹu٦%_z  Q 5{_!C R5c6m~3E<0M퐙hoRV `|3BG B`,^sh5@di%.S鶔S"d~~ei }4P|O8 G?TnoF dDg&A PvO:Q(ymUL#F'b0)l}3|oKNSXprS F`۫7 zj<;df8+U0#D^5#LLR)ĸe*3H5 ;>jܣ?i@Ѭ)[o쁿Ojpc>k;i0TQ+E&iNIL`³Ӟ.s|^'9Rw}߈8MkB)wrۑisCuۢXlAPɔ3tmkj D8BX䱧){*k9u0ah!1-ss;0lňY%,]\i~_g!c]Q`9'g } '~H^A@(z~{V&MTl ~ҀtmUy3t'{z$4o$NVc8xD@Kxq<cȣ,%[Ur]R4G_&(R\[!Eaل3|zZlck&N4Q}2<}z8"  _O Gm2Nox:`Ă@G9'fGܢ}F8:6R,_Fw]\pTK ..\ep) Vٿ2ֲ uN3. ReNdӪ힂^m޼8L}nrYy[Ƀö>|N'(B7|!E 4sK_T3s\? ' .,#ubɋ!\EзG"w^Z!\өmJP>(_{S Q   Gm2  P2/9ȯpDp.@&K,V?$lс QW n ᡧs{AƗ,mv(8Sv&\ģ-cBI^7M׵[9l{YQҝ89wT[$KM[%J/hgar4XW |y5q(KR ipR¯=V })70W;ȸ|ҝ_{S~n%sRЊ~\,3Dt*k1HtZjŋݲC=6sb_hٲc/`aB& -|w\-C|l1q(Vbtw>g8YeT%6}$I拁+6*wL<@}ld۶bYv1;+ODW6iskڞT3z>u@oTSsJtSZDHcVd$Ή2x7Y`saJ~;%0L&eoP,=X'ͨEU""vX DE=>܅inJ y2G3BswYНŝMv•`e6+cj|eriq S: zds:Ҧ IYCL`ߋ衻F%,cYn:. jvFy" Npф<[##cy菚=mI%Ffz$vҿ&T,I,v"G#0Bq(:uh pDHsxya AcZ",X#lڹ%5Y a8$/`ak {*&8ҠpX(AM^5*UKQѻf|b +PH|SèݢH`66J5˶A߿w)1)Zߺ6|pLs; 3:gKd9n ԯE $3P\DwT!bS&=zfB({xD3;v3D•M޺5G#J d*yLy3uW2qz%T>l5n2 =59Fq޳d3!7T֭55D%_{S  Q Gm2FDg7O }/ q@j}*f*%O,fw9#1$ErNIո粞 Ͳ4=e Aq2qkQ477/Z)񢦬\!fUW1ld/ڄI}dʲ-H?Qpi *D|ަE˷S\/H; ~Qk?HҐ>aiPxSY@Nq1F%1mtSS4*sequoia-keyring-linter-0.5.0/tests/data/sha256-expired-sha1-live-pub.pgp010064400017500001750000000030061376713201600241150ustar 00000000000000 _{SSPXvs.]x]hpFR+k'È3~gKQkcS [K=&q"HCx=/C2SNjxZ Gnz/YyOŠ:⯔

PvO:Q(ymUL#F'b0)l}3|oKNSXprS F`۫7 zj<;df8+U0#D^5#LLR@SHA256 Expired, SHA1 Live 8"  _O Gm2Nox:`Ă@G9'fGܢ}F8:6R,_Fw]\pTK ..\ep) Vٿ2ֲ uN3. ReNdӪ힂^m޼8L}nrYy[Ƀö>|N'(B7|!E 4sK_T3s\? ' .,#ubɋ!\EзG"w^Z!\өmJP>(_{S Q   Gm2  P2/9ȯpDp.@&K,V?$lс QW n ᡧs{AƗ,mv(8Sv&\ģ-cBI^7M׵[9l{YQҝ89wT[$KM[%J/hgar4XW |y5q(KR ipR¯=V })70W;ȸ|ҹ _{S~n%sRЊ~\,3Dt*k1HtZjŋݲC=6sb_hٲc/`aB& -|w\-C|l1q(Vbtw>g8YeT%6}$I拁+6*wL<@}ld۶bYv1;+ODW6iskڞT3z>u@oTSsJtSZDHcVd$Ή2x7Y`%_{S  Q Gm2FDg7O }/ q@j}*f*%O,fw9#1$ErNIո粞 Ͳ4=e Aq2qkQ477/Z)񢦬\!fUW1ld/ڄI}dʲ-H?Qpi *D|ަE˷S\/H; ~Qk?HҐ>aiPxSY@Nq1F%1mtSS4*sequoia-keyring-linter-0.5.0/tests/data/sha512-cert-sha1-revocation-priv.pgp010064400017500001750000000107761376713201600250250ustar 00000000000000X_4 b\o=BV7pzӞfϣ׾Dsi]vUKUSHV%)+;{.t L?wtjf?* ,ZT6A4et?ez U Id) PZ _"_x  õ9)WM9Lt[L% wt?fօ~ 5; a=hC~$ v!R̎R\EmڐрE`ڢJ&yѪ~bb{V&&Re Ey؊f MWBNMisRxfZ/|fQhcH-/'nJQ$IQ!M~uR&) X5ͷI|c%YU4CJ\ nw$2)jGc I6^5ȉ^2uNPubLb)`rA课e?E>$0eJqjا [MJEQ ›a6p2{20 \FPC>ou|7b|BF2/$V=( 1g8TB)RL8N/]T̎yUAw sŭ'wߟs+e< d.vՈuQa.%&Jc=SVޖZYv:n Pi: j7X:!3^nQSO&8p *fpu鰙.-K XT¥%&Rf'$ʺ+!sUH2&jv֢X(?Շ[ <ވZ T`eAY-%0{|F_Us[cV޸LTkÌoMV!h@Χ`E3Y7c&̣dwU}|<@/Ϩ&!\rgIX/ :Lf8Z/յ~9YrVSD-wZpb},#).у2Asbic&OUlz9~mqʣ A_`l堉 2!5=$ M&xם9~ _7*It was the butler. ם9~ p 3 *|S'^(ӌ%|bRXۢ^+BI#jڄZ3oVS@j"`_0u4//#~ :Jە3<5fWܙ㿂Bĩ[^(62Z 刓]\1b4-٨=a!DOp3>*| 3#YŬWQH߽!.UH1@6K7a/^(Y,Cոz_T<'sn@)Ƭ}K˝<.0lޗU[Y*k fo_(pqjk .L?V|O|p>Πо ) FWezu]ւ<}Gxd q<-R:+!l2 [x"9vf-5us * eش3&>Ѡ5 I-(^$g-SHA1 Revocation  >!5=$ M&xם9~ _4 g    ם9~ ^  Wn%PN+vWԤn 2YylR]2MKty\ m;Y{?eಊW>5EiOVe+vԘqW=?jǺ' o{#*耙ps7C.LNO޺ bքs)g=͞K{ߞƠvwK|T~jexY+櫹(1$.d*QRUB`@U>9D+%2!h>Qԡ&?pt":ys0Eۃ!wub56|bbr_<6VlRc5C UxY~ܦ4$yC4,KTx&^OiqW_4 C`9 Y# rLtt3ZHT+3=mP.J&NY#m;H?#^94:5HC2BZtH7)z>qE#V \Pyc!'$ˌ}\ o' X|8` bCq>0+BhYb a{f9H 9PY` aЭT(JUө㐌@k*E?܈'LEc]t٪\ )P@cA#P{(H|9v|+-]Ȼhk&4;S_P0SϡI>'%<$r5%83oHxh/bbEv( = M+M m52v@P1G%6<֦Ҽ:#s9W, s7[>j(@J$~c0LLV|=)cԋkZ+jD3šgGJs Yҩhd\AYv8yYU8Ǩo: #d^4UW &!5=$ M&xם9~ _4  g ם9~ OG2C&Lk,(|p)]UZK>qdˈp\ Zamcģ2NPg,~.v5 a7Gz<_-`:8Oz-?ԯyގf/%){ 6P ӧM'ȸ(i+hfʻmhd%+PMwy9p߿ղTZ确>&fՍ@GS=r% c+M@gB(,?msequoia-keyring-linter-0.5.0/tests/data/sha512-cert-sha1-revocation-pub.pgp010064400017500001750000000051511376713201600246220ustar 00000000000000_4 b\o=BV7pzӞfϣ׾Dsi]vUKUSHV%)+;{.t L?wtjf?* ,ZT6A4et?ez U Id) PZ _"_x  õ9)WM9Lt[L% wt?fօ~ 5; 2!5=$ M&xם9~ _7*It was the butler. ם9~ p 3 *|S'^(ӌ%|bRXۢ^+BI#jڄZ3oVS@j"`_0u4//#~ :Jە3<5fWܙ㿂Bĩ[^(62Z 刓]\1b4-٨=a!DOp3>*| 3#YŬWQH߽!.UH1@6K7a/^(Y,Cոz_T<'sn@)Ƭ}K˝<.0lޗU[Y*k fo_(pqjk .L?V|O|p>Πо ) FWezu]ւ<}Gxd q<-R:+!l2 [x"9vf-5us * eش3&>Ѡ5 I-(^$g-SHA1 Revocation  >!5=$ M&xם9~ _4 g    ם9~ ^  Wn%PN+vWԤn 2YylR]2MKty\ m;Y{?eಊW>5EiOVe+vԘqW=?jǺ' o{#*耙ps7C.LNO޺ bքs)g=͞K{ߞƠvwK|T~jexY+櫹(1$.d*QRUB`@U>9D+%2!h>Qԡ&?pt":ys0Eۃ!wub56|bbr_<6VlRc5C UxY~ܦ4$yC4,KTx&^Oiq_4 C`9 Y# rLtt3ZHT+3=mP.J&NY#m;H?#^94:5HC2BZtH7)z>qE#V \Pyc!'$ˌ}\ o' X|8` bCq>0+BhYb a{f9H 9PY` aЭT(JUө㐌@k*E?܈'LEc]t٪\ )P@cA#P{(H|9v|+-]Ȼhk&4;S_P0SϡI>'%<$r5%83oHxh/bbEv( &!5=$ M&xם9~ _4  g ם9~ OG2C&Lk,(|p)]UZK>qdˈp\ Zamcģ2NPg,~.v5 a7Gz<_-`:8Oz-?ԯyގf/%){ 6P ӧM'ȸ(i+hfʻmhd%+PMwy9p߿ղTZ确>&fՍ@GS=r% c+M@gB(,?msequoia-keyring-linter-0.5.0/tests/data/sha512-self-sig-sha1-revocation-pub.pgp010064400017500001750000000054031376713201600253760ustar 00000000000000 QGgc_gamEe` ^m2nDn|.=H8د(<J B Sop{lu1vzuqIf=F|TNܐxZ%bc'l{ oS8bC[yߠ'>qA=ކ0bX8QsܕA/#gʠwFN6>M] 1l͚ʕ2G ۀ!ud- ]aD]<r텺x"'{)O@T_Rw`l;?%$ ey c_a2JvgyP&5j;r,[ K2m P|@]V @PU=i 49mv.cTruK!J! EE0hbQz_zQ ^pĭ vifm|i_uARirSu,^m+Alex Abdo 0 V/ cZ쑪DMWd:: $a/͎Y ke$Cq,b0wڲѯp \] zDO+c)6`rBq0Pf@Q gzwkv:~'7 !/   V/i cZ쑪[:AyxE]7,cQTtv]}q=6E*Vle 1Zi9f=ڟ]oI`k#n V`^S,NPvmebR}6RiޭpzWNP~ؽX{ɿfٖ+O \k5^R=Xh={ tI&\g ɦ)wFظ8[4Sq;6W[0 @߹{DWf;M3cF~x54ga;G=/a@N IZXv)eeLh!CWj~MBߪO +[vpbYJvQ.@]%19w8?!=4K`E>(a F8c T lMaSFdJW嚙v[M%$Fy zI|eMaOX.roCPuqvPbߩ-֏FsvlUa.1& -Hdr1Z%}pP7[H=e5?v[t= =ewVW7Gw15fF`٧ʓ+?;+t9L?eqY O[v'yV߱7MJ5s,۩NmQu Bok+3ٛdnMW7 (Um^ +1&.A/I}=̣ 'a[l̉" I6$+Wo_UKoS18:Op-*|b(QI ډL˗1KV9' ]'xL$bBXPٛU!2}mGކ)w!` VUirqV^tRŗ4v͸d>뉔nP_C5!|MSX{8~Yt墟e2 ̟;#el,[t)0SYٚ k|T}PAMT߉J9]{_8E91b(<Ȟ_K _UarNyIc%4}D 5q%[B\nQlmo^Zsequoia-keyring-linter-0.5.0/tests/tests.rs010064400017500001750000000321351376713201600171700ustar 00000000000000#[cfg(test)] mod integration { use std::path; use assert_cmd::Command; use predicates::prelude::*; use sequoia_openpgp as openpgp; use openpgp::Cert; use openpgp::Packet; use openpgp::parse::Parse; fn dir() -> path::PathBuf { path::Path::new("tests").join("data") } // passwords: one '-p' option per element. // required_fixes: the number of fixes (= new top-level signatures) needed. // expected_fixes: the number of them that we can create. fn t(base: &str, prv: Option<&str>, passwords: &[&str], required_fixes: usize, expected_fixes: usize) { assert!(required_fixes >= expected_fixes); let dir = dir(); let mut suffixes = vec![ "pub" ]; if let Some(prv) = prv { suffixes.push(prv); } for suffix in suffixes.iter() { // Lint it. let filename = &format!("{}-{}.pgp", base, suffix); eprintln!("Linting {}", filename); Command::cargo_bin("sq-keyring-linter").unwrap() .current_dir(&dir) .arg(filename) .assert() .code(if required_fixes > 0 { 2 } else { 0 }); // Fix it. let filename = &format!("{}-{}.pgp", base, suffix); eprint!("Fixing {}", filename); if passwords.len() > 0 { eprint!(" (passwords: "); for (i, p) in passwords.iter().enumerate() { if i > 0 { eprint!(", "); } eprint!("{:?}", p) } eprint!(")"); } eprintln!("."); let expected_fixes = if suffix == &"pub" { // We only have public key material: we won't be able // to fix anything. 0 } else { expected_fixes }; let mut cmd = Command::cargo_bin("sq-keyring-linter").unwrap(); let mut cmd = cmd.current_dir(&dir) .args(&[ "--fix", &format!("{}-{}.pgp", base, suffix)]); for p in passwords.iter() { cmd = cmd.arg("-p").arg(p) } cmd.assert() // If not everything can be fixed, then --fix's exit code is 3. .code(if expected_fixes == required_fixes { 0 } else { 3 }) .stdout(predicate::function(|output: &[u8]| -> bool { if expected_fixes == 0 { // If there are no fixes, nothing is printed. output == b"" } else { // We got a certificate on stdout. Pass it // through the linter. Command::cargo_bin("sq-keyring-linter").unwrap() .current_dir(&dir) .arg("-") .write_stdin(output) .assert() .code( if expected_fixes == required_fixes { // Everything should have been fixed. 0 } else { // There are still issues. 2 }); // Check that the number of new signatures equals // the number of expected new signatures. let orig_sigs: isize = Cert::from_file(dir.clone().join(filename)).unwrap() .into_packets() .map(|p| { if let Packet::Signature(_) = p { 1 } else { 0 } }) .sum(); let fixed_sigs: isize = Cert::from_bytes(output) .map(|cert| { cert.into_packets() .map(|p| { match p { Packet::Signature(_) => 1, Packet::SecretKey(_) | Packet::SecretSubkey(_) => panic!("Secret key material \ should not be exported!"), _ => 0, } }) .sum() }) .map_err(|err| { eprintln!("Parsing fixed certificate: {}", err); 0 }) .unwrap(); let fixes = fixed_sigs - orig_sigs; if expected_fixes as isize != fixes { eprintln!("Expected {} fixes, \ found {} additional signatures", expected_fixes, fixes); false } else { true } } })); } } #[test] fn known_good() { t("gnupg-rsa-normal", Some("priv"), &[], 0, 0); t("gnupg-ecc-normal", Some("priv"), &[], 0, 0); } #[test] fn userid_certification() { // User ID: SHA256 // User ID: SHA1 // Enc Subkey: SHA256 t("sha1-userid", Some("priv"), &[], 1, 1); } #[test] fn revoked_userid_certification() { // A revoked User ID shouldn't be updated. // User ID: SHA256 // User ID: SHA1 (revoked) // Enc Subkey: SHA256 t("sha1-userid-revoked", Some("priv"), &[], 0, 0); } #[test] fn signing_subkey_binding_signature() { // User ID: SHA256 // Enc Subkey: SHA256 // Sig Subkey: SHA1 t("sha1-signing-subkey", Some("priv"), &[], 1, 1); } #[test] fn encryption_subkey_binding_signature() { // User ID: SHA256 // Enc Subkey: SHA256 // Enc Subkey: SHA1 t("sha1-encryption-subkey", Some("priv"), &[], 1, 1); } #[test] fn subkey_backsig() { // User ID: SHA256 // Enc Subkey: SHA256 // Sig Subkey: SHA256, backsig: SHA1 t("sha1-backsig-signing-subkey", Some("priv"), &[], 1, 1); } #[test] fn all_bad() { // User ID: SHA1 // Enc Subkey: SHA1 t("only-sha1", Some("priv"), &[], 2, 2); // We don't fix MD5 signatures. // // User ID: MD5 // Enc Subkey: MD5 t("only-md5", Some("priv"), &[], 2, 0); } #[test] fn passwords() { // User ID: SHA1 // Enc Subkey: SHA1 // Wrong password. t("all-sha1-password-Foobar", Some("priv"), &["foobar"], 2, 0); // Right password. t("all-sha1-password-Foobar", Some("priv"), &["Foobar"], 2, 2); // Try multiple passwords. t("all-sha1-password-Foobar", Some("priv"), &["Foobar", "bar"], 2, 2); t("all-sha1-password-Foobar", Some("priv"), &["bar", "Foobar"], 2, 2); } #[test] fn multiple_passwords() { // The primary is encrypted with foo and the signing subkey // with bar. We need to provide both, because the signing // subkey needs its backsig updated. // User ID: SHA256 // Enc Subkey: SHA256 // Enc Subkey: SHA1 // Sig Subkey: SHA1 // We only have the password for the signing subkey: we can't // update anything. t("multiple-passwords", Some("priv"), &["bar", "Foobar"], 2, 0); // We only have the password for the primary key: we can't // update the backsig. t("multiple-passwords", Some("priv"), &["foo", "Foobar"], 2, 1); // We have all passwords: we can fix everything. t("multiple-passwords", Some("priv"), &["bar", "Foobar", "foo"], 2, 2); } #[test] fn offline_subkeys() { // The User ID, the encryption subkey, and the signing subkey // all need new signatures. With just the primary key, we are // able to create two of the three required signatures. // User ID: SHA1 // Enc Subkey: SHA1 // Sig Subkey: SHA1 // We can't update the backsig. t("sha1-offline-subkeys", Some("offline"), &[], 3, 2); // We can fix everything. t("sha1-offline-subkeys", Some("priv"), &[], 3, 3); } #[test] fn sha1_authentication_subkey() { // User ID: SHA1 // Enc Subkey: SHA1 // Auth Subkey: SHA1 t("sha1-authentication-subkey", Some("priv"), &[], 3, 3); } #[test] fn authentication_subkey() { // An authentication subkey doesn't require a backsig. Make // sure we don't flag a missing backsig as an error. // User ID: SHA512 // Enc Subkey: SHA512 // Auth Subkey: SHA512 t("authentication-subkey", Some("priv"), &[], 0, 0); } #[test] fn sha1_userid_sha256_subkeys() { // The User ID is protected with a SHA-1 signature, but two // subkeys are protected with SHA256. Make sure the subkeys // don't get new binding signatures. // User ID: SHA1 // Enc Subkey: SHA1 // Sig Subkey: SHA256 // Enc Subkey: SHA256 t("sha1-userid-sha256-subkeys", Some("priv"), &[], 2, 2); } #[test] fn no_backsig() { // If a key doesn't have a backsig and needs one, it won't be // detected as an issue, because it is not valid under // SHA1+SP. That's okay. // User ID: SHA512 // Sig Subkey: SHA512, no backsig. t("no-backsig", Some("priv"), &[], 0, 0); } #[test] fn sha512_self_sig_sha1_revocation() { // Under the standard policy, SHA1 revocations are considered // bad. We assume that SP+SHA-1 is strictly more liberal than // SP (i.e., it accepts at least everything that SP accepts). // User ID: SHA512, SHA-1 revocation. t("sha512-self-sig-sha1-revocation", None, &[], 0, 0); } #[test] fn revoked_certificate() { // The certificate is only valid under SP+SHA1, and the // revocation certificate uses SHA1. There is no need to // upgrade the certificate or the revocation certificate. // User ID: SHA1 // Enc Subkey: SHA1 // Revocation: SHA1 t("sha1-cert-sha1-revocation", Some("priv"), &[], 0, 0); // The certificate is only valid under SP+SHA1, and the // revocation certificate uses SHA256. There is no need to // upgrade the certificate or the revocation certificate. // User ID: SHA1 // Enc Subkey: SHA1 // Revocation: SHA256 t("sha1-cert-sha256-revocation", Some("priv"), &[], 0, 0); // The certificate is valid under SP (the signatures use // SHA512), but there are two revocation certificates that use // SHA1. Make sure we upgrade them. // User ID: SHA512 // Enc Subkey: SHA512 // Revocation: SHA1 // Revocation: SHA1 t("sha512-cert-sha1-revocation", Some("priv"), &[], 2, 2); // The certificate is valid under SP (the signatures use // SHA256), and it is revoked using a SHA256 revocation // certificate, which is also valid under SP. It also has a // SHA-1 protected signing subkey. Because the certificate is // revoked and the revocation certificate uses SHA256, we // don't need to fix the SHA-1 signature. Make sure we don't. // User ID: SHA256 // Enc Subkey: SHA256 // Sig Subkey: SHA1 // Revocation: SHA256 t("sha256-cert-sha256-revocation", Some("priv"), &[], 0, 0); } #[test] fn expired_certificates() { // User ID: SHA256 (expired) // Enc Subkey: SHA256 t("sha256-expired", Some("priv"), &[], 0, 0); // User ID: SHA1 (expired) // Enc Subkey: SHA1 t("sha1-expired", Some("priv"), &[], 0, 0); // User ID: SHA256 (old, expired), SHA1 (new, live) // Enc Subkey: SHA256 t("sha256-expired-sha1-live", Some("priv"), &[], 1, 1); } #[test] fn list_keys() { Command::cargo_bin("sq-keyring-linter").unwrap() .current_dir(&dir()) .args(&[ "--list-keys", // 94F19D3CB5656E0BC3977C09A8AC5ACC2FB87104 "sha1-userid-pub.pgp", // 55EF7181C288067AE189FF12F5A5CD01D8070917 "gnupg-rsa-normal-pub.pgp" ]) .assert() // If there are issues, the exit code is 2. .code(2) .stdout(predicate::eq("94F19D3CB5656E0BC3977C09A8AC5ACC2FB87104\n")); } }