diff options
Diffstat (limited to 'docs')
-rw-r--r-- | docs/Complete-Guide-to-Publishing-OpenPGP-in-DNS.md | 832 | ||||
-rw-r--r-- | docs/DETAILS | 1225 | ||||
-rw-r--r-- | docs/Makefile | 153 | ||||
-rw-r--r-- | docs/NOTES-python-gnupg-3.1-audit.html | 946 | ||||
-rw-r--r-- | docs/NOTES-python-gnupg-3.1-audit.org | 232 | ||||
-rw-r--r-- | docs/NOTES-python-openpgp-implementations.txt | 31 | ||||
-rw-r--r-- | docs/OpenPGP-keys-in-DNS.md | 133 | ||||
-rw-r--r-- | docs/_static/DETAILS.html | 2677 | ||||
-rw-r--r-- | docs/_static/agogo.css | 337 | ||||
-rw-r--r-- | docs/_static/pygments.css | 69 | ||||
-rw-r--r-- | docs/change-license-emails.txt | 272 | ||||
-rw-r--r-- | docs/conf.py | 312 | ||||
-rw-r--r-- | docs/gnupg.rst | 131 | ||||
-rw-r--r-- | docs/gpg-migrate.txt | 208 | ||||
-rw-r--r-- | docs/index.rst | 44 | ||||
-rw-r--r-- | docs/make.bat | 190 |
16 files changed, 7792 insertions, 0 deletions
diff --git a/docs/Complete-Guide-to-Publishing-OpenPGP-in-DNS.md b/docs/Complete-Guide-to-Publishing-OpenPGP-in-DNS.md new file mode 100644 index 0000000..5112c97 --- /dev/null +++ b/docs/Complete-Guide-to-Publishing-OpenPGP-in-DNS.md @@ -0,0 +1,832 @@ +<!-- + +Livejournal Introduction: + +I recently wrestled with something, learned quite a lot, and came up with a document that I'm really rather proud of, that +shares knowledge that's not all out there in one place anywhere else. Along the way I've written some software that I'm +releasing, that makes all of what I've learned a lot easier, and may help make the world a little more secure. I'd like to +share it here. + +This is going to be a technical post. For that I apologize. The target of this post is anyone who has a GPG key that they'd +like to expand to a greater audience, and who controls DNS for any of the email domains they publish. Anyone that I host DNS +or mail for is also welcome to do this, if you use PGP, as part of the goal of writing this is to encourage adoption and use +of these methods + +<lj-cut text="This will be long and technical"> +--> + +# The complete guide to publishing PGP keys in DNS + +## Introduction + +Publishing PGP keys is a pain. There are many disjoint keyservers, three or +four _networks_ of which, which do (or don't) share information with each +other. Some are corporate, some are private. And it's a crapshoot as to +whose key is going to be on which, or worse, which will have the latest copy +of a person's key. + +For a long time, GPG has had a way to publish keys in DNS, but it hasn't been +well documented. This document hopes to change that. + +After reading this, you should: + +* Know the three ways to publish a key + +* Have at least a couple tools to do so + +* Have learned a bit more about DNS + +The target audience for this guide is a technical one. It's expected you +understand what DNS is, and what an RFC and a resource record is. + +There are three ways to publish a PGP key in DNS. Most modern versions of GPG +can retrieve from all three, although it's not enabled by default. There are +no compile-time options you need to enable it, and it's simple to turn on. Of +the three key-publishing methods, there are two that you probably shouldn't +use at the same time, and there are advantages and disadvantages to each, +which I hope to outline below, both in general and for each method. + +### Advantages to DNS publishing of your keys + +* It's universal. Your DNS is your own, and you don't have to worry about + which network of vastly-disconnectedkeyservers is caching your key. + +* Using DNS does not stop you from publishing via other means. + +* If you run an organization, you can easily publish all your employee-keys + via this method, and in the same step,define a signing-policy, such that a + person need only assign trust to your organization's "keysigning key" (or + theCEO's key, or the CTO's), without the trouble of running a keyserver. + +* DNSSEC can be (somewhat) used as an additional trust-path vector. More on + this in the notes at the bottom. + +* You do not have to be searching DNS for keys in order to publish. On the + same note, you do not have to be publishing in this manner to search + forothers there. + +### Disadvantages to DNS publishing + +* If you don't control your own DNS (or have a good relationship with your DNS + admin), this isn't going to beas easy or even possible. Ideally, you want + to be running BIND. + +* With two of the three methods listed here, you're going to need to be able + to put a CERT record into your DNS. Mostweb-enabled DNS tools probably will + not give you this ability. The third uses TXT records, which SPF has caused + to befairly universal in web-interfaces. However, it's also the least + standards-defined of the three. + +* Using at least some of these methods, it's not always a "set it and forget + it" procedure. You may need toperiodically re-export your key and + re-publish it, especially if you gain new signatures. + +* Using some of these methods, you're going to be putting some pretty large, + pretty unwiedly lines in your DNS zones. Not everyone will easily be able + to retrieve them, but again, you can still publish other ways. + +* Using some of these methods, DNS is just a means to an end: you still need + to publish your key elsewhere, like a webpage,and the DNS records just point + at it. + +* Initial verifications of most of these seem to imply that only DSA keys are + supported, although I welcome feedback. Itseems the community is trying to + get RSA keys to make a comeback. They're the only type supported by the + gpg2.0 card, andthey are the default keytype. There was a while where they + weren't, though. Since writing this document, I've discoveredthat "new" RSA + keys work, but ancient RSA keys with no subkeys tend to misbehave. + +### Turning on key-fetching via DNS + +Inside your GPG "options" file, find the "auto-key-locate" line, and add +"cert" and/or "pka" to the options. + + auto-key-locate cert pka (as well as other methods, like keyserver URLs) + + +Don't be surprised if a lot of people don't use this method. + +Note that you can also turn on two options during signature verification. +They are specified in a "verify-options" clause in your config file, or on the +command line, and they are (right from the GPG manpage): + + pka-lookups + + Enable PKA lookups to verify sender addresses. Note that + PKA is based on DNS, and so enabling this option may dis- + close information on when and what signatures are veri- + fied or to whom data is encrypted. This is similar to the + "web bug" described for the auto-key-retrieve feature. + +And: + + pka-trust-increase + + Raise the trust in a signature to full if the signature + passes PKA validation. This option is only meaningful if + pka-lookups is set. + + +You can also use the same options on the command line (as you'll see in this +document). + +## Types of PGP Key Records + +### DNS PKA Records + +Relevant RFCs: None that I can find. + +Other Docs: The GPG source and mailing lists. + +#### Advantages + +* It's a TXT record. Easy to put in a zonefile with most management software. +* No special tools required to generate, just three simple pieces of data. +* Since it uses a special subzone, you can manage the _pka namespace in a + separate zonefile. +* GPG has an option, when verifying a signature, to look up these records + (--verify-options pka-lookups), so it's doubly useful, both from a + distribution and a verification point. + +#### Disadvantages + +* As with IPGP certs, you're at the mercy of the URL. This doesn't put your + key in DNS, just the location of it, and the fingerprint. Some clients may + not be able to support https or http 1.1. +* Not RFC standard. + +#### Howto + +1. Figure out which key you want to export: + + %gpg --list-keys danm@prime.gushi.org + Warning: using insecure memory! + pub 1024D/624BB249 2000-10-02 <-- I'm going to use this one. + uid Daniel P. Mahoney <danm@prime.gushi.org> + uid Daniel Mahoney (Secondary Email) <gushi@gushi.org> + sub 2048g/DE20C529 2000-10-02 + pub 1024R/309C17C5 1997-05-08 + uid Daniel P. Mahoney <danm@prime.gushi.org> + +2. Export the key to a file (I use keyid.pub.asc, but it can be anything) + + %gpg --export --armor 624BB249 > 624BB249.pub.asc + Warning: using insecure memory! + % + +3. Get the fingerprint for your key: + + %gpg --list-keys --fingerprint 624BB249 + gpg: WARNING: using insecure memory! + gpg: please see http://www.gnupg.org/faq.html for more information + pub 1024D/624BB249 2000-10-02 + Key fingerprint = C206 3054 5492 95F3 3490 37FF FBBE 5A30 624B B249 <-- That bit is your fingerprint. + uid Daniel P. Mahoney <danm@prime.gushi.org> + uid Daniel Mahoney (Secondary Email) <gushi@gushi.org> + sub 2048g/DE20C529 2000-10-02 + +4. Copy the file somewhere, like your webspace. It need not live on the same + server. It needs to be accessable by the url you create in the next step. + + %cp 624BB249.pub.asc public_html/danm.pubkey.txt + +5. Make up your text record. The format is: + + danm._pka.prime.gushi.org. TXT "v=pka1;fpr=C2063054549295F3349037FFFBBE5A30624BB249;uri=http://prime.gushi.org/danm.pubkey.txt" + + +We'll take this in several parts. The record label is simply the email +address with "._pka." replacing the "@". danm@prime.gushi.org becomes +danm._pka.prime.gushi.org. Don't forget the trailing dot, if you're using the +fully qualified name. I recommend sticking with fully-qualified, for +simplicity. + +The body of the record is also simple. The v portion is just a version. +There's only one version as far as I can tell, 'pka1'. The fpr is the +fingerprint, with all whitespace stripped, and in uppercase. The uri is the +location a key can be retrieved from. All the "names" are lowercase, +separated by semicolons. + +6. Publish the above record in your DNS. Bump your serial number and reload + your nameserver. If you're using DNSSEC, re-sign your zone. + +#### Testing + +Most of the tests we're going to do for these are essentially the same +activity. See if our DNS server is handing out an answer, and then see if GPG +can retrieve it. + +1. A simple dig: + + %dig +short danm._pka.prime.gushi.org. TXT + "v=pka1\;fpr=C2063054549295F3349037FFFBBE5A30624BB249\;uri=http://prime.gushi.org/danm.pubkey.txt" + +(The backslashes before the semicolons are normal). Other than that, it seems +to make sense and match what I put in.) + +2. Test it with GPG. Rather than messing around with, and adding-from and + deleting from live keyrings, you can do: + + %echo "foo" | gpg --no-default-keyring --keyring /tmp/gpg-$$ --encrypt --armor --auto-key-locate pka -r you@you.com + + +(where you@you.com is the address of your primary key.) The /tmp/gpg-$$ +creates a random file named after your PID. What you should see, and what I +see, is something like this: + + gpg: WARNING: using insecure memory! + gpg: please see http://www.gnupg.org/faq.html for more information + gpg: keyring `/tmp/gpg-39996' created + gpg: requesting key 624BB249 from http server prime.gushi.org + gpg: key 624BB249: public key "Daniel P. Mahoney <danm@prime.gushi.org>" imported + gpg: public key of ultimately trusted key CF45887D not found + gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model + gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u + gpg: Total number processed: 1 + gpg: imported: 1 + gpg: automatically retrieved `danm@prime.gushi.org' via PKA + gpg: DE20C529: There is no assurance this key belongs to the named user + pub 2048g/DE20C529 2000-10-02 Daniel P. Mahoney <danm@prime.gushi.org> + Primary key fingerprint: C206 3054 5492 95F3 3490 37FF FBBE 5A30 624B B249 + Subkey fingerprint: CE40 B786 81E2 5CB9 F7D3 1318 9488 EB58 DE20 C529 + It is NOT certain that the key belongs to the person named + in the user ID. If you *really* know what you are doing, + you may answer the next question with yes. + Use this key anyway? (y/N) y + -----BEGIN PGP MESSAGE----- + Version: GnuPG v1.4.10 (FreeBSD) + hQIOA5SI61jeIMUpEAf/UotgWP8VQC9VTY36HaZeXO1CTFk90x0qlPrAhJk9YaoA + 2eHNKZSoHKqaLjzTbaWnWHnNZu0IllIS+qrAwNeIAhswfzDoc8Q9+/4sGSR3LmxA + 8SEwrJIvLmGVbqJEtnH8TTHIEao/lpL/d+ul4nLfbXRn0NW+MsaCAi8UsjbLlJeV + n4p0GQlpDoZCE55DTwMzfWMT84YVwuXTesuN+i7sSyJn2hT1rXuK1BCVcsgTcKdy + QhIo3EfKBlfFp74yiU7QCmlAujD6U6a93mmxezPIHVx/WGXgPExVRGgEzfT/tUcI + IQ2xMDUv4BF05hgm04GPGCbBY431j4UkdWWI6bvMLwgA2i01NmflH/6Z8+ss6J1M + e3RWnR7TPl5lDkXFBtLGAzO+HrsC5A32SbkTw+WsljCQLifJ2EalfoJ1QGY4Sp3v + H2YunwZLVPTc+D2JnrXfqNmi5zYZio8by3c8L0CgWdMwZ7PPxZpTOLN77/MIjBkJ + EBb8Z6SZCgzTIhN5z56ZgWFvmSKf1vKkeUcrgxMs+DnA+XqBMJ9w520JwoTLjJza + syrlYVhd+ktY21DYB9OJ5MZx2HMAtkUDRAzW1zoLcehk1kdZNzhpjU5hqSjT8/GN + trKFeqkmKemrq2GvMNyJyrEOB8e7KgbmXa95YKH0Wh2D4SWpXukegyCspmY4tDE+ + uckaFSao+48g8D6vs1irGSxBRjyhD/jPDblrgpo= + =NbgW + -----END PGP MESSAGE----- + +The "insecure memory" warning is a silly warning that the only way to turn off is to run GPG setuid root. +You can see in the output that the key comes from PKA. + +The "it is NOT certain" warning has nothing to do with the fact that it came +from DNS. You will get that warning every time you use that key (or any gpg +key) until you have edited it and assigned ownertrust to it, or until the key +is signed with a trusted signature, either from your personal web of trust, or +from a signing service like the pgp.com directory. + +3. Ask other people to run it for you and send you the resulting blob. You should be able to decrypt it with your private key. + +### PGP CERT Records + +Also known as: The "big" CERT record. + +Relevant RFCs: [RFC 2538](http://www.faqs.org/rfcs/rfc2538.html), +[RFC 4398](http://www.faqs.org/rfcs/rfc4398.html), specifically sections 2.1 +and 3.3 + +#### Advantages + +* DNS is all you need. You don't have to host the key elsewhere. As a DNS + nerd, this strikes me as very cool. + +* Suprisingly easy to verify with dig, if you have a base64 converter handy + (openssl includes one) + +#### Disadvantages + +* These records can get big. Really big. Especially if you have photo-ids on your keys. You can play with export-options to shrink it somewhat. Big dns packets may require EDNS, or dns-over-tcp, which not everyone supports, but support is becoming more widespread as a result of DNSSEC awareness. + +* Requires the make-dns-cert tool, which isn't built by default. + +* Requires you to have some control over your actual zonefile. Most control panels won't cut it. + +* Make-dns-cert currently generates a very ugly record for this. + + #### How to + +1. As before, the first step is to figure out which key we want. + + %gpg --list-keys danm@prime.gushi.org + Warning: using insecure memory! + pub 1024D/624BB249 2000-10-02 <-- I'm going to use this one. + uid Daniel P. Mahoney <danm@prime.gushi.org> + uid Daniel Mahoney (Secondary Email) <gushi@gushi.org> + sub 2048g/DE20C529 2000-10-02 + pub 1024R/309C17C5 1997-05-08 + uid Daniel P. Mahoney <danm@prime.gushi.org> + +2. We export the key, but this time, it needs to be binary. + + %gpg --export 624BB249 > 624BB249.pub.bin + Warning: using insecure memory! + +3. We run make-dns-cert on it. make-dns-cert comes with no manual or docs, + but running with -h gives you all the clue you need. + + make-dns-cert + -f fingerprint + -u URL + -k key file + -n DNS name + +So then, + + make-dns-cert -n danm.prime.gushi.org. -k 624BB249.pub.bin + <pre>`%make-dns-cert -n danm.prime.gushi.org. -k 624BB249.pub.bin + danm.prime.gushi.org. TYPE37 \# 1298 0003 0000 00 9901A20439D8DAF1110400F770EC6AA006076334BEC6DB6FBB237DC194BC0AB8 + 302C8953F04C28FC2085235D4F10EFA027234FBD63D142CCADD5213AD2B79A22C89ED9B4138370D8220D0F987F993A5364A4A7AC3D42F3765C384 + 71DDD0FF3372E4AE6F7BEE1E18EF464A0BEB5BBE860A08238891455EBE7CB53D567E981F78ADBD263206B0493ADCB74DD00A0FF0E9A1CD245415E + CEF59435162AFCE4CDD14BC70400EA38FF501256E773DEA299404854D99F4EDB2757AA911A9C77C68AB8D6622E517A556C43D21F0523C568F016C + D0DB89EF435F0D53B4E07434213F899E6578955DC2C147931E7B6901C9FD8A02705417D69A879B3CC196D2AC2EAEF311192EE89ABAF5A60942167 + B4625735FCBDFB5DE0E3AC1236A53FA4D7CDD7D75F5DE85AF50400867D9546B28B79AF10541053CF4AB06A6171BFD21458BFD12AF1AE2B2401CAD + 8851661F8AF6602F80EDAC99C79616BE1F910F4156242003779C68D7A079A8B18F89DD293E1B247E7420471300A4A0730AA61DE281CCC211FC405 + A0A8A79877999FF9042AD892AB927DA371E8883BBB370AB7A97841408C3486BB18598CF2559BB42844616E69656C20502E204D61686F6E6579203 + C64616E6D407072696D652E67757368692E6F72673E884E04101102000E050239D8DAF1040B030102021901000A0910FBBE5A30624BB249FA2E00 + 9B057503ED498695AE5ED73CA1B98EBAEE13F717E500A0921E0D92724459100266FEBBC29E911C8B0F530BB43244616E69656C204D61686F6E657 + 920285365636F6E6461727920456D61696C29203C67757368694067757368692E6F72673E8860041311020020050245D49FD7021B23060B090807 + 030204150208030416020301021E01021780000A0910FBBE5A30624BB249158400A082C8AF43DA8B85F740D6B1A6E9FF0B4490520B8C00A08F77D + 21FBF86C842963E8090DC0646D1DD7F95C9B9020D0439D8DAF4100800F64257B7087F081772A2BAD6A942F305E8F95311394FB6F16EB94B3820DA + 01A756A314E98F4055F3D007C6CB43A994ADF74C648649F80C83BD65E917D4A1D350F8F5595FDC76524F3D3D8DDBCE99E1579259CDFDB8AE744FC + 5FC76BC83C5473061CE7CC966FF15F9BBFD915EC701AAD35B9E8DA0A5723AD41AF0BF4600582BE5F488FD584E49DBCD20B49DE49107366B336C38 + 0D451D0F7C88B31C7C5B2D8EF6F3C923C043F0A55B188D8EBB558CB85D38D334FD7C175743A31D186CDE33212CB52AFF3CE1B1294018118D7C84A + 70A72D686C40319C807297ACA950CD9969FABD00A509B0246D3083D66A45D419F9C7CBD894B221926BAABA25EC355E9320B3B00020207FF5E1A3C + C5DA00E1E94EC8EF6C7FE9B49D944C71D8BBC817DD8E64A7344B9E48392E0B833B3B1DB7E6D5A38BE2826DEF0060F78C6417871EAF1CFBCBC47D2 + 7E93718D975E0A3A36D868C021D6B771740CE2918307D69D614BBF0632DC31932EA31397A7F3B04618C9A76C2F38265C7037E303EDD8AEF03D069 + 208E3FE9C4EA77D83E6311ED36C013D58C54E914B263A459E22D463A0288510C4752B99C163EEA0A55686979691AB0D9F9AA0C06C834446D7A723 + EC534D819301382621ACF8930C74E9FD28C8797718AEC2C30CF601E24194B799234104A3D6239657B1D4AD545BDAA637F61541435CB51B4D138FB + F55E1A9FD2EED860E4459D6795B6FCCA23155A8846041811020006050239D8DAF4000A0910FBBE5A30624BB249415A009E37BCFDC64E76CBF6A86 + 82B85EA161BD1DFB793DF00A0C471BC7B9723535CD855D8FF1EB93F01E251B698 + % + +The program prints that all on **one line**. + +Immediately, we notice a few things. + +* The record type isn't "CERT", it's "TYPE37". This confused me for a while until I discovered [RFC3597](http://www.faqs.org/rfcs/rfc3597.html) Basically, it's a way that a DNS server can handle a resource record it doesn't know about, by giving it some special fields like the "#", as well as a length (which is the 1298 you see there). + +* The rest of the record is on one line. I wrapped it for the purposes of brevity. If I were using this in a zonefile, I would need to be careful that I wrapped it on a byte-boundary (every two characters is a byte). If I miss the boundary, named will refuse to load it, dnssec-signzone won't touch it, etc. + +4. So the thing is ugly and you don't want to touch it. The easiest way to work with it is to drop all that into a file: + + %make-dns-cert -n danm.prime.gushi.org. -k 624BB249.pub.bin > 624BB249.big.cert + + +5. And then either read it into your editor, or tack it on like this: + + %cat 624BB249.big.cert >> your.zonefile + +Be sure to make a backup first. Either way, you never have to copy/paste the raw hex and worry about newlines being inserted where you don't want them. + +6. Before you reload your zone, you might want to use named-checkzone on it first: + + prime# named-checkzone gushi.org gushi.org.hosts + zone gushi.org/IN: loaded serial 2009102909 + OK + prime# + +7. Voice of experience: You may want to dial the TTL (which controls how long servers will cache your data) way down on the record above. It's not hard, just put a number before the TYPE37, with a space, i.e: + + danm.prime.gushi.org. 30 TYPE37 + +This way if it all goes terribly wrong, or you need to make changes, it won't be cached for very long. + +8. If it looks okay, bump your serial number and reload. + +#### Testing + +1. As above, you can dig, but you won't be able to easily read the results: + + prime# dig +short danm.prime.gushi.org CERT + ;; Truncated, retrying in TCP mode. + + +PGP 0 0 +mQGiBDnY2vERBAD3cOxqoAYHYzS+xttvuyN9wZS8CrgwLIlT8Ewo/CCF +I11PEO+gJyNPvWPRQsyt1SE60reaIsie2bQTg3DYIg0PmH+ZOlNkpKes +PULzdlw4Rx3dD/M3Lkrm977h4Y70ZKC+tbvoYKCCOIkUVevny1PVZ+mB +94rb0mMgawSTrct03QCg/w6aHNJFQV7O9ZQ1Fir85M3RS8cEAOo4/1AS +Vudz3qKZQEhU2Z9O2ydXqpEanHfGirjWYi5RelVsQ9IfBSPFaPAWzQ24 +nvQ18NU7TgdDQhP4meZXiVXcLBR5Mee2kByf2KAnBUF9aah5s8wZbSrC +6u8xEZLuiauvWmCUIWe0Ylc1/L37XeDjrBI2pT+k183X119d6Fr1BACG +fZVGsot5rxBUEFPPSrBqYXG/0hRYv9Eq8a4rJAHK2IUWYfivZgL4DtrJ +nHlha+H5EPQVYkIAN3nGjXoHmosY+J3Sk+GyR+dCBHEwCkoHMKph3igc +zCEfxAWgqKeYd5mf+QQq2JKrkn2jceiIO7s3CrepeEFAjDSGuxhZjPJV +m7QoRGFuaWVsIFAuIE1haG9uZXkgPGRhbm1AcHJpbWUuZ3VzaGkub3Jn +PohOBBARAgAOBQI52NrxBAsDAQICGQEACgkQ+75aMGJLskn6LgCbBXUD +7UmGla5e1zyhuY667hP3F+UAoJIeDZJyRFkQAmb+u8KekRyLD1MLtDJE +YW5pZWwgTWFob25leSAoU2Vjb25kYXJ5IEVtYWlsKSA8Z3VzaGlAZ3Vz +aGkub3JnPohgBBMRAgAgBQJF1J/XAhsjBgsJCAcDAgQVAggDBBYCAwEC +HgECF4AACgkQ+75aMGJLskkVhACggsivQ9qLhfdA1rGm6f8LRJBSC4wA +oI930h+/hshClj6AkNwGRtHdf5XJuQINBDnY2vQQCAD2Qle3CH8IF3Ki +utapQvMF6PlTETlPtvFuuUs4INoBp1ajFOmPQFXz0AfGy0OplK33TGSG +SfgMg71l6RfUodNQ+PVZX9x2Uk89PY3bzpnhV5JZzf24rnRPxfx2vIPF +RzBhznzJZv8V+bv9kV7HAarTW56NoKVyOtQa8L9GAFgr5fSI/VhOSdvN +ILSd5JEHNmszbDgNRR0PfIizHHxbLY7288kjwEPwpVsYjY67VYy4XTjT +NP18F1dDox0YbN4zISy1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM +2Zafq9AKUJsCRtMIPWakXUGfnHy9iUsiGSa6q6Jew1XpMgs7AAICB/9e +GjzF2gDh6U7I72x/6bSdlExx2LvIF92OZKc0S55IOS4Lgzs7Hbfm1aOL +4oJt7wBg94xkF4cerxz7y8R9J+k3GNl14KOjbYaMAh1rdxdAzikYMH1p +1hS78GMtwxky6jE5en87BGGMmnbC84JlxwN+MD7diu8D0Gkgjj/pxOp3 +2D5jEe02wBPVjFTpFLJjpFniLUY6AohRDEdSuZwWPuoKVWhpeWkasNn5 +qgwGyDREbXpyPsU02BkwE4JiGs+JMMdOn9KMh5dxiuwsMM9gHiQZS3mS +NBBKPWI5ZXsdStVFvapjf2FUFDXLUbTROPv1Xhqf0u7YYORFnWeVtvzK +IxVaiEYEGBECAAYFAjnY2vQACgkQ+75aMGJLsklBWgCeN7z9xk52y/ao +aCuF6hYb0d+3k98AoMRxvHuXI1Nc2FXY/x65PwHiUbaY + + +It's still ugly, but it's not AS ugly because it's base64, which includes +spaces, at least, and is easier to search for a pattern. Base64 can also be +easily wrapped on any boundary, which is nice. + +You can run your existing exported key through a base64 converter, like the +one built into the openssl binary, if you want to compare: + + %cat 624BB249.pub.bin | openssl enc -base64 + mQGiBDnY2vERBAD3cOxqoAYHYzS+xttvuyN9wZS8CrgwLIlT8Ewo/CCFI11PEO+g + JyNPvWPRQsyt1SE60reaIsie2bQTg3DYIg0PmH+ZOlNkpKesPULzdlw4Rx3dD/M3 + Lkrm977h4Y70ZKC+tbvoYKCCOIkUVevny1PVZ+mB94rb0mMgawSTrct03QCg/w6a + (...etc...) + OPv1Xhqf0u7YYORFnWeVtvzKIxVaiEYEGBECAAYFAjnY2vQACgkQ+75aMGJLsklB + WgCeN7z9xk52y/aoaCuF6hYb0d+3k98AoMRxvHuXI1Nc2FXY/x65PwHiUbaY + + +Now, while you could compare things byte-by-byte here, what I've done as a +"casual check" is just pick random strings in the text and see if they match +up. For example, you can see that "reaIsie2" is present in both. They both +start with and end with similar strings on every line. The real test, of +course, is to see if GPG recognizes it as a valid key. + +By the way, since I use DNSSEC, dnssec-signzone rewrites this record into the +proper "presentation format" for me, which is base64. If you want a similar +function, you can use named-compilezone to get some of the same effects, or +you can use the shell script I provide later in this document, with which you +don't even need make-dns-cert. + +2. Testing with gpg + +As above, the command to test this is remarkably simple: + + %rm /tmp/gpg-* + %echo "foo" | gpg --no-default-keyring --keyring /tmp/gpg-$$ --encrypt --armor --auto-key-locate cert -r danm@prime.gushi.org + gpg: keyring `/tmp/gpg-39996' created + gpg: key 624BB249: public key "Daniel P. Mahoney <danm@prime.gushi.org>" imported + gpg: Total number processed: 1 + gpg: imported: 1 + gpg: automatically retrieved `danm@prime.gushi.org' via DNS CERT + gpg: DE20C529: There is no assurance this key belongs to the named user + pub 2048g/DE20C529 2000-10-02 Daniel P. Mahoney <danm@prime.gushi.org> + Primary key fingerprint: C206 3054 5492 95F3 3490 37FF FBBE 5A30 624B B249 + Subkey fingerprint: CE40 B786 81E2 5CB9 F7D3 1318 9488 EB58 DE20 C529 + It is NOT certain that the key belongs to the person named + in the user ID. If you *really* know what you are doing, + you may answer the next question with yes. + Use this key anyway? (y/N) y + -----BEGIN PGP MESSAGE----- + Version: GnuPG v1.4.10 (FreeBSD) + hQIOA5SI61jeIMUpEAf/Sx7MKWm+e9EpUTSrDaBp4nJfDcBeqbYJulPRbDZz7eVW + 2+ol6sG0jWjuirbG1YppZccEr9mgqaQujdSXb/bleD8POS0TEWuf3aPswFQvHf90 + NLEzHt6BnfLoeobXXxyCflNaGX8zW+XgJtwZqAc2+jietuz8MOUhrf5m17CsW/wZ + IuEqwaek+K1irJp+w3rhaE08Jzb/S4CCifeW9J3mK57chQoPOu7Nz3rY666YKp/3 + 9T9StOgmFiNpvtFPNy4N7hHMHvbQwRsKlnkl+a7n0Aq2+OF4d1+/k2EE4uSGgcz0 + oHvee8DnuOx3P92mO4Jz5/0O0lwBD7I51iOjzUurTAgAiIM5sHV8/QFCVzH9Ule+ + gd8Wo5momcphkU/AXpce5Xgi/Vm4oGQ0x0queii8afUrzkpeN5SuwgQfAdOPiXW5 + 2bo527jBllxOxjeBasfky82XheTnLzbAQNvQNTEM9zE7zCl1LQJUZEJ1hVzcOevI + s+cm/AaGII9VkrAtSt3aLSRZuRJHFmhGvYd2Hz5WzcV1YFjXXP1eLwfetDBlaeB9 + /K5v4hZBkIZPbHX0DcLVrP96mCIT4wCBYSJw+I6n0E6Fz3IfybQG2HMfqWp966/c + 00ijx/aRDh42Dr/fTropuzzFzQr7weYDa1JnN3Zoftv6Zb/n+NcrmMiDCH8jJV6E + uMkaeeB5Mv7ssDQ9kPhO989CHFcznrE1lgOxjX8= + =NTLY + -----END PGP MESSAGE----- + +Okay, as above, try to decrypt that with your private key. + +### IPGP CERT Records + +Also known as: The "little" or "short" CERT record. (These terms are purely my +own). + +Relevant RFCs: [RFC 2538](http://www.faqs.org/rfcs/rfc2538.html), +[RFC 4398](http://www.faqs.org/rfcs/rfc4398.html), specifically sections 2.1 +and 3.3 + +IPGP certs are interesting. It's basically the same pieces of infomation that +are in the PKA record, as above, except that it's supported by an RFC. +Despite the RFC compliance, I am not sure if any non-gpg client knows to look +for them. However, because it's a DNS cert, make-dns-cert encodes the +information in binary, and your DNS server will see it in base64. So +verifying it visually is harder than verifying either of the above. + +#### Advantages + +* Small, easy-to-transmit records. +* Can use the same uri as the PKA record. + +#### Disadvantages + +* Relies on the URI scheme. I haven't yet been able to get a definitive list + of what uri schemes are supported, although I've seen http and finger. I've + also seen reports that unless gpg is compiled against curl, http 1.1 is not + supported (what this actually means is that any host that supports SSL will + probably work, because of some of the nuances of SSL). +* With PGP certs and IPGP certs, GPG will only parse the first key it gets, so + if you publish both, and one doesn't work, there's no failover. I've argued + that this should be fixed. +* Requires make-dns-cert, which is not built in GPG by default. (But see "A + Better Way" below) +* Requires publication in your main DNS zone. +* Despite being RFC compliant, GPG has additional trust vectors for PKA but + not this, despite the fact that they share basically the same information. +* Harder to verify with dig. + +#### Howto + +1. Note that some of these steps are redundant. If you're already doing a PKA + key, skip to step 5. + +2. Dig: + + %gpg --list-keys danm@prime.gushi.org + Warning: using insecure memory! + pub 1024D/624BB249 2000-10-02 <-- I'm going to use this one. + uid Daniel P. Mahoney <danm@prime.gushi.org> + uid Daniel Mahoney (Secondary Email) <gushi@gushi.org> + sub 2048g/DE20C529 2000-10-02 + pub 1024R/309C17C5 1997-05-08 + uid Daniel P. Mahoney <danm@prime.gushi.org> + +3. Export the key to a file (I use keyid.pub.asc, but it can be anything) + + %gpg --export --armor 624BB249 > 624BB249.pub.asc + Warning: using insecure memory! + % + +4. Get the fingerprint for your key: + + %gpg --list-keys --fingerprint 624BB249 + gpg: WARNING: using insecure memory! + gpg: please see http://www.gnupg.org/faq.html for more information + pub 1024D/624BB249 2000-10-02 + Key fingerprint = C206 3054 5492 95F3 3490 37FF FBBE 5A30 624B B249 <-- That bit is your fingerprint. + uid Daniel P. Mahoney <danm@prime.gushi.org> + uid Daniel Mahoney (Secondary Email) <gushi@gushi.org> + sub 2048g/DE20C529 2000-10-02 + +5. As above, run make-dns-cert. This time we use the -n, -f, and -u options: + + %make-dns-cert -n danm.prime.gushi.org. -f C2063054549295F3349037FFFBBE5A30624BB249 -u http://prime.gushi.org/danm.pubkey.txt + danm.prime.gushi.org. TYPE37 \# 64 0006 0000 00 14 C2063054549295F3349037FFFBBE5A30624BB249 687474703A2F2F7072696D652E67757368692E6F72672F64616E6D2E7075626B65792E747874 + % + + +6. Put the above in DNS. All on one line. Optionally add a TTL. + +7. IMPORTANT: make sure you don't have any other CERT records with the same + label (i.e. a "big" cert, as above). While it won't break things, you have + no control over which (of multiple) people will get. + +8. Reload your zone, and test. Testing will probably look VERY MUCH like the + above, but here are the steps anyway: + +#### Testing + +1. Dig: + + %dig +short danm.prime.gushi.org CERT + 6 0 0 FMIGMFRUkpXzNJA3//u+WjBiS7JJaHR0cDovL3ByaW1lLmd1c2hpLm9y Zy9kYW5tLnB1YmtleS50eHQ= + +Sadly, I haven't come across an easy way to decipher it yet, but there's +always gpg. + +2. GPG: + +Since we're fetching the same kind of record, the command is exactly the same +as before: + + %echo "foo" | gpg --no-default-keyring --keyring /tmp/gpg-$$ --encrypt --armor --auto-key-locate cert -r danm@prime.gushi.org + gpg: WARNING: using insecure memory! + gpg: please see http://www.gnupg.org/faq.html for more information + gpg: keyring `/tmp/gpg-39996' created + gpg: requesting key 624BB249 from http server prime.gushi.org + gpg: key 624BB249: public key "Daniel P. Mahoney <danm@prime.gushi.org>" imported + gpg: public key of ultimately trusted key CF45887D not found + gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model + gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u + gpg: Total number processed: 1 + gpg: imported: 1 + gpg: automatically retrieved `danm@prime.gushi.org' via DNS CERT + gpg: DE20C529: There is no assurance this key belongs to the named user + pub 2048g/DE20C529 2000-10-02 Daniel P. Mahoney <danm@prime.gushi.org> + Primary key fingerprint: C206 3054 5492 95F3 3490 37FF FBBE 5A30 624B B249 + Subkey fingerprint: CE40 B786 81E2 5CB9 F7D3 1318 9488 EB58 DE20 C529 + It is NOT certain that the key belongs to the person named + in the user ID. If you *really* know what you are doing, + you may answer the next question with yes. + Use this key anyway? (y/N) y + -----BEGIN PGP MESSAGE----- + Version: GnuPG v1.4.10 (FreeBSD) + hQIOA5SI61jeIMUpEAgApZurJi3hZmDaUFjB2j93eX/lTl96xq6T//sz6nT6jcTx + IPnq1RN8IrIQPjDBByHdqOZBT5hhblr9xi7NKIIv3W4q4L0z0fJx7NERPZNvn/H0 + DkTwfDgAvCRxcKjenpLSwKZFwLjyfS7wjlDr3HFX7Tila0hbzplHslvgTE0QMcd7 + 7oNmEyOL3z+yZr/afQGp2wpzDv4YB9zOiNHcHcenqX0yrtiqKozZ9VAldi53rb/q + f38lwInbveyAcEQkE2iFwhRsbMR4VLcsBoxY6D9brsBprt23ey8Rnv+bQ9IAR0VN + /WYzU4zUUqb8HmpNFXQLEgH8A2BENw+bxkVYHjSfWQf/cBSGAzfBQQVJ7qp4tN0Z + FRVe51dokbU4NM9tGBdCzFHWARVkQX/Ulekd4F3sxBR/sum1UOT2xl2THVBz7/Pq + UCrTRPA0uH4dIbL5JpfGZhqsJ079+wmUWUtJIiO2wXi7ePEA/DrBC6p7jlmjyYN/ + AeSKcPoTeLX+zryV5bECx4RO6S56EEcy0Ns0pASGMsgUnKL6Adrv3Y6ea3ZAOQMn + H9Uo28BKTKNUvUaBpN8cV8jIbKYPPW9i04kvEQRqs5rdamERCY1vVTqYTrcLsNqz + fF3KopX+V82X1oE2QuGdFfd8mK57ZXJL3VRUrfohQjhfYNKzougiP46rQQv79MYT + j8kazWyJUuufm6NVco1/35Zdp1UhHu8qTgXxrjo= + =zY9G + -----END PGP MESSAGE----- + % + +Strangely, the output doesn't say what PKA does (a PKA retrieval has a line +about fetching via HTTP), however, by checking my webserver logs, I can see it +retrieved it from there: + + %tail -200 /usr/local/apache/logs/prime.gushi.org.log | grep pubkey | tail -1 + prime.gushi.org 72.9.101.130 - - [28/Oct/2009:23:50:43 -0400] "GET /danm.pubkey.txt HTTP/1.1" 200 4337 "-" "-" + % + +As usual, test decryption, etc. You're done. + +## Further Steps + +* Figure out which of these are useful to you, and use them.* When someone + asks for your public key, tell them to run the above command instead of + mailing them your key or sending them a keyserver URL. + +* Consider using the pka-related verify-options. + +* Look into embracing DNSSEC. With a signed root, there's a good trust-path + vector here. Who knows, maybe some day GPG will be dnssec-aware so it will + give more credit to a secure DNS transaction. Without a signed root, there + are still ways to have those who care about security use it, through + services such as [ISC's DLV registry](http://dlv.isc.org). + +* On DNSSEC: At present, GPG cannot see the difference between an insecure + response (one from an unsigned zone) and a correctly validated one from a + signed zone. (In a signed zone, an unsigned or malformed will simply get a + SERVFAIL dns response). Look into sponsoring development of GPG to make it + as an application more aware of this. + +## A better way to generate records + +In reading over a lot of these commands, I've come across a few problems with +the tools involved. They either require you to assemble large records by +hand, or manipulate huge files. + +DNS has also come a long way since these tools were written, and RFCs have +solidified that have determined the "presentation format" (i.e. the "master +file format") of what CERT records should look like. + +On top of everything, the make-dns-cert tool is not built by default, and is +not present in most binary distributions (RPM's, deb packages, FreeBSD's +ports). + +Thus, I took it upon myself to rewrite make-dns-cert as a shell script. + +### Advantages + +* Extracts your key for you (takes a keyid as the argument). +* Formats all three record types for you, you can pipe it right into your zone + file. +* Takes email address as an argument, generates record label. +* No compiling needed. +* Should work with most systems. Requires openssl and sed, a few other + standard utilities. +* Generates base64-ified CERT records, split into easy, manageable pieces. +* Generates DNS-friendly comments, so repeating tasks are easy to reference. +* (Eventually) available as a tarball, or as a paste-and-go script. +* Arguments are in logical DNS record order `emailaddress keyid [url]`. +* Will generate an IPGP CERT record without a URI (this is legal per RFC4398). + +You can see sample output +[here](http://www.gushi.org/make-dns-cert/sample-output.txt), and you can view +the script itself +[here](http://www.gushi.org/make-dns-cert/make-dns-cert.sh.txt). Depending on +your MIME settings, you can probably get a download link if you go +[here](http://www.gushi.org/make-dns-cert/make-dns-cert.sh). If you see the +script rather than getting a download prompt, you can just save-as. + +README, Changelog, TODO coming soon. + +## Other notes + +I'm not 100 percent sure (mainly because I haven't tried), but with IPGP cert, +and PKA, I believe I could in theory point at a keyserver directly, for +example, specify a uri of +[http://pgp.mit.edu:11371/pks/lookup?op=get&search=0xB0307039309C17C5](http://pgp.mit.edu:11371/pks/lookup?op=get&search=0xB0307039309C17C5). +I'm a bit dubious about the question marks and equals-signs, or if I might +have to uri-encode things. It's something to be tried. + +I'm trying to convince the GPG people that this would be much better adopted +if the make-dns-cert tool was built/included by default, or if its function +were included in gpg rather than a third-party tool. This is analagous as to +how dnssec-keygen is used to generate SSHFP DNS records. + +It doesn't do any actual cryptography, just some binary conversion, so in +theory it could be rewritten in pure-perl, so there's nothing to compile. + +I've made the argument to the GPG developers that if multiple CERT records are +available, all should be tried if one fails. So far, if multiple exist, only +the first received is parsed, and of course, DNS round-robins the answers by +default. + +It took me quite a lot of trial and error to realize that there's a difference +between "modern" RSA keys, like this: + + %gpg --list-keys --fingerprint gushi@prime.gushi.org + pub 2048R/CF45887D 2009-10-29 + Key fingerprint = FCB0 485E 050D DDFA 83C6 76E3 E722 3C05 CF45 887D + uid Gushi Test <gushi@prime.gushi.org> + sub 2048R/C9761244 2009-10-29 + +and ancient RSA keys like this pgp2.6.2 monster: + + %gpg --list-keys --fingerprint danm@prime.gushi.org + pub 1024R/309C17C5 1997-05-08 + Key fingerprint = 04 4B 1A 2E C4 62 95 73 73 A4 EA D0 08 A4 45 76 + uid Daniel P. Mahoney <danm@prime.gushi.org> + +Note the lack of a subkey there. Note the weird fingerprint. I have not been +able to get this key to properly export with gpg. If someone knows the Deep +Magic, let me know. + +## References + +### Blog posts and list threads + +While researching this I came across little more than a few blog posts, and a +few short discussions on the gpg-devel mailing list. + +* [A blog entry](http://www.df7cb.de/blog/2007/openpgp-dns.html) that seems to + have things mostly right. + +* [GPG Mailing List Discussion](http://lists.gnupg.org/pipermail/gnupg-users/2006-April/028314.html) + which seems to date towhen these features were first added. + +* [My own thread](http://www.mail-archive.com/gnupg-users@gnupg.org/msg12336.html) + on the gnupg-users mailing list that led upto this doc. + +* [A slideshow of a talk given on PKA](ftp://ftp.g10code.com/people/werner/talks/pka-intro.ps.gz) + (really the only doc I couldfind with regard to PKA). Note that this is a + postscript doc, for reasons I cannot fathom. + +### RFCs + +* [RFC 3597](http://www.faqs.org/rfcs/rfc3597.html) defines the odd format of + the records that make-dns-cert generates, if itconfuses you. + +* [RFC 2538](http://www.faqs.org/rfcs/rfc2538.html), which was superseded by + [RFC4398](http://www.faqs.org/rfcs/rfc4398.html), defines the format for a + CERT record. + +## Todo + +* At least one GPG enthusiast has suggested to me that any tools I write to + handle keys should simply be able to insert themusing nsupdate. I don't + disagree, but there's a complicated metric there as some of these require + manipulation of a site'smain zone, or at the very least, many subzones. In + doing this I'd also like to find out a bit about how to do nsupdate + withsig(0) and KEY records, which with the right policies would mean I could + do this without touching named.conf. That may be the subject of a whole + other howto. + +* (Done) I need to get the shell script cleaned up a bit more, and generate + proper docs, and start tracking it with version control. + +* I should probably get the gumption up to formally license all this stuff. + For right now, I declare it under the + [ISCLicense](http://en.wikipedia.org/wiki/ISC_license). + +* I'd like to track down the full list of supported URI types for PKA/IPGP + CERT records. There doesn't seem to be a defined standard for it. + +## Epilogue + +### About the author + +Dan Mahoney is a Systems Admin in the Bay Area, California. In his spare time +he enjoys thinking for those brief fleeting moments what he would do if he had +more free time. Keyid 624BB249, or email address danm@prime.gushi.org. + +### About this Document + +This document was written in [gnu nano](http://nano-editor.org), and HTML was +generated using [Markdown](http://daringfireball.net/projects/markdown). + +Markdown rocks. + +Originally published on my livejournal at +[http://gushi.livejournal.com/524199.html](http://gushi.livejournal.com/524199.html), +its main home is at +[http://www.gushi.org/make-dns-cert/HOWTO.html](http://www.gushi.org/make-dns-cert/HOWTO.html), +which is where later versions will be published. + +Free to use, comments to the above email address are welcome. diff --git a/docs/DETAILS b/docs/DETAILS new file mode 100644 index 0000000..d5c5cea --- /dev/null +++ b/docs/DETAILS @@ -0,0 +1,1225 @@ +# doc/DETAILS -*- org -*- +#+TITLE: GnuPG Details +# Globally disable superscripts and subscripts: +#+OPTIONS: ^:{} +# + +# Note: This file uses org-mode; it should be easy to read as plain +# text but be aware of some markup peculiarities: Verbatim code is +# enclosed in #+begin-example, #+end-example blocks or marked by a +# colon as the first non-white-space character, words bracketed with +# equal signs indicate a monospace font, and the usual /italics/, +# *bold*, and _underline_ conventions are recognized. + +This is the DETAILS file for GnuPG which specifies some internals and +parts of the external API for GPG and GPGSM. + +* Format of the colon listings + The format is a based on colon separated record, each recods starts + with a tag string and extends to the end of the line. Here is an + example: +#+begin_example +$ gpg --with-colons --list-keys \ + --with-fingerprint --with-fingerprint wk@gnupg.org +pub:f:1024:17:6C7EE1B8621CC013:899817715:1055898235::m:::scESC: +fpr:::::::::ECAF7590EB3443B5C7CF3ACB6C7EE1B8621CC013: +uid:f::::::::Werner Koch <wk@g10code.com>: +uid:f::::::::Werner Koch <wk@gnupg.org>: +sub:f:1536:16:06AD222CADF6A6E1:919537416:1036177416:::::e: +fpr:::::::::CF8BCC4B18DE08FCD8A1615906AD222CADF6A6E1: +sub:r:1536:20:5CE086B5B5A18FF4:899817788:1025961788:::::esc: +fpr:::::::::AB059359A3B81F410FCFF97F5CE086B5B5A18FF4: +#+end_example + +The double =--with-fingerprint= prints the fingerprint for the subkeys +too. Old versions of gpg used a lighly different format and required +the use of the option =--fixed-list-mode= to conform to format +described here. + +** Description of the fields +*** Field 1 - Type of record + + - pub :: Public key + - crt :: X.509 certificate + - crs :: X.509 certificate and private key available + - sub :: Subkey (secondary key) + - sec :: Secret key + - ssb :: Secret subkey (secondary key) + - uid :: User id (only field 10 is used). + - uat :: User attribute (same as user id except for field 10). + - sig :: Signature + - rev :: Revocation signature + - fpr :: Fingerprint (fingerprint is in field 10) + - pkd :: Public key data [*] + - grp :: Keygrip + - rvk :: Revocation key + - tru :: Trust database information [*] + - spk :: Signature subpacket [*] + - cfg :: Configuration data [*] + + Records marked with an asterisk are described at [[*Special%20field%20formats][*Special fields]]. + +*** Field 2 - Validity + + This is a letter describing the computed validity of a key. + Currently this is a single letter, but be prepared that additional + information may follow in some future versions. Note that GnuPG < + 2.1 does not set this field for secret key listings. + + - o :: Unknown (this key is new to the system) + - i :: The key is invalid (e.g. due to a missing self-signature) + - d :: The key has been disabled + (deprecated - use the 'D' in field 12 instead) + - r :: The key has been revoked + - e :: The key has expired + - - :: Unknown validity (i.e. no value assigned) + - q :: Undefined validity. '-' and 'q' may safely be treated as + the same value for most purposes + - n :: The key is not valid + - m :: The key is marginal valid. + - f :: The key is fully valid + - u :: The key is ultimately valid. This often means that the + secret key is available, but any key may be marked as + ultimately valid. + - w :: The key has a well known private part. + - s :: The key has special validity. This means that it might be + self-signed and expected to be used in the STEED sytem. + + If the validity information is given for a UID or UAT record, it + describes the validity calculated based on this user ID. If given + for a key record it describes the validity taken from the best + rated user ID. + + For X.509 certificates a 'u' is used for a trusted root + certificate (i.e. for the trust anchor) and an 'f' for all other + valid certificates. + +*** Field 3 - Key length + + The length of key in bits. + +*** Field 4 - Public key algorithm + + The values here are those from the OpenPGP specs or if they are + greather than 255 the algorithm ids as used by Libgcrypt. + +*** Field 5 - KeyID + + This is the 64 bit keyid as specified by OpenPGP and the last 64 + bit of the SHA-1 fingerprint of an X.509 certifciate. + +*** Field 6 - Creation date + + The creation date of the key is given in UTC. For UID and UAT + records, this is used for the self-signature date. Note that the + date is usally printed in seconds since epoch, however, we are + migrating to an ISO 8601 format (e.g. "19660205T091500"). This is + currently only relevant for X.509. A simple way to detect the new + format is to scan for the 'T'. Note that old versions of gpg + without using the =--fixed-list-mode= option used a "yyyy-mm-tt" + format. + +*** Field 7 - Expiration date + + Key or UID/UAT expiration date or empty if it does not expire. + +*** Field 8 - Certificate S/N, UID hash, trust signature info + + Used for serial number in crt records. For UID and UAT records, + this is a hash of the user ID contents used to represent that + exact user ID. For trust signatures, this is the trust depth + seperated by the trust value by a space. + +*** Field 9 - Ownertrust + + This is only used on primary keys. This is a single letter, but + be prepared that additional information may follow in future + versions. For trust signatures with a regular expression, this is + the regular expression value, quoted as in field 10. + +*** Field 10 - User-ID + The value is quoted like a C string to avoid control characters + (the colon is quoted =\x3a=). For a "pub" record this field is + not used on --fixed-list-mode. A UAT record puts the attribute + subpacket count here, a space, and then the total attribute + subpacket size. In gpgsm the issuer name comes here. A FPR + record stores the fingerprint here. The fingerprint of a + revocation key is stored here. +*** Field 11 - Signature class + + Signature class as per RFC-4880. This is a 2 digit hexnumber + followed by either the letter 'x' for an exportable signature or + the letter 'l' for a local-only signature. The class byte of an + revocation key is also given here, 'x' and 'l' is used the same + way. This field if not used for X.509. + +*** Field 12 - Key capabilities + + The defined capabilities are: + + - e :: Encrypt + - s :: Sign + - c :: Certify + - a :: Authentication + - ? :: Unknown capability + + A key may have any combination of them in any order. In addition + to these letters, the primary key has uppercase versions of the + letters to denote the _usable_ capabilities of the entire key, and + a potential letter 'D' to indicate a disabled key. + +*** Field 13 - Issuer certificate fingerprint or other info + + Used in FPR records for S/MIME keys to store the fingerprint of + the issuer certificate. This is useful to build the certificate + path based on certificates stored in the local key database it is + only filled if the issuer certificate is available. The root has + been reached if this is the same string as the fingerprint. The + advantage of using this value is that it is guaranteed to have + been been build by the same lookup algorithm as gpgsm uses. + + For "uid" records this field lists the preferences in the same way + gpg's --edit-key menu does. + + For "sig" records, this is the fingerprint of the key that issued + the signature. Note that this is only filled in if the signature + verified correctly. Note also that for various technical reasons, + this fingerprint is only available if --no-sig-cache is used. + +*** Field 14 - Flag field + + Flag field used in the --edit menu output + +*** Field 15 - S/N of a token + + Used in sec/sbb to print the serial number of a token (internal + protect mode 1002) or a '#' if that key is a simple stub (internal + protect mode 1001) + +*** Field 16 - Hash algorithm + + For sig records, this is the used hash algorithm. For example: + 2 = SHA-1, 8 = SHA-256. + +** Special fields + +*** PKD - Public key data + + If field 1 has the tag "pkd", a listing looks like this: +#+begin_example +pkd:0:1024:B665B1435F4C2 .... FF26ABB: + ! ! !-- the value + ! !------ for information number of bits in the value + !--------- index (eg. DSA goes from 0 to 3: p,q,g,y) +#+end_example + +*** TRU - Trust database information + Example for a "tru" trust base record: +#+begin_example + tru:o:0:1166697654:1:3:1:5 +#+end_example + + - Field 2 :: Reason for staleness of trust. If this field is + empty, then the trustdb is not stale. This field may + have multiple flags in it: + + - o :: Trustdb is old + - t :: Trustdb was built with a different trust model + than the one we are using now. + + - Field 3 :: Trust model + + - 0 :: Classic trust model, as used in PGP 2.x. + - 1 :: PGP trust model, as used in PGP 6 and later. + This is the same as the classic trust model, + except for the addition of trust signatures. + + GnuPG before version 1.4 used the classic trust model + by default. GnuPG 1.4 and later uses the PGP trust + model by default. + + - Field 4 :: Date trustdb was created in seconds since Epoch. + - Field 5 :: Date trustdb will expire in seconds since Epoch. + - Field 6 :: Number of marginally trusted users to introduce a new + key signer (gpg's option --marginals-needed). + - Field 7 :: Number of completely trusted users to introduce a new + key signer. (gpg's option --completes-needed) + + - Field 8 :: Maximum depth of a certification chain. (gpg's option + --max-cert-depth) + +*** SPK - Signature subpacket records + + - Field 2 :: Subpacket number as per RFC-4880 and later. + - Field 3 :: Flags in hex. Currently the only two bits assigned + are 1, to indicate that the subpacket came from the + hashed part of the signature, and 2, to indicate the + subpacket was marked critical. + - Field 4 :: Length of the subpacket. Note that this is the + length of the subpacket, and not the length of field + 5 below. Due to the need for %-encoding, the length + of field 5 may be up to 3x this value. + - Field 5 :: The subpacket data. Printable ASCII is shown as + ASCII, but other values are rendered as %XX where XX + is the hex value for the byte. + +*** CFG - Configuration data + + --list-config outputs information about the GnuPG configuration + for the benefit of frontends or other programs that call GnuPG. + There are several list-config items, all colon delimited like the + rest of the --with-colons output. The first field is always "cfg" + to indicate configuration information. The second field is one of + (with examples): + + - version :: The third field contains the version of GnuPG. + + : cfg:version:1.3.5 + + - pubkey :: The third field contains the public key algorithms + this version of GnuPG supports, separated by + semicolons. The algorithm numbers are as specified in + RFC-4880. Note that in contrast to the --status-fd + interface these are _not_ the Libgcrypt identifiers. + + : cfg:pubkey:1;2;3;16;17 + + - cipher :: The third field contains the symmetric ciphers this + version of GnuPG supports, separated by semicolons. + The cipher numbers are as specified in RFC-4880. + + : cfg:cipher:2;3;4;7;8;9;10 + + - digest :: The third field contains the digest (hash) algorithms + this version of GnuPG supports, separated by + semicolons. The digest numbers are as specified in + RFC-4880. + + : cfg:digest:1;2;3;8;9;10 + + - compress :: The third field contains the compression algorithms + this version of GnuPG supports, separated by + semicolons. The algorithm numbers are as specified + in RFC-4880. + + : cfg:compress:0;1;2;3 + + - group :: The third field contains the name of the group, and the + fourth field contains the values that the group expands + to, separated by semicolons. + + For example, a group of: + : group mynames = paige 0x12345678 joe patti + would result in: + : cfg:group:mynames:patti;joe;0x12345678;paige + + +* Format of the --status-fd output + + Every line is prefixed with "[GNUPG:] ", followed by a keyword with + the type of the status line and some arguments depending on the type + (maybe none); an application should always be prepared to see more + arguments in future versions. + +** General status codes +*** NEWSIG + May be issued right before a signature verification starts. This + is useful to define a context for parsing ERROR status messages. + No arguments are currently defined. + +*** GOODSIG <long_keyid_or_fpr> <username> + The signature with the keyid is good. For each signature only one + of the codes GOODSIG, BADSIG, EXPSIG, EXPKEYSIG, REVKEYSIG or + ERRSIG will be emitted. In the past they were used as a marker + for a new signature; new code should use the NEWSIG status + instead. The username is the primary one encoded in UTF-8 and %XX + escaped. The fingerprint may be used instead of the long keyid if + it is available. This is the case with CMS and might eventually + also be available for OpenPGP. + +*** EXPSIG <long_keyid_or_fpr> <username> + The signature with the keyid is good, but the signature is + expired. The username is the primary one encoded in UTF-8 and %XX + escaped. The fingerprint may be used instead of the long keyid if + it is available. This is the case with CMS and might eventually + also be available for OpenPGP. + +*** EXPKEYSIG <long_keyid_or_fpr> <username> + The signature with the keyid is good, but the signature was made + by an expired key. The username is the primary one encoded in + UTF-8 and %XX escaped. The fingerprint may be used instead of the + long keyid if it is available. This is the case with CMS and + might eventually also be available for OpenPGP. + +*** REVKEYSIG <long_keyid_or_fpr> <username> + The signature with the keyid is good, but the signature was made + by a revoked key. The username is the primary one encoded in UTF-8 + and %XX escaped. The fingerprint may be used instead of the long + keyid if it is available. This is the case with CMS and might + eventually also beñ available for OpenPGP. + +*** BADSIG <long_keyid_or_fpr> <username> + The signature with the keyid has not been verified okay. The + username is the primary one encoded in UTF-8 and %XX escaped. The + fingerprint may be used instead of the long keyid if it is + available. This is the case with CMS and might eventually also be + available for OpenPGP. + +*** ERRSIG <keyid> <pkalgo> <hashalgo> <sig_class> <time> <rc> + It was not possible to check the signature. This may be caused by + a missing public key or an unsupported algorithm. A RC of 4 + indicates unknown algorithm, a 9 indicates a missing public + key. The other fields give more information about this signature. + sig_class is a 2 byte hex-value. The fingerprint may be used + instead of the keyid if it is available. This is the case with + gpgsm and might eventually also be available for OpenPGP. + + Note, that TIME may either be the number of seconds since Epoch or + the letter 'T'. + an ISO 8601 string. The latter can be detected by the presence of + +*** VALIDSIG <args> + + The args are: + + - <fingerprint_in_hex> + - <sig_creation_date> + - <sig-timestamp> + - <expire-timestamp> + - <sig-version> + - <reserved> + - <pubkey-algo> + - <hash-algo> + - <sig-class> + - [ <primary-key-fpr> ] + + This status indicates that the signature is good. This is the same + as GOODSIG but has the fingerprint as the argument. Both status + lines are emitted for a good signature. All arguments here are on + one long line. sig-timestamp is the signature creation time in + seconds after the epoch. expire-timestamp is the signature + expiration time in seconds after the epoch (zero means "does not + expire"). sig-version, pubkey-algo, hash-algo, and sig-class (a + 2-byte hex value) are all straight from the signature packet. + PRIMARY-KEY-FPR is the fingerprint of the primary key or identical + to the first argument. This is useful to get back to the primary + key without running gpg again for this purpose. + + The primary-key-fpr parameter is used for OpenPGP and not + class is not defined for CMS and currently set to 0 and 00. + available for CMS signatures. The sig-version as well as the sig + + Note, that *-TIMESTAMP may either be a number of seconds since + Epoch or an ISO 8601 string which can be detected by the presence + of the letter 'T'. + +*** SIG_ID <radix64_string> <sig_creation_date> <sig-timestamp> + This is emitted only for signatures of class 0 or 1 which have + been verified okay. The string is a signature id and may be used + in applications to detect replay attacks of signed messages. Note + that only DLP algorithms give unique ids - others may yield + duplicated ones when they have been created in the same second. + + Note, that SIG-TIMESTAMP may either be a number of seconds since + Epoch or an ISO 8601 string which can be detected by the presence + of the letter 'T'. + +*** ENC_TO <long_keyid> <keytype> <keylength> + The message is encrypted to this LONG_KEYID. KEYTYPE is the + numerical value of the public key algorithm or 0 if it is not + known, KEYLENGTH is the length of the key or 0 if it is not known + (which is currently always the case). Gpg prints this line + always; Gpgsm only if it knows the certificate. + +*** BEGIN_DECRYPTION + Mark the start of the actual decryption process. This is also + emitted when in --list-only mode. +*** END_DECRYPTION + Mark the end of the actual decryption process. This are also + emitted when in --list-only mode. +*** DECRYPTION_INFO <mdc_method> <sym_algo> + Print information about the symmetric encryption algorithm and the + MDC method. This will be emitted even if the decryption fails. + +*** DECRYPTION_FAILED + The symmetric decryption failed - one reason could be a wrong + passphrase for a symmetrical encrypted message. + +*** DECRYPTION_OKAY + The decryption process succeeded. This means, that either the + correct secret key has been used or the correct passphrase for a + conventional encrypted message was given. The program itself may + return an errorcode because it may not be possible to verify a + signature for some reasons. + +*** SESSION_KEY <algo>:<hexdigits> + The session key used to decrypt the message. This message will + only be emitted when the special option --show-session-key is + used. The format is suitable to be passed to the option + --override-session-key + +*** BEGIN_ENCRYPTION <mdc_method> <sym_algo> + Mark the start of the actual encryption process. + +*** END_ENCRYPTION + Mark the end of the actual encryption process. + +*** FILE_START <what> <filename> + Start processing a file <filename>. <what> indicates the performed + operation: + - 1 :: verify + - 2 :: encrypt + - 3 :: decrypt + +*** FILE_DONE + Marks the end of a file processing which has been started + by FILE_START. + +*** BEGIN_SIGNING + Mark the start of the actual signing process. This may be used as + an indication that all requested secret keys are ready for use. + +*** ALREADY_SIGNED <long-keyid> + Warning: This is experimental and might be removed at any time. + +*** SIG_CREATED <type> <pk_algo> <hash_algo> <class> <timestamp> <keyfpr> + A signature has been created using these parameters. + Values for type <type> are: + - D :: detached + - C :: cleartext + - S :: standard + (only the first character should be checked) + + <class> are 2 hex digits with the OpenPGP signature class. + + Note, that TIMESTAMP may either be a number of seconds since Epoch + or an ISO 8601 string which can be detected by the presence of the + letter 'T'. + +*** NOTATION_ + There are actually two related status codes to convey notation + data: + + - NOTATION_NAME <name> + - NOTATION_DATA <string> + + <name> and <string> are %XX escaped; the data may be split among + several NOTATION_DATA lines. + +*** POLICY_URL <string> + Note that URL in <string> is %XX escaped. + +*** PLAINTEXT <format> <timestamp> <filename> + This indicates the format of the plaintext that is about to be + written. The format is a 1 byte hex code that shows the format of + the plaintext: 62 ('b') is binary data, 74 ('t') is text data with + no character set specified, and 75 ('u') is text data encoded in + the UTF-8 character set. The timestamp is in seconds since the + epoch. If a filename is available it gets printed as the third + argument, percent-escaped as usual. + +*** PLAINTEXT_LENGTH <length> + This indicates the length of the plaintext that is about to be + written. Note that if the plaintext packet has partial length + encoding it is not possible to know the length ahead of time. In + that case, this status tag does not appear. + +*** ATTRIBUTE <arguments> + The list or argemnts are: + - <fpr> + - <octets> + - <type> + - <index> + - <count> + - <timestamp> + - <expiredate> + - <flags> + + This is one long line issued for each attribute subpacket when an + attribute packet is seen during key listing. <fpr> is the + fingerprint of the key. <octets> is the length of the attribute + subpacket. <type> is the attribute type (e.g. 1 for an image). + <index> and <count> indicate that this is the N-th indexed + subpacket of count total subpackets in this attribute packet. + <timestamp> and <expiredate> are from the self-signature on the + attribute packet. If the attribute packet does not have a valid + self-signature, then the timestamp is 0. <flags> are a bitwise OR + of: + - 0x01 :: this attribute packet is a primary uid + - 0x02 :: this attribute packet is revoked + - 0x04 :: this attribute packet is expired + +*** SIG_SUBPACKET <type> <flags> <len> <data> + This indicates that a signature subpacket was seen. The format is + the same as the "spk" record above. + +** Key related +*** INV_RECP, INV_SGNR + The two similar status codes: + + - INV_RECP <reason> <requested_recipient> + - INV_SGNR <reason> <requested_sender> + + are issued for each unusable recipient/sender. The reasons codes + currently in use are: + + - 0 :: No specific reason given + - 1 :: Not Found + - 2 :: Ambigious specification + - 3 :: Wrong key usage + - 4 :: Key revoked + - 5 :: Key expired + - 6 :: No CRL known + - 7 :: CRL too old + - 8 :: Policy mismatch + - 9 :: Not a secret key + - 10 :: Key not trusted + - 11 :: Missing certificate + - 12 :: Missing issuer certificate + + Note that for historical reasons the INV_RECP status is also used + for gpgsm's SIGNER command where it relates to signer's of course. + Newer GnuPG versions are using INV_SGNR; applications should + ignore the INV_RECP during the sender's command processing once + they have seen an INV_SGNR. Different codes are used so that they + can be distinguish while doing an encrypt+sign operation. +*** NO_RECP <reserved> + Issued if no recipients are usable. + +*** NO_SGNR <reserved> + Issued if no senders are usable. + +*** KEYEXPIRED <expire-timestamp> + The key has expired. expire-timestamp is the expiration time in + seconds since Epoch. This status line is not very useful because + it will also be emitted for expired subkeys even if this subkey is + not used. To check whether a key used to sign a message has + expired, the EXPKEYSIG status line is to be used. + + Note, that the TIMESTAMP may either be a number of seconds since + Epoch or an ISO 8601 string which can be detected by the presence + of the letter 'T'. + +*** KEYREVOKED + The used key has been revoked by its owner. No arguments yet. + +*** NO_PUBKEY <long keyid> + The public key is not available + +*** NO_SECKEY <long keyid> + The secret key is not available + +*** KEY_CREATED <type> <fingerprint> [<handle>] + A key has been created. Values for <type> are: + - B :: primary and subkey + - P :: primary + - S :: subkey + The fingerprint is one of the primary key for type B and P and the + one of the subkey for S. Handle is an arbitrary non-whitespace + string used to match key parameters from batch key creation run. + +*** KEY_NOT_CREATED [<handle>] + The key from batch run has not been created due to errors. + +*** TRUST_ + These are several similar status codes: + + - TRUST_UNDEFINED <error_token> + - TRUST_NEVER <error_token> + - TRUST_MARGINAL [0 [<validation_model>]] + - TRUST_FULLY [0 [<validation_model>]] + - TRUST_ULTIMATE [0 [<validation_model>]] + + For good signatures one of these status lines are emitted to + indicate the validity of the key used to create the signature. + The error token values are currently only emitted by gpgsm. + + VALIDATION_MODEL describes the algorithm used to check the + validity of the key. The defaults are the standard Web of Trust + model for gpg and the the standard X.509 model for gpgsm. The + defined values are + + - pgp :: The standard PGP WoT. + - shell :: The standard X.509 model. + - chain :: The chain model. + - steed :: The STEED model. + + Note that the term =TRUST_= in the status names is used for + historic reasons; we now speak of validity. + +*** PKA_TRUST_ + This is is one: + + - PKA_TRUST_GOOD <mailbox> + - PKA_TRUST_BAD <mailbox> + + Depending on the outcome of the PKA check one of the above status + codes is emitted in addition to a =TRUST_*= status. + +** Remote control +*** GET_BOOL, GET_LINE, GET_HIDDEN, GOT_IT + + These status line are used with --command-fd for interactive + control of the process. + +*** USERID_HINT <long main keyid> <string> + Give a hint about the user ID for a certain keyID. + +*** NEED_PASSPHRASE <long keyid> <long main keyid> <keytype> <keylength> + Issued whenever a passphrase is needed. KEYTYPE is the numerical + value of the public key algorithm or 0 if this is not applicable, + KEYLENGTH is the length of the key or 0 if it is not known (this + is currently always the case). + +*** NEED_PASSPHRASE_SYM <cipher_algo> <s2k_mode> <s2k_hash> + Issued whenever a passphrase for symmetric encryption is needed. + +*** NEED_PASSPHRASE_PIN <card_type> <chvno> [<serialno>] + Issued whenever a PIN is requested to unlock a card. + +*** MISSING_PASSPHRASE + No passphrase was supplied. An application which encounters this + message may want to stop parsing immediately because the next + message will probably be a BAD_PASSPHRASE. However, if the + application is a wrapper around the key edit menu functionality it + might not make sense to stop parsing but simply ignoring the + following BAD_PASSPHRASE. + +*** BAD_PASSPHRASE <long keyid> + The supplied passphrase was wrong or not given. In the latter + case you may have seen a MISSING_PASSPHRASE. + +*** GOOD_PASSPHRASE + The supplied passphrase was good and the secret key material + is therefore usable. + +** Import/Export +*** IMPORT_CHECK <long keyid> <fingerprint> <user ID> + This status is emitted in interactive mode right before + the "import.okay" prompt. + +*** IMPORTED <long keyid> <username> + The keyid and name of the signature just imported + +*** IMPORT_OK <reason> [<fingerprint>] + The key with the primary key's FINGERPRINT has been imported. + REASON flags are: + + - 0 :: Not actually changed + - 1 :: Entirely new key. + - 2 :: New user IDs + - 4 :: New signatures + - 8 :: New subkeys + - 16 :: Contains private key. + + The flags may be ORed. + +*** IMPORT_PROBLEM <reason> [<fingerprint>] + Issued for each import failure. Reason codes are: + + - 0 :: No specific reason given. + - 1 :: Invalid Certificate. + - 2 :: Issuer Certificate missing. + - 3 :: Certificate Chain too long. + - 4 :: Error storing certificate. + +*** IMPORT_RES <args> + Final statistics on import process (this is one long line). The + args are a list of unsigned numbers separated by white space: + + - <count> + - <no_user_id> + - <imported> + - <imported_rsa> + - <unchanged> + - <n_uids> + - <n_subk> + - <n_sigs> + - <n_revoc> + - <sec_read> + - <sec_imported> + - <sec_dups> + - <skipped_new_keys> + - <not_imported> + +** Smartcard related +*** CARDCTRL <what> [<serialno>] + This is used to control smartcard operations. Defined values for + WHAT are: + + - 1 :: Request insertion of a card. Serialnumber may be given + to request a specific card. Used by gpg 1.4 w/o + scdaemon + - 2 :: Request removal of a card. Used by gpg 1.4 w/o scdaemon. + - 3 :: Card with serialnumber detected + - 4 :: No card available + - 5 :: No card reader available + - 6 :: No card support available + +*** SC_OP_FAILURE [<code>] + An operation on a smartcard definitely failed. Currently there is + no indication of the actual error code, but application should be + prepared to later accept more arguments. Defined values for + <code> are: + + - 0 :: unspecified error (identically to a missing CODE) + - 1 :: canceled + - 2 :: bad PIN + +*** SC_OP_SUCCESS + A smart card operaion succeeded. This status is only printed for + certain operation and is mostly useful to check whether a PIN + change really worked. + +** Miscellaneous status codes +*** NODATA <what> + No data has been found. Codes for WHAT are: + + - 1 :: No armored data. + - 2 :: Expected a packet but did not found one. + - 3 :: Invalid packet found, this may indicate a non OpenPGP + message. + - 4 :: Signature expected but not found + + You may see more than one of these status lines. + +*** UNEXPECTED <what> + Unexpected data has been encountered. Codes for WHAT are: + - 0 :: Not further specified + +*** TRUNCATED <maxno> + The output was truncated to MAXNO items. This status code is + issued for certain external requests. + +*** ERROR <error location> <error code> [<more>] + This is a generic error status message, it might be followed by + error location specific data. <error code> and <error_location> + should not contain spaces. The error code is a either a string + commencing with a letter or such a string prefixed with a + numerical error code and an underscore; e.g.: "151011327_EOF". + +*** SUCCESS [<location>] + Postive confirimation that an operation succeeded. <location> is + optional but if given should not contain spaces. Used only with a + few commands. + +*** BADARMOR + The ASCII armor is corrupted. No arguments yet. + +*** DELETE_PROBLEM <reason_code> + Deleting a key failed. Reason codes are: + - 1 :: No such key + - 2 :: Must delete secret key first + - 3 :: Ambigious specification + +*** PROGRESS <what> <char> <cur> <total> + Used by the primegen and Public key functions to indicate + progress. <char> is the character displayed with no --status-fd + enabled, with the linefeed replaced by an 'X'. <cur> is the + current amount done and <total> is amount to be done; a <total> of + 0 indicates that the total amount is not known. The condition + : TOTAL && CUR == TOTAL + may be used to detect the end of an operation. + + Well known values for WHAT are: + + - pk_dsa :: DSA key generation + - pk_elg :: Elgamal key generation + - primegen :: Prime generation + - need_entropy :: Waiting for new entropy in the RNG + - tick :: Generic tick without any special meaning - useful + for letting clients know that the server is still + working. + - starting_agent :: A gpg-agent was started because it is not + running as a daemon. + - learncard :: Send by the agent and gpgsm while learing + the data of a smartcard. + - card_busy :: A smartcard is still working + +*** BACKUP_KEY_CREATED <fingerprint> <fname> + A backup of a key identified by <fingerprint> has been writte to + the file <fname>; <fname> is percent-escaped. + +*** MOUNTPOINT <name> + <name> is a percent-plus escaped filename describing the + mountpoint for the current operation (e.g. used by "g13 --mount"). + This may either be the specified mountpoint or one randomly + choosen by g13. + +*** PINENTRY_LAUNCHED <pid> + This status line is emitted by gpg to notify a client that a + Pinentry has been launched. <pid> is the PID of the Pinentry. It + may be used to display a hint to the user but can't be used to + synchronize with Pinentry. Note that there is also an Assuan + inquiry line with the same name used internally or, if enabled, + send to the client instead of this status line. Such an inquiry + may be used to sync with Pinentry + +** Obsolete status codes +*** SIGEXPIRED + Removed on 2011-02-04. This is deprecated in favor of KEYEXPIRED. +*** RSA_OR_IDEA + Obsolete. This status message used to be emitted for requests to + use the IDEA or RSA algorithms. It has been dropped from GnuPG + 2.1 after the respective patents expired. +*** SHM_INFO, SHM_GET, SHM_GET_BOOL, SHM_GET_HIDDEN + These were used for the ancient shared memory based co-processing. +*** BEGIN_STREAM, END_STREAM + Used to issued by the experimental pipemode. + + +* Format of the --attribute-fd output + + When --attribute-fd is set, during key listings (--list-keys, + --list-secret-keys) GnuPG dumps each attribute packet to the file + descriptor specified. --attribute-fd is intended for use with + --status-fd as part of the required information is carried on the + ATTRIBUTE status tag (see above). + + The contents of the attribute data is specified by RFC 4880. For + convenience, here is the Photo ID format, as it is currently the + only attribute defined: + + - Byte 0-1 :: The length of the image header. Due to a historical + accident (i.e. oops!) back in the NAI PGP days, this + is a little-endian number. Currently 16 (0x10 0x00). + + - Byte 2 :: The image header version. Currently 0x01. + + - Byte 3 :: Encoding format. 0x01 == JPEG. + + - Byte 4-15 :: Reserved, and currently unused. + + All other data after this header is raw image (JPEG) data. + + +* Unattended key generation + + Please see the GnuPG manual for a description. + + +* Layout of the TrustDB + + The TrustDB is built from fixed length records, where the first byte + describes the record type. All numeric values are stored in network + byte order. The length of each record is 40 bytes. The first record + of the DB is always of type 1 and this is the only record of this + type. + + FIXME: The layout changed, document it here. +#+begin_example + Record type 0: + -------------- + Unused record, can be reused for any purpose. + + Record type 1: + -------------- + Version information for this TrustDB. This is always the first + record of the DB and the only one with type 1. + 1 byte value 1 + 3 bytes 'gpg' magic value + 1 byte Version of the TrustDB (2) + 1 byte marginals needed + 1 byte completes needed + 1 byte max_cert_depth + The three items are used to check whether the cached + validity value from the dir record can be used. + 1 u32 locked flags [not used] + 1 u32 timestamp of trustdb creation + 1 u32 timestamp of last modification which may affect the validity + of keys in the trustdb. This value is checked against the + validity timestamp in the dir records. + 1 u32 timestamp of last validation [currently not used] + (Used to keep track of the time, when this TrustDB was checked + against the pubring) + 1 u32 record number of keyhashtable [currently not used] + 1 u32 first free record + 1 u32 record number of shadow directory hash table [currently not used] + It does not make sense to combine this table with the key table + because the keyid is not in every case a part of the fingerprint. + 1 u32 record number of the trusthashtbale + + + Record type 2: (directory record) + -------------- + Informations about a public key certificate. + These are static values which are never changed without user interaction. + + 1 byte value 2 + 1 byte reserved + 1 u32 LID . (This is simply the record number of this record.) + 1 u32 List of key-records (the first one is the primary key) + 1 u32 List of uid-records + 1 u32 cache record + 1 byte ownertrust + 1 byte dirflag + 1 byte maximum validity of all the user ids + 1 u32 time of last validity check. + 1 u32 Must check when this time has been reached. + (0 = no check required) + + + Record type 3: (key record) + -------------- + Informations about a primary public key. + (This is mainly used to lookup a trust record) + + 1 byte value 3 + 1 byte reserved + 1 u32 LID + 1 u32 next - next key record + 7 bytes reserved + 1 byte keyflags + 1 byte pubkey algorithm + 1 byte length of the fingerprint (in bytes) + 20 bytes fingerprint of the public key + (This is the value we use to identify a key) + + Record type 4: (uid record) + -------------- + Informations about a userid + We do not store the userid but the hash value of the userid because that + is sufficient. + + 1 byte value 4 + 1 byte reserved + 1 u32 LID points to the directory record. + 1 u32 next next userid + 1 u32 pointer to preference record + 1 u32 siglist list of valid signatures + 1 byte uidflags + 1 byte validity of the key calculated over this user id + 20 bytes ripemd160 hash of the username. + + + Record type 5: (pref record) + -------------- + This record type is not anymore used. + + 1 byte value 5 + 1 byte reserved + 1 u32 LID; points to the directory record (and not to the uid record!). + (or 0 for standard preference record) + 1 u32 next + 30 byte preference data + + Record type 6 (sigrec) + ------------- + Used to keep track of key signatures. Self-signatures are not + stored. If a public key is not in the DB, the signature points to + a shadow dir record, which in turn has a list of records which + might be interested in this key (and the signature record here + is one). + + 1 byte value 6 + 1 byte reserved + 1 u32 LID points back to the dir record + 1 u32 next next sigrec of this uid or 0 to indicate the + last sigrec. + 6 times + 1 u32 Local_id of signatures dir or shadow dir record + 1 byte Flag: Bit 0 = checked: Bit 1 is valid (we have a real + directory record for this) + 1 = valid is set (but may be revoked) + + + + Record type 8: (shadow directory record) + -------------- + This record is used to reserve a LID for a public key. We + need this to create the sig records of other keys, even if we + do not yet have the public key of the signature. + This record (the record number to be more precise) will be reused + as the dir record when we import the real public key. + + 1 byte value 8 + 1 byte reserved + 1 u32 LID (This is simply the record number of this record.) + 2 u32 keyid + 1 byte pubkey algorithm + 3 byte reserved + 1 u32 hintlist A list of records which have references to + this key. This is used for fast access to + signature records which are not yet checked. + Note, that this is only a hint and the actual records + may not anymore hold signature records for that key + but that the code cares about this. + 18 byte reserved + + + + Record Type 10 (hash table) + -------------- + Due to the fact that we use fingerprints to lookup keys, we can + implement quick access by some simple hash methods, and avoid + the overhead of gdbm. A property of fingerprints is that they can be + used directly as hash values. (They can be considered as strong + random numbers.) + What we use is a dynamic multilevel architecture, which combines + hashtables, record lists, and linked lists. + + This record is a hashtable of 256 entries; a special property + is that all these records are stored consecutively to make one + big table. The hash value is simple the 1st, 2nd, ... byte of + the fingerprint (depending on the indirection level). + + When used to hash shadow directory records, a different table is used + and indexed by the keyid. + + 1 byte value 10 + 1 byte reserved + n u32 recnum; n depends on the record length: + n = (reclen-2)/4 which yields 9 for the current record length + of 40 bytes. + + the total number of such record which makes up the table is: + m = (256+n-1) / n + which is 29 for a record length of 40. + + To look up a key we use the first byte of the fingerprint to get + the recnum from this hashtable and look up the addressed record: + - If this record is another hashtable, we use 2nd byte + to index this hash table and so on. + - if this record is a hashlist, we walk all entries + until we found one a matching one. + - if this record is a key record, we compare the + fingerprint and to decide whether it is the requested key; + + + Record type 11 (hash list) + -------------- + see hash table for an explanation. + This is also used for other purposes. + + 1 byte value 11 + 1 byte reserved + 1 u32 next next hash list record + n times n = (reclen-5)/5 + 1 u32 recnum + + For the current record length of 40, n is 7 + + + + Record type 254 (free record) + --------------- + All these records form a linked list of unused records. + 1 byte value 254 + 1 byte reserved (0) + 1 u32 next_free +#+end_example + + +* GNU extensions to the S2K algorithm + + S2K mode 101 is used to identify these extensions. + After the hash algorithm the 3 bytes "GNU" are used to make + clear that these are extensions for GNU, the next bytes gives the + GNU protection mode - 1000. Defined modes are: + - 1001 :: Do not store the secret part at all. + - 1002 :: A stub to access smartcards (not used in 1.2.x) + +* Keyserver helper message format + + The keyserver may be contacted by a Unix Domain socket or via TCP. + + The format of a request is: +#+begin_example + command-tag + "Content-length:" digits + CRLF +#+end_example + + Where command-tag is + +#+begin_example + NOOP + GET <user-name> + PUT + DELETE <user-name> +#+end_example + +The format of a response is: + +#+begin_example + "GNUPG/1.0" status-code status-text + "Content-length:" digits + CRLF +#+end_example +followed by <digits> bytes of data + +Status codes are: + + - 1xx :: Informational - Request received, continuing process + + - 2xx :: Success - The action was successfully received, understood, + and accepted + + - 4xx :: Client Error - The request contains bad syntax or cannot be + fulfilled + + - 5xx :: Server Error - The server failed to fulfill an apparently + valid request + + +* Object identifiers + + OIDs below the GnuPG arc: + +#+begin_example + 1.3.6.1.4.1.11591.2 GnuPG + 1.3.6.1.4.1.11591.2.1 notation + 1.3.6.1.4.1.11591.2.1.1 pkaAddress + 1.3.6.1.4.1.11591.2.2 X.509 extensions + 1.3.6.1.4.1.11591.2.2.1 standaloneCertificate + 1.3.6.1.4.1.11591.2.2.2 wellKnownPrivateKey + 1.3.6.1.4.1.11591.2.12242973 invalid encoded OID +#+end_example + + + +* Miscellaneous notes + +** v3 fingerprints + For packet version 3 we calculate the keyids this way: + - RSA :: Low 64 bits of n + - ELGAMAL :: Build a v3 pubkey packet (with CTB 0x99) and + calculate a RMD160 hash value from it. This is used + as the fingerprint and the low 64 bits are the keyid. + +** Simplified revocation certificates + Revocation certificates consist only of the signature packet; + "--import" knows how to handle this. The rationale behind it is to + keep them small. + +** Documentation on HKP (the http keyserver protocol): + + A minimalistic HTTP server on port 11371 recognizes a GET for + /pks/lookup. The standard http URL encoded query parameters are + this (always key=value): + + - op=index (like pgp -kv), op=vindex (like pgp -kvv) and op=get (like + pgp -kxa) + + - search=<stringlist>. This is a list of words that must occur in the key. + The words are delimited with space, points, @ and so on. The delimiters + are not searched for and the order of the words doesn't matter (but see + next option). + + - exact=on. This switch tells the hkp server to only report exact matching + keys back. In this case the order and the "delimiters" are important. + + - fingerprint=on. Also reports the fingerprints when used with 'index' or + 'vindex' + + The keyserver also recognizes http-POSTs to /pks/add. Use this to upload + keys. + + + A better way to do this would be a request like: + + /pks/lookup/<gnupg_formatierte_user_id>?op=<operation> + + This can be implemented using Hurd's translator mechanism. + However, I think the whole key server stuff has to be re-thought; + I have some ideas and probably create a white paper. diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..2d43a93 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,153 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = -E -n +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +help: + @echo "Please use \`make <target>' where <target> is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/python-gnupg.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/python-gnupg.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/python-gnupg" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/python-gnupg" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." diff --git a/docs/NOTES-python-gnupg-3.1-audit.html b/docs/NOTES-python-gnupg-3.1-audit.html new file mode 100644 index 0000000..fbd6e0d --- /dev/null +++ b/docs/NOTES-python-gnupg-3.1-audit.html @@ -0,0 +1,946 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> +<head> +<title>python-gnupg audit</title> +<meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"/> +<meta name="title" content="python-gnupg audit"/> +<meta name="generator" content="Org-mode"/> +<meta name="generated" content="2013-02-01 Fri"/> +<meta name="author" content="isis"/> +<meta name="description" content=""/> +<meta name="keywords" content=""/> +<style type="text/css"> + <!--/*--><![CDATA[/*><!--*/ + html { font-family: Times, serif; font-size: 12pt; } + .title { text-align: center; } + .todo { color: red; } + .done { color: green; } + .tag { background-color: #add8e6; font-weight:normal } + .target { } + .timestamp { color: #bebebe; } + .timestamp-kwd { color: #5f9ea0; } + .right {margin-left:auto; margin-right:0px; text-align:right;} + .left {margin-left:0px; margin-right:auto; text-align:left;} + .center {margin-left:auto; margin-right:auto; text-align:center;} + p.verse { margin-left: 3% } + pre { + border: 1pt solid #AEBDCC; + background-color: #F3F5F7; + padding: 5pt; + font-family: courier, monospace; + font-size: 90%; + overflow:auto; + } + table { border-collapse: collapse; } + td, th { vertical-align: top; } + th.right { text-align:center; } + th.left { text-align:center; } + th.center { text-align:center; } + td.right { text-align:right; } + td.left { text-align:left; } + td.center { text-align:center; } + dt { font-weight: bold; } + div.figure { padding: 0.5em; } + div.figure p { text-align: center; } + div.inlinetask { + padding:10px; + border:2px solid gray; + margin:10px; + background: #ffffcc; + } + textarea { overflow-x: auto; } + .linenr { font-size:smaller } + .code-highlighted {background-color:#ffff00;} + .org-info-js_info-navigation { border-style:none; } + #org-info-js_console-label { font-size:10px; font-weight:bold; + white-space:nowrap; } + .org-info-js_search-highlight {background-color:#ffff00; color:#000000; + font-weight:bold; } + /*]]>*/--> +</style> +<script type="text/javascript"> +/* +@licstart The following is the entire license notice for the +JavaScript code in this tag. + +Copyright (C) 2012 Free Software Foundation, Inc. + +The JavaScript code in this tag is free software: you can +redistribute it and/or modify it under the terms of the GNU +General Public License (GNU GPL) as published by the Free Software +Foundation, either version 3 of the License, or (at your option) +any later version. The code is distributed WITHOUT ANY WARRANTY; +without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. + +As additional permission under GNU GPL version 3 section 7, you +may distribute non-source (e.g., minimized or compacted) forms of +that code without the copy of the GNU GPL normally required by +section 4, provided you include this license notice and a URL +through which recipients can access the Corresponding Source. + + +@licend The above is the entire license notice +for the JavaScript code in this tag. +*/ +<!--/*--><![CDATA[/*><!--*/ + function CodeHighlightOn(elem, id) + { + var target = document.getElementById(id); + if(null != target) { + elem.cacheClassElem = elem.className; + elem.cacheClassTarget = target.className; + target.className = "code-highlighted"; + elem.className = "code-highlighted"; + } + } + function CodeHighlightOff(elem, id) + { + var target = document.getElementById(id); + if(elem.cacheClassElem) + elem.className = elem.cacheClassElem; + if(elem.cacheClassTarget) + target.className = elem.cacheClassTarget; + } +/*]]>*///--> +</script> + +</head> +<body> + +<div id="preamble"> + +</div> + +<div id="content"> +<h1 class="title">python-gnupg audit</h1> + +<p> <span class="timestamp-wrapper"> <span class="timestamp">2013-02-01 Fri</span></span><br/> +</p> + +<div id="table-of-contents"> +<h2>Table of Contents</h2> +<div id="text-table-of-contents"> +<ul> +<li><a href="#sec-1">1 gnugp._<sub>main</sub>_<sub>()</sub></a> +<ul> +<li><a href="#sec-1-1">1.1 comments</a></li> +<li><a href="#sec-1-2">1.2 def <sub>copy</sub><sub>data</sub>(instream, outstream)</a> +<ul> +<li><a href="#sec-1-2-1">1.2.1 L79:</a></li> +<li><a href="#sec-1-2-2">1.2.2 L78:</a></li> +<li><a href="#sec-1-2-3">1.2.3 L88:</a></li> +</ul> +</li> +<li><a href="#sec-1-3">1.3 def <sub>threaded</sub><sub>copy</sub><sub>data</sub>(instream, outstream):</a> +<ul> +<li><a href="#sec-1-3-1">1.3.1 L99:</a></li> +</ul> +</li> +<li><a href="#sec-1-4">1.4 def <sub>write</sub><sub>passphrase</sub>(stream, passphrase, encoding):</a> +<ul> +<li><a href="#sec-1-4-1">1.4.1 L110:</a></li> +</ul></li> +</ul> +</li> +<li><a href="#sec-2">2 class Verify(object)</a></li> +<li><a href="#sec-3">3 class ImportResult(object)</a></li> +<li><a href="#sec-4">4 class ListKeys(list):</a></li> +<li><a href="#sec-5">5 class Crypt(Verify):</a> +<ul> +<li><a href="#sec-5-1">5.1 def _<sub>init</sub>_<sub>(self, gpg)</sub></a> +<ul> +<li><a href="#sec-5-1-1">5.1.1 L338</a></li> +</ul></li> +</ul> +</li> +<li><a href="#sec-6">6 class GenKey(object)</a></li> +<li><a href="#sec-7">7 class DeleteResult(object)</a></li> +<li><a href="#sec-8">8 class Sign(object)</a></li> +<li><a href="#sec-9">9 class GPG(object)</a> +<ul> +<li> +<ul> +<li><a href="#sec-9-1">9.1 L474:</a></li> +</ul> +</li> +<li><a href="#sec-9-1">9.1 def _<sub>init</sub>_<sub>(self, gpgbinary='gpg', gnupghome=None, verbose=False, use<sub>agent</sub>=False, keyring=None)</sub></a> +<ul> +<li><a href="#sec-9-1-1">9.1.1 L494-495:</a></li> +</ul> +</li> +<li><a href="#sec-9-2">9.2 def <sub>open</sub><sub>subprocess</sub>(self, args, passphrase=False)</a> +<ul> +<li><a href="#sec-9-2-1">9.2.1 L515:</a></li> +</ul> +</li> +<li><a href="#sec-9-3">9.3 def <sub>collect</sub><sub>output</sub>(self, process, result, writer=None, stdin=None)</a></li> +<li><a href="#sec-9-4">9.4 def <sub>handle</sub><sub>io</sub>(self, args, file, result, passphrase=None, binary=False)</a> +<ul> +<li><a href="#sec-9-4-1">9.4.1 L601:</a></li> +</ul> +</li> +<li><a href="#sec-9-5">9.5 def sign(self, message, **kwargs)</a> +<ul> +<li><a href="#sec-9-5-1">9.5.1 L617-619:</a></li> +</ul> +</li> +<li><a href="#sec-9-6">9.6 def sign<sub>file</sub>(self, file, keyid=None, passphrase=None, clearsign=True, detach=False, binary=False)</a> +<ul> +<li><a href="#sec-9-6-1">9.6.1 L632-635:</a></li> +<li><a href="#sec-9-6-2">9.6.2 L626-641:</a></li> +</ul> +</li> +<li><a href="#sec-9-7">9.7 def verify(self, data):</a> +<ul> +<li><a href="#sec-9-7-1">9.7.1 L668-670:</a></li> +</ul> +</li> +<li><a href="#sec-9-8">9.8 def verify<sub>file</sub>(self, file, data<sub>filename</sub>=None)</a> +<ul> +<li><a href="#sec-9-8-1">9.8.1 L683:</a></li> +<li><a href="#sec-9-8-2">9.8.2 L684:</a></li> +<li><a href="#sec-9-8-3">9.8.3 L690:</a></li> +</ul> +</li> +<li><a href="#sec-9-9">9.9 def import<sub>keys</sub>(self, key<sub>data</sub>)</a> +<ul> +<li><a href="#sec-9-9-1">9.9.1 L749:</a></li> +</ul> +</li> +<li><a href="#sec-9-10">9.10 def recieve<sub>keys</sub>(self, keyserver, *keyids)</a> +<ul> +<li><a href="#sec-9-10-1">9.10.1 L770:</a></li> +</ul> +</li> +<li><a href="#sec-9-11">9.11 def export<sub>keys</sub>(self, keyids, secret=False)</a> +<ul> +<li><a href="#sec-9-11-1">9.11.1 L795-796:</a></li> +</ul> +</li> +<li><a href="#sec-9-12">9.12 def list<sub>keys</sub>(self, secret=False)</a> +<ul> +<li><a href="#sec-9-12-1">9.12.1 L827:</a></li> +</ul> +</li> +<li><a href="#sec-9-13">9.13 def gen<sub>key</sub>(self, input)</a> +<ul> +<li><a href="#sec-9-13-1">9.13.1 L864:</a></li> +</ul> +</li> +<li><a href="#sec-9-14">9.14 def gen<sub>key</sub><sub>input</sub>(self, **kwargs)</a> +<ul> +<li><a href="#sec-9-14-1">9.14.1 L981-983:</a></li> +</ul> +</li> +<li><a href="#sec-9-15">9.15 def encrypt<sub>file</sub>(self, file, recipiencts, sign=None, …)</a> +<ul> +<li><a href="#sec-9-15-1">9.15.1 L939:</a></li> +</ul> +</li> +<li><a href="#sec-9-16">9.16 def encrypt(self, data, recipients, **kwargs):</a> +<ul> +<li><a href="#sec-9-16-1">9.16.1 L997:</a></li> +</ul> +</li> +<li><a href="#sec-9-17">9.17 def decrypt(self, message **kwargs):</a> +<ul> +<li><a href="#sec-9-17-1">9.17.1 L1003:</a></li> +</ul> +</li> +<li><a href="#sec-9-18">9.18 def decrypt<sub>file</sub>(self, file, always<sub>trust</sub>=False, passphrase=None, output=None)</a> +<ul> +<li><a href="#sec-9-18-1">9.18.1 L1013:</a></li> +</ul></li> +</ul> +</li> +<li><a href="#sec-10">10 POC</a></li> +</ul> +</div> +</div> + +<div id="outline-container-1" class="outline-2"> +<h2 id="sec-1"><span class="section-number-2">1</span> gnugp._<sub>main</sub>_<sub>()</sub></h2> +<div class="outline-text-2" id="text-1"> + + +</div> + +<div id="outline-container-1-1" class="outline-3"> +<h3 id="sec-1-1"><span class="section-number-3">1.1</span> comments</h3> +<div class="outline-text-3" id="text-1-1"> + +<p>L58 NullHandler?? see self.<sub>write</sub><sub>passphrase</sub> +L61 there nifty check for p3k +</p></div> + +</div> + +<div id="outline-container-1-2" class="outline-3"> +<h3 id="sec-1-2"><span class="section-number-3">1.2</span> def <sub>copy</sub><sub>data</sub>(instream, outstream) <span class="tag"><span class="cleanup">cleanup</span></span></h3> +<div class="outline-text-3" id="text-1-2"> + +<p> copies data from one stream to another, 1024 bytes at a time. +</p> +</div> + +<div id="outline-container-1-2-1" class="outline-4"> +<h4 id="sec-1-2-1"><span class="section-number-4">1.2.1</span> L79: <span class="tag"><span class="bad_logic">bad_logic</span></span></h4> +<div class="outline-text-4" id="text-1-2-1"> + +<p> instream is apparently a file descriptor, but is not checked nor + encased in a try/except block. +</p> +</div> + +</div> + +<div id="outline-container-1-2-2" class="outline-4"> +<h4 id="sec-1-2-2"><span class="section-number-4">1.2.2</span> L78: <span class="tag"><span class="hanging_fd">hanging_fd</span> <span class="bad_logic">bad_logic</span></span></h4> +<div class="outline-text-4" id="text-1-2-2"> + +<p> while True: loop, should be +</p><pre class="example"> +with open(instream) as instrm: +</pre> + +</div> + +</div> + +<div id="outline-container-1-2-3" class="outline-4"> +<h4 id="sec-1-2-3"><span class="section-number-4">1.2.3</span> L88: <span class="tag"><span class="bad_exception_handling">bad_exception_handling</span></span></h4> +<div class="outline-text-4" id="text-1-2-3"> + +<pre class="example"> +except: +</pre> + +<p> should catch an IOError, or whatever specific error is raised for broken + pipes. +</p></div> +</div> + +</div> + +<div id="outline-container-1-3" class="outline-3"> +<h3 id="sec-1-3"><span class="section-number-3">1.3</span> def <sub>threaded</sub><sub>copy</sub><sub>data</sub>(instream, outstream):</h3> +<div class="outline-text-3" id="text-1-3"> + + +</div> + +<div id="outline-container-1-3-1" class="outline-4"> +<h4 id="sec-1-3-1"><span class="section-number-4">1.3.1</span> L99:</h4> +<div class="outline-text-4" id="text-1-3-1"> + +<p> this just wraps self.<sub>copy</sub><sub>data</sub> in a thread +</p></div> +</div> + +</div> + +<div id="outline-container-1-4" class="outline-3"> +<h3 id="sec-1-4"><span class="section-number-3">1.4</span> def <sub>write</sub><sub>passphrase</sub>(stream, passphrase, encoding): <span class="tag"><span class="vuln">vuln</span> <span class="cleanup">cleanup</span></span></h3> +<div class="outline-text-3" id="text-1-4"> + + +</div> + +<div id="outline-container-1-4-1" class="outline-4"> +<h4 id="sec-1-4-1"><span class="section-number-4">1.4.1</span> L110: <span class="tag"><span class="writes_passphrase_to_disk">writes_passphrase_to_disk</span></span></h4> +<div class="outline-text-4" id="text-1-4-1"> + +<p> logger writes passphrase into debug log. this should be patched. +</p></div> +</div> +</div> + +</div> + +<div id="outline-container-2" class="outline-2"> +<h2 id="sec-2"><span class="section-number-2">2</span> class Verify(object)</h2> +<div class="outline-text-2" id="text-2"> + +<p> basic parsing class, no errors found +</p></div> + +</div> + +<div id="outline-container-3" class="outline-2"> +<h2 id="sec-3"><span class="section-number-2">3</span> class ImportResult(object)</h2> +<div class="outline-text-2" id="text-3"> + +<p> basic parsing class, no errors found +</p></div> + +</div> + +<div id="outline-container-4" class="outline-2"> +<h2 id="sec-4"><span class="section-number-2">4</span> class ListKeys(list):</h2> +<div class="outline-text-2" id="text-4"> + +<p> basic parsing class, no errors found +</p></div> + +</div> + +<div id="outline-container-5" class="outline-2"> +<h2 id="sec-5"><span class="section-number-2">5</span> class Crypt(Verify):</h2> +<div class="outline-text-2" id="text-5"> + +<p> basic parsing class, no errors found +</p> +</div> + +<div id="outline-container-5-1" class="outline-3"> +<h3 id="sec-5-1"><span class="section-number-3">5.1</span> def _<sub>init</sub>_<sub>(self, gpg)</sub> <span class="tag"><span class="cleanup">cleanup</span></span></h3> +<div class="outline-text-3" id="text-5-1"> + + +</div> + +<div id="outline-container-5-1-1" class="outline-4"> +<h4 id="sec-5-1-1"><span class="section-number-4">5.1.1</span> L338 <span class="tag"><span class="mro_conflict">mro_conflict</span></span></h4> +<div class="outline-text-4" id="text-5-1-1"> + + + + + +<pre class="src src-python">Verify.__init__(<span style="color: #00cdcd; font-weight: bold;">self</span>,gpg) +</pre> + + +<p> + should be changed to: +</p> + + + +<pre class="src src-python"><span style="color: #0000ee; font-weight: bold;">super</span>(Verify, <span style="color: #00cdcd; font-weight: bold;">self</span>).__init__(gpg) +</pre> + +</div> +</div> +</div> + +</div> + +<div id="outline-container-6" class="outline-2"> +<h2 id="sec-6"><span class="section-number-2">6</span> class GenKey(object)</h2> +<div class="outline-text-2" id="text-6"> + +<p> basic parsing class, no errors found +</p></div> + +</div> + +<div id="outline-container-7" class="outline-2"> +<h2 id="sec-7"><span class="section-number-2">7</span> class DeleteResult(object)</h2> +<div class="outline-text-2" id="text-7"> + +<p> basic parsing class, no errors found +</p></div> + +</div> + +<div id="outline-container-8" class="outline-2"> +<h2 id="sec-8"><span class="section-number-2">8</span> class Sign(object)</h2> +<div class="outline-text-2" id="text-8"> + +<p> basic parsing class, no errors found +</p></div> + +</div> + +<div id="outline-container-9" class="outline-2"> +<h2 id="sec-9"><span class="section-number-2">9</span> class GPG(object) <span class="tag"><span class="exploitable">exploitable</span></span></h2> +<div class="outline-text-2" id="text-9"> + + +</div> + +<div id="outline-container-9-1" class="outline-4"> +<h4 id="sec-9-1"><span class="section-number-4">9.1</span> L474: <span class="tag"><span class="cleanup">cleanup</span></span></h4> +<div class="outline-text-4" id="text-9-1"> + +<pre class="example"> +cls.__doc__ +</pre> + +<p> should go directly underneath class signature +</p></div> + +</div> + +<div id="outline-container-9-1" class="outline-3"> +<h3 id="sec-9-1"><span class="section-number-3">9.1</span> def _<sub>init</sub>_<sub>(self, gpgbinary='gpg', gnupghome=None, verbose=False, use<sub>agent</sub>=False, keyring=None)</sub> <span class="tag"><span class="bug">bug</span></span></h3> +<div class="outline-text-3" id="text-9-1"> + + +</div> + +<div id="outline-container-9-1-1" class="outline-4"> +<h4 id="sec-9-1-1"><span class="section-number-4">9.1.1</span> L494-495: <span class="tag"><span class="type_error">type_error</span></span></h4> +<div class="outline-text-4" id="text-9-1-1"> + + + + + +<pre class="src src-python"><span style="color: #00cdcd; font-weight: bold;">if</span> gnupghome <span style="color: #00cdcd; font-weight: bold;">and</span> <span style="color: #00cdcd; font-weight: bold;">not</span> os.path.isdir(<span style="color: #00cdcd; font-weight: bold;">self</span>.gnupghome): + os.makedirs(<span style="color: #00cdcd; font-weight: bold;">self</span>.gnupghome,0x1C0) +</pre> + + + +<pre class="example">In [20]: os.makedirs? +Type: function +String Form:<function makedirs at 0x7f8ddeb6cc08> +File: /usr/lib/python2.7/os.py +Definition: os.makedirs(name, mode=511) +Docstring: +makedirs(path [, mode=0777]) +Super-mkdir; create a leaf directory and all intermediate ones. +Works like mkdir, except that any intermediate path segment (not +just the rightmost) will be created if it does not exist. This is +recursive. + +setting mode=0x1c0 is equivalent to mode=hex(0700), which +may cause bugs on some systems, see +http://ubuntuforums.org/showthread.php?t=2044879 + +this could be do to the complete lack of input validation in +os.makedirs, and it's calling of the os.mkdir() built-in, which +may vary depending on the python compilation: +</pre> + + + +<pre class="src src-python">Source: +<span style="color: #00cdcd; font-weight: bold;">def</span> <span style="color: #0000ee; font-weight: bold;">makedirs</span>(name, mode=0777): + <span style="color: #00cd00;">"""makedirs(path [, mode=0777])</span> + +<span style="color: #00cd00;"> Super-mkdir; create a leaf directory and all intermediate ones.</span> +<span style="color: #00cd00;"> Works like mkdir, except that any intermediate path segment (not</span> +<span style="color: #00cd00;"> just the rightmost) will be created if it does not exist. This is</span> +<span style="color: #00cd00;"> recursive.</span> +<span style="color: #00cd00;"> """</span> + <span style="color: #cdcd00;">head</span>, <span style="color: #cdcd00;">tail</span> = path.split(name) + <span style="color: #00cdcd; font-weight: bold;">if</span> <span style="color: #00cdcd; font-weight: bold;">not</span> tail: + <span style="color: #cdcd00;">head</span>, <span style="color: #cdcd00;">tail</span> = path.split(head) + <span style="color: #00cdcd; font-weight: bold;">if</span> head <span style="color: #00cdcd; font-weight: bold;">and</span> tail <span style="color: #00cdcd; font-weight: bold;">and</span> <span style="color: #00cdcd; font-weight: bold;">not</span> path.exists(head): + <span style="color: #00cdcd; font-weight: bold;">try</span>: + makedirs(head, mode) + <span style="color: #00cdcd; font-weight: bold;">except</span> <span style="color: #00cd00;">OSError</span>, e: + <span style="color: #cdcd00;"># </span><span style="color: #cdcd00;">be happy if someone already created the path</span> + <span style="color: #00cdcd; font-weight: bold;">if</span> e.errno != errno.EEXIST: + <span style="color: #00cdcd; font-weight: bold;">raise</span> + <span style="color: #00cdcd; font-weight: bold;">if</span> tail == curdir: <span style="color: #cdcd00;"># </span><span style="color: #cdcd00;">xxx/newdir/. exists if xxx/newdir exists</span> + <span style="color: #00cdcd; font-weight: bold;">return</span> + mkdir(name, mode) +</pre> + + +</div> +</div> + +</div> + +<div id="outline-container-9-2" class="outline-3"> +<h3 id="sec-9-2"><span class="section-number-3">9.2</span> def <sub>open</sub><sub>subprocess</sub>(self, args, passphrase=False) <span class="tag"><span class="vuln">vuln</span></span></h3> +<div class="outline-text-3" id="text-9-2"> + + +</div> + +<div id="outline-container-9-2-1" class="outline-4"> +<h4 id="sec-9-2-1"><span class="section-number-4">9.2.1</span> L515: <span class="tag"><span class="unvalidated_user_input">unvalidated_user_input</span></span></h4> +<div class="outline-text-4" id="text-9-2-1"> + +<pre class="example"> +cmd.extend(args) +</pre> + + +<p> + cmd is a list of strings, eventually joined with cmd=' '.join(cmd), and + the args are unvalidated in this function. Then this concatenation of args + is fed directly into subprocess.Popen(cmd, shell=True, stdin=PIPE, + stdout=PIPE, stderr=PIPE). THIS SHOULD BE PATCHED. +</p> +</div> +</div> + +</div> + +<div id="outline-container-9-3" class="outline-3"> +<h3 id="sec-9-3"><span class="section-number-3">9.3</span> def <sub>collect</sub><sub>output</sub>(self, process, result, writer=None, stdin=None)</h3> +<div class="outline-text-3" id="text-9-3"> + +<p> sends stdout to self.<sub>read</sub><sub>data</sub>() and stderr to self.<sub>read</sub><sub>response</sub>() +</p> +</div> + +</div> + +<div id="outline-container-9-4" class="outline-3"> +<h3 id="sec-9-4"><span class="section-number-3">9.4</span> def <sub>handle</sub><sub>io</sub>(self, args, file, result, passphrase=None, binary=False) <span class="tag"><span class="vuln">vuln</span> <span class="cleanup">cleanup</span></span></h3> +<div class="outline-text-3" id="text-9-4"> + + +</div> + +<div id="outline-container-9-4-1" class="outline-4"> +<h4 id="sec-9-4-1"><span class="section-number-4">9.4.1</span> L601: <span class="tag"><span class="unvalidated_user_input">unvalidated_user_input</span> <span class="type_check_in_call">type_check_in_call</span></span></h4> +<div class="outline-text-4" id="text-9-4-1"> + +<pre class="example"> +p = self._open_subprocess(args, passphrase is not None) +</pre> + + +<p> + you shouldn't assign or type check in a function call +</p> +</div> +</div> + +</div> + +<div id="outline-container-9-5" class="outline-3"> +<h3 id="sec-9-5"><span class="section-number-3">9.5</span> def sign(self, message, **kwargs) <span class="tag"><span class="cleanup">cleanup</span></span></h3> +<div class="outline-text-3" id="text-9-5"> + + +</div> + +<div id="outline-container-9-5-1" class="outline-4"> +<h4 id="sec-9-5-1"><span class="section-number-4">9.5.1</span> L617-619: <span class="tag"><span class="hanging_fd">hanging_fd</span></span></h4> +<div class="outline-text-4" id="text-9-5-1"> + +<p> calls self.<sub>make</sub><sub>binary</sub><sub>stream</sub>(), which leaves the file descriptor for + the encoded message to be encrypted hanging between scopes. +</p> +</div> +</div> + +</div> + +<div id="outline-container-9-6" class="outline-3"> +<h3 id="sec-9-6"><span class="section-number-3">9.6</span> def sign<sub>file</sub>(self, file, keyid=None, passphrase=None, clearsign=True, detach=False, binary=False) <span class="tag"><span class="cleanup">cleanup</span></span></h3> +<div class="outline-text-3" id="text-9-6"> + + +</div> + +<div id="outline-container-9-6-1" class="outline-4"> +<h4 id="sec-9-6-1"><span class="section-number-4">9.6.1</span> L632-635: <span class="tag"><span class="bad_logic">bad_logic</span></span></h4> +<div class="outline-text-4" id="text-9-6-1"> + + + + +<pre class="src src-python"><span style="color: #00cdcd; font-weight: bold;">if</span> detach: + args.append(<span style="color: #00cd00;">"--detach-sign"</span>) +<span style="color: #00cdcd; font-weight: bold;">elif</span> clearsign: + args.append(<span style="color: #00cd00;">"--clearsign"</span>) +</pre> + + +<p> + the logic here allows that if a user erroneously specifies both options, + rather than doing what the system gnupg would do (that is, do –clearsign, + and ignore the –attach-sign), python-gnupg would ignore both. +</p> +</div> + +</div> + +<div id="outline-container-9-6-2" class="outline-4"> +<h4 id="sec-9-6-2"><span class="section-number-4">9.6.2</span> L626-641:</h4> +<div class="outline-text-4" id="text-9-6-2"> + +<p> input 'args' into self.<sub>open</sub><sub>subprocess</sub>() is defined as static strings. +</p> +</div> +</div> + +</div> + +<div id="outline-container-9-7" class="outline-3"> +<h3 id="sec-9-7"><span class="section-number-3">9.7</span> def verify(self, data): <span class="tag"><span class="cleanup">cleanup</span></span></h3> +<div class="outline-text-3" id="text-9-7"> + + +</div> + +<div id="outline-container-9-7-1" class="outline-4"> +<h4 id="sec-9-7-1"><span class="section-number-4">9.7.1</span> L668-670: <span class="tag"><span class="hanging_fd">hanging_fd</span></span></h4> +<div class="outline-text-4" id="text-9-7-1"> + +<p> same hanging file descriptor problem as in self.sign() +</p> +</div> +</div> + +</div> + +<div id="outline-container-9-8" class="outline-3"> +<h3 id="sec-9-8"><span class="section-number-3">9.8</span> def verify<sub>file</sub>(self, file, data<sub>filename</sub>=None) <span class="tag"><span class="vuln">vuln</span> <span class="cleanup">cleanup</span></span></h3> +<div class="outline-text-3" id="text-9-8"> + + +</div> + +<div id="outline-container-9-8-1" class="outline-4"> +<h4 id="sec-9-8-1"><span class="section-number-4">9.8.1</span> L683: <span class="tag"><span class="hanging_fd">hanging_fd</span></span></h4> +<div class="outline-text-4" id="text-9-8-1"> + +<p> more potentially hanging file descriptors… +</p></div> + +</div> + +<div id="outline-container-9-8-2" class="outline-4"> +<h4 id="sec-9-8-2"><span class="section-number-4">9.8.2</span> L684: <span class="tag"><span class="hanging_fd">hanging_fd</span></span></h4> +<div class="outline-text-4" id="text-9-8-2"> + +<p> oh look, another hanging file descriptor. imagine that. +</p></div> + +</div> + +<div id="outline-container-9-8-3" class="outline-4"> +<h4 id="sec-9-8-3"><span class="section-number-4">9.8.3</span> L690: <span class="tag"><span class="unvalidated_user_input">unvalidated_user_input</span></span></h4> +<div class="outline-text-4" id="text-9-8-3"> + +<pre class="example"> +args.append('"%s"' % data_filename) +</pre> + +<p> well, there's the exploit. see included POC script. +</p> +</div> +</div> + +</div> + +<div id="outline-container-9-9" class="outline-3"> +<h3 id="sec-9-9"><span class="section-number-3">9.9</span> def import<sub>keys</sub>(self, key<sub>data</sub>) <span class="tag"><span class="vuln">vuln</span></span></h3> +<div class="outline-text-3" id="text-9-9"> + + +</div> + +<div id="outline-container-9-9-1" class="outline-4"> +<h4 id="sec-9-9-1"><span class="section-number-4">9.9.1</span> L749: <span class="tag"><span class="unvalidated_user_input">unvalidated_user_input</span></span></h4> +<div class="outline-text-4" id="text-9-9-1"> + +<p> this function could potentially allow an attacker with a GPG exploit to + use it, because it passes key generation parameter directly into the + internal packet parsers of GPG. however, without a GPG exploit for one of + the GPG packet parsers (for explanation of GPG packets look into pgpdump), + this function alone is not exploitable. +</p> +</div> +</div> + +</div> + +<div id="outline-container-9-10" class="outline-3"> +<h3 id="sec-9-10"><span class="section-number-3">9.10</span> def recieve<sub>keys</sub>(self, keyserver, *keyids) <span class="tag"><span class="vuln">vuln</span></span></h3> +<div class="outline-text-3" id="text-9-10"> + + +</div> + +<div id="outline-container-9-10-1" class="outline-4"> +<h4 id="sec-9-10-1"><span class="section-number-4">9.10.1</span> L770: <span class="tag"><span class="unvalidated_user_input">unvalidated_user_input</span></span></h4> +<div class="outline-text-4" id="text-9-10-1"> + +<pre class="example"> +args.extend(keyids) +</pre> + + +</div> +</div> + +</div> + +<div id="outline-container-9-11" class="outline-3"> +<h3 id="sec-9-11"><span class="section-number-3">9.11</span> def export<sub>keys</sub>(self, keyids, secret=False) <span class="tag"><span class="vuln">vuln</span></span></h3> +<div class="outline-text-3" id="text-9-11"> + + +</div> + +<div id="outline-container-9-11-1" class="outline-4"> +<h4 id="sec-9-11-1"><span class="section-number-4">9.11.1</span> L795-796: <span class="tag"><span class="unvalidated_user_input">unvalidated_user_input</span></span></h4> +<div class="outline-text-4" id="text-9-11-1"> + +<p> args problem again. exploitable though parameter ``keyids``. +</p> +</div> +</div> + +</div> + +<div id="outline-container-9-12" class="outline-3"> +<h3 id="sec-9-12"><span class="section-number-3">9.12</span> def list<sub>keys</sub>(self, secret=False)</h3> +<div class="outline-text-3" id="text-9-12"> + + +</div> + +<div id="outline-container-9-12-1" class="outline-4"> +<h4 id="sec-9-12-1"><span class="section-number-4">9.12.1</span> L827:</h4> +<div class="outline-text-4" id="text-9-12-1"> + +<p> args is static string. +</p> +</div> +</div> + +</div> + +<div id="outline-container-9-13" class="outline-3"> +<h3 id="sec-9-13"><span class="section-number-3">9.13</span> def gen<sub>key</sub>(self, input) <span class="tag"><span class="cleanup">cleanup</span></span></h3> +<div class="outline-text-3" id="text-9-13"> + + +</div> + +<div id="outline-container-9-13-1" class="outline-4"> +<h4 id="sec-9-13-1"><span class="section-number-4">9.13.1</span> L864:</h4> +<div class="outline-text-4" id="text-9-13-1"> + +<p> args, passed to self.<sub>handle</sub><sub>io</sub>(), which in turn passes args directly to + Popen(), is set to a static string. this function is halfway okay, though + it really could be more careful with the ``input`` parameter. +</p> +</div> +</div> + +</div> + +<div id="outline-container-9-14" class="outline-3"> +<h3 id="sec-9-14"><span class="section-number-3">9.14</span> def gen<sub>key</sub><sub>input</sub>(self, **kwargs) <span class="tag"><span class="vuln">vuln</span></span></h3> +<div class="outline-text-3" id="text-9-14"> + + +</div> + +<div id="outline-container-9-14-1" class="outline-4"> +<h4 id="sec-9-14-1"><span class="section-number-4">9.14.1</span> L981-983: <span class="tag"><span class="unvalidated_user_input">unvalidated_user_input</span></span></h4> +<div class="outline-text-4" id="text-9-14-1"> + +<p> this function could potentially allow an attacker with a GPG exploit to + use it, because it passes key generation parameter directly into the + internal packet parsers of GPG. however, without a GPG exploit for one of + the GPG packet parsers (for explanation of GPG packets look into pgpdump), + this function alone is not exploitable. +</p> +</div> +</div> + +</div> + +<div id="outline-container-9-15" class="outline-3"> +<h3 id="sec-9-15"><span class="section-number-3">9.15</span> def encrypt<sub>file</sub>(self, file, recipiencts, sign=None, …) <span class="tag"><span class="vuln">vuln</span></span></h3> +<div class="outline-text-3" id="text-9-15"> + + +</div> + +<div id="outline-container-9-15-1" class="outline-4"> +<h4 id="sec-9-15-1"><span class="section-number-4">9.15.1</span> L939: <span class="tag"><span class="unvalidated_user_input">unvalidated_user_input</span></span></h4> +<div class="outline-text-4" id="text-9-15-1"> + +<p> several of the inputs to this function are unvalidated, turned into + strings, and passed to Popen(). exploitable. +</p> +</div> +</div> + +</div> + +<div id="outline-container-9-16" class="outline-3"> +<h3 id="sec-9-16"><span class="section-number-3">9.16</span> def encrypt(self, data, recipients, **kwargs): <span class="tag"><span class="vuln">vuln</span></span></h3> +<div class="outline-text-3" id="text-9-16"> + + +</div> + +<div id="outline-container-9-16-1" class="outline-4"> +<h4 id="sec-9-16-1"><span class="section-number-4">9.16.1</span> L997: <span class="tag"><span class="unvalidated_user_input">unvalidated_user_input</span></span></h4> +<div class="outline-text-4" id="text-9-16-1"> + +<p> exploitable, passes kwargs to self.encrypt<sub>file</sub>() +</p> +</div> +</div> + +</div> + +<div id="outline-container-9-17" class="outline-3"> +<h3 id="sec-9-17"><span class="section-number-3">9.17</span> def decrypt(self, message **kwargs): <span class="tag"><span class="vuln">vuln</span></span></h3> +<div class="outline-text-3" id="text-9-17"> + + +</div> + +<div id="outline-container-9-17-1" class="outline-4"> +<h4 id="sec-9-17-1"><span class="section-number-4">9.17.1</span> L1003: <span class="tag"><span class="unvalidated_user_input">unvalidated_user_input</span></span></h4> +<div class="outline-text-4" id="text-9-17-1"> + +<p> kwargs are passed to self.decrypt<sub>file</sub>(), unvalidated, making this + function also exploitable +</p> +</div> +</div> + +</div> + +<div id="outline-container-9-18" class="outline-3"> +<h3 id="sec-9-18"><span class="section-number-3">9.18</span> def decrypt<sub>file</sub>(self, file, always<sub>trust</sub>=False, passphrase=None, output=None) <span class="tag"><span class="vuln">vuln</span></span></h3> +<div class="outline-text-3" id="text-9-18"> + + +</div> + +<div id="outline-container-9-18-1" class="outline-4"> +<h4 id="sec-9-18-1"><span class="section-number-4">9.18.1</span> L1013: <span class="tag"><span class="unvalidated_user_input">unvalidated_user_input</span></span></h4> +<div class="outline-text-4" id="text-9-18-1"> + +<p> unvalidated user input: this function is also exploitable +</p> +</div> +</div> +</div> + +</div> + +<div id="outline-container-10" class="outline-2"> +<h2 id="sec-10"><span class="section-number-2">10</span> POC</h2> +<div class="outline-text-2" id="text-10"> + +<p>CANNOT INCLUDE FILE ../python-gnupg-0.3.1/python-gnupg-exploit.py +</p></div> +</div> +</div> + +<div id="postamble"> +<p class="date">Date: 2013-02-01 Fri</p> +<p class="author">Author: isis</p> +<p class="email"><a href="mailto:isis@leap.se">isis@leap.se</a></p> +<p class="creator"><a href="http://orgmode.org">Org</a> version 7.9.2 with <a href="http://www.gnu.org/software/emacs/">Emacs</a> version 24</p> +<a href="http://validator.w3.org/check?uri=referer">Validate XHTML 1.0</a> + +</div> +</body> +</html> diff --git a/docs/NOTES-python-gnupg-3.1-audit.org b/docs/NOTES-python-gnupg-3.1-audit.org new file mode 100644 index 0000000..b80fb39 --- /dev/null +++ b/docs/NOTES-python-gnupg-3.1-audit.org @@ -0,0 +1,232 @@ +#+TITLE: python-gnupg audit +#+AUTHOR: isis +#+EMAIL: isis@leap.se +#+DATE: 2013-02-01 Fri +#+DESCRIPTION: +#+KEYWORDS: +#+LANGUAGE: en +#+OPTIONS: H:3 num:t toc:t \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t +#+OPTIONS: TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc +#+INFOJS_OPT: view:nil toc:2 ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js +#+EXPORT_SELECT_TAGS: export +#+EXPORT_EXCLUDE_TAGS: noexport +#+LINK_UP: +#+LINK_HOME: +#+XSLT: + +[2013-02-01 Fri] + +* gnugp.__main__() +** comments +L58 NullHandler?? see self._write_passphrase +L61 there nifty check for p3k +** def _copy_data(instream, outstream) :cleanup: + copies data from one stream to another, 1024 bytes at a time. +*** L79: :bad_logic: + instream is apparently a file descriptor, but is not checked nor + encased in a try/except block. + +*** L78: :hanging_fd:bad_logic: + while True: loop, should be + : with open(instream) as instrm: +*** L88: :bad_exception_handling: + : except: + should catch an IOError, or whatever specific error is raised for broken + pipes. +** def _threaded_copy_data(instream, outstream): +*** L99: + this just wraps self._copy_data in a thread +** def _write_passphrase(stream, passphrase, encoding): :vuln:cleanup: +*** L110: :writes_passphrase_to_disk: + logger writes passphrase into debug log. this should be patched. +* class Verify(object) + basic parsing class, no errors found +* class ImportResult(object) + basic parsing class, no errors found +* class ListKeys(list): + basic parsing class, no errors found +* class Crypt(Verify): + basic parsing class, no errors found +** def __init__(self, gpg) :cleanup: +*** L338 :mro_conflict: + + #+BEGIN_SRC python + Verify.__init__(self,gpg) + #+END_SRC + + should be changed to: + + #+BEGIN_SRC python + super(Verify, self).__init__(gpg) + #+END_SRC +* class GenKey(object) + basic parsing class, no errors found +* class DeleteResult(object) + basic parsing class, no errors found +* class Sign(object) + basic parsing class, no errors found +* class GPG(object) :exploitable: +*** L474: :cleanup: + : cls.__doc__ + should go directly underneath class signature +** def __init__(self, gpgbinary='gpg', gnupghome=None, verbose=False, use_agent=False, keyring=None) :bug: +*** L494-495: :type_error: + + #+BEGIN_SRC python + if gnupghome and not os.path.isdir(self.gnupghome): + os.makedirs(self.gnupghome,0x1C0) + #+END_SRC + + #+BEGIN_EXAMPLE + In [20]: os.makedirs? + Type: function + String Form:<function makedirs at 0x7f8ddeb6cc08> + File: /usr/lib/python2.7/os.py + Definition: os.makedirs(name, mode=511) + Docstring: + makedirs(path [, mode=0777]) + Super-mkdir; create a leaf directory and all intermediate ones. + Works like mkdir, except that any intermediate path segment (not + just the rightmost) will be created if it does not exist. This is + recursive. + + setting mode=0x1c0 is equivalent to mode=hex(0700), which + may cause bugs on some systems, see + http://ubuntuforums.org/showthread.php?t=2044879 + + this could be do to the complete lack of input validation in + os.makedirs, and it's calling of the os.mkdir() built-in, which + may vary depending on the python compilation: + #+END_EXAMPLE + + #+BEGIN_SRC python + Source: + def makedirs(name, mode=0777): + """makedirs(path [, mode=0777]) + + Super-mkdir; create a leaf directory and all intermediate ones. + Works like mkdir, except that any intermediate path segment (not + just the rightmost) will be created if it does not exist. This is + recursive. + """ + head, tail = path.split(name) + if not tail: + head, tail = path.split(head) + if head and tail and not path.exists(head): + try: + makedirs(head, mode) + except OSError, e: + # be happy if someone already created the path + if e.errno != errno.EEXIST: + raise + if tail == curdir: # xxx/newdir/. exists if xxx/newdir exists + return + mkdir(name, mode) + #+END_SRC + +** def _open_subprocess(self, args, passphrase=False) :vuln: +*** L515: :unvalidated_user_input: + : cmd.extend(args) + + cmd is a list of strings, eventually joined with cmd=' '.join(cmd), and + the args are unvalidated in this function. Then this concatenation of args + is fed directly into subprocess.Popen(cmd, shell=True, stdin=PIPE, + stdout=PIPE, stderr=PIPE). THIS SHOULD BE PATCHED. + +** def _collect_output(self, process, result, writer=None, stdin=None) + sends stdout to self._read_data() and stderr to self._read_response() + +** def _handle_io(self, args, file, result, passphrase=None, binary=False) :vuln:cleanup: +*** L601: :unvalidated_user_input:type_check_in_call: + : p = self._open_subprocess(args, passphrase is not None) + + you shouldn't assign or type check in a function call + +** def sign(self, message, **kwargs) :cleanup: +*** L617-619: :hanging_fd: + calls self._make_binary_stream(), which leaves the file descriptor for + the encoded message to be encrypted hanging between scopes. + +** def sign_file(self, file, keyid=None, passphrase=None, clearsign=True, detach=False, binary=False) :cleanup: +*** L632-635: :bad_logic: + #+BEGIN_SRC python + if detach: + args.append("--detach-sign") + elif clearsign: + args.append("--clearsign") + #+END_SRC + + the logic here allows that if a user erroneously specifies both options, + rather than doing what the system gnupg would do (that is, do --clearsign, + and ignore the --attach-sign), python-gnupg would ignore both. + +*** L626-641: + input 'args' into self._open_subprocess() is defined as static strings. + +** def verify(self, data): :cleanup: +*** L668-670: :hanging_fd: + same hanging file descriptor problem as in self.sign() + +** def verify_file(self, file, data_filename=None) :vuln:cleanup: +*** L683: :hanging_fd: + more potentially hanging file descriptors... +*** L684: :hanging_fd: + oh look, another hanging file descriptor. imagine that. +*** L690: :unvalidated_user_input: + : args.append('"%s"' % data_filename) + well, there's the exploit. see included POC script. + +** def import_keys(self, key_data) :vuln: +*** L749: :unvalidated_user_input: + this function could potentially allow an attacker with a GPG exploit to + use it, because it passes key generation parameter directly into the + internal packet parsers of GPG. however, without a GPG exploit for one of + the GPG packet parsers (for explanation of GPG packets look into pgpdump), + this function alone is not exploitable. + +** def recieve_keys(self, keyserver, *keyids) :vuln: +*** L770: :unvalidated_user_input: + : args.extend(keyids) + +** def export_keys(self, keyids, secret=False) :vuln: +*** L795-796: :unvalidated_user_input: + args problem again. exploitable though parameter ``keyids``. + +** def list_keys(self, secret=False) +*** L827: + args is static string. + +** def gen_key(self, input) :cleanup: +*** L864: + args, passed to self._handle_io(), which in turn passes args directly to + Popen(), is set to a static string. this function is halfway okay, though + it really could be more careful with the ``input`` parameter. + +** def gen_key_input(self, **kwargs) :vuln: +*** L981-983: :unvalidated_user_input: + this function could potentially allow an attacker with a GPG exploit to + use it, because it passes key generation parameter directly into the + internal packet parsers of GPG. however, without a GPG exploit for one of + the GPG packet parsers (for explanation of GPG packets look into pgpdump), + this function alone is not exploitable. + +** def encrypt_file(self, file, recipiencts, sign=None, ...) :vuln: +*** L939: :unvalidated_user_input: + several of the inputs to this function are unvalidated, turned into + strings, and passed to Popen(). exploitable. + +** def encrypt(self, data, recipients, **kwargs): :vuln: +*** L997: :unvalidated_user_input: + exploitable, passes kwargs to self.encrypt_file() + +** def decrypt(self, message **kwargs): :vuln: +*** L1003: :unvalidated_user_input: + kwargs are passed to self.decrypt_file(), unvalidated, making this + function also exploitable + +** def decrypt_file(self, file, always_trust=False, passphrase=None, output=None) :vuln: +*** L1013: :unvalidated_user_input: + unvalidated user input: this function is also exploitable + +* POC +#+INCLUDE: "../python-gnupg-0.3.1/python-gnupg-exploit.py" python diff --git a/docs/NOTES-python-openpgp-implementations.txt b/docs/NOTES-python-openpgp-implementations.txt new file mode 100644 index 0000000..bf60728 --- /dev/null +++ b/docs/NOTES-python-openpgp-implementations.txt @@ -0,0 +1,31 @@ +-*- mode: org -*- + +* Other Python OpenPGP libraries and utilities: + +*** pygpgme - https://launchpad.net/pygpgme +A limited set of Python wrappers around GPGME +http://www.gnupg.org/documentation/manuals/gpgme/ + +*** py-gnupg - https://github.com/kevinoid/py-gnupg/blob/master/GnuPGInterface.py +Focuses mainly on using file handles to interact with GnuPG. + +*** OpenPGP-Python - https://github.com/singpolyma/OpenPGP-Python +The commit messages are a bit worrysome and the code has some scary +error-prone-looking method chaining going on, a five minute glance over the +/OpenPGP/Crypto.py file and it appears this is actually a valid OpenPGP +implementation, built using D.Litzenberger's PyCrypto library. +https://github.com/dlitz/pycrypto + +This person also wrote OpenPGP-Haskell: +https://github.com/singpolyma/OpenPGP-Haskell + +...and OpenPGP-PHP (/horrorface): https://github.com/singpolyma/openpgp-php and +an HTTP server as a shell script with a pretty crazy pipe hack. + +...and kudos on this one, it's an attempt at a mnemnonic system for squaring +Zooko's Triangle (L17 being a function named "countLeadingCrapAndZeros"): +https://github.com/singpolyma/mnemonicode/blob/master/mnencode.c#L17 + +* GnuPG unattended key generation scripts: + +*** mandos-keygen http://bzr.recompile.se/loggerhead/mandos/trunk/annotate/523/mandos-keygen?start_revid=616 diff --git a/docs/OpenPGP-keys-in-DNS.md b/docs/OpenPGP-keys-in-DNS.md new file mode 100644 index 0000000..56cb542 --- /dev/null +++ b/docs/OpenPGP-keys-in-DNS.md @@ -0,0 +1,133 @@ +[Christoph Berg's Blog](../index.html)/ + +[2007](../2007.html)/ + +</span> +<span class="title"> +OpenPGP keys in DNS + +</span> +</span> + +</div> + +<div class="actions"> + +* [RecentChanges](../recentchanges.html) +* [History](http://svn.df7cb.de/viewcvs.cgi/trunk/2007/openpgp-dns.mdwn?root=blog&view=log) +</div> + +</div> + +<div id="pagebody"> + +<div id="content"> + +The latest addition to the mutt CVS tree is PKA support via gpgme. While trying +to figure out how that works in mutt (I haven't yet...) I configured my DNS +server for PKA and CERT records. + +## PKA + +PKA (public key association) puts a pointer where to obtain a key into a TXT +record. At the same time that can be used to verify that a key belongs to a +mail address. The documentation is at the +[g10code website](http://www.g10code.de/docs/pka-intro.de.pdf) +(only in German so far). I put the following into the df7cb.de zone: + +<p> +cb._pka IN TXT "v=pka1;fpr=D224C8B07E63A6946DA32E07C5AF774A58510B5A;uri=finger:cb@df7cb.de" + +<pre> +$ host -t TXT cb._pka.df7cb.de +cb._pka.df7cb.de descriptive text "v=pka1\;fpr=D224C8B07E63A6946DA32E07C5AF774A58510B5A\;uri=finger:cb@df7cb.de" +</pre> + +Now gpg can be told to use PKA to find the key: + +<pre> +$ echo foo | gpg --auto-key-locate pka --recipient cb@df7cb.de --encrypt -a +gpg: no keyserver known (use option --keyserver) +gpg: requesting key 58510B5A from finger:cb@df7cb.de +gpg: key 58510B5A: public key "Christoph Berg " imported +gpg: Total number processed: 1 +gpg: imported: 1 +gpg: automatically retrieved `cb@df7cb.de' via PKA +</pre> + +## CERT + +CERT records work similarly. Records are generated by make-dns-cert (from the +tools directory in the gnupg source). cb.gpg is a stripped-down gpg keyring +(created with pgp-clean -s and converting from .asc to .gpg). + +<pre> +$ ./make-dns-cert -f D224C8B07E63A6946DA32E07C5AF774A58510B5A -n cb +cb TYPE37 \# 26 0006 0000 00 14 D224C8B07E63A6946DA32E07C5AF774A58510B5A +$ ./make-dns-cert -k cb.gpg -n cb +cb TYPE37 \# 1338 0003 0000 00 9901A20440 [...] 509C96D4BFF17B7 +</pre> + +With a new bind and host (backports.org!) the format looks a bit nicer, that's +also what I copied into the zone file: + +<pre> +$ host -t CERT cb.df7cb.de +;; Truncated, retrying in TCP mode. +cb.df7cb.de has CERT record PGP 0 0 mQGiBECBGdAR [...] UDlCcltS/8Xtw== +cb.df7cb.de has CERT record 6 0 0 FNIkyLB+Y6aUbaMuB8Wvd0pYUQta +</pre> + +Again, gpg can be told to use that: + +<pre> +$ echo foo | gpg --auto-key-locate cert --recipient cb@df7cb.de --encrypt -a +gpg: key 58510B5A: public key "Christoph Berg " imported +gpg: Total number processed: 1 +gpg: imported: 1 +gpg: automatically retrieved `cb@df7cb.de' via DNS CERT +</pre> + +Thanks to weasel for some hints on using CERT. + +## SSHFP + +I'm also mentioning SSHFP records here since it fits in the topic - I have been +using them for some months now: + +<pre> +$ host -t SSHFP tesla.df7cb.de +tesla.df7cb.de has SSHFP record 1 1 EE49B803541293656C33B86ECD781BD8F1D78AB5 +tesla.df7cb.de has SSHFP record 2 1 3E82FB5EE8AA0205305F0D0186F94D6FB3E0E744 +$ ssh -o 'VerifyHostKeyDNS yes' tesla.df7cb.de +The authenticity of host 'tesla.df7cb.de (88.198.227.218)' can't be established. +RSA key fingerprint is 5a:c9:38:ca:c0:2b:11:c1:c8:fb:f1:ad:73:a1:9c:8b. +Matching host key fingerprint found in DNS. +Are you sure you want to continue connecting (yes/no)? +</pre> + +The records are generated with ssh-keygen -r. + +</div> + +</div> + +<div id="footer" class="pagefooter"> + +<div id="pageinfo"> + +<div class="tags"> +Tags: + +[debian](../tag/debian.html) + +</div> + +<div class="pagedate"> +Last edited <span class="date">Do 17 Feb 2011 13:21:52 CET</span> +<!-- Created <span class="date">Do 01 Mär 2007 20:01:27 CET</span> --> +</div> + +</div> + +<!-- from Christoph Berg's Blog --> diff --git a/docs/_static/DETAILS.html b/docs/_static/DETAILS.html new file mode 100644 index 0000000..7b0b9f8 --- /dev/null +++ b/docs/_static/DETAILS.html @@ -0,0 +1,2677 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> +<head> +<title>GnuPG Details</title> +<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> +<meta name="title" content="GnuPG Details"/> +<meta name="generator" content="Org-mode"/> +<meta name="generated" content="2013-07-03T09:52+0000"/> +<meta name="author" content="isis"/> +<meta name="description" content=""/> +<meta name="keywords" content=""/> +<style type="text/css"> + <!--/*--><![CDATA[/*><!--*/ + html { font-family: Times, serif; font-size: 12pt; } + .title { text-align: center; } + .todo { color: red; } + .done { color: green; } + .tag { background-color: #add8e6; font-weight:normal } + .target { } + .timestamp { color: #bebebe; } + .timestamp-kwd { color: #5f9ea0; } + .right {margin-left:auto; margin-right:0px; text-align:right;} + .left {margin-left:0px; margin-right:auto; text-align:left;} + .center {margin-left:auto; margin-right:auto; text-align:center;} + p.verse { margin-left: 3% } + pre { + border: 1pt solid #AEBDCC; + background-color: #F3F5F7; + padding: 5pt; + font-family: courier, monospace; + font-size: 90%; + overflow:auto; + } + table { border-collapse: collapse; } + td, th { vertical-align: top; } + th.right { text-align:center; } + th.left { text-align:center; } + th.center { text-align:center; } + td.right { text-align:right; } + td.left { text-align:left; } + td.center { text-align:center; } + dt { font-weight: bold; } + div.figure { padding: 0.5em; } + div.figure p { text-align: center; } + div.inlinetask { + padding:10px; + border:2px solid gray; + margin:10px; + background: #ffffcc; + } + textarea { overflow-x: auto; } + .linenr { font-size:smaller } + .code-highlighted {background-color:#ffff00;} + .org-info-js_info-navigation { border-style:none; } + #org-info-js_console-label { font-size:10px; font-weight:bold; + white-space:nowrap; } + .org-info-js_search-highlight {background-color:#ffff00; color:#000000; + font-weight:bold; } + /*]]>*/--> +</style> +<script type="text/javascript"> +/* +@licstart The following is the entire license notice for the +JavaScript code in this tag. + +Copyright (C) 2012 Free Software Foundation, Inc. + +The JavaScript code in this tag is free software: you can +redistribute it and/or modify it under the terms of the GNU +General Public License (GNU GPL) as published by the Free Software +Foundation, either version 3 of the License, or (at your option) +any later version. The code is distributed WITHOUT ANY WARRANTY; +without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. + +As additional permission under GNU GPL version 3 section 7, you +may distribute non-source (e.g., minimized or compacted) forms of +that code without the copy of the GNU GPL normally required by +section 4, provided you include this license notice and a URL +through which recipients can access the Corresponding Source. + + +@licend The above is the entire license notice +for the JavaScript code in this tag. +*/ +<!--/*--><![CDATA[/*><!--*/ + function CodeHighlightOn(elem, id) + { + var target = document.getElementById(id); + if(null != target) { + elem.cacheClassElem = elem.className; + elem.cacheClassTarget = target.className; + target.className = "code-highlighted"; + elem.className = "code-highlighted"; + } + } + function CodeHighlightOff(elem, id) + { + var target = document.getElementById(id); + if(elem.cacheClassElem) + elem.className = elem.cacheClassElem; + if(elem.cacheClassTarget) + target.className = elem.cacheClassTarget; + } +/*]]>*///--> +</script> +<script type="text/css" href="./agogo.css" /> +</head> +<body> + +<div id="preamble"> + +</div> + +<div id="content"> +<h1 class="title">GnuPG Details</h1> + + +<p> +This is the DETAILS file for GnuPG which specifies some internals and +parts of the external API for GPG and GPGSM. +</p> + +<div id="table-of-contents"> +<h2>Table of Contents</h2> +<div id="text-table-of-contents"> +<ul> +<li><a href="#sec-1">1 Format of the colon listings</a> +<ul> +<li><a href="#sec-1-1">1.1 Description of the fields</a> +<ul> +<li><a href="#sec-1-1-1">1.1.1 Field 1 - Type of record</a></li> +<li><a href="#sec-1-1-2">1.1.2 Field 2 - Validity</a></li> +<li><a href="#sec-1-1-3">1.1.3 Field 3 - Key length</a></li> +<li><a href="#sec-1-1-4">1.1.4 Field 4 - Public key algorithm</a></li> +<li><a href="#sec-1-1-5">1.1.5 Field 5 - KeyID</a></li> +<li><a href="#sec-1-1-6">1.1.6 Field 6 - Creation date</a></li> +<li><a href="#sec-1-1-7">1.1.7 Field 7 - Expiration date</a></li> +<li><a href="#sec-1-1-8">1.1.8 Field 8 - Certificate S/N, UID hash, trust signature info</a></li> +<li><a href="#sec-1-1-9">1.1.9 Field 9 - Ownertrust</a></li> +<li><a href="#sec-1-1-10">1.1.10 Field 10 - User-ID</a></li> +<li><a href="#sec-1-1-11">1.1.11 Field 11 - Signature class</a></li> +<li><a href="#sec-1-1-12">1.1.12 Field 12 - Key capabilities</a></li> +<li><a href="#sec-1-1-13">1.1.13 Field 13 - Issuer certificate fingerprint or other info</a></li> +<li><a href="#sec-1-1-14">1.1.14 Field 14 - Flag field</a></li> +<li><a href="#sec-1-1-15">1.1.15 Field 15 - S/N of a token</a></li> +<li><a href="#sec-1-1-16">1.1.16 Field 16 - Hash algorithm</a></li> +</ul> +</li> +<li><a href="#sec-1-2">1.2 Special fields</a> +<ul> +<li><a href="#sec-1-2-1">1.2.1 PKD - Public key data</a></li> +<li><a href="#sec-1-2-2">1.2.2 TRU - Trust database information</a></li> +<li><a href="#sec-1-2-3">1.2.3 SPK - Signature subpacket records</a></li> +<li><a href="#sec-1-2-4">1.2.4 CFG - Configuration data</a></li> +</ul></li> +</ul> +</li> +<li><a href="#sec-2">2 Format of the –status-fd output</a> +<ul> +<li><a href="#sec-2-1">2.1 General status codes</a> +<ul> +<li><a href="#sec-2-1-1">2.1.1 NEWSIG</a></li> +<li><a href="#sec-2-1-2">2.1.2 GOODSIG <long_keyid_or_fpr> <username></a></li> +<li><a href="#sec-2-1-3">2.1.3 EXPSIG <long_keyid_or_fpr> <username></a></li> +<li><a href="#sec-2-1-4">2.1.4 EXPKEYSIG <long_keyid_or_fpr> <username></a></li> +<li><a href="#sec-2-1-5">2.1.5 REVKEYSIG <long_keyid_or_fpr> <username></a></li> +<li><a href="#sec-2-1-6">2.1.6 BADSIG <long_keyid_or_fpr> <username></a></li> +<li><a href="#sec-2-1-7">2.1.7 ERRSIG <keyid> <pkalgo> <hashalgo> <sig_class> <time> <rc></a></li> +<li><a href="#sec-2-1-8">2.1.8 VALIDSIG <args></a></li> +<li><a href="#sec-2-1-9">2.1.9 SIG_ID <radix64_string> <sig_creation_date> <sig-timestamp></a></li> +<li><a href="#sec-2-1-10">2.1.10 ENC_TO <long_keyid> <keytype> <keylength></a></li> +<li><a href="#sec-2-1-11">2.1.11 BEGIN_DECRYPTION</a></li> +<li><a href="#sec-2-1-12">2.1.12 END_DECRYPTION</a></li> +<li><a href="#sec-2-1-13">2.1.13 DECRYPTION_INFO <mdc_method> <sym_algo></a></li> +<li><a href="#sec-2-1-14">2.1.14 DECRYPTION_FAILED</a></li> +<li><a href="#sec-2-1-15">2.1.15 DECRYPTION_OKAY</a></li> +<li><a href="#sec-2-1-16">2.1.16 SESSION_KEY <algo>:<hexdigits></a></li> +<li><a href="#sec-2-1-17">2.1.17 BEGIN_ENCRYPTION <mdc_method> <sym_algo></a></li> +<li><a href="#sec-2-1-18">2.1.18 END_ENCRYPTION</a></li> +<li><a href="#sec-2-1-19">2.1.19 FILE_START <what> <filename></a></li> +<li><a href="#sec-2-1-20">2.1.20 FILE_DONE</a></li> +<li><a href="#sec-2-1-21">2.1.21 BEGIN_SIGNING</a></li> +<li><a href="#sec-2-1-22">2.1.22 ALREADY_SIGNED <long-keyid></a></li> +<li><a href="#sec-2-1-23">2.1.23 SIG_CREATED <type> <pk_algo> <hash_algo> <class> <timestamp> <keyfpr></a></li> +<li><a href="#sec-2-1-24">2.1.24 NOTATION_</a></li> +<li><a href="#sec-2-1-25">2.1.25 POLICY_URL <string></a></li> +<li><a href="#sec-2-1-26">2.1.26 PLAINTEXT <format> <timestamp> <filename></a></li> +<li><a href="#sec-2-1-27">2.1.27 PLAINTEXT_LENGTH <length></a></li> +<li><a href="#sec-2-1-28">2.1.28 ATTRIBUTE <arguments></a></li> +<li><a href="#sec-2-1-29">2.1.29 SIG_SUBPACKET <type> <flags> <len> <data></a></li> +</ul> +</li> +<li><a href="#sec-2-2">2.2 Key related</a> +<ul> +<li><a href="#sec-2-2-1">2.2.1 INV_RECP, INV_SGNR</a></li> +<li><a href="#sec-2-2-2">2.2.2 NO_RECP <reserved></a></li> +<li><a href="#sec-2-2-3">2.2.3 NO_SGNR <reserved></a></li> +<li><a href="#sec-2-2-4">2.2.4 KEYEXPIRED <expire-timestamp></a></li> +<li><a href="#sec-2-2-5">2.2.5 KEYREVOKED</a></li> +<li><a href="#sec-2-2-6">2.2.6 NO_PUBKEY <long keyid></a></li> +<li><a href="#sec-2-2-7">2.2.7 NO_SECKEY <long keyid></a></li> +<li><a href="#sec-2-2-8">2.2.8 KEY_CREATED <type> <fingerprint> [<handle>]</a></li> +<li><a href="#sec-2-2-9">2.2.9 KEY_NOT_CREATED [<handle>]</a></li> +<li><a href="#sec-2-2-10">2.2.10 TRUST_</a></li> +<li><a href="#sec-2-2-11">2.2.11 PKA_TRUST_</a></li> +</ul> +</li> +<li><a href="#sec-2-3">2.3 Remote control</a> +<ul> +<li><a href="#sec-2-3-1">2.3.1 GET_BOOL, GET_LINE, GET_HIDDEN, GOT_IT</a></li> +<li><a href="#sec-2-3-2">2.3.2 USERID_HINT <long main keyid> <string></a></li> +<li><a href="#sec-2-3-3">2.3.3 NEED_PASSPHRASE <long keyid> <long main keyid> <keytype> <keylength></a></li> +<li><a href="#sec-2-3-4">2.3.4 NEED_PASSPHRASE_SYM <cipher_algo> <s2k_mode> <s2k_hash></a></li> +<li><a href="#sec-2-3-5">2.3.5 NEED_PASSPHRASE_PIN <card_type> <chvno> [<serialno>]</a></li> +<li><a href="#sec-2-3-6">2.3.6 MISSING_PASSPHRASE</a></li> +<li><a href="#sec-2-3-7">2.3.7 BAD_PASSPHRASE <long keyid></a></li> +<li><a href="#sec-2-3-8">2.3.8 GOOD_PASSPHRASE</a></li> +</ul> +</li> +<li><a href="#sec-2-4">2.4 Import/Export</a> +<ul> +<li><a href="#sec-2-4-1">2.4.1 IMPORT_CHECK <long keyid> <fingerprint> <user ID></a></li> +<li><a href="#sec-2-4-2">2.4.2 IMPORTED <long keyid> <username></a></li> +<li><a href="#sec-2-4-3">2.4.3 IMPORT_OK <reason> [<fingerprint>]</a></li> +<li><a href="#sec-2-4-4">2.4.4 IMPORT_PROBLEM <reason> [<fingerprint>]</a></li> +<li><a href="#sec-2-4-5">2.4.5 IMPORT_RES <args></a></li> +</ul> +</li> +<li><a href="#sec-2-5">2.5 Smartcard related</a> +<ul> +<li><a href="#sec-2-5-1">2.5.1 CARDCTRL <what> [<serialno>]</a></li> +<li><a href="#sec-2-5-2">2.5.2 SC_OP_FAILURE [<code>]</a></li> +<li><a href="#sec-2-5-3">2.5.3 SC_OP_SUCCESS</a></li> +</ul> +</li> +<li><a href="#sec-2-6">2.6 Miscellaneous status codes</a> +<ul> +<li><a href="#sec-2-6-1">2.6.1 NODATA <what></a></li> +<li><a href="#sec-2-6-2">2.6.2 UNEXPECTED <what></a></li> +<li><a href="#sec-2-6-3">2.6.3 TRUNCATED <maxno></a></li> +<li><a href="#sec-2-6-4">2.6.4 ERROR <error location> <error code> [<more>]</a></li> +<li><a href="#sec-2-6-5">2.6.5 SUCCESS [<location>]</a></li> +<li><a href="#sec-2-6-6">2.6.6 BADARMOR</a></li> +<li><a href="#sec-2-6-7">2.6.7 DELETE_PROBLEM <reason_code></a></li> +<li><a href="#sec-2-6-8">2.6.8 PROGRESS <what> <char> <cur> <total></a></li> +<li><a href="#sec-2-6-9">2.6.9 BACKUP_KEY_CREATED <fingerprint> <fname></a></li> +<li><a href="#sec-2-6-10">2.6.10 MOUNTPOINT <name></a></li> +<li><a href="#sec-2-6-11">2.6.11 PINENTRY_LAUNCHED <pid></a></li> +</ul> +</li> +<li><a href="#sec-2-7">2.7 Obsolete status codes</a> +<ul> +<li><a href="#sec-2-7-1">2.7.1 SIGEXPIRED</a></li> +<li><a href="#sec-2-7-2">2.7.2 RSA_OR_IDEA</a></li> +<li><a href="#sec-2-7-3">2.7.3 SHM_INFO, SHM_GET, SHM_GET_BOOL, SHM_GET_HIDDEN</a></li> +<li><a href="#sec-2-7-4">2.7.4 BEGIN_STREAM, END_STREAM</a></li> +</ul></li> +</ul> +</li> +<li><a href="#sec-3">3 Format of the –attribute-fd output</a></li> +<li><a href="#sec-4">4 Unattended key generation</a></li> +<li><a href="#sec-5">5 Layout of the TrustDB</a></li> +<li><a href="#sec-6">6 GNU extensions to the S2K algorithm</a></li> +<li><a href="#sec-7">7 Keyserver helper message format</a></li> +<li><a href="#sec-8">8 Object identifiers</a></li> +<li><a href="#sec-9">9 Miscellaneous notes</a> +<ul> +<li><a href="#sec-9-1">9.1 v3 fingerprints</a></li> +<li><a href="#sec-9-2">9.2 Simplified revocation certificates</a></li> +<li><a href="#sec-9-3">9.3 Documentation on HKP (the http keyserver protocol):</a></li> +</ul> +</li> +</ul> +</div> +</div> + +<div id="outline-container-1" class="outline-2"> +<h2 id="sec-1"><span class="section-number-2">1</span> Format of the colon listings</h2> +<div class="outline-text-2" id="text-1"> + +<p> The format is a based on colon separated record, each recods starts + with a tag string and extends to the end of the line. Here is an + example: +</p> + + +<pre class="example">$ gpg --with-colons --list-keys \ + --with-fingerprint --with-fingerprint wk@gnupg.org +pub:f:1024:17:6C7EE1B8621CC013:899817715:1055898235::m:::scESC: +fpr:::::::::ECAF7590EB3443B5C7CF3ACB6C7EE1B8621CC013: +uid:f::::::::Werner Koch <wk@g10code.com>: +uid:f::::::::Werner Koch <wk@gnupg.org>: +sub:f:1536:16:06AD222CADF6A6E1:919537416:1036177416:::::e: +fpr:::::::::CF8BCC4B18DE08FCD8A1615906AD222CADF6A6E1: +sub:r:1536:20:5CE086B5B5A18FF4:899817788:1025961788:::::esc: +fpr:::::::::AB059359A3B81F410FCFF97F5CE086B5B5A18FF4: +</pre> + + +<p> +The double <code>--with-fingerprint</code> prints the fingerprint for the subkeys +too. Old versions of gpg used a lighly different format and required +the use of the option <code>--fixed-list-mode</code> to conform to format +described here. +</p> + +</div> + +<div id="outline-container-1-1" class="outline-3"> +<h3 id="sec-1-1"><span class="section-number-3">1.1</span> Description of the fields</h3> +<div class="outline-text-3" id="text-1-1"> + + +</div> + +<div id="outline-container-1-1-1" class="outline-4"> +<h4 id="sec-1-1-1"><span class="section-number-4">1.1.1</span> Field 1 - Type of record</h4> +<div class="outline-text-4" id="text-1-1-1"> + + +<dl> +<dt>pub</dt><dd>Public key +</dd> +<dt>crt</dt><dd>X.509 certificate +</dd> +<dt>crs</dt><dd>X.509 certificate and private key available +</dd> +<dt>sub</dt><dd>Subkey (secondary key) +</dd> +<dt>sec</dt><dd>Secret key +</dd> +<dt>ssb</dt><dd>Secret subkey (secondary key) +</dd> +<dt>uid</dt><dd>User id (only field 10 is used). +</dd> +<dt>uat</dt><dd>User attribute (same as user id except for field 10). +</dd> +<dt>sig</dt><dd>Signature +</dd> +<dt>rev</dt><dd>Revocation signature +</dd> +<dt>fpr</dt><dd>Fingerprint (fingerprint is in field 10) +</dd> +<dt>pkd</dt><dd>Public key data [*] +</dd> +<dt>grp</dt><dd>Keygrip +</dd> +<dt>rvk</dt><dd>Revocation key +</dd> +<dt>tru</dt><dd>Trust database information [*] +</dd> +<dt>spk</dt><dd>Signature subpacket [*] +</dd> +<dt>cfg</dt><dd>Configuration data [*] +</dd> +</dl> + + +<p> + Records marked with an asterisk are described at <a href="#Special-field-formats">*Special fields</a>. +</p> +</div> + +</div> + +<div id="outline-container-1-1-2" class="outline-4"> +<h4 id="sec-1-1-2"><span class="section-number-4">1.1.2</span> Field 2 - Validity</h4> +<div class="outline-text-4" id="text-1-1-2"> + + +<p> + This is a letter describing the computed validity of a key. + Currently this is a single letter, but be prepared that additional + information may follow in some future versions. Note that GnuPG < + 2.1 does not set this field for secret key listings. +</p> +<dl> +<dt>o</dt><dd>Unknown (this key is new to the system) +</dd> +<dt>i</dt><dd>The key is invalid (e.g. due to a missing self-signature) +</dd> +<dt>d</dt><dd>The key has been disabled + (deprecated - use the 'D' in field 12 instead) +</dd> +<dt>r</dt><dd>The key has been revoked +</dd> +<dt>e</dt><dd>The key has expired +</dd> +<dt>-</dt><dd>Unknown validity (i.e. no value assigned) +</dd> +<dt>q</dt><dd>Undefined validity. '-' and 'q' may safely be treated as + the same value for most purposes +</dd> +<dt>n</dt><dd>The key is not valid +</dd> +<dt>m</dt><dd>The key is marginal valid. +</dd> +<dt>f</dt><dd>The key is fully valid +</dd> +<dt>u</dt><dd>The key is ultimately valid. This often means that the + secret key is available, but any key may be marked as + ultimately valid. +</dd> +<dt>w</dt><dd>The key has a well known private part. +</dd> +<dt>s</dt><dd>The key has special validity. This means that it might be + self-signed and expected to be used in the STEED sytem. +</dd> +</dl> + + +<p> + If the validity information is given for a UID or UAT record, it + describes the validity calculated based on this user ID. If given + for a key record it describes the validity taken from the best + rated user ID. +</p> +<p> + For X.509 certificates a 'u' is used for a trusted root + certificate (i.e. for the trust anchor) and an 'f' for all other + valid certificates. +</p> +</div> + +</div> + +<div id="outline-container-1-1-3" class="outline-4"> +<h4 id="sec-1-1-3"><span class="section-number-4">1.1.3</span> Field 3 - Key length</h4> +<div class="outline-text-4" id="text-1-1-3"> + + +<p> + The length of key in bits. +</p> +</div> + +</div> + +<div id="outline-container-1-1-4" class="outline-4"> +<h4 id="sec-1-1-4"><span class="section-number-4">1.1.4</span> Field 4 - Public key algorithm</h4> +<div class="outline-text-4" id="text-1-1-4"> + + +<p> + The values here are those from the OpenPGP specs or if they are + greather than 255 the algorithm ids as used by Libgcrypt. +</p> +</div> + +</div> + +<div id="outline-container-1-1-5" class="outline-4"> +<h4 id="sec-1-1-5"><span class="section-number-4">1.1.5</span> Field 5 - KeyID</h4> +<div class="outline-text-4" id="text-1-1-5"> + + +<p> + This is the 64 bit keyid as specified by OpenPGP and the last 64 + bit of the SHA-1 fingerprint of an X.509 certifciate. +</p> +</div> + +</div> + +<div id="outline-container-1-1-6" class="outline-4"> +<h4 id="sec-1-1-6"><span class="section-number-4">1.1.6</span> Field 6 - Creation date</h4> +<div class="outline-text-4" id="text-1-1-6"> + + +<p> + The creation date of the key is given in UTC. For UID and UAT + records, this is used for the self-signature date. Note that the + date is usally printed in seconds since epoch, however, we are + migrating to an ISO 8601 format (e.g. "19660205T091500"). This is + currently only relevant for X.509. A simple way to detect the new + format is to scan for the 'T'. Note that old versions of gpg + without using the <code>--fixed-list-mode</code> option used a "yyyy-mm-tt" + format. +</p> +</div> + +</div> + +<div id="outline-container-1-1-7" class="outline-4"> +<h4 id="sec-1-1-7"><span class="section-number-4">1.1.7</span> Field 7 - Expiration date</h4> +<div class="outline-text-4" id="text-1-1-7"> + + +<p> + Key or UID/UAT expiration date or empty if it does not expire. +</p> +</div> + +</div> + +<div id="outline-container-1-1-8" class="outline-4"> +<h4 id="sec-1-1-8"><span class="section-number-4">1.1.8</span> Field 8 - Certificate S/N, UID hash, trust signature info</h4> +<div class="outline-text-4" id="text-1-1-8"> + + +<p> + Used for serial number in crt records. For UID and UAT records, + this is a hash of the user ID contents used to represent that + exact user ID. For trust signatures, this is the trust depth + seperated by the trust value by a space. +</p> +</div> + +</div> + +<div id="outline-container-1-1-9" class="outline-4"> +<h4 id="sec-1-1-9"><span class="section-number-4">1.1.9</span> Field 9 - Ownertrust</h4> +<div class="outline-text-4" id="text-1-1-9"> + + +<p> + This is only used on primary keys. This is a single letter, but + be prepared that additional information may follow in future + versions. For trust signatures with a regular expression, this is + the regular expression value, quoted as in field 10. +</p> +</div> + +</div> + +<div id="outline-container-1-1-10" class="outline-4"> +<h4 id="sec-1-1-10"><span class="section-number-4">1.1.10</span> Field 10 - User-ID</h4> +<div class="outline-text-4" id="text-1-1-10"> + +<p> The value is quoted like a C string to avoid control characters + (the colon is quoted <code>\x3a</code>). For a "pub" record this field is + not used on –fixed-list-mode. A UAT record puts the attribute + subpacket count here, a space, and then the total attribute + subpacket size. In gpgsm the issuer name comes here. A FPR + record stores the fingerprint here. The fingerprint of a + revocation key is stored here. +</p></div> + +</div> + +<div id="outline-container-1-1-11" class="outline-4"> +<h4 id="sec-1-1-11"><span class="section-number-4">1.1.11</span> Field 11 - Signature class</h4> +<div class="outline-text-4" id="text-1-1-11"> + + +<p> + Signature class as per RFC-4880. This is a 2 digit hexnumber + followed by either the letter 'x' for an exportable signature or + the letter 'l' for a local-only signature. The class byte of an + revocation key is also given here, 'x' and 'l' is used the same + way. This field if not used for X.509. +</p> +</div> + +</div> + +<div id="outline-container-1-1-12" class="outline-4"> +<h4 id="sec-1-1-12"><span class="section-number-4">1.1.12</span> Field 12 - Key capabilities</h4> +<div class="outline-text-4" id="text-1-1-12"> + + +<p> + The defined capabilities are: +</p> +<dl> +<dt>e</dt><dd>Encrypt +</dd> +<dt>s</dt><dd>Sign +</dd> +<dt>c</dt><dd>Certify +</dd> +<dt>a</dt><dd>Authentication +</dd> +<dt>?</dt><dd>Unknown capability +</dd> +</dl> + + +<p> + A key may have any combination of them in any order. In addition + to these letters, the primary key has uppercase versions of the + letters to denote the <span style="text-decoration:underline;">usable</span> capabilities of the entire key, and + a potential letter 'D' to indicate a disabled key. +</p> +</div> + +</div> + +<div id="outline-container-1-1-13" class="outline-4"> +<h4 id="sec-1-1-13"><span class="section-number-4">1.1.13</span> Field 13 - Issuer certificate fingerprint or other info</h4> +<div class="outline-text-4" id="text-1-1-13"> + + +<p> + Used in FPR records for S/MIME keys to store the fingerprint of + the issuer certificate. This is useful to build the certificate + path based on certificates stored in the local key database it is + only filled if the issuer certificate is available. The root has + been reached if this is the same string as the fingerprint. The + advantage of using this value is that it is guaranteed to have + been been build by the same lookup algorithm as gpgsm uses. +</p> +<p> + For "uid" records this field lists the preferences in the same way + gpg's –edit-key menu does. +</p> +<p> + For "sig" records, this is the fingerprint of the key that issued + the signature. Note that this is only filled in if the signature + verified correctly. Note also that for various technical reasons, + this fingerprint is only available if –no-sig-cache is used. +</p> +</div> + +</div> + +<div id="outline-container-1-1-14" class="outline-4"> +<h4 id="sec-1-1-14"><span class="section-number-4">1.1.14</span> Field 14 - Flag field</h4> +<div class="outline-text-4" id="text-1-1-14"> + + +<p> + Flag field used in the –edit menu output +</p> +</div> + +</div> + +<div id="outline-container-1-1-15" class="outline-4"> +<h4 id="sec-1-1-15"><span class="section-number-4">1.1.15</span> Field 15 - S/N of a token</h4> +<div class="outline-text-4" id="text-1-1-15"> + + +<p> + Used in sec/sbb to print the serial number of a token (internal + protect mode 1002) or a '#' if that key is a simple stub (internal + protect mode 1001) +</p> +</div> + +</div> + +<div id="outline-container-1-1-16" class="outline-4"> +<h4 id="sec-1-1-16"><span class="section-number-4">1.1.16</span> Field 16 - Hash algorithm</h4> +<div class="outline-text-4" id="text-1-1-16"> + + +<p> + For sig records, this is the used hash algorithm. For example: + 2 = SHA-1, 8 = SHA-256. +</p> +</div> +</div> + +</div> + +<div id="outline-container-1-2" class="outline-3"> +<h3 id="sec-1-2"><span class="section-number-3">1.2</span> Special fields</h3> +<div class="outline-text-3" id="text-1-2"> + + + +</div> + +<div id="outline-container-1-2-1" class="outline-4"> +<h4 id="sec-1-2-1"><span class="section-number-4">1.2.1</span> PKD - Public key data</h4> +<div class="outline-text-4" id="text-1-2-1"> + + +<p> + If field 1 has the tag "pkd", a listing looks like this: +</p> + + +<pre class="example">pkd:0:1024:B665B1435F4C2 .... FF26ABB: + ! ! !-- the value + ! !------ for information number of bits in the value + !--------- index (eg. DSA goes from 0 to 3: p,q,g,y) +</pre> + + +</div> + +</div> + +<div id="outline-container-1-2-2" class="outline-4"> +<h4 id="sec-1-2-2"><span class="section-number-4">1.2.2</span> TRU - Trust database information</h4> +<div class="outline-text-4" id="text-1-2-2"> + +<p> Example for a "tru" trust base record: +</p> + + +<pre class="example">tru:o:0:1166697654:1:3:1:5 +</pre> + + +<dl> +<dt>Field 2</dt><dd>Reason for staleness of trust. If this field is + empty, then the trustdb is not stale. This field may + have multiple flags in it: + +<dl> +<dt>o</dt><dd>Trustdb is old +</dd> +<dt>t</dt><dd>Trustdb was built with a different trust model + than the one we are using now. + +</dd> +</dl> + +</dd> +<dt>Field 3</dt><dd>Trust model + +<dl> +<dt>0</dt><dd>Classic trust model, as used in PGP 2.x. +</dd> +<dt>1</dt><dd>PGP trust model, as used in PGP 6 and later. + This is the same as the classic trust model, + except for the addition of trust signatures. + +</dd> +</dl> + +<p> GnuPG before version 1.4 used the classic trust model + by default. GnuPG 1.4 and later uses the PGP trust + model by default. +</p> +</dd> +<dt>Field 4</dt><dd>Date trustdb was created in seconds since Epoch. +</dd> +<dt>Field 5</dt><dd>Date trustdb will expire in seconds since Epoch. +</dd> +<dt>Field 6</dt><dd>Number of marginally trusted users to introduce a new + key signer (gpg's option –marginals-needed). +</dd> +<dt>Field 7</dt><dd>Number of completely trusted users to introduce a new + key signer. (gpg's option –completes-needed) + +</dd> +<dt>Field 8</dt><dd>Maximum depth of a certification chain. (gpg's option + –max-cert-depth) +</dd> +</dl> + + +</div> + +</div> + +<div id="outline-container-1-2-3" class="outline-4"> +<h4 id="sec-1-2-3"><span class="section-number-4">1.2.3</span> SPK - Signature subpacket records</h4> +<div class="outline-text-4" id="text-1-2-3"> + + +<dl> +<dt>Field 2</dt><dd>Subpacket number as per RFC-4880 and later. +</dd> +<dt>Field 3</dt><dd>Flags in hex. Currently the only two bits assigned + are 1, to indicate that the subpacket came from the + hashed part of the signature, and 2, to indicate the + subpacket was marked critical. +</dd> +<dt>Field 4</dt><dd>Length of the subpacket. Note that this is the + length of the subpacket, and not the length of field + 5 below. Due to the need for %-encoding, the length + of field 5 may be up to 3x this value. +</dd> +<dt>Field 5</dt><dd>The subpacket data. Printable ASCII is shown as + ASCII, but other values are rendered as %XX where XX + is the hex value for the byte. +</dd> +</dl> + + +</div> + +</div> + +<div id="outline-container-1-2-4" class="outline-4"> +<h4 id="sec-1-2-4"><span class="section-number-4">1.2.4</span> CFG - Configuration data</h4> +<div class="outline-text-4" id="text-1-2-4"> + + +<p> + –list-config outputs information about the GnuPG configuration + for the benefit of frontends or other programs that call GnuPG. + There are several list-config items, all colon delimited like the + rest of the –with-colons output. The first field is always "cfg" + to indicate configuration information. The second field is one of + (with examples): +</p> +<dl> +<dt>version</dt><dd>The third field contains the version of GnuPG. + +<pre class="example"> +cfg:version:1.3.5 +</pre> + + +</dd> +<dt>pubkey</dt><dd>The third field contains the public key algorithms + this version of GnuPG supports, separated by + semicolons. The algorithm numbers are as specified in + RFC-4880. Note that in contrast to the –status-fd + interface these are <span style="text-decoration:underline;">not</span> the Libgcrypt identifiers. + +<pre class="example"> +cfg:pubkey:1;2;3;16;17 +</pre> + + +</dd> +<dt>cipher</dt><dd>The third field contains the symmetric ciphers this + version of GnuPG supports, separated by semicolons. + The cipher numbers are as specified in RFC-4880. + +<pre class="example"> +cfg:cipher:2;3;4;7;8;9;10 +</pre> + + +</dd> +<dt>digest</dt><dd>The third field contains the digest (hash) algorithms + this version of GnuPG supports, separated by + semicolons. The digest numbers are as specified in + RFC-4880. + +<pre class="example"> +cfg:digest:1;2;3;8;9;10 +</pre> + + +</dd> +<dt>compress</dt><dd>The third field contains the compression algorithms + this version of GnuPG supports, separated by + semicolons. The algorithm numbers are as specified + in RFC-4880. + +<pre class="example"> +cfg:compress:0;1;2;3 +</pre> + + +</dd> +<dt>group</dt><dd>The third field contains the name of the group, and the + fourth field contains the values that the group expands + to, separated by semicolons. + +<p> + For example, a group of: +</p><pre class="example"> +group mynames = paige 0x12345678 joe patti +</pre> + +<p> would result in: +</p><pre class="example"> +cfg:group:mynames:patti;joe;0x12345678;paige +</pre> + +</dd> +</dl> + + + +</div> +</div> +</div> + +</div> + +<div id="outline-container-2" class="outline-2"> +<h2 id="sec-2"><span class="section-number-2">2</span> Format of the –status-fd output</h2> +<div class="outline-text-2" id="text-2"> + + +<p> + Every line is prefixed with "[GNUPG:] ", followed by a keyword with + the type of the status line and some arguments depending on the type + (maybe none); an application should always be prepared to see more + arguments in future versions. +</p> + +</div> + +<div id="outline-container-2-1" class="outline-3"> +<h3 id="sec-2-1"><span class="section-number-3">2.1</span> General status codes</h3> +<div class="outline-text-3" id="text-2-1"> + + +</div> + +<div id="outline-container-2-1-1" class="outline-4"> +<h4 id="sec-2-1-1"><span class="section-number-4">2.1.1</span> NEWSIG</h4> +<div class="outline-text-4" id="text-2-1-1"> + +<p> May be issued right before a signature verification starts. This + is useful to define a context for parsing ERROR status messages. + No arguments are currently defined. +</p> +</div> + +</div> + +<div id="outline-container-2-1-2" class="outline-4"> +<h4 id="sec-2-1-2"><span class="section-number-4">2.1.2</span> GOODSIG <long_keyid_or_fpr> <username></h4> +<div class="outline-text-4" id="text-2-1-2"> + +<p> The signature with the keyid is good. For each signature only one + of the codes GOODSIG, BADSIG, EXPSIG, EXPKEYSIG, REVKEYSIG or + ERRSIG will be emitted. In the past they were used as a marker + for a new signature; new code should use the NEWSIG status + instead. The username is the primary one encoded in UTF-8 and %XX + escaped. The fingerprint may be used instead of the long keyid if + it is available. This is the case with CMS and might eventually + also be available for OpenPGP. +</p> +</div> + +</div> + +<div id="outline-container-2-1-3" class="outline-4"> +<h4 id="sec-2-1-3"><span class="section-number-4">2.1.3</span> EXPSIG <long_keyid_or_fpr> <username></h4> +<div class="outline-text-4" id="text-2-1-3"> + +<p> The signature with the keyid is good, but the signature is + expired. The username is the primary one encoded in UTF-8 and %XX + escaped. The fingerprint may be used instead of the long keyid if + it is available. This is the case with CMS and might eventually + also be available for OpenPGP. +</p> +</div> + +</div> + +<div id="outline-container-2-1-4" class="outline-4"> +<h4 id="sec-2-1-4"><span class="section-number-4">2.1.4</span> EXPKEYSIG <long_keyid_or_fpr> <username></h4> +<div class="outline-text-4" id="text-2-1-4"> + +<p> The signature with the keyid is good, but the signature was made + by an expired key. The username is the primary one encoded in + UTF-8 and %XX escaped. The fingerprint may be used instead of the + long keyid if it is available. This is the case with CMS and + might eventually also be available for OpenPGP. +</p> +</div> + +</div> + +<div id="outline-container-2-1-5" class="outline-4"> +<h4 id="sec-2-1-5"><span class="section-number-4">2.1.5</span> REVKEYSIG <long_keyid_or_fpr> <username></h4> +<div class="outline-text-4" id="text-2-1-5"> + +<p> The signature with the keyid is good, but the signature was made + by a revoked key. The username is the primary one encoded in UTF-8 + and %XX escaped. The fingerprint may be used instead of the long + keyid if it is available. This is the case with CMS and might + eventually also beñ available for OpenPGP. +</p> +</div> + +</div> + +<div id="outline-container-2-1-6" class="outline-4"> +<h4 id="sec-2-1-6"><span class="section-number-4">2.1.6</span> BADSIG <long_keyid_or_fpr> <username></h4> +<div class="outline-text-4" id="text-2-1-6"> + +<p> The signature with the keyid has not been verified okay. The + username is the primary one encoded in UTF-8 and %XX escaped. The + fingerprint may be used instead of the long keyid if it is + available. This is the case with CMS and might eventually also be + available for OpenPGP. +</p> +</div> + +</div> + +<div id="outline-container-2-1-7" class="outline-4"> +<h4 id="sec-2-1-7"><span class="section-number-4">2.1.7</span> ERRSIG <keyid> <pkalgo> <hashalgo> <sig_class> <time> <rc></h4> +<div class="outline-text-4" id="text-2-1-7"> + +<p> It was not possible to check the signature. This may be caused by + a missing public key or an unsupported algorithm. A RC of 4 + indicates unknown algorithm, a 9 indicates a missing public + key. The other fields give more information about this signature. + sig_class is a 2 byte hex-value. The fingerprint may be used + instead of the keyid if it is available. This is the case with + gpgsm and might eventually also be available for OpenPGP. +</p> +<p> + Note, that TIME may either be the number of seconds since Epoch or + the letter 'T'. + an ISO 8601 string. The latter can be detected by the presence of +</p> +</div> + +</div> + +<div id="outline-container-2-1-8" class="outline-4"> +<h4 id="sec-2-1-8"><span class="section-number-4">2.1.8</span> VALIDSIG <args></h4> +<div class="outline-text-4" id="text-2-1-8"> + + +<p> + The args are: +</p> +<ul> +<li><fingerprint_in_hex> +</li> +<li><sig_creation_date> +</li> +<li><sig-timestamp> +</li> +<li><expire-timestamp> +</li> +<li><sig-version> +</li> +<li><reserved> +</li> +<li><pubkey-algo> +</li> +<li><hash-algo> +</li> +<li><sig-class> +</li> +<li>[ <primary-key-fpr> ] +</li> +</ul> + + +<p> + This status indicates that the signature is good. This is the same + as GOODSIG but has the fingerprint as the argument. Both status + lines are emitted for a good signature. All arguments here are on + one long line. sig-timestamp is the signature creation time in + seconds after the epoch. expire-timestamp is the signature + expiration time in seconds after the epoch (zero means "does not + expire"). sig-version, pubkey-algo, hash-algo, and sig-class (a + 2-byte hex value) are all straight from the signature packet. + PRIMARY-KEY-FPR is the fingerprint of the primary key or identical + to the first argument. This is useful to get back to the primary + key without running gpg again for this purpose. +</p> +<p> + The primary-key-fpr parameter is used for OpenPGP and not + class is not defined for CMS and currently set to 0 and 00. + available for CMS signatures. The sig-version as well as the sig +</p> +<p> + Note, that *-TIMESTAMP may either be a number of seconds since + Epoch or an ISO 8601 string which can be detected by the presence + of the letter 'T'. +</p> +</div> + +</div> + +<div id="outline-container-2-1-9" class="outline-4"> +<h4 id="sec-2-1-9"><span class="section-number-4">2.1.9</span> SIG_ID <radix64_string> <sig_creation_date> <sig-timestamp></h4> +<div class="outline-text-4" id="text-2-1-9"> + +<p> This is emitted only for signatures of class 0 or 1 which have + been verified okay. The string is a signature id and may be used + in applications to detect replay attacks of signed messages. Note + that only DLP algorithms give unique ids - others may yield + duplicated ones when they have been created in the same second. +</p> +<p> + Note, that SIG-TIMESTAMP may either be a number of seconds since + Epoch or an ISO 8601 string which can be detected by the presence + of the letter 'T'. +</p> +</div> + +</div> + +<div id="outline-container-2-1-10" class="outline-4"> +<h4 id="sec-2-1-10"><span class="section-number-4">2.1.10</span> ENC_TO <long_keyid> <keytype> <keylength></h4> +<div class="outline-text-4" id="text-2-1-10"> + +<p> The message is encrypted to this LONG_KEYID. KEYTYPE is the + numerical value of the public key algorithm or 0 if it is not + known, KEYLENGTH is the length of the key or 0 if it is not known + (which is currently always the case). Gpg prints this line + always; Gpgsm only if it knows the certificate. +</p> +</div> + +</div> + +<div id="outline-container-2-1-11" class="outline-4"> +<h4 id="sec-2-1-11"><span class="section-number-4">2.1.11</span> BEGIN_DECRYPTION</h4> +<div class="outline-text-4" id="text-2-1-11"> + +<p> Mark the start of the actual decryption process. This is also + emitted when in –list-only mode. +</p></div> + +</div> + +<div id="outline-container-2-1-12" class="outline-4"> +<h4 id="sec-2-1-12"><span class="section-number-4">2.1.12</span> END_DECRYPTION</h4> +<div class="outline-text-4" id="text-2-1-12"> + +<p> Mark the end of the actual decryption process. This are also + emitted when in –list-only mode. +</p></div> + +</div> + +<div id="outline-container-2-1-13" class="outline-4"> +<h4 id="sec-2-1-13"><span class="section-number-4">2.1.13</span> DECRYPTION_INFO <mdc_method> <sym_algo></h4> +<div class="outline-text-4" id="text-2-1-13"> + +<p> Print information about the symmetric encryption algorithm and the + MDC method. This will be emitted even if the decryption fails. +</p> +</div> + +</div> + +<div id="outline-container-2-1-14" class="outline-4"> +<h4 id="sec-2-1-14"><span class="section-number-4">2.1.14</span> DECRYPTION_FAILED</h4> +<div class="outline-text-4" id="text-2-1-14"> + +<p> The symmetric decryption failed - one reason could be a wrong + passphrase for a symmetrical encrypted message. +</p> +</div> + +</div> + +<div id="outline-container-2-1-15" class="outline-4"> +<h4 id="sec-2-1-15"><span class="section-number-4">2.1.15</span> DECRYPTION_OKAY</h4> +<div class="outline-text-4" id="text-2-1-15"> + +<p> The decryption process succeeded. This means, that either the + correct secret key has been used or the correct passphrase for a + conventional encrypted message was given. The program itself may + return an errorcode because it may not be possible to verify a + signature for some reasons. +</p> +</div> + +</div> + +<div id="outline-container-2-1-16" class="outline-4"> +<h4 id="sec-2-1-16"><span class="section-number-4">2.1.16</span> SESSION_KEY <algo>:<hexdigits></h4> +<div class="outline-text-4" id="text-2-1-16"> + +<p> The session key used to decrypt the message. This message will + only be emitted when the special option –show-session-key is + used. The format is suitable to be passed to the option + –override-session-key +</p> +</div> + +</div> + +<div id="outline-container-2-1-17" class="outline-4"> +<h4 id="sec-2-1-17"><span class="section-number-4">2.1.17</span> BEGIN_ENCRYPTION <mdc_method> <sym_algo></h4> +<div class="outline-text-4" id="text-2-1-17"> + +<p> Mark the start of the actual encryption process. +</p> +</div> + +</div> + +<div id="outline-container-2-1-18" class="outline-4"> +<h4 id="sec-2-1-18"><span class="section-number-4">2.1.18</span> END_ENCRYPTION</h4> +<div class="outline-text-4" id="text-2-1-18"> + +<p> Mark the end of the actual encryption process. +</p> +</div> + +</div> + +<div id="outline-container-2-1-19" class="outline-4"> +<h4 id="sec-2-1-19"><span class="section-number-4">2.1.19</span> FILE_START <what> <filename></h4> +<div class="outline-text-4" id="text-2-1-19"> + +<p> Start processing a file <filename>. <what> indicates the performed + operation: +</p><dl> +<dt>1</dt><dd>verify +</dd> +<dt>2</dt><dd>encrypt +</dd> +<dt>3</dt><dd>decrypt +</dd> +</dl> + + +</div> + +</div> + +<div id="outline-container-2-1-20" class="outline-4"> +<h4 id="sec-2-1-20"><span class="section-number-4">2.1.20</span> FILE_DONE</h4> +<div class="outline-text-4" id="text-2-1-20"> + +<p> Marks the end of a file processing which has been started + by FILE_START. +</p> +</div> + +</div> + +<div id="outline-container-2-1-21" class="outline-4"> +<h4 id="sec-2-1-21"><span class="section-number-4">2.1.21</span> BEGIN_SIGNING</h4> +<div class="outline-text-4" id="text-2-1-21"> + +<p> Mark the start of the actual signing process. This may be used as + an indication that all requested secret keys are ready for use. +</p> +</div> + +</div> + +<div id="outline-container-2-1-22" class="outline-4"> +<h4 id="sec-2-1-22"><span class="section-number-4">2.1.22</span> ALREADY_SIGNED <long-keyid></h4> +<div class="outline-text-4" id="text-2-1-22"> + +<p> Warning: This is experimental and might be removed at any time. +</p> +</div> + +</div> + +<div id="outline-container-2-1-23" class="outline-4"> +<h4 id="sec-2-1-23"><span class="section-number-4">2.1.23</span> SIG_CREATED <type> <pk_algo> <hash_algo> <class> <timestamp> <keyfpr></h4> +<div class="outline-text-4" id="text-2-1-23"> + +<p> A signature has been created using these parameters. + Values for type <type> are: +</p><dl> +<dt>D</dt><dd>detached +</dd> +<dt>C</dt><dd>cleartext +</dd> +<dt>S</dt><dd>standard +</dd> +</dl> + +<p> (only the first character should be checked) +</p> +<p> + <class> are 2 hex digits with the OpenPGP signature class. +</p> +<p> + Note, that TIMESTAMP may either be a number of seconds since Epoch + or an ISO 8601 string which can be detected by the presence of the + letter 'T'. +</p> +</div> + +</div> + +<div id="outline-container-2-1-24" class="outline-4"> +<h4 id="sec-2-1-24"><span class="section-number-4">2.1.24</span> NOTATION_</h4> +<div class="outline-text-4" id="text-2-1-24"> + +<p> There are actually two related status codes to convey notation + data: +</p> +<ul> +<li>NOTATION_NAME <name> +</li> +<li>NOTATION_DATA <string> +</li> +</ul> + + +<p> + <name> and <string> are %XX escaped; the data may be split among + several NOTATION_DATA lines. +</p> +</div> + +</div> + +<div id="outline-container-2-1-25" class="outline-4"> +<h4 id="sec-2-1-25"><span class="section-number-4">2.1.25</span> POLICY_URL <string></h4> +<div class="outline-text-4" id="text-2-1-25"> + +<p> Note that URL in <string> is %XX escaped. +</p> +</div> + +</div> + +<div id="outline-container-2-1-26" class="outline-4"> +<h4 id="sec-2-1-26"><span class="section-number-4">2.1.26</span> PLAINTEXT <format> <timestamp> <filename></h4> +<div class="outline-text-4" id="text-2-1-26"> + +<p> This indicates the format of the plaintext that is about to be + written. The format is a 1 byte hex code that shows the format of + the plaintext: 62 ('b') is binary data, 74 ('t') is text data with + no character set specified, and 75 ('u') is text data encoded in + the UTF-8 character set. The timestamp is in seconds since the + epoch. If a filename is available it gets printed as the third + argument, percent-escaped as usual. +</p> +</div> + +</div> + +<div id="outline-container-2-1-27" class="outline-4"> +<h4 id="sec-2-1-27"><span class="section-number-4">2.1.27</span> PLAINTEXT_LENGTH <length></h4> +<div class="outline-text-4" id="text-2-1-27"> + +<p> This indicates the length of the plaintext that is about to be + written. Note that if the plaintext packet has partial length + encoding it is not possible to know the length ahead of time. In + that case, this status tag does not appear. +</p> +</div> + +</div> + +<div id="outline-container-2-1-28" class="outline-4"> +<h4 id="sec-2-1-28"><span class="section-number-4">2.1.28</span> ATTRIBUTE <arguments></h4> +<div class="outline-text-4" id="text-2-1-28"> + +<p> The list or argemnts are: +</p><ul> +<li><fpr> +</li> +<li><octets> +</li> +<li><type> +</li> +<li><index> +</li> +<li><count> +</li> +<li><timestamp> +</li> +<li><expiredate> +</li> +<li><flags> +</li> +</ul> + + +<p> + This is one long line issued for each attribute subpacket when an + attribute packet is seen during key listing. <fpr> is the + fingerprint of the key. <octets> is the length of the attribute + subpacket. <type> is the attribute type (e.g. 1 for an image). + <index> and <count> indicate that this is the N-th indexed + subpacket of count total subpackets in this attribute packet. + <timestamp> and <expiredate> are from the self-signature on the + attribute packet. If the attribute packet does not have a valid + self-signature, then the timestamp is 0. <flags> are a bitwise OR + of: +</p><dl> +<dt>0x01</dt><dd>this attribute packet is a primary uid +</dd> +<dt>0x02</dt><dd>this attribute packet is revoked +</dd> +<dt>0x04</dt><dd>this attribute packet is expired +</dd> +</dl> + + +</div> + +</div> + +<div id="outline-container-2-1-29" class="outline-4"> +<h4 id="sec-2-1-29"><span class="section-number-4">2.1.29</span> SIG_SUBPACKET <type> <flags> <len> <data></h4> +<div class="outline-text-4" id="text-2-1-29"> + +<p> This indicates that a signature subpacket was seen. The format is + the same as the "spk" record above. +</p> +</div> +</div> + +</div> + +<div id="outline-container-2-2" class="outline-3"> +<h3 id="sec-2-2"><span class="section-number-3">2.2</span> Key related</h3> +<div class="outline-text-3" id="text-2-2"> + + +</div> + +<div id="outline-container-2-2-1" class="outline-4"> +<h4 id="sec-2-2-1"><span class="section-number-4">2.2.1</span> INV_RECP, INV_SGNR</h4> +<div class="outline-text-4" id="text-2-2-1"> + +<p> The two similar status codes: +</p> +<ul> +<li>INV_RECP <reason> <requested_recipient> +</li> +<li>INV_SGNR <reason> <requested_sender> +</li> +</ul> + + +<p> + are issued for each unusable recipient/sender. The reasons codes + currently in use are: +</p> +<dl> +<dt>0</dt><dd>No specific reason given +</dd> +<dt>1</dt><dd>Not Found +</dd> +<dt>2</dt><dd>Ambigious specification +</dd> +<dt>3</dt><dd>Wrong key usage +</dd> +<dt>4</dt><dd>Key revoked +</dd> +<dt>5</dt><dd>Key expired +</dd> +<dt>6</dt><dd>No CRL known +</dd> +<dt>7</dt><dd>CRL too old +</dd> +<dt>8</dt><dd>Policy mismatch +</dd> +<dt>9</dt><dd>Not a secret key +</dd> +<dt>10</dt><dd>Key not trusted +</dd> +<dt>11</dt><dd>Missing certificate +</dd> +<dt>12</dt><dd>Missing issuer certificate +</dd> +</dl> + + +<p> + Note that for historical reasons the INV_RECP status is also used + for gpgsm's SIGNER command where it relates to signer's of course. + Newer GnuPG versions are using INV_SGNR; applications should + ignore the INV_RECP during the sender's command processing once + they have seen an INV_SGNR. Different codes are used so that they + can be distinguish while doing an encrypt+sign operation. +</p></div> + +</div> + +<div id="outline-container-2-2-2" class="outline-4"> +<h4 id="sec-2-2-2"><span class="section-number-4">2.2.2</span> NO_RECP <reserved></h4> +<div class="outline-text-4" id="text-2-2-2"> + +<p> Issued if no recipients are usable. +</p> +</div> + +</div> + +<div id="outline-container-2-2-3" class="outline-4"> +<h4 id="sec-2-2-3"><span class="section-number-4">2.2.3</span> NO_SGNR <reserved></h4> +<div class="outline-text-4" id="text-2-2-3"> + +<p> Issued if no senders are usable. +</p> +</div> + +</div> + +<div id="outline-container-2-2-4" class="outline-4"> +<h4 id="sec-2-2-4"><span class="section-number-4">2.2.4</span> KEYEXPIRED <expire-timestamp></h4> +<div class="outline-text-4" id="text-2-2-4"> + +<p> The key has expired. expire-timestamp is the expiration time in + seconds since Epoch. This status line is not very useful because + it will also be emitted for expired subkeys even if this subkey is + not used. To check whether a key used to sign a message has + expired, the EXPKEYSIG status line is to be used. +</p> +<p> + Note, that the TIMESTAMP may either be a number of seconds since + Epoch or an ISO 8601 string which can be detected by the presence + of the letter 'T'. +</p> +</div> + +</div> + +<div id="outline-container-2-2-5" class="outline-4"> +<h4 id="sec-2-2-5"><span class="section-number-4">2.2.5</span> KEYREVOKED</h4> +<div class="outline-text-4" id="text-2-2-5"> + +<p> The used key has been revoked by its owner. No arguments yet. +</p> +</div> + +</div> + +<div id="outline-container-2-2-6" class="outline-4"> +<h4 id="sec-2-2-6"><span class="section-number-4">2.2.6</span> NO_PUBKEY <long keyid></h4> +<div class="outline-text-4" id="text-2-2-6"> + +<p> The public key is not available +</p> +</div> + +</div> + +<div id="outline-container-2-2-7" class="outline-4"> +<h4 id="sec-2-2-7"><span class="section-number-4">2.2.7</span> NO_SECKEY <long keyid></h4> +<div class="outline-text-4" id="text-2-2-7"> + +<p> The secret key is not available +</p> +</div> + +</div> + +<div id="outline-container-2-2-8" class="outline-4"> +<h4 id="sec-2-2-8"><span class="section-number-4">2.2.8</span> KEY_CREATED <type> <fingerprint> [<handle>]</h4> +<div class="outline-text-4" id="text-2-2-8"> + +<p> A key has been created. Values for <type> are: +</p><dl> +<dt>B</dt><dd>primary and subkey +</dd> +<dt>P</dt><dd>primary +</dd> +<dt>S</dt><dd>subkey +</dd> +</dl> + +<p> The fingerprint is one of the primary key for type B and P and the + one of the subkey for S. Handle is an arbitrary non-whitespace + string used to match key parameters from batch key creation run. +</p> +</div> + +</div> + +<div id="outline-container-2-2-9" class="outline-4"> +<h4 id="sec-2-2-9"><span class="section-number-4">2.2.9</span> KEY_NOT_CREATED [<handle>]</h4> +<div class="outline-text-4" id="text-2-2-9"> + +<p> The key from batch run has not been created due to errors. +</p> +</div> + +</div> + +<div id="outline-container-2-2-10" class="outline-4"> +<h4 id="sec-2-2-10"><span class="section-number-4">2.2.10</span> TRUST_</h4> +<div class="outline-text-4" id="text-2-2-10"> + +<p> These are several similar status codes: +</p> +<ul> +<li>TRUST_UNDEFINED <error_token> +</li> +<li>TRUST_NEVER <error_token> +</li> +<li>TRUST_MARGINAL [0 [<validation_model>]] +</li> +<li>TRUST_FULLY [0 [<validation_model>]] +</li> +<li>TRUST_ULTIMATE [0 [<validation_model>]] +</li> +</ul> + + +<p> + For good signatures one of these status lines are emitted to + indicate the validity of the key used to create the signature. + The error token values are currently only emitted by gpgsm. +</p> +<p> + VALIDATION_MODEL describes the algorithm used to check the + validity of the key. The defaults are the standard Web of Trust + model for gpg and the the standard X.509 model for gpgsm. The + defined values are +</p> +<dl> +<dt>pgp </dt><dd>The standard PGP WoT. +</dd> +<dt>shell</dt><dd>The standard X.509 model. +</dd> +<dt>chain</dt><dd>The chain model. +</dd> +<dt>steed</dt><dd>The STEED model. +</dd> +</dl> + + +<p> + Note that the term <code>TRUST_</code> in the status names is used for + historic reasons; we now speak of validity. +</p> +</div> + +</div> + +<div id="outline-container-2-2-11" class="outline-4"> +<h4 id="sec-2-2-11"><span class="section-number-4">2.2.11</span> PKA_TRUST_</h4> +<div class="outline-text-4" id="text-2-2-11"> + +<p> This is is one: +</p> +<ul> +<li>PKA_TRUST_GOOD <mailbox> +</li> +<li>PKA_TRUST_BAD <mailbox> +</li> +</ul> + + +<p> + Depending on the outcome of the PKA check one of the above status + codes is emitted in addition to a <code>TRUST_*</code> status. +</p> +</div> +</div> + +</div> + +<div id="outline-container-2-3" class="outline-3"> +<h3 id="sec-2-3"><span class="section-number-3">2.3</span> Remote control</h3> +<div class="outline-text-3" id="text-2-3"> + + +</div> + +<div id="outline-container-2-3-1" class="outline-4"> +<h4 id="sec-2-3-1"><span class="section-number-4">2.3.1</span> GET_BOOL, GET_LINE, GET_HIDDEN, GOT_IT</h4> +<div class="outline-text-4" id="text-2-3-1"> + + +<p> + These status line are used with –command-fd for interactive + control of the process. +</p> +</div> + +</div> + +<div id="outline-container-2-3-2" class="outline-4"> +<h4 id="sec-2-3-2"><span class="section-number-4">2.3.2</span> USERID_HINT <long main keyid> <string></h4> +<div class="outline-text-4" id="text-2-3-2"> + +<p> Give a hint about the user ID for a certain keyID. +</p> +</div> + +</div> + +<div id="outline-container-2-3-3" class="outline-4"> +<h4 id="sec-2-3-3"><span class="section-number-4">2.3.3</span> NEED_PASSPHRASE <long keyid> <long main keyid> <keytype> <keylength></h4> +<div class="outline-text-4" id="text-2-3-3"> + +<p> Issued whenever a passphrase is needed. KEYTYPE is the numerical + value of the public key algorithm or 0 if this is not applicable, + KEYLENGTH is the length of the key or 0 if it is not known (this + is currently always the case). +</p> +</div> + +</div> + +<div id="outline-container-2-3-4" class="outline-4"> +<h4 id="sec-2-3-4"><span class="section-number-4">2.3.4</span> NEED_PASSPHRASE_SYM <cipher_algo> <s2k_mode> <s2k_hash></h4> +<div class="outline-text-4" id="text-2-3-4"> + +<p> Issued whenever a passphrase for symmetric encryption is needed. +</p> +</div> + +</div> + +<div id="outline-container-2-3-5" class="outline-4"> +<h4 id="sec-2-3-5"><span class="section-number-4">2.3.5</span> NEED_PASSPHRASE_PIN <card_type> <chvno> [<serialno>]</h4> +<div class="outline-text-4" id="text-2-3-5"> + +<p> Issued whenever a PIN is requested to unlock a card. +</p> +</div> + +</div> + +<div id="outline-container-2-3-6" class="outline-4"> +<h4 id="sec-2-3-6"><span class="section-number-4">2.3.6</span> MISSING_PASSPHRASE</h4> +<div class="outline-text-4" id="text-2-3-6"> + +<p> No passphrase was supplied. An application which encounters this + message may want to stop parsing immediately because the next + message will probably be a BAD_PASSPHRASE. However, if the + application is a wrapper around the key edit menu functionality it + might not make sense to stop parsing but simply ignoring the + following BAD_PASSPHRASE. +</p> +</div> + +</div> + +<div id="outline-container-2-3-7" class="outline-4"> +<h4 id="sec-2-3-7"><span class="section-number-4">2.3.7</span> BAD_PASSPHRASE <long keyid></h4> +<div class="outline-text-4" id="text-2-3-7"> + +<p> The supplied passphrase was wrong or not given. In the latter + case you may have seen a MISSING_PASSPHRASE. +</p> +</div> + +</div> + +<div id="outline-container-2-3-8" class="outline-4"> +<h4 id="sec-2-3-8"><span class="section-number-4">2.3.8</span> GOOD_PASSPHRASE</h4> +<div class="outline-text-4" id="text-2-3-8"> + +<p> The supplied passphrase was good and the secret key material + is therefore usable. +</p> +</div> +</div> + +</div> + +<div id="outline-container-2-4" class="outline-3"> +<h3 id="sec-2-4"><span class="section-number-3">2.4</span> Import/Export</h3> +<div class="outline-text-3" id="text-2-4"> + + +</div> + +<div id="outline-container-2-4-1" class="outline-4"> +<h4 id="sec-2-4-1"><span class="section-number-4">2.4.1</span> IMPORT_CHECK <long keyid> <fingerprint> <user ID></h4> +<div class="outline-text-4" id="text-2-4-1"> + +<p> This status is emitted in interactive mode right before + the "import.okay" prompt. +</p> +</div> + +</div> + +<div id="outline-container-2-4-2" class="outline-4"> +<h4 id="sec-2-4-2"><span class="section-number-4">2.4.2</span> IMPORTED <long keyid> <username></h4> +<div class="outline-text-4" id="text-2-4-2"> + +<p> The keyid and name of the signature just imported +</p> +</div> + +</div> + +<div id="outline-container-2-4-3" class="outline-4"> +<h4 id="sec-2-4-3"><span class="section-number-4">2.4.3</span> IMPORT_OK <reason> [<fingerprint>]</h4> +<div class="outline-text-4" id="text-2-4-3"> + +<p> The key with the primary key's FINGERPRINT has been imported. + REASON flags are: +</p> +<dl> +<dt>0</dt><dd>Not actually changed +</dd> +<dt>1</dt><dd>Entirely new key. +</dd> +<dt>2</dt><dd>New user IDs +</dd> +<dt>4</dt><dd>New signatures +</dd> +<dt>8</dt><dd>New subkeys +</dd> +<dt>16</dt><dd>Contains private key. +</dd> +</dl> + + +<p> + The flags may be ORed. +</p> +</div> + +</div> + +<div id="outline-container-2-4-4" class="outline-4"> +<h4 id="sec-2-4-4"><span class="section-number-4">2.4.4</span> IMPORT_PROBLEM <reason> [<fingerprint>]</h4> +<div class="outline-text-4" id="text-2-4-4"> + +<p> Issued for each import failure. Reason codes are: +</p> +<dl> +<dt>0</dt><dd>No specific reason given. +</dd> +<dt>1</dt><dd>Invalid Certificate. +</dd> +<dt>2</dt><dd>Issuer Certificate missing. +</dd> +<dt>3</dt><dd>Certificate Chain too long. +</dd> +<dt>4</dt><dd>Error storing certificate. +</dd> +</dl> + + +</div> + +</div> + +<div id="outline-container-2-4-5" class="outline-4"> +<h4 id="sec-2-4-5"><span class="section-number-4">2.4.5</span> IMPORT_RES <args></h4> +<div class="outline-text-4" id="text-2-4-5"> + +<p> Final statistics on import process (this is one long line). The + args are a list of unsigned numbers separated by white space: +</p> +<ul> +<li><count> +</li> +<li><no_user_id> +</li> +<li><imported> +</li> +<li><imported_rsa> +</li> +<li><unchanged> +</li> +<li><n_uids> +</li> +<li><n_subk> +</li> +<li><n_sigs> +</li> +<li><n_revoc> +</li> +<li><sec_read> +</li> +<li><sec_imported> +</li> +<li><sec_dups> +</li> +<li><skipped_new_keys> +</li> +<li><not_imported> +</li> +</ul> + + +</div> +</div> + +</div> + +<div id="outline-container-2-5" class="outline-3"> +<h3 id="sec-2-5"><span class="section-number-3">2.5</span> Smartcard related</h3> +<div class="outline-text-3" id="text-2-5"> + + +</div> + +<div id="outline-container-2-5-1" class="outline-4"> +<h4 id="sec-2-5-1"><span class="section-number-4">2.5.1</span> CARDCTRL <what> [<serialno>]</h4> +<div class="outline-text-4" id="text-2-5-1"> + +<p> This is used to control smartcard operations. Defined values for + WHAT are: +</p> +<dl> +<dt>1</dt><dd>Request insertion of a card. Serialnumber may be given + to request a specific card. Used by gpg 1.4 w/o + scdaemon +</dd> +<dt>2</dt><dd>Request removal of a card. Used by gpg 1.4 w/o scdaemon. +</dd> +<dt>3</dt><dd>Card with serialnumber detected +</dd> +<dt>4</dt><dd>No card available +</dd> +<dt>5</dt><dd>No card reader available +</dd> +<dt>6</dt><dd>No card support available +</dd> +</dl> + + +</div> + +</div> + +<div id="outline-container-2-5-2" class="outline-4"> +<h4 id="sec-2-5-2"><span class="section-number-4">2.5.2</span> SC_OP_FAILURE [<code>]</h4> +<div class="outline-text-4" id="text-2-5-2"> + +<p> An operation on a smartcard definitely failed. Currently there is + no indication of the actual error code, but application should be + prepared to later accept more arguments. Defined values for + <code> are: +</p> +<dl> +<dt>0</dt><dd>unspecified error (identically to a missing CODE) +</dd> +<dt>1</dt><dd>canceled +</dd> +<dt>2</dt><dd>bad PIN +</dd> +</dl> + + +</div> + +</div> + +<div id="outline-container-2-5-3" class="outline-4"> +<h4 id="sec-2-5-3"><span class="section-number-4">2.5.3</span> SC_OP_SUCCESS</h4> +<div class="outline-text-4" id="text-2-5-3"> + +<p> A smart card operaion succeeded. This status is only printed for + certain operation and is mostly useful to check whether a PIN + change really worked. +</p> +</div> +</div> + +</div> + +<div id="outline-container-2-6" class="outline-3"> +<h3 id="sec-2-6"><span class="section-number-3">2.6</span> Miscellaneous status codes</h3> +<div class="outline-text-3" id="text-2-6"> + + +</div> + +<div id="outline-container-2-6-1" class="outline-4"> +<h4 id="sec-2-6-1"><span class="section-number-4">2.6.1</span> NODATA <what></h4> +<div class="outline-text-4" id="text-2-6-1"> + +<p> No data has been found. Codes for WHAT are: +</p> +<dl> +<dt>1</dt><dd>No armored data. +</dd> +<dt>2</dt><dd>Expected a packet but did not found one. +</dd> +<dt>3</dt><dd>Invalid packet found, this may indicate a non OpenPGP + message. +</dd> +<dt>4</dt><dd>Signature expected but not found +</dd> +</dl> + + +<p> + You may see more than one of these status lines. +</p> +</div> + +</div> + +<div id="outline-container-2-6-2" class="outline-4"> +<h4 id="sec-2-6-2"><span class="section-number-4">2.6.2</span> UNEXPECTED <what></h4> +<div class="outline-text-4" id="text-2-6-2"> + +<p> Unexpected data has been encountered. Codes for WHAT are: +</p><dl> +<dt>0</dt><dd>Not further specified +</dd> +</dl> + + +</div> + +</div> + +<div id="outline-container-2-6-3" class="outline-4"> +<h4 id="sec-2-6-3"><span class="section-number-4">2.6.3</span> TRUNCATED <maxno></h4> +<div class="outline-text-4" id="text-2-6-3"> + +<p> The output was truncated to MAXNO items. This status code is + issued for certain external requests. +</p> +</div> + +</div> + +<div id="outline-container-2-6-4" class="outline-4"> +<h4 id="sec-2-6-4"><span class="section-number-4">2.6.4</span> ERROR <error location> <error code> [<more>]</h4> +<div class="outline-text-4" id="text-2-6-4"> + +<p> This is a generic error status message, it might be followed by + error location specific data. <error code> and <error_location> + should not contain spaces. The error code is a either a string + commencing with a letter or such a string prefixed with a + numerical error code and an underscore; e.g.: "151011327_EOF". +</p> +</div> + +</div> + +<div id="outline-container-2-6-5" class="outline-4"> +<h4 id="sec-2-6-5"><span class="section-number-4">2.6.5</span> SUCCESS [<location>]</h4> +<div class="outline-text-4" id="text-2-6-5"> + +<p> Postive confirimation that an operation succeeded. <location> is + optional but if given should not contain spaces. Used only with a + few commands. +</p> +</div> + +</div> + +<div id="outline-container-2-6-6" class="outline-4"> +<h4 id="sec-2-6-6"><span class="section-number-4">2.6.6</span> BADARMOR</h4> +<div class="outline-text-4" id="text-2-6-6"> + +<p> The ASCII armor is corrupted. No arguments yet. +</p> +</div> + +</div> + +<div id="outline-container-2-6-7" class="outline-4"> +<h4 id="sec-2-6-7"><span class="section-number-4">2.6.7</span> DELETE_PROBLEM <reason_code></h4> +<div class="outline-text-4" id="text-2-6-7"> + +<p> Deleting a key failed. Reason codes are: +</p><dl> +<dt>1</dt><dd>No such key +</dd> +<dt>2</dt><dd>Must delete secret key first +</dd> +<dt>3</dt><dd>Ambigious specification +</dd> +</dl> + + +</div> + +</div> + +<div id="outline-container-2-6-8" class="outline-4"> +<h4 id="sec-2-6-8"><span class="section-number-4">2.6.8</span> PROGRESS <what> <char> <cur> <total></h4> +<div class="outline-text-4" id="text-2-6-8"> + +<p> Used by the primegen and Public key functions to indicate + progress. <char> is the character displayed with no –status-fd + enabled, with the linefeed replaced by an 'X'. <cur> is the + current amount done and <total> is amount to be done; a <total> of + 0 indicates that the total amount is not known. The condition +</p><pre class="example"> + TOTAL && CUR == TOTAL +</pre> + +<p> may be used to detect the end of an operation. +</p> +<p> + Well known values for WHAT are: +</p> +<dl> +<dt>pk_dsa </dt><dd>DSA key generation +</dd> +<dt>pk_elg </dt><dd>Elgamal key generation +</dd> +<dt>primegen</dt><dd>Prime generation +</dd> +<dt>need_entropy</dt><dd>Waiting for new entropy in the RNG +</dd> +<dt>tick</dt><dd>Generic tick without any special meaning - useful + for letting clients know that the server is still + working. +</dd> +<dt>starting_agent</dt><dd>A gpg-agent was started because it is not + running as a daemon. +</dd> +<dt>learncard</dt><dd>Send by the agent and gpgsm while learing + the data of a smartcard. +</dd> +<dt>card_busy</dt><dd>A smartcard is still working +</dd> +</dl> + + +</div> + +</div> + +<div id="outline-container-2-6-9" class="outline-4"> +<h4 id="sec-2-6-9"><span class="section-number-4">2.6.9</span> BACKUP_KEY_CREATED <fingerprint> <fname></h4> +<div class="outline-text-4" id="text-2-6-9"> + +<p> A backup of a key identified by <fingerprint> has been writte to + the file <fname>; <fname> is percent-escaped. +</p> +</div> + +</div> + +<div id="outline-container-2-6-10" class="outline-4"> +<h4 id="sec-2-6-10"><span class="section-number-4">2.6.10</span> MOUNTPOINT <name></h4> +<div class="outline-text-4" id="text-2-6-10"> + +<p> <name> is a percent-plus escaped filename describing the + mountpoint for the current operation (e.g. used by "g13 –mount"). + This may either be the specified mountpoint or one randomly + choosen by g13. +</p> +</div> + +</div> + +<div id="outline-container-2-6-11" class="outline-4"> +<h4 id="sec-2-6-11"><span class="section-number-4">2.6.11</span> PINENTRY_LAUNCHED <pid></h4> +<div class="outline-text-4" id="text-2-6-11"> + +<p> This status line is emitted by gpg to notify a client that a + Pinentry has been launched. <pid> is the PID of the Pinentry. It + may be used to display a hint to the user but can't be used to + synchronize with Pinentry. Note that there is also an Assuan + inquiry line with the same name used internally or, if enabled, + send to the client instead of this status line. Such an inquiry + may be used to sync with Pinentry +</p> +</div> +</div> + +</div> + +<div id="outline-container-2-7" class="outline-3"> +<h3 id="sec-2-7"><span class="section-number-3">2.7</span> Obsolete status codes</h3> +<div class="outline-text-3" id="text-2-7"> + + +</div> + +<div id="outline-container-2-7-1" class="outline-4"> +<h4 id="sec-2-7-1"><span class="section-number-4">2.7.1</span> SIGEXPIRED</h4> +<div class="outline-text-4" id="text-2-7-1"> + +<p> Removed on 2011-02-04. This is deprecated in favor of KEYEXPIRED. +</p></div> + +</div> + +<div id="outline-container-2-7-2" class="outline-4"> +<h4 id="sec-2-7-2"><span class="section-number-4">2.7.2</span> RSA_OR_IDEA</h4> +<div class="outline-text-4" id="text-2-7-2"> + +<p> Obsolete. This status message used to be emitted for requests to + use the IDEA or RSA algorithms. It has been dropped from GnuPG + 2.1 after the respective patents expired. +</p></div> + +</div> + +<div id="outline-container-2-7-3" class="outline-4"> +<h4 id="sec-2-7-3"><span class="section-number-4">2.7.3</span> SHM_INFO, SHM_GET, SHM_GET_BOOL, SHM_GET_HIDDEN</h4> +<div class="outline-text-4" id="text-2-7-3"> + +<p> These were used for the ancient shared memory based co-processing. +</p></div> + +</div> + +<div id="outline-container-2-7-4" class="outline-4"> +<h4 id="sec-2-7-4"><span class="section-number-4">2.7.4</span> BEGIN_STREAM, END_STREAM</h4> +<div class="outline-text-4" id="text-2-7-4"> + +<p> Used to issued by the experimental pipemode. +</p> + +</div> +</div> +</div> + +</div> + +<div id="outline-container-3" class="outline-2"> +<h2 id="sec-3"><span class="section-number-2">3</span> Format of the –attribute-fd output</h2> +<div class="outline-text-2" id="text-3"> + + +<p> + When –attribute-fd is set, during key listings (–list-keys, + –list-secret-keys) GnuPG dumps each attribute packet to the file + descriptor specified. –attribute-fd is intended for use with + –status-fd as part of the required information is carried on the + ATTRIBUTE status tag (see above). +</p> +<p> + The contents of the attribute data is specified by RFC 4880. For + convenience, here is the Photo ID format, as it is currently the + only attribute defined: +</p> +<dl> +<dt>Byte 0-1</dt><dd>The length of the image header. Due to a historical + accident (i.e. oops!) back in the NAI PGP days, this + is a little-endian number. Currently 16 (0x10 0x00). + +</dd> +<dt>Byte 2</dt><dd>The image header version. Currently 0x01. + +</dd> +<dt>Byte 3</dt><dd>Encoding format. 0x01 == JPEG. + +</dd> +<dt>Byte 4-15</dt><dd>Reserved, and currently unused. +</dd> +</dl> + + +<p> + All other data after this header is raw image (JPEG) data. +</p> + +</div> + +</div> + +<div id="outline-container-4" class="outline-2"> +<h2 id="sec-4"><span class="section-number-2">4</span> Unattended key generation</h2> +<div class="outline-text-2" id="text-4"> + + +<p> + Please see the GnuPG manual for a description. +</p> + +</div> + +</div> + +<div id="outline-container-5" class="outline-2"> +<h2 id="sec-5"><span class="section-number-2">5</span> Layout of the TrustDB</h2> +<div class="outline-text-2" id="text-5"> + + +<p> + The TrustDB is built from fixed length records, where the first byte + describes the record type. All numeric values are stored in network + byte order. The length of each record is 40 bytes. The first record + of the DB is always of type 1 and this is the only record of this + type. +</p> +<p> + FIXME: The layout changed, document it here. +</p> + + +<pre class="example">Record type 0: +-------------- + Unused record, can be reused for any purpose. + +Record type 1: +-------------- + Version information for this TrustDB. This is always the first + record of the DB and the only one with type 1. + 1 byte value 1 + 3 bytes 'gpg' magic value + 1 byte Version of the TrustDB (2) + 1 byte marginals needed + 1 byte completes needed + 1 byte max_cert_depth + The three items are used to check whether the cached + validity value from the dir record can be used. + 1 u32 locked flags [not used] + 1 u32 timestamp of trustdb creation + 1 u32 timestamp of last modification which may affect the validity + of keys in the trustdb. This value is checked against the + validity timestamp in the dir records. + 1 u32 timestamp of last validation [currently not used] + (Used to keep track of the time, when this TrustDB was checked + against the pubring) + 1 u32 record number of keyhashtable [currently not used] + 1 u32 first free record + 1 u32 record number of shadow directory hash table [currently not used] + It does not make sense to combine this table with the key table + because the keyid is not in every case a part of the fingerprint. + 1 u32 record number of the trusthashtbale + + +Record type 2: (directory record) +-------------- + Informations about a public key certificate. + These are static values which are never changed without user interaction. + + 1 byte value 2 + 1 byte reserved + 1 u32 LID . (This is simply the record number of this record.) + 1 u32 List of key-records (the first one is the primary key) + 1 u32 List of uid-records + 1 u32 cache record + 1 byte ownertrust + 1 byte dirflag + 1 byte maximum validity of all the user ids + 1 u32 time of last validity check. + 1 u32 Must check when this time has been reached. + (0 = no check required) + + +Record type 3: (key record) +-------------- + Informations about a primary public key. + (This is mainly used to lookup a trust record) + + 1 byte value 3 + 1 byte reserved + 1 u32 LID + 1 u32 next - next key record + 7 bytes reserved + 1 byte keyflags + 1 byte pubkey algorithm + 1 byte length of the fingerprint (in bytes) + 20 bytes fingerprint of the public key + (This is the value we use to identify a key) + +Record type 4: (uid record) +-------------- + Informations about a userid + We do not store the userid but the hash value of the userid because that + is sufficient. + + 1 byte value 4 + 1 byte reserved + 1 u32 LID points to the directory record. + 1 u32 next next userid + 1 u32 pointer to preference record + 1 u32 siglist list of valid signatures + 1 byte uidflags + 1 byte validity of the key calculated over this user id + 20 bytes ripemd160 hash of the username. + + +Record type 5: (pref record) +-------------- + This record type is not anymore used. + + 1 byte value 5 + 1 byte reserved + 1 u32 LID; points to the directory record (and not to the uid record!). + (or 0 for standard preference record) + 1 u32 next + 30 byte preference data + +Record type 6 (sigrec) +------------- + Used to keep track of key signatures. Self-signatures are not + stored. If a public key is not in the DB, the signature points to + a shadow dir record, which in turn has a list of records which + might be interested in this key (and the signature record here + is one). + + 1 byte value 6 + 1 byte reserved + 1 u32 LID points back to the dir record + 1 u32 next next sigrec of this uid or 0 to indicate the + last sigrec. + 6 times + 1 u32 Local_id of signatures dir or shadow dir record + 1 byte Flag: Bit 0 = checked: Bit 1 is valid (we have a real + directory record for this) + 1 = valid is set (but may be revoked) + + + +Record type 8: (shadow directory record) +-------------- + This record is used to reserve a LID for a public key. We + need this to create the sig records of other keys, even if we + do not yet have the public key of the signature. + This record (the record number to be more precise) will be reused + as the dir record when we import the real public key. + + 1 byte value 8 + 1 byte reserved + 1 u32 LID (This is simply the record number of this record.) + 2 u32 keyid + 1 byte pubkey algorithm + 3 byte reserved + 1 u32 hintlist A list of records which have references to + this key. This is used for fast access to + signature records which are not yet checked. + Note, that this is only a hint and the actual records + may not anymore hold signature records for that key + but that the code cares about this. + 18 byte reserved + + + +Record Type 10 (hash table) +-------------- + Due to the fact that we use fingerprints to lookup keys, we can + implement quick access by some simple hash methods, and avoid + the overhead of gdbm. A property of fingerprints is that they can be + used directly as hash values. (They can be considered as strong + random numbers.) + What we use is a dynamic multilevel architecture, which combines + hashtables, record lists, and linked lists. + + This record is a hashtable of 256 entries; a special property + is that all these records are stored consecutively to make one + big table. The hash value is simple the 1st, 2nd, ... byte of + the fingerprint (depending on the indirection level). + + When used to hash shadow directory records, a different table is used + and indexed by the keyid. + + 1 byte value 10 + 1 byte reserved + n u32 recnum; n depends on the record length: + n = (reclen-2)/4 which yields 9 for the current record length + of 40 bytes. + + the total number of such record which makes up the table is: + m = (256+n-1) / n + which is 29 for a record length of 40. + + To look up a key we use the first byte of the fingerprint to get + the recnum from this hashtable and look up the addressed record: + - If this record is another hashtable, we use 2nd byte + to index this hash table and so on. + - if this record is a hashlist, we walk all entries + until we found one a matching one. + - if this record is a key record, we compare the + fingerprint and to decide whether it is the requested key; + + +Record type 11 (hash list) +-------------- + see hash table for an explanation. + This is also used for other purposes. + + 1 byte value 11 + 1 byte reserved + 1 u32 next next hash list record + n times n = (reclen-5)/5 + 1 u32 recnum + + For the current record length of 40, n is 7 + + + +Record type 254 (free record) +--------------- + All these records form a linked list of unused records. + 1 byte value 254 + 1 byte reserved (0) + 1 u32 next_free +</pre> + + + +</div> + +</div> + +<div id="outline-container-6" class="outline-2"> +<h2 id="sec-6"><span class="section-number-2">6</span> GNU extensions to the S2K algorithm</h2> +<div class="outline-text-2" id="text-6"> + + +<p> + S2K mode 101 is used to identify these extensions. + After the hash algorithm the 3 bytes "GNU" are used to make + clear that these are extensions for GNU, the next bytes gives the + GNU protection mode - 1000. Defined modes are: +</p><dl> +<dt>1001</dt><dd>Do not store the secret part at all. +</dd> +<dt>1002</dt><dd>A stub to access smartcards (not used in 1.2.x) +</dd> +</dl> + + +</div> + +</div> + +<div id="outline-container-7" class="outline-2"> +<h2 id="sec-7"><span class="section-number-2">7</span> Keyserver helper message format</h2> +<div class="outline-text-2" id="text-7"> + + +<p> + The keyserver may be contacted by a Unix Domain socket or via TCP. +</p> +<p> + The format of a request is: +</p> + + +<pre class="example">command-tag +"Content-length:" digits +CRLF +</pre> + + +<p> + Where command-tag is +</p> + + + +<pre class="example">NOOP +GET <user-name> +PUT +DELETE <user-name> +</pre> + + +<p> +The format of a response is: +</p> + + + +<pre class="example">"GNUPG/1.0" status-code status-text +"Content-length:" digits +CRLF +</pre> + +<p> +followed by <digits> bytes of data +</p> +<p> +Status codes are: +</p> +<dl> +<dt>1xx</dt><dd>Informational - Request received, continuing process + +</dd> +<dt>2xx</dt><dd>Success - The action was successfully received, understood, + and accepted + +</dd> +<dt>4xx</dt><dd>Client Error - The request contains bad syntax or cannot be + fulfilled + +</dd> +<dt>5xx</dt><dd>Server Error - The server failed to fulfill an apparently + valid request +</dd> +</dl> + + + +</div> + +</div> + +<div id="outline-container-8" class="outline-2"> +<h2 id="sec-8"><span class="section-number-2">8</span> Object identifiers</h2> +<div class="outline-text-2" id="text-8"> + + +<p> + OIDs below the GnuPG arc: +</p> + + + +<pre class="example">1.3.6.1.4.1.11591.2 GnuPG +1.3.6.1.4.1.11591.2.1 notation +1.3.6.1.4.1.11591.2.1.1 pkaAddress +1.3.6.1.4.1.11591.2.2 X.509 extensions +1.3.6.1.4.1.11591.2.2.1 standaloneCertificate +1.3.6.1.4.1.11591.2.2.2 wellKnownPrivateKey +1.3.6.1.4.1.11591.2.12242973 invalid encoded OID +</pre> + + + + +</div> + +</div> + +<div id="outline-container-9" class="outline-2"> +<h2 id="sec-9"><span class="section-number-2">9</span> Miscellaneous notes</h2> +<div class="outline-text-2" id="text-9"> + + + +</div> + +<div id="outline-container-9-1" class="outline-3"> +<h3 id="sec-9-1"><span class="section-number-3">9.1</span> v3 fingerprints</h3> +<div class="outline-text-3" id="text-9-1"> + +<p> For packet version 3 we calculate the keyids this way: +</p><dl> +<dt>RSA</dt><dd>Low 64 bits of n +</dd> +<dt>ELGAMAL</dt><dd>Build a v3 pubkey packet (with CTB 0x99) and + calculate a RMD160 hash value from it. This is used + as the fingerprint and the low 64 bits are the keyid. +</dd> +</dl> + + +</div> + +</div> + +<div id="outline-container-9-2" class="outline-3"> +<h3 id="sec-9-2"><span class="section-number-3">9.2</span> Simplified revocation certificates</h3> +<div class="outline-text-3" id="text-9-2"> + +<p> Revocation certificates consist only of the signature packet; + "–import" knows how to handle this. The rationale behind it is to + keep them small. +</p> +</div> + +</div> + +<div id="outline-container-9-3" class="outline-3"> +<h3 id="sec-9-3"><span class="section-number-3">9.3</span> Documentation on HKP (the http keyserver protocol):</h3> +<div class="outline-text-3" id="text-9-3"> + + +<p> + A minimalistic HTTP server on port 11371 recognizes a GET for + /pks/lookup. The standard http URL encoded query parameters are + this (always key=value): +</p> +<ul> +<li>op=index (like pgp -kv), op=vindex (like pgp -kvv) and op=get (like + pgp -kxa) + +</li> +<li>search=<stringlist>. This is a list of words that must occur in the key. + The words are delimited with space, points, @ and so on. The delimiters + are not searched for and the order of the words doesn't matter (but see + next option). + +</li> +<li>exact=on. This switch tells the hkp server to only report exact matching + keys back. In this case the order and the "delimiters" are important. + +</li> +<li>fingerprint=on. Also reports the fingerprints when used with 'index' or + 'vindex' +</li> +</ul> + + +<p> + The keyserver also recognizes http-POSTs to /pks/add. Use this to upload + keys. +</p> + +<p> + A better way to do this would be a request like: +</p> +<p> + /pks/lookup/<gnupg_formatierte_user_id>?op=<operation> +</p> +<p> + This can be implemented using Hurd's translator mechanism. + However, I think the whole key server stuff has to be re-thought; + I have some ideas and probably create a white paper. +</p></div> +</div> +</div> +</div> + +<div id="postamble"> +<p class="date">Date: 2013-07-03T09:52+0000</p> +<p class="author">Author: isis</p> +<p class="email"><a href="mailto:isis@wintermute.patternsinthevoid.net">isis@wintermute.patternsinthevoid.net</a></p> +<p class="creator"><a href="http://orgmode.org">Org</a> version 7.9.2 with <a href="http://www.gnu.org/software/emacs/">Emacs</a> version 24</p> +<a href="http://validator.w3.org/check?uri=referer">Validate XHTML 1.0</a> + +</div> +</body> +</html> diff --git a/docs/_static/agogo.css b/docs/_static/agogo.css new file mode 100644 index 0000000..2bdc26f --- /dev/null +++ b/docs/_static/agogo.css @@ -0,0 +1,337 @@ +* { + margin: 0px; + padding: 0px; +} + +body { + font-family: "Verdana", Arial, sans-serif; + line-height: 1.4em; + font-size: 14px; + color: black; + background-color: #eeeeec; +} + + +/* Page layout */ + +div.header, div.content, div.footer { + width: 70em; + margin-left: auto; + margin-right: auto; +} + +div.header-wrapper { + background: url(bgtop.png) top left repeat-x; + border-bottom: 3px solid #2e3436; +} + +div.headertitle a { + font-family: "Georgia", "Times New Roman", serif; + font-size: 2em; + color: rgb(252, 175, 62); + font-weight: normal; +} + +h1 { + color: #204a87; +} + +/* Default body styles */ +a { + text-decoration: none; + color: #ce5c00; +} + +.clearer { + clear: both; +} + +.left { + float: left; +} + +.right { + float: right; +} + +h1, h2, h3, h4 { + font-family: "Georgia", "Times New Roman", serif; + font-weight: normal; + color: #3465a4; + margin-bottom: .8em; +} + +h1 { + color: #204a87; +} + +h2 { + padding-bottom: .5em; + border-bottom: 1px solid #3465a4; +} + +a.headerlink { + visibility: hidden; + color: #dddddd; + padding-left: .3em; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink { + visibility: visible; +} + + + +/* Header */ + +div.header { + padding-top: 10px; + padding-bottom: 10px; +} + +div.header h1 { + font-family: "Georgia", "Times New Roman", serif; + font-weight: normal; + font-size: 160%; + letter-spacing: .08em; +} + +div.header h1 a { + color: white; +} + +div.header div.rel { + margin-top: 1em; +} + +div.header div.rel a { + color: #fcaf3e; + letter-spacing: .1em; + text-transform: uppercase; +} + + +/* Content */ +div.content-wrapper { + background-color: white; + padding-top: 20px; + padding-bottom: 20px; +} + +div.document { + width: 50em; + float: left; +} + +div.body { + padding-right: 2em; + text-align: justify; +} + +div.document ul { + margin-left: 1.2em; + list-style-type: square; +} + +div.document dd { + margin-left: 1.2em; + margin-top: .4em; + margin-bottom: 1em; +} + +div.document .section { + margin-top: 1.7em; +} +div.document .section:first-child { + margin-top: 0px; +} + +div.document div.highlight { + padding: 3px; + background-color: #eeeeec; + border-top: 2px solid #dddddd; + border-bottom: 2px solid #dddddd; + margin-top: .8em; + margin-bottom: .8em; +} + +div.document h2 { + margin-top: .7em; +} + +div.document p { + margin-bottom: .5em; +} + +div.document li.toctree-l1 { + margin-bottom: 1em; +} + +div.document .descname { + font-weight: bold; +} + +div.document .docutils.literal { + background-color: #eeeeec; + padding: 1px; +} + +div.document .docutils.xref.literal { + background-color: transparent; + padding: 0px; +} + + +/* Sidebar */ + +div.sidebar { + width: 20em; + float: right; + font-size: .9em; +} + +div.sidebar h3 { + color: #2e3436; + text-transform: uppercase; + font-size: 130%; + letter-spacing: .1em; +} + +div.sidebar ul { + list-style-type: none; +} + +div.sidebar li.toctree-l1 a { + display: block; + padding: 1px; + border: 1px solid #dddddd; + background-color: #eeeeec; + margin-bottom: .4em; + padding-left: 3px; + color: #2e3436; +} + +div.sidebar li.toctree-l2 a { + background-color: transparent; + border: none; + border-bottom: 1px solid #dddddd; +} + +div.sidebar li.toctree-l2:last-child a { + border-bottom: none; +} + +div.sidebar li.toctree-l1.current a { + border-right: 5px solid #fcaf3e; +} + +div.sidebar li.toctree-l1.current li.toctree-l2 a { + border-right: none; +} + + +/* Footer */ + +div.footer-wrapper { + background: url(bgfooter.png) top left repeat-x; + border-top: 4px solid #babdb6; + padding-top: 10px; + padding-bottom: 10px; + min-height: 80px; +} + +div.footer, div.footer a { + color: #888a85; +} + +div.footer .right { + text-align: right; +} + +div.footer .left { + text-transform: uppercase; +} + + +/* Styles copied form basic theme */ + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li div.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable dl, table.indextable dd { + margin-top: 0; + margin-bottom: 0; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} diff --git a/docs/_static/pygments.css b/docs/_static/pygments.css new file mode 100644 index 0000000..45bae6e --- /dev/null +++ b/docs/_static/pygments.css @@ -0,0 +1,69 @@ +.hll { background-color: #ffffcc } +.c { color: #8f5902; font-style: italic } /* Comment */ +.err { color: #a40000; border: 1px solid #ef2929 } /* Error */ +.g { color: #000000 } /* Generic */ +.k { color: #204a87; font-weight: bold } /* Keyword */ +.l { color: #000000 } /* Literal */ +.n { color: #000000 } /* Name */ +.o { color: #ce5c00; font-weight: bold } /* Operator */ +.x { color: #000000 } /* Other */ +.p { color: #000000; font-weight: bold } /* Punctuation */ +.cm { color: #8f5902; font-style: italic } /* Comment.Multiline */ +.cp { color: #8f5902; font-style: italic } /* Comment.Preproc */ +.c1 { color: #8f5902; font-style: italic } /* Comment.Single */ +.cs { color: #8f5902; font-style: italic } /* Comment.Special */ +.gd { color: #a40000 } /* Generic.Deleted */ +.ge { color: #000000; font-style: italic } /* Generic.Emph */ +.gr { color: #ef2929 } /* Generic.Error */ +.gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.gi { color: #00A000 } /* Generic.Inserted */ +.go { color: #000000; font-style: italic } /* Generic.Output */ +.gp { color: #8f5902 } /* Generic.Prompt */ +.gs { color: #000000; font-weight: bold } /* Generic.Strong */ +.gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.gt { color: #a40000; font-weight: bold } /* Generic.Traceback */ +.kc { color: #204a87; font-weight: bold } /* Keyword.Constant */ +.kd { color: #204a87; font-weight: bold } /* Keyword.Declaration */ +.kn { color: #204a87; font-weight: bold } /* Keyword.Namespace */ +.kp { color: #204a87; font-weight: bold } /* Keyword.Pseudo */ +.kr { color: #204a87; font-weight: bold } /* Keyword.Reserved */ +.kt { color: #204a87; font-weight: bold } /* Keyword.Type */ +.ld { color: #000000 } /* Literal.Date */ +.m { color: #0000cf; font-weight: bold } /* Literal.Number */ +.s { color: #4e9a06 } /* Literal.String */ +.na { color: #c4a000 } /* Name.Attribute */ +.nb { color: #204a87 } /* Name.Builtin */ +.nc { color: #000000 } /* Name.Class */ +.no { color: #000000 } /* Name.Constant */ +.nd { color: #5c35cc; font-weight: bold } /* Name.Decorator */ +.ni { color: #ce5c00 } /* Name.Entity */ +.ne { color: #cc0000; font-weight: bold } /* Name.Exception */ +.nf { color: #000000 } /* Name.Function */ +.nl { color: #f57900 } /* Name.Label */ +.nn { color: #000000 } /* Name.Namespace */ +.nx { color: #000000 } /* Name.Other */ +.py { color: #000000 } /* Name.Property */ +.nt { color: #204a87; font-weight: bold } /* Name.Tag */ +.nv { color: #000000 } /* Name.Variable */ +.ow { color: #204a87; font-weight: bold } /* Operator.Word */ +.w { color: #f8f8f8; text-decoration: underline } /* Text.Whitespace */ +.mf { color: #0000cf; font-weight: bold } /* Literal.Number.Float */ +.mh { color: #0000cf; font-weight: bold } /* Literal.Number.Hex */ +.mi { color: #0000cf; font-weight: bold } /* Literal.Number.Integer */ +.mo { color: #0000cf; font-weight: bold } /* Literal.Number.Oct */ +.sb { color: #4e9a06 } /* Literal.String.Backtick */ +.sc { color: #4e9a06 } /* Literal.String.Char */ +.sd { color: #8f5902; font-style: italic } /* Literal.String.Doc */ +.s2 { color: #4e9a06 } /* Literal.String.Double */ +.se { color: #4e9a06 } /* Literal.String.Escape */ +.sh { color: #4e9a06 } /* Literal.String.Heredoc */ +.si { color: #4e9a06 } /* Literal.String.Interpol */ +.sx { color: #4e9a06 } /* Literal.String.Other */ +.sr { color: #4e9a06 } /* Literal.String.Regex */ +.s1 { color: #4e9a06 } /* Literal.String.Single */ +.ss { color: #4e9a06 } /* Literal.String.Symbol */ +.bp { color: #3465a4 } /* Name.Builtin.Pseudo */ +.vc { color: #000000 } /* Name.Variable.Class */ +.vg { color: #000000 } /* Name.Variable.Global */ +.vi { color: #000000 } /* Name.Variable.Instance */ +.il { color: #0000cf; font-weight: bold } /* Literal.Number.Integer.Long */ diff --git a/docs/change-license-emails.txt b/docs/change-license-emails.txt new file mode 100644 index 0000000..7086089 --- /dev/null +++ b/docs/change-license-emails.txt @@ -0,0 +1,272 @@ +From: intrigeri <intrigeri@boum.org> +To: Isis! <isis@patternsinthevoid.net> +Subject: AGPL library, really? +Date: Thu, 04 Jul 2013 17:38:46 +0000 + +Hi isis, + +I see on https://pypi.python.org/pypi/gnupg that you released this +library under AGPLv3. Is this correct? + +If it is, then you might be interested to have a look to this long +ongoing thread on debian-devel mailing-list where I've seen explained +(by people I trust on this topic) that AGPLv3 is really not well +suited for libraries -- to start with, quite some of its terms are +ambiguous when one tries to apply them to a library: +https://lists.debian.org/debian-devel/2013/07/msg00031.html + +Cheers, +-- + intrigeri + | GnuPG key @ https://gaffer.ptitcanardnoir.org/intrigeri/intrigeri.asc + | OTR fingerprint @ https://gaffer.ptitcanardnoir.org/intrigeri/otr.asc + + +From: isis agora lovecruft <isis@patternsinthevoid.net> +To: intrigeri <intrigeri@boum.org> +Subject: Re: AGPL library, really? +Date: Sun, 07 Jul 2013 04:20:13 +0000 + +Hi intrigeri! + +intrigeri transcribed 2.3K bytes: +> I see on https://pypi.python.org/pypi/gnupg that you released this +> library under AGPLv3. Is this correct? + +Yes, that it correct. + +> If it is, then you might be interested to have a look to this long +> ongoing thread on debian-devel mailing-list where I've seen explained +> (by people I trust on this topic) that AGPLv3 is really not well +> suited for libraries -- to start with, quite some of its terms are +> ambiguous when one tries to apply them to a library: +> https://lists.debian.org/debian-devel/2013/07/msg00031.html + +Okay, thanks! + +/me reads… + +I think this message better describes why AGPL is bad for libraries: +https://lists.debian.org/debian-devel/2013/07/msg00041.html or, at least, I +understood that one better than the first. + +I certainly do not want to make problems for Debian, and now that a bunch of +Tor, LEAP, CryptoParty, and Freebox projects, and perhaps soon Pip too, will +be depending on this, I *really* don't want to make anyone else's license hell +worse. + +Attached is an email from leap@lists.riseup.net where we had fisticuffs over +licensing opinions, wherein I explained my preference for AGPL for +everything. Essentially, I do not want people/corporations/etc. to use my work +in a closed source application and then potentially make changes to patch +found vulnerabilities without contributing those patches back to the main +codebase. + +Though, you're correct, this doesn't make sense for a library, as a +closed-source web-service frontend to this Python module likely isn't going to +get anyone exploited except the person running the service. So it doesn't make +as much sense. + +Do you know if it is okay for me to re-license it as regular GPL? + +Do you have any advice on which of GPLv(2|3)(\+)* that I should use? + +Thanks for pointing this out so quickly before it caused trouble, by the +way. :) + +-- + ♥Ⓐisis agora lovecruft +_________________________________________________________ +GPG: 4096R/A3ADB67A2CDB8B35 +Current Keys: https://blog.patternsinthevoid.net/isis.txt + +--Attachment 1-- + Date: Tue, 28 May 2013 04:13:56 +0000 + From: isis agora lovecruft <isis@patternsinthevoid.net> + To: micah <micah@riseup.net> + Cc: leap@lists.riseup.net + X-GPG-Public-Key-URL: https://blog.patternsinthevoid.net/isis.txt + X-Louis-Lingg: In this hope do I say to you I despise you. I despise your + order, your laws, your force-propped authority. Hang me for it! + Subject: Re: [leap] license + + micah transcribed 1.3K bytes: + > Tomas Touceda <chiiph@riseup.net> writes: + > + > > On 05/13/2013 05:32 PM, elijah wrote: + > >> if you have any wisdom or opinions regarding the ever joyful and + > >> uncontroversial topic of free software licenses, then please deposit + > >> said wisdom or opinions in this wiki: + > >> + > >> https://we.riseup.net/leap/license + > >> + > >> in a nutshell, we need to decide on a license for the client. + > > + > > Does anybody have license knowledge a priori? Or should I get started + > > reading licenses? + > + > I'm supposed to have a more than zero knowledge of what constitutes free + > licenses due to my debian training, and debian is world-renknowned for + > having a particularly nasty debian-legal mailing list where licenses are + > chewed up and spit out... but I personally hate the topic and tend to + > avoid it as much as possible. + > + > So basically my opinons are: + > + > 1. no license that is incompatible with the DFSG[0] (debian free + > software guidelines) - it seems like we are probably in agreement about + > this? + + ACK + + > 2. BSD multi-claused licenses and MIT are confusing and annoying, so I + > tend to think they should be avoided due to this + > + + ACK + + > 3. openssl derived works require granting an exception with GPL licenses + > (an exception is trivial), so I prefer gnutls code where possible + > + + ACK + + > 4. it seems weird to make things AGPL that aren't webapps + > + + I started release everything I could AGPLv3 three years ago, after a + conversation with some other activist free-software devs: + + Me: "I want a license which says 'If you are part of any governing body or + corporation which contracts to any private or public military entity, then + you should go fuck youself. And no, you cannot use my software -- I will + sue your pants off.'" + + Them: "Isis, that is silly, and even na=C3=AFve. Universities are libraries are + often 'part of governing bodies', you don't want to exclude them, do you? + And also, you're like not going to see the blobs your code is included + in...it will get privately installed on custom military and law + enforcement hardware, and when they're done with it it'll go and rot + outside on a base or in a police confiscation parking lot somewhere." + + Me: "Hum. I hate talking about licenses anyway." + + Them: "Yeah, it sucks. But it's important for us to take this seriously, + because the tools we're working on have the potential for helping us + better organise at protests, as well as better help the cops kettle us + into paddy wagons." [one of the tools was a crisis mapping thing] + + Different one of them: "Perhaps you both should read AGPL, and see if that + helps. I don't think using law against them is going to work, because we + can't assume they will play by the rules, but if we're arguing licenses + anyway..." + + AGPL also seems useful when it seems possible that shady closed-source + startups are going to add a fancier UI or other feature to your code, and then + market it. This is especially worrying, not because they are "stealing users", + but because it's never clear if vulns discovered in your own code have been + fixed in theirs and vice versa. Or, it could get used in way that is + dangerous, or that it wasn't meant for. (For example, there is currently a + concern that a certain shell company is going to use OONI's code on these + little android-system-on-a-USB dongly thingies...and there are certain dangers + with Tor on Android that these people either don't understand or have no + intention of warning users about.) + + Anyway. There is my argument for AGPL. + + Though I also hate these discussions, don't care about laws, think reformism + is bunk, WTFPL is the only sane LICENSE, and all that jazz, so I'm going to go + stand over there -----------------------------------------------------------> + and watch everybody else duke it out. :) + + -- + ♥Ⓐ isis agora lovecruft + _________________________________________________________ + GPG: 4096R/A3ADB67A2CDB8B35 + Current Keys: https://blog.patternsinthevoid.net/isis.txt +--End Attachment 1-- + +From: intrigeri <intrigeri@boum.org> +To: Isis! <isis@patternsinthevoid.net> +Subject: Re: AGPL library, really? +Date: Tue, 09 Jul 2013 18:30:46 +0000 + +Hi isis, + +isis agora lovecruft wrote (07 Jul 2013 04:20:13 GMT) : +> I think this message better describes why AGPL is bad for libraries: +> https://lists.debian.org/debian-devel/2013/07/msg00041.html +> or, at least, I understood that one better than the first. + +TBH, I've pointed you at the beginning of the thread because I was too +lazy to go fetch the best email in there. I'm glad it helps anyway. + +> Do you know if it is okay for me to re-license it as regular GPL? + +I've just re-read a bit to confirm, and my conclusion is that: yeah, +as the sole copyright holder (is this the case?) you can freely +re-licence to whatever you want. + +> Do you have any advice on which of GPLv(2|3)(\+)* that I should use? + +I usually do GPL-3+, but I would not be able to defend it seriously +against v2 or v2+. + +> Thanks for pointing this out so quickly before it caused trouble, by the +> way. :) + +Np. + +Cheers! +-- + intrigeri + | GnuPG key @ https://gaffer.ptitcanardnoir.org/intrigeri/intrigeri.asc + | OTR fingerprint @ https://gaffer.ptitcanardnoir.org/intrigeri/otr.asc + +From: isis agora lovecruft <isis@patternsinthevoid.net> +To: intrigeri <intrigeri@boum.org> +Subject: Re: AGPL library, really? +Date: Thu, 11 Jul 2013 09:24:12 +0000 + +intrigeri transcribed 2.6K bytes: +> isis agora lovecruft wrote (07 Jul 2013 04:20:13 GMT) : +> > Do you know if it is okay for me to re-license it as regular GPL? +> +> I've just re-read a bit to confirm, and my conclusion is that: yeah, +> as the sole copyright holder (is this the case?) you can freely +> re-licence to whatever you want. + +Hey intrigeri, + +I've decided to re-license with your recommendation of GPL3+. Is it okay to +credit you and/or publicly point to these emails as the basis for the +rationale for the switch? + +-- + ♥Ⓐ isis agora lovecruft +_________________________________________________________ +GPG: 4096R/A3ADB67A2CDB8B35 +Current Keys: https://blog.patternsinthevoid.net/isis.txt + +From: intrigeri <intrigeri@boum.org> +To: Isis! <isis@patternsinthevoid.net> +Subject: Re: AGPL library, really? +Date: Sun, 14 Jul 2013 22:33:35 +0000 + +Hi isis, + +> Is it okay to credit you and/or publicly point to these emails as +> the basis for the rationale for the switch? + +Feel free to credit me if you wish, but I certainly don't feel it's +necessary. + +I feel a bit lazy to read this thread again to check if it's fine to +publish stuff from there, so if you don't mind, I'd rather skip this +part ;) + +Cheers, +-- + intrigeri + | GnuPG key @ https://gaffer.ptitcanardnoir.org/intrigeri/intrigeri.asc + | OTR fingerprint @ https://gaffer.ptitcanardnoir.org/intrigeri/otr.asc diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..4986e0b --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,312 @@ +# -*- coding: utf-8 -*- +# +# python-gnupg documentation build configuration file, created by +# sphinx-quickstart on Fri Apr 5 22:38:47 2013. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os +import psutil + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.insert(0, os.path.abspath('./../')) +sys.path.insert(0, os.path.abspath('.')) + +# -- Autodoc settings ---------------------------------------------------------- +## trying to set this somewhere... +autodoc_member_order = 'bysource' +autodoc_default_flags = ['members', 'show-inheritance', 'undoc-members', 'show-hidden'] +autoclass_content = 'both' + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +needs_sphinx = '1.1' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc', + 'sphinx.ext.viewcode', + 'sphinx.ext.intersphinx', + 'sphinx.ext.doctest', + 'sphinxcontrib.fulltoc', + ] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_static'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'gnupg' +copyright = u'2013, Isis Agora Lovecruft' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +import gnupg +version = gnupg.__version__ +# The full version, including alpha/beta/rc tags. +release = gnupg.__version__ + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +today_fmt = '%d %B %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +add_module_names = False + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +show_authors = True + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'monokai' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'http://docs.python.org/': None} + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' +html_theme = 'scrolls' +#html_theme = 'traditional' +#html_theme = 'nature' +#html_theme = 'pyramid' +html_theme = 'agogo' +#html_theme = 'haiku' +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +html_theme_options = { +# 'stickysidebar': 'true', +# 'rightsidebar':'true', + 'nosidebar': 'false', +# 'full_logo': 'false' + 'sidebarwidth': '300' + } + +# Add any paths that contain custom themes here, relative to this directory. +html_theme_path = ['_static'] + +# The name for this set of Sphinx documents. If None, it defaults to +# "<project> v<release> documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +html_short_title = "gnupg: Python Module Documentation" + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +html_last_updated_fmt = '%A, %d %B %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a <link> tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +html_file_suffix = '.html' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'gnupgdoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'python-gnupg.tex', u'python-gnupg Documentation', + u'Isis Agora Lovecruft', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'gnupg Python Module Docs', u'gnupg Python Module Documentation', + [u'Isis Agora Lovecruft'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------------ + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'python-gnupg', u'python-gnupg Documentation', + u'Isis Agora Lovecruft', 'python-gnupg', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + + +# -- Options for Epub output --------------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = u'python-gnupg' +epub_author = u'Isis Agora Lovecruft' +epub_publisher = u'Isis Agora Lovecruft' +epub_copyright = u'2013, Isis Agora Lovecruft' + +# The language of the text. It defaults to the language option +# or en if the language is not set. +#epub_language = '' + +# The scheme of the identifier. Typical schemes are ISBN or URL. +#epub_scheme = '' + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +#epub_identifier = '' + +# A unique identification for the text. +#epub_uid = '' + +# A tuple containing the cover image and cover page html template filenames. +#epub_cover = () + +# HTML files that should be inserted before the pages created by sphinx. +# The format is a list of tuples containing the path and title. +#epub_pre_files = [] + +# HTML files shat should be inserted after the pages created by sphinx. +# The format is a list of tuples containing the path and title. +#epub_post_files = [] + +# A list of files that should not be packed into the epub file. +#epub_exclude_files = [] + +# The depth of the table of contents in toc.ncx. +#epub_tocdepth = 3 + +# Allow duplicate toc entries. +#epub_tocdup = True diff --git a/docs/gnupg.rst b/docs/gnupg.rst new file mode 100644 index 0000000..fc8a479 --- /dev/null +++ b/docs/gnupg.rst @@ -0,0 +1,131 @@ +gnupg package +============= + +gnupg module +------------ + +This module contains public classes for working with GnuPG_. To get started, +do: + +>>> import gnupg +>>> gpg = gnupg.GPG() + + +.. automodule:: gnupg + :members: + :undoc-members: + :private-members: + :show-inheritance: + +.. _meta: + +meta module +----------- + +Contains the meta and base classes which :class:`gnupg.GPG` inherits +from. Mostly, you shouldn't ever need to touch anything in here, unless you're +doing some serious hacking. + + +.. automodule:: gnupg._meta + :members: + :private-members: + :special-members: + :exclude-members: _agent_proc, __module__, __dict__, _decode_errors, init, + __weakref__, _result_map, __metaclass__ + :show-inheritance: + +.. _parsers: + +parsers module +-------------- + +These are classes for parsing both user inputs and status file descriptor +flags from GnuPG's output. The latter are used in order to determine what our +GnuPG process is doing and retrieve information about its operations, which +are stored in corresponding classes in +:attr:`~gnupg._meta.GPGBase._result_map`. Some status flags aren't handled yet +-- information on *all* of the flags (well, at least the documented ones…) can +be found in the :file:`docs/DETAILS` file in GnuPG's source_, which has been +included here_ as well. + + +.. automodule:: gnupg._parsers + :members: + :undoc-members: + :private-members: + :show-inheritance: + + +.. _util: + +util module +----------- + +You shouldn't really need to mess with this module either, it mostly deals +with low-level IO and file handling operations, de-/en- coding issues, and +setting up basic package facilities such as logging. + +.. automodule:: gnupg._util + :members: + :undoc-members: + :private-members: + :show-inheritance: + + +About this fork +--------------- + +This is a modified version of python-gnupg_, (forked from version 0.3.2) which +was created by Vinay Sajip, which itself is a modification of GPG.py written +by Steve Traugott, which in turn is a modification of the pycrypto GnuPG +interface written by A.M. Kuchling. + +This version is patched to sanitize untrusted inputs, due to the necessity of +executing ``subprocess.Popen([...], shell=True)`` in order to communicate with +GnuPG. Several speed improvements were also made based on code profiling, and +the API has been cleaned up to support an easier, more Pythonic, interaction. + + +Previous Authors' Documentation +------------------------------- + +Steve Traugott's documentation: + | + | Portions of this module are derived from A.M. Kuchling's well-designed + | GPG.py, using Richard Jones' updated version 1.3, which can be found in + | the pycrypto CVS repository on Sourceforge: + | + | http://pycrypto.cvs.sourceforge.net/viewvc/pycrypto/gpg/GPG.py + | + | This module is *not* forward-compatible with amk's; some of the old + | interface has changed. For instance, since I've added decrypt + | functionality, I elected to initialize with a 'gpghome' argument instead + | of 'keyring', so that gpg can find both the public and secret keyrings. + | I've also altered some of the returned objects in order for the caller to + | not have to know as much about the internals of the result classes. + | + | While the rest of ISconf is released under the GPL, I am releasing this + | single file under the same terms that A.M. Kuchling used for pycrypto. + | + | Steve Traugott, stevegt@terraluna.org + | Thu Jun 23 21:27:20 PDT 2005 + + +Vinay Sajip's documentation: + | + | This version of the module has been modified from Steve Traugott's version + | (see http://trac.t7a.org/isconf/browser/trunk/lib/python/isconf/GPG.py) by + | Vinay Sajip to make use of the subprocess module (Steve's version uses + | os.fork() and so does not work on Windows). Renamed to gnupg.py to avoid + | confusion with the previous versions. + | + | A unittest harness (test_gnupg.py) has also been added. + | + | Modifications Copyright (C) 2008-2012 Vinay Sajip. All rights reserved. + + +.. _GnuPG: http://gnupg.org +.. _python-gnupg: https://code.google.com/p/python-gnupg/ +.. _source: http://http://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=shortlog;h=refs/heads/master +.. _here: ./_static/DETAILS.html diff --git a/docs/gpg-migrate.txt b/docs/gpg-migrate.txt new file mode 100644 index 0000000..1d07450 --- /dev/null +++ b/docs/gpg-migrate.txt @@ -0,0 +1,208 @@ +# taken from http://atom.smasher.org/gpg/gpg-migrate.txt on 8 Aug 2013 + +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +HOW TO MIGRATE A (SUB)KEY INTO A NEW KEY + +this document [is intended to] explain how to migrate a key or subkey from +one OpenPGP key into another OpenPGP key. + +here i'll walk you through the steps of migrating my old primary signing +key (3D7D41E3) into my new key (D9F57808). the process of migrating +encryption (and signing) subkeys is nearly identical. for the adventurous, +you can even migrate several keys at once using this method (i recommend +going through it once or twice with only one key). + +============================================================================ + +doing this requires: + 1) basic knowledge of a *nix command line and how to use it + 2) advanced knowledge of gpg and how to use it + 3) common sense (BACKUP YOUR DATA!!) + +please note: + * this works for me. that does not necessarily mean that it will + work for you + * if you screw something up, it's *YOUR* problem, not mine + * this was tested with GnuPG 1.2.4, and written on or about + 12 May 2004 + * updates, if there are any, will probably be noted above + * comments and suggestions about this tutorial should be sent to: + <atom {at} smasher.org> + * questions about gpg should be sent to the gnupg-users mailing + list: http://lists.gnupg.org/mailman/listinfo/gnupg-users + +============================================================================ + +* old key: 3EBE 2810 30AE 601D 54B2 4A90 9C28 0BBF 3D7D 41E3 + +pub 1024D/3D7D41E3 2003-10-04 Atom Smasher <atom@suspicious.org> +uid Atom Smasher <atom@smasher.org> +sub 2048g/1E88BF71 2003-10-04 [expires: 2005-01-26] + +================ + +* new key: 762A 3B98 A3C3 96C9 C6B7 582A B88D 52E4 D9F5 7808 + +pub 4096R/D9F57808 2004-05-11 Atom Smasher <atom@smasher.org> +uid Atom Smasher <atom@suspicious.org> +sub 1024D/3D7D41E3 2003-10-04 [expires: 2006-02-13] +sub 2048g/1E88BF71 2003-10-04 [expires: 2006-01-26] + +=================================== + +backup the new keys: + $ gpg --export D9F57808 > D9F57808_original.txt + $ gpg --export-secret-key D9F57808 > D9F57808_original_secret.txt + +and the old keys: + $ gpg --export 3D7D41E3 > 3D7D41E3_original.txt + $ gpg --export-secret-key 3D7D41E3 > 3D7D41E3_original_secret.txt + +break the old secret key into pieces: + $ gpg --export-secret-key 3D7D41E3 | gpgsplit -vp OLD_SEC + +=================================== + +in this case, the old primary key needs to be converted into a subkey. +pgpdump shows that it's a primary key: + $ pgpdump OLD_SEC000001-005.secret_key + Old: Secret Key Packet(tag 5) + <<snip>> + +only do this if you're converting a PRIMARY KEY into a SUBKEY: open that +file in a hex editor and refer to RFC2440 4.2 & 4.3. i recommend setting +the hex editor into a binary display. in this example the first byte is +"10010101" and it needs to be changed to "10011101". the change can be +confirmed with pgpdump: + $ pgpdump OLD_SEC000001-005.secret_key + Old: Secret Subkey Packet(tag 7) + <<snip>> + +we've now converted the old primary key into a subkey. if you're moving a +subkey from one key to another, you don't have to do that. + +=================================== + +use "edit-key" and add a subkey of the same type (DSA, for this example) +and size to the new key. this subkey will be discarded, but we need to +generate it for now: this seems to be the quickest way to generate a +keybinding signature with the correct features. + +exit from "edit-key" and save. + +=================================== + +split the current version of the new public key: + $ gpg --export D9F57808 | gpgsplit -vp TEMP_KEY1 +the only part we need from that split is the binding signature that was +just generated. + +delete (from the keyring) both the private and public copies of the new +key: + $ gpg --delete-secret-key D9F57808 + $ gpg --delete-key D9F57808 + +also delete (from the keyring) both the private and public copies of the +old key. + +because the subkey that we're adding to the new key does not correspond to +the subkey binding signature that was created for it, gpg will not allow +the key to be imported. the way around that is to "force feed" the key into +the keyring, bypassing the normal sanity checks. once it's in the keyring +we can make it all work. + +* note: the actual file names that you're using may differ somewhat from +mine. when in doubt (or rather, when you're not sure), use pgpdump to +examine the contents of files. + +~import~ (directly into the secret keyring) the original copy of the new +key (D9F57808_original_secret.txt), the edited copy of the old primary key +(now a subkey, OLD_SEC000001-005.secret_key) and the binding signature of +the subkey that we just generated (TEMP_KEY1000007-002.sig): + $ cat D9F57808_original_secret.txt \ + OLD_SEC000001-005.secret_key \ + TEMP_KEY1000007-002.sig >> ~/.gnupg/secring.gpg + +~import~ (directly into the public keyring) a public key by adding +"| gpgsplit --no-split --secret-to-public" to the above command like this: + $ cat D9F57808_original_secret.txt \ + OLD_SEC000001-005.secret_key \ + TEMP_KEY1000007-002.sig \ + | gpgsplit --no-split --secret-to-public >> ~/.gnupg/pubring.gpg + +now we have to make a *valid* keybinding signature for the subkey that we +just added. use "edit-key", select the newly added subkey, and reset it's +expiration date. that will generate a valid keybinding signature. + +while in "edit-key", reset the password. otherwise you may inadvertently +create a key with multiple passwords, as described here - + http://atom.smasher.org/gpg/gpg-passwords.txt + +exit from "edit-key" and save. + +========================= + +this last part makes no sense to me (but it doesn't seem to work +otherwise). + +back up (export) the latest version of the public and private keys: + $ gpg --export-secret-key D9F57808 > new-key.sec + $ gpg --export D9F57808 > new-key.pub + +delete (from the keyring) the private and public key: + $ gpg --delete-secret-key D9F57808 + $ gpg --delete-key D9F57808 + +also, delete (from the keyring) all copies of the old (sub)key that was +just added to the new key. + +import the new public and private keys: + $ gpg --import new-key.sec new-key.pub + +========================= + +before you publish your new key: + +* make sure the key is "ultimately trusted". deleting and importing will +have removed it from the trust db. since you own the key, ultimate trust +seems reasonable. + +* check all expiration dates and preferences. some of these operations may +have changed your expiration dates and preferences; reset as necessary. + +* test out all key components for creating and verifying signatures, and +encryption/decryption. use the bang (!) to force each (sub)key: + create & verify signatures: + $ date | gpg -u 'D9F57808!' --clearsign | gpg -v --verify + $ date | gpg -u '3D7D41E3!' --clearsign | gpg -v --verify + encrypt/decrypt: + $ date | gpg -ear 'D9F57808!' | gpg -v --decrypt + $ date | gpg -ear '1E88BF71!' | gpg -v --decrypt + +* after testing out the keys locally, send your new public key to one or +two people and test all key components (sending signed/encrypted messages +to each other using all key components). make sure that they first delete +(from their keyrings) your old key! and make sure that they understand that +the key should NOT be circulated until all functions are verified to be +working! + +* when putting the new key into circulation, it's probably a good idea to +expire/revoke the old key. include a revocation comment that specifies the +new key ID and instructions to delete the old key from the keyring. + +* note on key revocation: according to the OpenPGP standards a revocation +generated by a sub key will be ignored, unless that subkey has been +designated (by the primary key) as a revocation key. GnuPG seems to behave +correctly, but some versions of PGP(tm) may not. if someone is claiming +that your new key is revoked, have then remove all of your old and current +keys from their keyring: then re-import your current key(s). + +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.2.4 (FreeBSD) + +iD8DBQFApwlpnCgLvz19QeMRAhrpAJ4rhLrmVDjABh8CpPdTZ5jNMi7LsgCgp35S +6qcUe4csx1p5AE2rAsvDi9c= +=y7bA +-----END PGP SIGNATURE----- diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..c266353 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,44 @@ +.. gnupg documentation master file, created by + sphinx-quickstart on Fri Apr 5 22:38:47 2013. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +gnupg: Python Package Documentation +=================================== +A Python interface for handling interactions with GnuPG, including keyfile +generation, keyring maintainance, import and export, encryption and +decryption, sending to and recieving from keyservers, and signing and +verification. + +Contents: + +.. toctree:: + :maxdepth: 2 + + gnupg + + +Source, license, & bug reports +============================== +The source code which was used to generate this documentation is accessible by +clicking the little `source` links next to the docs. Current source code can +be found in this github repository_. The **master** branch always reflects the +latest release, all releases are tagged with signed, annotated git tags, and +the **develop** branch represents the state of the next release. + +This package is released under GPLv3_ or greater. + +If you find a bug, or would like to request a feature, please use our public +bugtracker_ on github. Patches warmly welcome. + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + +.. _source: https://github.com/isislovecruft/python-gnupg +.. _repository: https://github.com/isislovecruft/python-gnupg +.. _GPLv3: https://www.gnu.org/licenses/gpl.txt +.. _bugtracker: https://github.com/isislovecruft/python-gnupg/issues diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..fa3950f --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,190 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +set I18NSPHINXOPTS=%SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^<target^>` where ^<target^> is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\python-gnupg.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\python-gnupg.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +:end |