An 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 programmatically 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 ... ```