diff --git a/.gitignore b/.gitignore index ec7b6c5..aa50428 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,19 @@ oldsite/ stage/ scratch/ /web/sitemap.org .*.orgx /web/theindex.inc /web/faq/gnupg-faq.pdf /web/faq/gnupg-faq.tex /web/faq/gnupg-faq.txt /web/swdb.lst /web/swdb.lst.sig /misc/blog.gnupg.org/index.html /misc/blog.gnupg.org/20*.html /misc/blog.gnupg.org/headlines.txt /misc/id/eddsa-for-openpgp/draft.txt +*~ +.DS_Store +._.DS_Store +default.profraw diff --git a/misc/howtos.gnupg.org/en/GPGMEpythonHOWTOen.html b/misc/howtos.gnupg.org/en/GPGMEpythonHOWTOen.html new file mode 100644 index 0000000..8b503d3 --- /dev/null +++ b/misc/howtos.gnupg.org/en/GPGMEpythonHOWTOen.html @@ -0,0 +1,2003 @@ + + + + + + + +GNU Privacy Guard (GnuPG) Made Easy Python Bindings HOWTO (English) + + + + + + +
+

GNU Privacy Guard (GnuPG) Made Easy Python Bindings HOWTO (English)

+
+

Table of Contents

+ +
+ + +
+

1 Introduction

+
+ + + +++ ++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Version:0.1.0
Author:Ben McGinnes <ben@gnupg.org>
Author GPG Key:DB4724E6FA4286C92B4E55C4321E4E2373590E5D
Language:Australian English, British English
xml:lang:en-AU, en-GB, en
+ +

+This document provides basic instruction in how to use the GPGME +Python bindings to programmatically leverage the GPGME library. +

+
+ + +
+

1.1 Python 2 versus Python 3

+
+

+Though the GPGME Python bindings themselves provide support for +both Python 2 and 3, the focus is unequivocally on Python 3 and +specifically from Python 3.4 and above. As a consequence all the +examples and instructions in this guide use Python 3 code. +

+ +

+Much of it will work with Python 2, but much of it also deals with +Python 3 byte literals, particularly when reading and writing data. +Developers concentrating on Python 2.7, and possibly even 2.6, will +need to make the appropriate modifications to support the older +string and unicode types as opposed to bytes. +

+ +

+There are multiple reasons for concentrating on Python 3; some of +which relate to the immediate integration of these bindings, some +of which relate to longer term plans for both GPGME and the python +bindings and some of which relate to the impending EOL period for +Python 2.7. Essentially, though, there is little value in tying +the bindings to a version of the language which is a dead end and +the advantages offered by Python 3 over Python 2 make handling the +data types with which GPGME deals considerably easier. +

+
+
+ + +
+

1.2 Examples

+
+

+All of the examples found in this document can be found as Python 3 +scripts in the lang/python/examples/howto directory. +

+
+
+
+ + +
+

2 GPGME Concepts

+
+
+ + +
+

2.1 A C API

+
+

+Unlike many modern APIs with which programmers will be more +familiar with these days, the GPGME API is a C API. The API is +intended for use by C coders who would be able to access its +features by including the gpgme.h header file with their own C +source code and then access its functions just as they would any +other C headers. +

+ +

+This is a very effective method of gaining complete access to the +API and in the most efficient manner possible. It does, however, +have the drawback that it cannot be directly used by other +languages without some means of providing an interface to those +languages. This is where the need for bindings in various +languages stems. +

+
+
+ + +
+

2.2 Python bindings

+
+

+The Python bindings for GPGME provide a higher level means of +accessing the complete feature set of GPGME itself. It also +provides a more pythonic means of calling these API functions. +

+ +

+The bindings are generated dynamically with SWIG and the copy of +gpgme.h generated when GPGME is compiled. +

+ +

+This means that a version of the Python bindings is fundamentally +tied to the exact same version of GPGME used to generate that copy +of gpgme.h. +

+
+
+ + +
+

2.3 Difference between the Python bindings and other GnuPG Python packages

+
+

+There have been numerous attempts to add GnuPG support to Python +over the years. Some of the most well known are listed here, along +with what differentiates them. +

+
+ + +
+

2.3.1 The python-gnupg package maintained by Vinay Sajip

+
+

+This is arguably the most popular means of integrating GPG with +Python. The package utilises the subprocess module to implement +wrappers for the gpg and gpg2 executables normally invoked on +the command line (gpg.exe and gpg2.exe on Windows). +

+ +

+The popularity of this package stemmed from its ease of use and +capability in providing the most commonly required features. +

+ +

+Unfortunately it has been beset by a number of security issues in +the past; most of which stemmed from using unsafe methods of +accessing the command line via the subprocess calls. While some +effort has been made over the last two to three years (as of 2018) +to mitigate this, particularly by no longer providing shell access +through those subprocess calls, the wrapper is still somewhat +limited in the scope of its GnuPG features coverage. +

+ +

+The python-gnupg package is available under the MIT license. +

+
+
+ + +
+

2.3.2 The gnupg package created and maintained by Isis Lovecruft

+
+

+In 2015 Isis Lovecruft from the Tor Project forked and then +re-implemented the python-gnupg package as just gnupg. This new +package also relied on subprocess to call the gpg or gpg2 +binaries, but did so somewhat more securely. +

+ +

+The naming and version numbering selected for this package, +however, resulted in conflicts with the original python-gnupg and +since its functions were called in a different manner to +python-gnupg, the release of this package also resulted in a great +deal of consternation when people installed what they thought was +an upgrade that subsequently broke the code relying on it. +

+ +

+The gnupg package is available under the GNU General Public +License version 3.0 (or any later version). +

+
+
+ + +
+

2.3.3 The PyME package maintained by Martin Albrecht

+
+

+This package is the origin of these bindings, though they are +somewhat different now. For details of when and how the PyME +package was folded back into GPGME itself see the Short History +document1 in this Python bindings docs directory.2 +

+ +

+The PyME package was first released in 2002 and was also the first +attempt to implement a low level binding to GPGME. In doing so it +provided access to considerably more functionality than either the +python-gnupg or gnupg packages. +

+ +

+The PyME package is only available for Python 2.6 and 2.7. +

+ +

+Porting the PyME package to Python 3.4 in 2015 is what resulted in +it being folded into the GPGME project and the current bindings +are the end result of that effort. +

+ +

+The PyME package is available under the same dual licensing as +GPGME itself: the GNU General Public License version 2.0 (or any +later version) and the GNU Lesser General Public License version +2.1 (or any later version). +

+
+
+
+
+ + +
+

3 GPGME Python bindings installation

+
+
+ + +
+

3.1 No PyPI

+
+

+Most third-party Python packages and modules are available and +distributed through the Python Package Installer, known as PyPI. +

+ +

+Due to the nature of what these bindings are and how they work, it +is infeasible to install the GPGME Python bindings in the same way. +

+ +

+This is because the bindings use SWIG to dynamically generate C +bindings against gpgme.h and gpgme.h is generated from +gpgme.h.in at compile time when GPGME is built from source. Thus +to include a package in PyPI which actually built correctly would +require either statically built libraries for every architecture +bundled with it or a full implementation of C for each +architecture. +

+
+
+ + +
+

3.2 Requirements

+
+

+The GPGME Python bindings only have three requirements: +

+ +
    +
  1. A suitable version of Python 2 or Python 3. With Python 2 that +means Python 2.7 and with Python 3 that means Python 3.4 or +higher.
  2. +
  3. SWIG.
  4. +
  5. GPGME itself. Which also means that all of GPGME's dependencies +must be installed too.
  6. +
+
+
+ + +
+

3.3 Installation

+
+

+Installing the Python bindings is effectively achieved by compiling +and installing GPGME itself. +

+ +

+Once SWIG is installed with Python and all the dependencies for +GPGME are installed you only need to confirm that the version(s) of +Python you want the bindings installed for are in your $PATH. +

+ +

+By default GPGME will attempt to install the bindings for the most +recent or highest version number of Python 2 and Python 3 it +detects in $PATH. It specifically checks for the python and +python3 executables first and then checks for specific version +numbers. +

+ +

+For Python 2 it checks for these executables in this order: +python, python2 and python2.7. +

+ +

+For Python 3 it checks for these executables in this order: +python3, python3.6, python3.5 and python3.4. +

+
+ + +
+

3.3.1 Installing GPGME

+
+

+See the GPGME README file for details of how to install GPGME from +source. +

+
+
+
+
+ + +
+

4 Fundamentals

+
+

+Before we can get to the fun stuff, there are a few matters +regarding GPGME's design which hold true whether you're dealing with +the C code directly or these Python bindings. +

+
+ + +
+

4.1 No REST

+
+

+The first part of which is or will be fairly blatantly obvious upon +viewing the first example, but it's worth reiterating anyway. That +being that this API is not a REST API. Nor indeed could it +ever be one. +

+ +

+Most, if not all, Python programmers (and not just Python +programmers) know how easy it is to work with a RESTful API. In +fact they've become so popular that many other APIs attempt to +emulate REST-like behaviour as much as they are able. Right down +to the use of JSON formatted output to facilitate the use of their +API without having to retrain developers. +

+ +

+This API does not do that. It would not be able to do that and +also provide access to the entire C API on which it's built. It +does, however, provide a very pythonic interface on top of the +direct bindings and it's this pythonic layer with which this HOWTO +deals with. +

+
+
+ + +
+

4.2 Context

+
+

+One of the reasons which prevents this API from being RESTful is +that most operations require more than one instruction to the API +to perform the task. Sure, there are certain functions which can +be performed simultaneously, particularly if the result known or +strongly anticipated (e.g. selecting and encrypting to a key known +to be in the public keybox). +

+ +

+There are many more, however, which cannot be manipulated so +readily: they must be performed in a specific sequence and the +result of one operation has a direct bearing on the outcome of +subsequent operations. Not merely by generating an error either. +

+ +

+When dealing with this type of persistent state on the web, full of +both the RESTful and REST-like, it's most commonly referred to as a +session. In GPGME, however, it is called a context and every +operation type has one. +

+
+
+
+ + +
+

5 Working with keys

+
+
+ + +
+

5.1 Key selection

+
+

+Selecting keys to encrypt to or to sign with will be a common +occurrence when working with GPGMe and the means available for +doing so are quite simple. +

+ +

+They do depend on utilising a Context; however once the data is +recorded in another variable, that Context does not need to be the +same one which subsequent operations are performed. +

+ +

+The easiest way to select a specific key is by searching for that +key's key ID or fingerprint, preferably the full fingerprint +without any spaces in it. A long key ID will probably be okay, but +is not advised and short key IDs are already a problem with some +being generated to match specific patterns. It does not matter +whether the pattern is upper or lower case. +

+ +

+So this is the best method: +

+ +
+
import gpg
+
+k = gpg.Context().keylist(pattern="258E88DCBD3CD44D8E7AB43F6ECB6AF0DEADBEEF")
+keys = list(k)
+
+
+ +

+This is passable and very likely to be common: +

+ +
+
import gpg
+
+k = gpg.Context().keylist(pattern="0x6ECB6AF0DEADBEEF")
+keys = list(k)
+
+
+ +

+And this is a really bad idea: +

+ +
+
import gpg
+
+k = gpg.Context().keylist(pattern="0xDEADBEEF")
+keys = list(k)
+
+
+ +

+Alternatively it may be that the intention is to create a list of +keys which all match a particular search string. For instance all +the addresses at a particular domain, like this: +

+ +
+
import gpg
+
+ncsc = gpg.Context().keylist(pattern="ncsc.mil")
+nsa = list(ncsc)
+
+
+
+ + +
+

5.1.1 Counting keys

+
+

+Counting the number of keys in your public keybox (pubring.kbx), +the format which has superseded the old keyring format +(pubring.gpg and secring.gpg), or the number of secret keys is +a very simple task. +

+ +
+
import gpg
+
+c = gpg.Context()
+seckeys = c.keylist(pattern=None, secret=True)
+pubkeys = c.keylist(pattern=None, secret=False)
+
+seclist = list(seckeys)
+secnum = len(seclist)
+
+publist = list(pubkeys)
+pubnum = len(publist)
+
+print("""
+Number of secret keys:  {0}
+Number of public keys:  {1}
+""".format(secnum, pubnum))
+
+
+
+
+
+ + +
+

5.2 Get key

+
+

+An alternative method of getting a single key via its fingerprint +is available directly within a Context with Context().get_key. +This is the preferred method of selecting a key in order to modify +it, sign or certify it and for obtaining relevant data about a +single key as a part of other functions; when verifying a signature +made by that key, for instance. +

+ +

+By default this method will select public keys, but it can select +secret keys as well. +

+ +

+This first example demonstrates selecting the current key of Werner +Koch, which is due to expire at the end of 2018: +

+ +
+
import gpg
+
+fingerprint = "80615870F5BAD690333686D0F2AD85AC1E42B367"
+key = gpg.Context().get_key(fingerprint)
+
+
+ +

+Whereas this example demonstrates selecting the author's current +key with the secret key word argument set to True: +

+ +
+
import gpg
+
+fingerprint = "DB4724E6FA4286C92B4E55C4321E4E2373590E5D"
+key = gpg.Context().get_key(fingerprint, secret=True)
+
+
+ +

+It is, of course, quite possible to select expired, disabled and +revoked keys with this function, but only to effectively display +information about those keys. +

+ +

+It is also possible to use both unicode or string literals and byte +literals with the fingerprint when getting a key in this way. +

+
+
+
+ + +
+

6 Basic Functions

+
+

+The most frequently called features of any cryptographic library +will be the most fundamental tasks for encryption software. In this +section we will look at how to programmatically encrypt data, +decrypt it, sign it and verify signatures. +

+
+ + +
+

6.1 Encryption

+
+

+Encrypting is very straight forward. In the first example below +the message, text, is encrypted to a single recipient's key. In +the second example the message will be encrypted to multiple +recipients. +

+
+ + +
+

6.1.1 Encrypting to one key

+
+

+Once the the Context is set the main issues with encrypting data +is essentially reduced to key selection and the keyword arguments +specified in the gpg.Context().encrypt() method. +

+ +

+Those keyword arguments are: recipients, a list of keys +encrypted to (covered in greater detail in the following section); +sign, whether or not to sign the plaintext data, see subsequent +sections on signing and verifying signatures below (defaults to +True); sink, to write results or partial results to a secure +sink instead of returning it (defaults to None); passphrase, +only used when utilising symmetric encryption (defaults to +None); always_trust, used to override the trust model settings +for recipient keys (defaults to False); add_encrypt_to, +utilises any preconfigured encrypt-to or default-key settings +in the user's gpg.conf file (defaults to False); prepare, +prepare for encryption (defaults to False); expect_sign, +prepare for signing (defaults to False); compress, compresses +the plaintext prior to encryption (defaults to True). +

+ +
+
import gpg
+
+a_key = "0x12345678DEADBEEF"
+text = b"""Some text to test with.
+
+Since the text in this case must be bytes, it is most likely that
+the input form will be a separate file which is opened with "rb"
+as this is the simplest method of obtaining the correct data
+format.
+"""
+
+c = gpg.Context(armor=True)
+rkey = list(c.keylist(pattern=a_key, secret=False))
+ciphertext, result, sign_result = c.encrypt(text, recipients=rkey, sign=False)
+
+with open("secret_plans.txt.asc", "wb") as afile:
+    afile.write(ciphertext)
+
+
+ +

+Though this is even more likely to be used like this; with the +plaintext input read from a file, the recipient keys used for +encryption regardless of key trust status and the encrypted output +also encrypted to any preconfigured keys set in the gpg.conf +file: +

+ +
+
import gpg
+
+a_key = "0x12345678DEADBEEF"
+
+with open("secret_plans.txt", "rb") as afile:
+    text = afile.read()
+
+c = gpg.Context(armor=True)
+rkey = list(c.keylist(pattern=a_key, secret=False))
+ciphertext, result, sign_result = c.encrypt(text, recipients=rkey,
+                        sign=True, always_trust=True,
+                        add_encrypt_to=True)
+
+with open("secret_plans.txt.asc", "wb") as afile:
+    afile.write(ciphertext)
+
+
+ +

+If the recipients paramater is empty then the plaintext is +encrypted symmetrically. If no passphrase is supplied as a +parameter or via a callback registered with the Context() then +an out-of-band prompt for the passphrase via pinentry will be +invoked. +

+
+
+ + +
+

6.1.2 Encrypting to multiple keys

+
+

+Encrypting to multiple keys essentially just expands upon the key +selection process and the recipients from the previous examples. +

+ +

+The following example encrypts a message (text) to everyone with +an email address on the gnupg.org domain,3 but does not encrypt +to a default key or other key which is configured to normally +encrypt to. +

+ +
+
import gpg
+
+text = b"""Oh look, another test message.
+
+The same rules apply as with the previous example and more likely
+than not, the message will actually be drawn from reading the
+contents of a file or, maybe, from entering data at an input()
+prompt.
+
+Since the text in this case must be bytes, it is most likely that
+the input form will be a separate file which is opened with "rb"
+as this is the simplest method of obtaining the correct data
+format.
+"""
+
+c = gpg.Context(armor=True)
+rpattern = list(c.keylist(pattern="@gnupg.org", secret=False))
+logrus = []
+
+for i in range(len(rpattern)):
+    if rpattern[i].can_encrypt == 1:
+    logrus.append(rpattern[i])
+
+ciphertext, result, sign_result = c.encrypt(text, recipients=logrus, sign=False,
+                        always_trust=True)
+
+with open("secret_plans.txt.asc", "wb") as afile:
+    afile.write(ciphertext)
+
+
+ +

+All it would take to change the above example to sign the message +and also encrypt the message to any configured default keys would +be to change the c.encrypt line to this: +

+ +
+
ciphertext, result, sign_result = c.encrypt(text, recipients=logrus,
+                        always_trust=True,
+                        add_encrypt_to=True)
+
+
+ +

+The only keyword arguments requiring modification are those for +which the default values are changing. The default value of +sign is True, the default of always_trust is False, the +default of add_encrypt_to is False. +

+ +

+If always_trust is not set to True and any of the recipient +keys are not trusted (e.g. not signed or locally signed) then the +encryption will raise an error. It is possible to mitigate this +somewhat with something more like this: +

+ +
+
import gpg
+
+with open("secret_plans.txt.asc", "rb") as afile:
+    text = afile.read()
+
+c = gpg.Context(armor=True)
+rpattern = list(c.keylist(pattern="@gnupg.org", secret=False))
+logrus = []
+
+for i in range(len(rpattern)):
+    if rpattern[i].can_encrypt == 1:
+    logrus.append(rpattern[i])
+
+try:
+    ciphertext, result, sign_result = c.encrypt(text, recipients=logrus, add_encrypt_to=True)
+except gpg.errors.InvalidRecipients as e:
+    for i in range(len(e.recipients)):
+    for n in range(len(logrus)):
+        if logrus[n].fpr == e.recipients[i].fpr:
+        logrus.remove(logrus[n])
+        else:
+        pass
+    try:
+    ciphertext, result, sign_result = c.encrypt(text, recipients=logrus, add_encrypt_to=True)
+    except:
+    pass
+
+with open("secret_plans.txt.asc", "wb") as afile:
+    afile.write(ciphertext)
+
+
+ +

+This will attempt to encrypt to all the keys searched for, then +remove invalid recipients if it fails and try again. +

+
+
+
+ + +
+

6.2 Decryption

+
+

+Decrypting something encrypted to a key in one's secret keyring is +fairly straight forward. +

+ +

+In this example code, however, preconfiguring either +gpg.Context() or gpg.core.Context() as c is unnecessary +because there is no need to modify the Context prior to conducting +the decryption and since the Context is only used once, setting it +to c simply adds lines for no gain. +

+ +
+
import gpg
+
+ciphertext = input("Enter path and filename of encrypted file: ")
+newfile = input("Enter path and filename of file to save decrypted data to: ")
+with open(ciphertext, "rb") as cfile:
+    plaintext, result, verify_result = gpg.Context().decrypt(cfile)
+with open(newfile, "wb") as nfile:
+    nfile.write(plaintext)
+
+
+ +

+The data available in plaintext in this example is the decrypted +content as a byte object in plaintext[0], the recipient key IDs +and algorithms in plaintext[1] and the results of verifying any +signatures of the data in plaintext[0]. +

+
+
+ + +
+

6.3 Signing text and files

+
+

+The following sections demonstrate how to specify keys to sign with. +

+
+ + +
+

6.3.1 Signing key selection

+
+

+By default GPGME and the Python bindings will use the default key +configured for the user invoking the GPGME API. If there is no +default key specified and there is more than one secret key +available it may be necessary to specify the key or keys with +which to sign messages and files. +

+ +
+
import gpg
+
+logrus = input("Enter the email address or string to match signing keys to: ")
+hancock = gpg.Context().keylist(pattern=logrus, secret=True)
+sig_src = list(hancock)
+
+
+ +

+The signing examples in the following sections include the +explicitly designated signers parameter in two of the five +examples; once where the resulting signature would be ASCII +armoured and once where it would not be armoured. +

+ +

+While it would be possible to enter a key ID or fingerprint here +to match a specific key, it is not possible to enter two +fingerprints and match two keys since the patten expects a string, +bytes or None and not a list. A string with two fingerprints +won't match any single key. +

+
+
+ + +
+

6.3.2 Normal or default signing messages or files

+
+

+The normal or default signing process is essentially the same as +is most often invoked when also encrypting a message or file. So +when the encryption component is not utilised, the result is to +produce an encoded and signed output which may or may not be ASCII +armoured and which may or may not also be compressed. +

+ +

+By default compression will be used unless GnuPG detects that the +plaintext is already compressed. ASCII armouring will be +determined according to the value of gpg.Context().armor. +

+ +

+The compression algorithm is selected in much the same way as the +symmetric encryption algorithm or the hash digest algorithm is +when multiple keys are involved; from the preferences saved into +the key itself or by comparison with the preferences with all +other keys involved. +

+ +
+
import gpg
+
+text0 = """Declaration of ... something.
+
+"""
+text = text0.encode()
+
+c = gpg.Context(armor=True, signers=sig_src)
+signed_data, result = c.sign(text, mode=gpg.constants.sig.mode.NORMAL)
+
+with open("/path/to/statement.txt.asc", "w") as afile:
+    afile.write(signed_data.decode())
+
+
+ +

+Though everything in this example is accurate, it is more likely +that reading the input data from another file and writing the +result to a new file will be performed more like the way it is done +in the next example. Even if the output format is ASCII armoured. +

+ +
+
import gpg
+
+with open("/path/to/statement.txt", "rb") as tfile:
+    text = tfile.read()
+
+c = gpg.Context()
+signed_data, result = c.sign(text, mode=gpg.constants.sig.mode.NORMAL)
+
+with open("/path/to/statement.txt.sig", "wb") as afile:
+    afile.write(signed_data)
+
+
+
+
+ + +
+

6.3.3 Detached signing messages and files

+
+

+Detached signatures will often be needed in programmatic uses of +GPGME, either for signing files (e.g. tarballs of code releases) +or as a component of message signing (e.g. PGP/MIME encoded +email). +

+ +
+
import gpg
+
+text0 = """Declaration of ... something.
+
+"""
+text = text0.encode()
+
+c = gpg.Context(armor=True)
+signed_data, result = c.sign(text, mode=gpg.constants.sig.mode.DETACH)
+
+with open("/path/to/statement.txt.asc", "w") as afile:
+    afile.write(signed_data.decode())
+
+
+ +

+As with normal signatures, detached signatures are best handled as +byte literals, even when the output is ASCII armoured. +

+ +
+
import gpg
+
+with open("/path/to/statement.txt", "rb") as tfile:
+    text = tfile.read()
+
+c = gpg.Context(signers=sig_src)
+signed_data, result = c.sign(text, mode=gpg.constants.sig.mode.DETACH)
+
+with open("/path/to/statement.txt.sig", "wb") as afile:
+    afile.write(signed_data)
+
+
+
+
+ + +
+

6.3.4 Clearsigning messages or text

+
+

+Though PGP/in-line messages are no longer encouraged in favour of +PGP/MIME, there is still sometimes value in utilising in-line +signatures. This is where clear-signed messages or text is of +value. +

+ +
+
import gpg
+
+text0 = """Declaration of ... something.
+
+"""
+text = text0.encode()
+
+c = gpg.Context()
+signed_data, result = c.sign(text, mode=gpg.constants.sig.mode.CLEAR)
+
+with open("/path/to/statement.txt.asc", "w") as afile:
+    afile.write(signed_data.decode())
+
+
+ +

+In spite of the appearance of a clear-signed message, the data +handled by GPGME in signing it must still be byte literals. +

+ +
+
import gpg
+
+with open("/path/to/statement.txt", "rb") as tfile:
+    text = tfile.read()
+
+c = gpg.Context()
+signed_data, result = c.sign(text, mode=gpg.constants.sig.mode.CLEAR)
+
+with open("/path/to/statement.txt.asc", "wb") as afile:
+    afile.write(signed_data)
+
+
+
+
+
+ + +
+

6.4 Signature verification

+
+

+Essentially there are two principal methods of verification of a +signature. The first of these is for use with the normal or +default signing method and for clear-signed messages. The second is +for use with files and data with detached signatures. +

+ +

+The following example is intended for use with the default signing +method where the file was not ASCII armoured: +

+ +
+
import gpg
+import time
+
+filename = "statement.txt"
+gpg_file = "statement.txt.gpg"
+
+c = gpg.Context()
+
+try:
+    data, result = c.verify(open(gpg_file))
+    verified = True
+except gpg.errors.BadSignatures as e:
+    verified = False
+    print(e)
+
+if verified is True:
+    for i in range(len(result.signatures)):
+    sign = result.signatures[i]
+    print("""Good signature from:
+{0}
+with key {1}
+made at {2}
+""".format(c.get_key(sign.fpr).uids[0].uid,
+       sign.fpr, time.ctime(sign.timestamp)))
+else:
+    pass
+
+
+ +

+Whereas this next example, which is almost identical would work +with normal ASCII armoured files and with clear-signed files: +

+ +
+
import gpg
+import time
+
+filename = "statement.txt"
+asc_file = "statement.txt.asc"
+
+c = gpg.Context()
+
+try:
+    data, result = c.verify(open(asc_file))
+    verified = True
+except gpg.errors.BadSignatures as e:
+    verified = False
+    print(e)
+
+if verified is True:
+    for i in range(len(result.signatures)):
+    sign = result.signatures[i]
+    print("""Good signature from:
+{0}
+with key {1}
+made at {2}
+""".format(c.get_key(sign.fpr).uids[0].uid,
+       sign.fpr, time.ctime(sign.timestamp)))
+else:
+    pass
+
+
+ +

+In both of the previous examples it is also possible to compare the +original data that was signed against the signed data in data to +see if it matches with something like this: +

+ +
+
with open(filename, "rb") as afile:
+    text = afile.read()
+
+if text == data:
+    print("Good signature.")
+else:
+    pass
+
+
+ +

+The following two examples, however, deal with detached signatures. +With his method of verification the data that was signed does not +get returned since it is already being explicitly referenced in the +first argument of c.verify. So data is None and only the +information in result is available. +

+ +
+
import gpg
+import time
+
+filename = "statement.txt"
+sig_file = "statement.txt.sig"
+
+c = gpg.Context()
+
+try:
+    data, result = c.verify(open(filename), open(sig_file))
+    verified = True
+except gpg.errors.BadSignatures as e:
+    verified = False
+    print(e)
+
+if verified is True:
+    for i in range(len(result.signatures)):
+    sign = result.signatures[i]
+    print("""Good signature from:
+{0}
+with key {1}
+made at {2}
+""".format(c.get_key(sign.fpr).uids[0].uid,
+       sign.fpr, time.ctime(sign.timestamp)))
+else:
+    pass
+
+
+ +
+
import gpg
+import time
+
+filename = "statement.txt"
+asc_file = "statement.txt.asc"
+
+c = gpg.Context()
+
+try:
+    data, result = c.verify(open(filename), open(asc_file))
+    verified = True
+except gpg.errors.BadSignatures as e:
+    verified = False
+    print(e)
+
+if verified is not None:
+    for i in range(len(result.signatures)):
+    sign = result.signatures[i]
+    print("""Good signature from:
+{0}
+with key {1}
+made at {2}
+""".format(c.get_key(sign.fpr).uids[0].uid,
+       sign.fpr, time.ctime(sign.timestamp)))
+else:
+    pass
+
+
+
+
+
+ + +
+

7 Creating keys and subkeys

+
+

+The one thing, aside from GnuPG itself, that GPGME depends on, of +course, is the keys themselves. So it is necessary to be able to +generate them and modify them by adding subkeys, revoking or +disabling them, sometimes deleting them and doing the same for user +IDs. +

+ +

+In the following examples a key will be created for the world's +greatest secret agent, Danger Mouse. Since Danger Mouse is a secret +agent he needs to be able to protect information to SECRET level +clearance, so his keys will be 3072-bit keys. +

+ +

+The pre-configured gpg.conf file which sets cipher, digest and +other preferences contains the following configuration parameters: +

+ +
+
expert
+allow-freeform-uid
+allow-secret-key-import
+trust-model tofu+pgp
+tofu-default-policy unknown
+enable-large-rsa
+enable-dsa2
+# cert-digest-algo SHA256
+cert-digest-algo SHA512
+default-preference-list TWOFISH CAMELLIA256 AES256 CAMELLIA192 AES192 CAMELLIA128 AES BLOWFISH IDEA CAST5 3DES SHA512 SHA384 SHA256 SHA224 RIPEMD160 SHA1 ZLIB BZIP2 ZIP Uncompressed
+personal-cipher-preferences TWOFISH CAMELLIA256 AES256 CAMELLIA192 AES192 CAMELLIA128 AES BLOWFISH IDEA CAST5 3DES
+personal-digest-preferences SHA512 SHA384 SHA256 SHA224 RIPEMD160 SHA1
+personal-compress-preferences ZLIB BZIP2 ZIP Uncompressed
+
+
+
+ + +
+

7.1 Primary key

+
+

+Generating a primary key uses the create_key method in a Context. +It contains multiple arguments and keyword arguments, including: +userid, algorithm, expires_in, expires, sign, encrypt, +certify, authenticate, passphrase and force. The defaults +for all of those except userid, algorithm, expires_in, +expires and passphrase is False. The defaults for +algorithm and passphrase is None. The default for +expires_in is 0. The default for expires is True. There +is no default for userid. +

+ +

+If passphrase is left as None then the key will not be +generated with a passphrase, if passphrase is set to a string +then that will be the passphrase and if passphrase is set to +True then gpg-agent will launch pinentry to prompt for a +passphrase. For the sake of convenience, these examples will keep +passphrase set to None. +

+ +
+
import gpg
+
+c = gpg.Context()
+
+c.home_dir = "~/.gnupg-dm"
+userid = "Danger Mouse <dm@secret.example.net>"
+
+dmkey = c.create_key(userid, algorithm = "rsa3072", expires_in = 31536000,
+             sign = True, certify = True)
+
+
+ +

+One thing to note here is the use of setting the c.home_dir +parameter. This enables generating the key or keys in a different +location. In this case to keep the new key data created for this +example in a separate location rather than adding it to existing +and active key store data. As with the default directory, +~/.gnupg, any temporary or separate directory needs the +permissions set to only permit access by the directory owner. On +posix systems this means setting the directory permissions to 700. +

+ +

+The successful generation of the key can be confirmed via the +returned GenkeyResult object, which includes the following data: +

+ +
+
print("""
+Fingerprint:  {0}
+Primary Key:  {1}
+ Public Key:  {2}
+ Secret Key:  {3}
+    Sub Key:  {4}
+   User IDs:  {5}
+""".format(dmkey.fpr, dmkey.primary, dmkey.pubkey, dmkey.seckey, dmkey.sub,
+       dmkey.uid))
+
+
+ +

+Alternatively the information can be confirmed using the command +line program: +

+ +
+
bash-4.4$ gpg --homedir ~/.gnupg-dm -K
+~/.gnupg-dm/pubring.kbx
+----------------------
+sec   rsa3072 2018-03-15 [SC] [expires: 2019-03-15]
+      177B7C25DB99745EE2EE13ED026D2F19E99E63AA
+uid           [ultimate] Danger Mouse <dm@secret.example.net>
+
+bash-4.4$
+
+
+ +

+As with generating keys manually, to preconfigure expanded +preferences for the cipher, digest and compression algorithms, the +gpg.conf file must contain those details in the home directory in +which the new key is being generated. I used a cut down version of +my own gpg.conf file in order to be able to generate this: +

+ +
+
bash-4.4$ gpg --homedir ~/.gnupg-dm --edit-key 177B7C25DB99745EE2EE13ED026D2F19E99E63AA showpref quit
+Secret key is available.
+
+sec  rsa3072/026D2F19E99E63AA
+     created: 2018-03-15  expires: 2019-03-15  usage: SC
+     trust: ultimate      validity: ultimate
+[ultimate] (1). Danger Mouse <dm@secret.example.net>
+
+[ultimate] (1). Danger Mouse <dm@secret.example.net>
+     Cipher: TWOFISH, CAMELLIA256, AES256, CAMELLIA192, AES192, CAMELLIA128, AES, BLOWFISH, IDEA, CAST5, 3DES
+     Digest: SHA512, SHA384, SHA256, SHA224, RIPEMD160, SHA1
+     Compression: ZLIB, BZIP2, ZIP, Uncompressed
+     Features: MDC, Keyserver no-modify
+
+bash-4.4$
+
+
+
+
+ + +
+

7.2 Subkeys

+
+

+Adding subkeys to a primary key is fairly similar to creating the +primary key with the create_subkey method. Most of the arguments +are the same, but not quite all. Instead of the userid argument +there is now a key argument for selecting which primary key to +add the subkey to. +

+ +

+In the following example an encryption subkey will be added to the +primary key. Since Danger Mouse is a security conscious secret +agent, this subkey will only be valid for about six months, half +the length of the primary key. +

+ +
+
import gpg
+
+c = gpg.Context()
+c.home_dir = "~/.gnupg-dm"
+
+key = c.get_key(dmkey.fpr, secret = True)
+dmsub = c.create_subkey(key, algorithm = "rsa3072", expires_in = 15768000,
+            encrypt = True)
+
+
+ +

+As with the primary key, the results here can be checked with: +

+ +
+
print("""
+Fingerprint:  {0}
+Primary Key:  {1}
+ Public Key:  {2}
+ Secret Key:  {3}
+    Sub Key:  {4}
+   User IDs:  {5}
+""".format(dmsub.fpr, dmsub.primary, dmsub.pubkey, dmsub.seckey, dmsub.sub,
+       dmsub.uid))
+
+
+ +

+As well as on the command line with: +

+ +
+
bash-4.4$ gpg --homedir ~/.gnupg-dm -K
+~/.gnupg-dm/pubring.kbx
+----------------------
+sec   rsa3072 2018-03-15 [SC] [expires: 2019-03-15]
+      177B7C25DB99745EE2EE13ED026D2F19E99E63AA
+uid           [ultimate] Danger Mouse <dm@secret.example.net>
+ssb   rsa3072 2018-03-15 [E] [expires: 2018-09-13]
+
+bash-4.4$
+
+
+
+
+ + +
+

7.3 User IDs

+
+

+By comparison to creating primary keys and subkeys, adding a new +user ID to an existing key is much simpler. The method used to do +this is key_add_uid and the only arguments it takes are for the +key and the new uid. +

+ +
+
import gpg
+
+c = gpg.Context()
+c.home_dir = "~/.gnupg-dm"
+
+dmfpr = "177B7C25DB99745EE2EE13ED026D2F19E99E63AA"
+key = c.get_key(dmfpr, secret = True)
+uid = "Danger Mouse <danger.mouse@secret.example.net>"
+
+c.key_add_uid(key, uid)
+
+
+ +

+Unsurprisingly the result of this is: +

+ +
+
bash-4.4$ gpg --homedir ~/.gnupg-dm -K
+~/.gnupg-dm/pubring.kbx
+----------------------
+sec   rsa3072 2018-03-15 [SC] [expires: 2019-03-15]
+      177B7C25DB99745EE2EE13ED026D2F19E99E63AA
+uid           [ultimate] Danger Mouse <danger.mouse@secret.example.net>
+uid           [ultimate] Danger Mouse <dm@secret.example.net>
+ssb   rsa3072 2018-03-15 [E] [expires: 2018-09-13]
+
+bash-4.4$
+
+
+
+
+ + +
+

7.4 Key certification

+
+

+Since key certification is more frequently referred to as key +signing, the method used to perform this function is key_sign. +

+ +

+The key_sign method takes four arguments: key, uids, +expires_in and local. The default value of uids is None +and which results in all user IDs being selected. The default +values of expires_in snd local is False; which result in the +signature never expiring and being able to be exported. +

+ +

+The key is the key being signed rather than the key doing the +signing. To change the key doing the signing refer to the signing +key selection above for signing messages and files. +

+ +

+If the uids value is not None then it must either be a string +to match a single user ID or a list of strings to match multiple +user IDs. In this case the matching of those strings must be +precise and it is case sensitive. +

+ +

+To sign Danger Mouse's key for just the initial user ID with a +signature which will last a little over a month, do this: +

+ +
+
import gpg
+
+c = gpg.Context()
+uid = "Danger Mouse <dm@secret.example.net>"
+
+dmfpr = "177B7C25DB99745EE2EE13ED026D2F19E99E63AA"
+key = c.get_key(dmfpr, secret = True)
+c.key_sign(key, uids = uid, expires_in = 2764800)
+
+
+
+
+
+ + +
+

8 Miscellaneous work-arounds

+
+
+ + +
+

8.1 Group lines

+
+

+There is not yet an easy way to access groups configured in the +gpg.conf file from within GPGME. As a consequence these central +groupings of keys cannot be shared amongst multiple programs, such +as MUAs readily. +

+ +

+The following code, however, provides a work-around for obtaining +this information in Python. +

+ +
+
import subprocess
+
+lines = subprocess.getoutput("gpgconf --list-options gpg").splitlines()
+
+for i in range(len(lines)):
+    if lines[i].startswith("group") is True:
+    line = lines[i]
+    else:
+    pass
+
+groups = line.split(":")[-1].replace('"', '').split(',')
+
+group_lines = groups
+for i in range(len(group_lines)):
+    group_lines[i] = group_lines[i].split("=")
+
+group_lists = group_lines
+for i in range(len(group_lists)):
+    group_lists[i][1] = group_lists[i][1].split()
+
+
+ +

+The result of that code is that group_lines is a list of lists +where group_lines[i][0] is the name of the group and +group_lines[i][1] is the key IDs of the group as a string. +

+ +

+The group_lists result is very similar in that it is a list of +lists. The first part, group_lists[i][0] matches +group_lines[i][0] as the name of the group, but +group_lists[i][1] is the key IDs of the group as a string. +

+
+
+
+ + +
+ + + + +
+ + +
+ + +
+

9.2 License GPL compatible

+
+

+This file is free software; as a special exception the author gives +unlimited permission to copy and/or distribute it, with or without +modifications, as long as this notice is preserved. +

+ +

+This file is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY, to the extent permitted by law; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. +

+
+
+
+
+

Footnotes:

+
+ +
1

+Short_History.org and/or Short_History.html. +

+ +
2

+The lang/python/docs/ directory in the GPGME source. +

+ +
3

+You probably don't really want to do this. Searching the +keyservers for "gnupg.org" produces over 400 results, the majority of +which aren't actually at the gnupg.org domain, but just included a +comment regarding the project in their key somewhere. +

+ + +
+
+
+

Author: Ben McGinnes

+

Created: 2018-03-22 Thu 10:59

+

Validate

+
+ + diff --git a/misc/id/openpgp-webkey-service/draft.org b/misc/id/openpgp-webkey-service/draft.org index fb0eb60..a57ddfc 100644 --- a/misc/id/openpgp-webkey-service/draft.org +++ b/misc/id/openpgp-webkey-service/draft.org @@ -1,720 +1,729 @@ # openpgp-webkey-service #+startup: showall #+options: toc:nil #+macro: RFC [](#RFC$1) #+macro: https_scheme ~https://~ #+begin_src rfc ]> OpenPGP Web Key Directory GnuPG e.V.
wk@gnupg.org https://gnupg.org/verein
Security &pandocAbstract;
&pandocMiddle; &rfc.2119; &rfc.2782; &rfc.3156; &rfc.4880; &rfc.5785; &rfc.6189; &pandocBack;
#+end_src * Abstract This specification describes a service to locate OpenPGP keys by mail address using a Web service and the HTTPS protocol. It also provides a method for secure communication between the key owner and the mail provider to publish and revoke the public key. * Middle * Introduction This memo describes a method to associate OpenPGP keys with a mail address and how to look them up using a web service with a well-known URI. In addition a mail based protocol is given to allow a client to setup such an association and to maintain it. * Notational Conventions The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in {{{RFC(2119)}}}. * Web Key Directory A major use case for OpenPGP is the encryption of mail. A common difficulty of sending encrypted mails to a new communication partner is to find the appropriate public key of the recipient. Unless an off-channel key exchange has been done, there are no easy ways to discover the required key. The common practice is to search the network of public key servers for a key matching the recipient's mail address. This practise bears the problem that the keyservers are not able to give a positive confirmation that a key actually belongs to the mail addresses given in the key. Further, there are often several keys matching a mail address and thus one needs to pick a key on good luck. This is clearly not a secure way to setup an end-to-end encryption. Even if the need for a trusted key for an initial mail message is relinquished, a non-authenticated key may be a wrong one and the actual recipient would receive a mail which she can't decrypt, due to the use of a wrong key. Methods to overcome this problem are - sending an initial unencrypted message with the public key attached, - using the OpenPGP DANE protocol to lookup the recipients key via the DNS. The first method has the obvious problems of not even trying to encrypt the initial mail, an extra mail round-trip, and problems with unattended key discovery. The latter method works fine but requires that mail providers need to set up a separate DNS resolver to provide the key. The administration of a DNS zone is often not in the hands of small mail installations. Thus an update of the DNS resource records needs to be delegated to the ISP running the DNS service. Further, DNS lookups are not encrypted and missing all confidentially. Even if the participating MUAs are using STARTTLS to encrypt the mail exchange, a DNS lookup for the key unnecessarily identifies the local-part of the recipients mail address to any passive eavesdroppers. This memo specified a new method for key discovery using an encrypted https connection. ** Key Discovery Although URIs are able to encode all kind of characters, straightforward implementations of a key directory may want to store the local-part of a mail address directly in the file system. This forbids the use of certain characters in the local-part. To allow for such an implementation method the URI uses an encoded form of the local-part which can be directly mapped to a file name. OpenPGP defines its User IDs, and thus the mail address, as UTF-8 strings. To help with the common pattern of using capitalized names (e.g. "Joe.Doe@example.org") for mail addresses, and under the premise that almost all MTAs treat the local-part case-insensitive and that the domain-part is required to be compared case-insensitive anyway, all upper-case ASCII characters in a User ID are mapped to lowercase. Non-ASCII characters are not changed. The so mapped local-part is hashed using the SHA-1 algorithm. The resulting 160 bit digest is encoded using the Z-Base-32 method as described in {{{RFC(6189)}}}, section 5.1.6. The resulting string has a fixed length of 32 octets. To form the URI, the following parts are concatenated: - The scheme {{{https_scheme}}}, - the domain-part, - the string ~/.well-known/openpgpkey/hu/~, - and the above constructed 32 octet string. For example the URI to lookup the key for Joe.Doe@Example.ORG is: #+BEGIN_EXAMPLE https://example.org/.well-known/openpgpkey/ hu/iy9q119eutrkn8s1mk4r39qejnbu3n5q #+END_EXAMPLE (line has been wrapped for rendering purposes) DNS SRV resource records ({{{RFC(2782)}}}) may be used to query a different host or a port other than 443. For example: #+BEGIN_EXAMPLE _openpgpkey._tcp.example.org. IN SRV 0 0 8443 wkd.example.org. #+END_EXAMPLE changes the above to query the host "wkd.example.org" at port 8443 instead of the host "example.org" at port 443. The target (in the example "wkd.example.org") MUST be a sub-domain of the domain-part (here "example.org"). If the target is not a sub-domain, the SRV RR MUST be be ignored. The recommended name for the sub-domain is "wkd". The HTTP GET method MUST return the binary representation of the OpenPGP key for the given mail address. The key needs to carry a User ID packet ({{{RFC(4880)}}}) with that mail address. Note that the key may be revoked or expired - it is up to the client to handle such conditions. To ease distribution of revoked keys, a server may return revoked keys in addition to a new key. The keys are returned by a single request as concatenated key blocks. The server MUST accept the HTTP HEAD method to allow a client to check for the existence of a key. The server SHOULD use "application/octet-string" as the Content-Type for the data but clients SHOULD also accept any other Content-Type. The server MUST NOT return an ASCII armored version of the key. The server MUST serve a Policy Flags file as specified below. That file is even required if the Web Key Directory Update Protocol is not supported. * Web Key Directory Update Protocol To put keys into the key directory a protocol to automate the task is desirable. The protocol defined here is entirely based on mail and the assumption that a mail provider can securely deliver mail to the INBOX of a user (e.g. an IMAP folder). Note that the same protocol may also be used for submitting keys for use with OpenPGP DANE. We assume that the user already created a key for her mail account alice@example.org. To install the key at her provider's Web Key Directory, she performs the following steps: 1. She retrieves a file which contains one line with the mail address used to submit the key to the mail provider. The DNS SRV rules described for the Web Key Directory apply here as well. See below for the syntax of that file. For a mail address at the domain "example.org" the URI of the file is #+begin_example https://example.org/.well-known/openpgpkey/submission-address #+end_example 2. She sends her key using SMTP (or any other transport mechanism) to the provider using the submission address and key format as specified by PGP/MIME. 3. The provider checks that the received key has a User ID which matches an account name of the provider. 4. The provider sends an encrypted message containing a nonce and the fingerprint of the key to the mail account of the user. Note that a similar scheme is used by the well known caff(1) tool to help with key signing parties. 5. A legitimate user will be able to decrypt the message because she created the key and is in charge of the private key. This step verifies that the submitted key has actually been created by the owner of the account. 6. The user sends the decrypted nonce back to the submission address as a confirmation that the private key is owned by her and that the provider may now publish the key. Although technically not required, it is suggested that the mail to the provider is encrypted. The public key for this is retrieved using the key lookup protocol described above. 7. The provider receives the nonce, matches it with its database of pending confirmations and then publishes the key. Finally the provider sends a mail back to the user to notify her of the publication of her key. The message data structures used for the above protocol are specified in detail below. In the following sections the string "WELLKNOWN" denotes the first part of an URI specific for a domain. In the examples the domain "example.org" is assumed, thus #+BEGIN_EXAMPLE WELLKNOWN := https://example.org/.well-known/openpgpkey #+END_EXAMPLE The term "target key" denotes the to be published key, the term "submission key" the key associated with the submission-address of the mail provider. ** The Submission Address The address of the submission file is #+BEGIN_EXAMPLE WELLKNOWN/submission-address #+END_EXAMPLE The file consists of exactly one line, terminated by a LF, or the sequence of CR and LF, with the full mail address to be used for submission of a key to the mail provider. For example the content of the file may be #+BEGIN_EXAMPLE key-submission-example.org@directory.example.org #+END_EXAMPLE ** The Submission Mail The mail used to submit a key to the mail provider MUST comply to the PGP/MIME specification ({{{RFC(3156)}}}, section 7), which states that the Content-Type must be "application/pgp-keys", there are no required or optional parameters, and the body part contains the ASCII-armored transferable Public Key Packets as defined in {{{RFC(4880)}}}, section 11.1. The mail provider MUST publish a key capable of signing and encryption for the submission-address in the Web Key Directory or via DANE. The key to be published MUST be submitted using a PGP/MIME encrypted message ({{{RFC(3156)}}}, section 4). The message MUST NOT be signed (because the authenticity of the signing key has not yet been confirmed). After decryption of the message at the mail provider a single "application/pgp-keys" part, as specified above, is expected. ** The Confirmation Request The mail provider sends a confirmation mail in response to a received key publication request. The message MUST be sent from the submission-address of the mail provider to the mail address extracted from the target key. The message needs to be a PGP/MIME signed message using the submission key of the provider for the signature. The signed message MUST have two parts: The first part MUST have "text" as its Content-Type and can be used to explain the purpose of the mail. For example it may point to this RFC and explain on how to manually perform the protocol. The second part MUST have "application/vnd.gnupg.wkd" if the protocol version of the server is 5 or later; without a known protocol version or a version less than 5, "application/vnd.gnupg.wks" MUST be used as its Content-Type and carry an OpenPGP encrypted message in ASCII Armor format. The message MUST be encrypted to the target key and MUST NOT be signed. After decryption a text file in the Web Key data format must be yielded. That data format consists of name-value pairs with one name-value pair per LF or CR+LF terminated line. Empty lines are allowed and will be ignored by the receiver. A colon is used to terminate a name. In a confirmation request the following names MUST be send in the specified order: - type :: The value must be "confirmation-request". - sender :: This is the mailbox the user is expected to sent the confirmation response to. The value must match the mailbox part of the "From:" address of this request. Exactly one address MUST be given. - address :: The value is the addr-spec part of the target key's mail address. The value SHOULD match the addr-spec part of the recipient's address. The value MUST be UTF-8 encoded as required for an OpenPGP User ID. - fingerprint :: The value is the fingerprint of the target key. The fingerprint is given in uppercase hex encoding without any interleaving spaces. - nonce :: The value is a string with a minimum length of 16 octets and a maximum length of 64 octets. The string must entirely be made up of random ASCII letters or digits. This nonce will be sent back to the mail provider as proof that the recipient is the legitimate owner of the target-key. The receiver of that message is expected to verify the outer signature and disregard the entire message if it can't be verified or has not been signed by the key associated with the submission address. After the message as been verified the receiver decrypts the second part of the message, checks that the "fingerprint" matches the target key, checks that the "address" matches a User ID of the target key, and checks the other constrains of the request format. If any constraint is not asserted, or the fingerprint or User ID do not match the target key, or there is no pending publication requests (i.e. a mail recently sent o the submission address), the user MAY be notified about this fake confirmation attempt. In other cases the confirmation request is legitimate and the MUA shall silently send a response as described in the next section. The rationale for the outer signature used with this request is to allow early detection of spam mails. This can be done prior to the decryption step and avoids asking the user to enter a passphrase to perform the decryption for a non-legitimate message. The use of a simple encrypted attachment, instead of using PGP/MIME encryption, is to convey the Content-Type of that attachment in the clear and also to prevent automatic decryption of that attachment by PGP/MIME aware clients. The MUA may in fact detect this confirmation request and present a customized dialog for confirming that request. ** The Confirmation Response A response to a confirmation request MUST only be send in the positive case; there is no negative confirmation response. A mail service provider is expected to cancel a pending key submission after a suitable time without a confirmation. The mail service provider SHOULD NOT retry the sending of a confirmation request after the first request has been send successfully. The user MUST send the confirmation response from her target mail address to the "from" address of the confirmation request. The message MUST be signed and encrypted using the PGP/MIME Combined format ({{{RFC(3156)}}}, section 6.2). The signing key is the target key and the encryption key is the key associated with the provider's submission address. The Content-Type used for the plaintext message MUST match the Content-Type of the request. The format is the same as described above for the Confirmation Request. The body must contain three name-value pairs in this order: - type :: The value must be "confirmation-response". - sender :: The value must match the mailbox part of the "From:" address of this response. Exactly one address MUST be given. - nonce :: The value is the value of the "nonce" parameter from the confirmation request. ** Policy Flags For key generation and submission it is useful to tell the client about certain properties of the mail provider in advance. This can be done with a file at the URL #+BEGIN_EXAMPLE WELLKNOWN/policy #+END_EXAMPLE A site supporting the Web Key Directory MUST serve this file; it is sufficient if that file has a zero length. Clients may use this file to check for Web Key Directory support. -The file contains keywords and optioanlly values, one per line with +The file contains keywords and optionally values, one per line with each line terminated by a LF or the sequence of CR and LF. Empty lines and lines starting with a '#' character are considered comment lines. A keyword is made up of lowercase letters, digits, hyphens, or dots. An underscore is allowed as a name space delimiters; see below. The first character must be a letter. Keywords which are defined to require a value are directly followed by a colon and then after optional white space the value. Clients MUST use case-insensitive matching for the keyword. Currently defined keywords are: - mailbox-only :: The mail server provider does only accept keys with only a mailbox in the User ID. In particular User IDs with a real name in addition to the mailbox will be rejected as invalid. - dane-only :: The mail server provider does not run a Web Key Directory but only an OpenPGP DANE service. The Web Key Directory Update protocol is used to update the keys for the DANE service. - auth-submit :: The submission of the mail to the server is done using an authenticated connection. Thus the submitted key will be published immediately without any confirmation request. - protocol-version :: This keyword can be used to explicitly claim the support of a specific version of the Web Key Directory update protocol. This is in general not needed but implementations may have workarounds for providers which only support an old protocol version. If these providers update to a newer version they should add this keyword so that the implementation can disable the workaround. The value is an integer corresponding to the respective draft revision number. +- submission-address :: An alternative way to specify the submission + address. The value is the addr-spec part of the address to send + requests to this server. If this keyword is used in addition to + the =submission-address= file, both MUST have the same value. + # Fixme: Add a protocol-version value for the final RFC. More keywords will be defined in updates to this I-D. There is no registry except for this document. For experimental use of new features or for provider specific settings, keywords MUST be prefixed with a domain name and an underscore. * Security Considerations The use of SHA-1 for the mapping of the local-part to a fixed string is not a security feature but merely used to map the local-part to a fixed-sized string made from a well defined set of characters. It is not intended to conceal information about a mail address. The domain name part of the mail address is not part of the hash to avoid problems with internationalized domain names. Instead a separate URL is required for each domain name. The use of DNS SRV records reduces the certainty that a mail address belongs to a domain. For example an attacker may change the target to a host in a sub-domain under their control and thus gain full control over all keys. An implementation may want to weight the certainty of a mapping different if it has been retrieved via a sub-domain and in particular if a non-recommended name is used for the sub-domain. +To make it a bit harder to test for published keys, the server +responsible to serve the WELLKNOWN directory SHOULD NOT create an +index file for that directory or any sub-directory. + * IANA Considerations ** Well-Known URI IANA is requested to assign a well-known URI in the "Well-Known URIs" registry as defined by {{{RFC(5785)}}}: URI suffix: openpgpkey Change controller: IETF Specification document: This * Acknowledgments The author would like to acknowledge the help of the individuals who kindly voiced their opinions on the GnuPG mailing lists, in particular, the help of Bernhard Reiter and Guilhem Moulin. * Back * Sample Protocol Run The following non-normative example can be used by implementors as guidance. Note that GnuPG version 2.1.12 supports the key discovery described in version -00 of this document (auto-key-locate method "wkd"). Version 2.1.16 can run the protocol described in this document but is also able to run the protocol version specified by -01. For backward compatibility this example uses the Content-Type as required for versions of this protocol prior to -04; if the client knows that the server support -04 "vnd.gnupg.wkd" should be used. ** Sample Keys This is the provider's submission key: #+begin_example -----BEGIN PGP PRIVATE KEY BLOCK----- lFgEV/TAohYJKwYBBAHaRw8BAQdAB/k9YQfSTI8qQqqK1KimH/BsvzsowWItSQPT FP+fOC4AAP46uJ3Snno3Vy+kORye3rf0VvWvuz82voEQLxG6WpfHhREEtBprZXkt c3VibWlzc2lvbkBleGFtcGxlLm5ldIh5BBMWCAAhBQJX9MCiAhsDBQsJCAcCBhUI CQoLAgQWAgMBAh4BAheAAAoJEKhtNooW0cqEWMUA/0e9XaeptszWC9ZvPg8INL6a BvRqPBYGU7PGmuXsxBovAQDyckOykG0UAfHVyN1w4gSK/biMcnqVr857i8/HuvjW C5xdBFf0wKISCisGAQQBl1UBBQEBB0Apvaoe4MtSEJ1fpds/4DFl2kXXBpnVji/s Wg9btdthNQMBCAcAAP9FJX99T1LEJzBnvBBnc6bimnT6/1OKM9RdO4R0/uVP6BFL iGEEGBYIAAkFAlf0wKICGwwACgkQqG02ihbRyoTlGwD9FBr92osjL7HkhhZZ7Z2D My3b9zpoZeMjvPg5YPqpdKMA/jhZoHuZCRMBYf7YRFb8aXtuyetDFZYrkjnum+OG HFAD =Hnwd -----END PGP PRIVATE KEY BLOCK----- #+end_example This is the target key to be published: #+begin_example -----BEGIN PGP PRIVATE KEY BLOCK----- lFgEV2o9XRYJKwYBBAHaRw8BAQdAZ8zkuQDL9x7rcvvoo6s3iEF1j88Dknd9nZhL nTEoBRkAAP94nCZMM4WY2IORXfM6phLGSz3RsHvs/vA1Opaus4+R3BKJtBtwYXRy aWNlLmx1bXVtYmFAZXhhbXBsZS5uZXSIeQQTFggAIQUCV2o9XQIbAwULCQgHAgYV CAkKCwIEFgIDAQIeAQIXgAAKCRATlWNoKgINCpkNAQDFDcwJUzsxu7aJUiPdpYXj 4uVarrXakxEE8mGFotWhLAD9GH4rqLDYIE3NKEU0s+Okt4tEIwJaV8H1NNPPPMiK 3g2cXQRXaj2NEgorBgEEAZdVAQUBAQdAFnnmZc99TuKk5iCq9wmYZUVF2RcXN2Cs qAl8iGQQUWsDAQgHAAD/VN/VGmlcwGBPcLTya2hfU4t37nMcFCKdNSXjJ5DFA0AP PohhBBgWCAAJBQJXaj2NAhsMAAoJEBOVY2gqAg0Ky4UA/0GmVaXzXemLvv1Xw4yx Eaz/KfKKGc4RJ+38fyqUzw8NAQCohQ+ki3I5f84EXLZEiUiLsnVtOn1HNxvND/gW TiFZBA== =GHi7 -----END PGP PRIVATE KEY BLOCK----- #+end_example ** Sample Messages The first message triggeres the publication requests. #+begin_example From: patrice.lumumba@example.net To: key-submission@example.net Subject: Key publishing request MIME-Version: 1.0 Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; boundary="=-=01-e8k41e11ob31eefa36wo=-=" Date: Wed, 05 Oct 2016 10:15:51 +0000 --=-=01-e8k41e11ob31eefa36wo=-= Content-Type: application/pgp-encrypted Version: 1 --=-=01-e8k41e11ob31eefa36wo=-= Content-Type: application/octet-stream -----BEGIN PGP MESSAGE----- hF4DUgLY5tvmW2sSAQdAR1AcqvFpQe/fHRZbf0xcnl9Tb+AtwaX2yZnZXGELGHsw 1/e3E0JptwM5tpRAVe71ooF8Zq4jl76ZgQKfj/SyjpLJxyoEDy2N5wTQaqW4JtML 0ukB1vh7dIRDxBJX/LQIJC0wz8o1Q3vjcLJKFFvDb7YrerABpPIzwOAupcgIbQHj 5m1+2WU5CL8ffyJy2h1jV2X4OnvWF1Sn6J6SVD6DfZpOPRt9TxSemJrN1LJ3lG0N ts8AuYmCOeC1H2r5TYyxqkC98JF8+Nvyxd/fwne8IOjK9uixkNMC5H9/ZOH0YWCb wBnNB4iXuym4OIPxiLkDymsVF0ww/XrODE9Y259EGmO45VFNrJAX3HFs9/PcMCVk n2qMyEkr8LHiXeEPun6Z54RHUPYv2cUkEZ0hhSJ+rtBxkc/5D/cAScCEXRKFSKEF jLJAvLK/u/ga5DAzVai+vh6b6Bq+YVPaD9GWMhWj4CgR90p9LULi6S/Hzwhv9Wzf 8fJoJOaDjyvRDgr09jYLWamxkS9NWxqwy6MXJvxwbNdd5XtqiW4Y4o0Ll1hDJhxR ljn/XvotXKwhKN+4QGhIXDVt4Dl4XxS5ptWfVTau8W8DYqDsU2obEcfsirZv53M1 Q9FCD8CD9+dkBt8VAJekCWVhEltcRHxlrznbk2jxm93xSD2o6gZ5X0VSaSUXyEhm J+8F3gyTHGgbq/TgyjFoockWh5EtGgAFuWvmPJCF5PO/UaNeoKwgwSJBu6oTXkHx R4nvvMRcj5UgTsKpZ79NiDQukbjG5ScNT5TCUiiZsBXBqBx3fD61EH6cAuh4P3Kr iM7PY4fwAHo890Dx+Qlt =WIhx -----END PGP MESSAGE----- --=-=01-e8k41e11ob31eefa36wo=-=-- #+end_example The server decrypts this message to #+begin_example Content-Type: application/pgp-keys -----BEGIN PGP PUBLIC KEY BLOCK----- mDMEV2o9XRYJKwYBBAHaRw8BAQdAZ8zkuQDL9x7rcvvoo6s3iEF1j88Dknd9nZhL nTEoBRm0G3BhdHJpY2UubHVtdW1iYUBleGFtcGxlLm5ldIh5BBMWCAAhBQJXaj1d AhsDBQsJCAcCBhUICQoLAgQWAgMBAh4BAheAAAoJEBOVY2gqAg0KmQ0BAMUNzAlT OzG7tolSI92lhePi5VqutdqTEQTyYYWi1aEsAP0YfiuosNggTc0oRTSz46S3i0Qj AlpXwfU00888yIreDbg4BFdqPY0SCisGAQQBl1UBBQEBB0AWeeZlz31O4qTmIKr3 CZhlRUXZFxc3YKyoCXyIZBBRawMBCAeIYQQYFggACQUCV2o9jQIbDAAKCRATlWNo KgINCsuFAP9BplWl813pi779V8OMsRGs/ynyihnOESft/H8qlM8PDQEAqIUPpIty OX/OBFy2RIlIi7J1bTp9RzcbzQ/4Fk4hWQQ= =qRfF -----END PGP PUBLIC KEY BLOCK----- #+end_example and returns this confirmation request #+begin_example From: key-submission@example.net To: patrice.lumumba@example.net Subject: Confirm your key publication MIME-Version: 1.0 Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; boundary="=-=01-wrzqued738dfx4x97u7y=-=" Date: Wed, 05 Oct 2016 10:16:57 +0000 --=-=01-wrzqued738dfx4x97u7y=-= Content-Type: application/pgp-encrypted Version: 1 --=-=01-wrzqued738dfx4x97u7y=-= Content-Type: application/octet-stream -----BEGIN PGP MESSAGE----- hF4DkYWHjk/NdMASAQdAluQeqhECpU2T0zEyBAEbFzhLkpubN160wjkFCrtUc0Mw FwYgM2fp9cvTMdJ/xjkvmAcIEOT4AY/hn1yFQ4z0KG0gCkSac+8mkDylnPdxlXYw 0sBSAXlbqpVA7eUpFuU2Zs10zbIXxlwe6osR5wUIJut/RCOsYQmfvxC55x8mUX5/ zgTnNzlMzye5ws4pTgAeQm2x0Yv018L8IZgY5KxwJLBzlss0wLZ45ZcS80hR11Fx NCow1fKF8lMnOJxagTEOih807nctz8vT5bR1gx0d7N3LM+th8nAg9/6Ghf1XTpLo MzwGW0FtOG7Dg1Uxbw2bjaOuRBeh6IIpmNAw1pmIfnNu7PpoRydU5w1K/R8MT06z MKdJ7IW5mVGes9EGnG3e4mjuILvNaZhfYy+a73IhDSaPm3oqdl1Qx7tbNg6lGjn6 KStCYAcPGPp3m7aWkfsPGThOVRhEXqaFFywfwSVEj1pdIRjDFA== =Cdjh -----END PGP MESSAGE----- --=-=01-wrzqued738dfx4x97u7y=-=-- #+end_example The client decrypts the attachment as #+begin_example Content-Type: application/vnd.gnupg.wks Content-Transfer-Encoding: 8bit type: confirmation-request sender: key-submission@example.net address: patrice.lumumba@example.net fingerprint: B21DEAB4F875FB3DA42F1D1D139563682A020D0A nonce: f5pscz57zj6fk11wekk8gx4cmrb659a7 #+end_example creates this response #+begin_example Content-Type: application/vnd.gnupg.wks Content-Transfer-Encoding: 8bit type: confirmation-response sender: key-submission@example.net address: patrice.lumumba@example.net nonce: f5pscz57zj6fk11wekk8gx4cmrb659a7 #+end_example and sends it encrypted to the server #+begin_example From: patrice.lumumba@example.net To: key-submission@example.net Subject: Key publication confirmation MIME-Version: 1.0 Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; boundary="=-=01-iacqg4og4pqz11a5cg1o=-=" Date: Wed, 05 Oct 2016 10:18:52 +0000 --=-=01-iacqg4og4pqz11a5cg1o=-= Content-Type: application/pgp-encrypted Version: 1 --=-=01-iacqg4og4pqz11a5cg1o=-= Content-Type: application/octet-stream -----BEGIN PGP MESSAGE----- hF4DUgLY5tvmW2sSAQdAnB1C3PMjS4AsGU0qaCqBdWQO5i6blWEyZrEsY+JZY1Qw ooNq7zdVWOHhL9LPGAALAgoL3Qfz+dN2u5QamSQ/LJ2c8M0XipNs3lqlNH63yQN1 0sAmAc3W8xkwul+rf6OLK/gMi6WzM4fnUhd4D1LJGIJoNUN0l3636C7ecOt2lkMl 5bVAYg/SyMT3ymyfQnvtiem2T5DSnPsS1g6n6QNXWvkqvX9yGxNsNDJEHTuGJB8k OJoRlfWQTEo6pgA89febWl1EdeM1pPLstQ2uZE8NPjXoY1nMxAlu+iPYsR41/4sg dqwOv5BPLh/GIat8hh9SPWCA9iKlgSQ/EIv5DpjQogEzpriT55dkgfvSVYIAcOdO ShZ91YKkcZffevdY72omqTk10a1SUXehPooIlRFmroDsi3VDaRKrUIo= =7uve -----END PGP MESSAGE----- --=-=01-iacqg4og4pqz11a5cg1o=-=-- #+end_example * Changes Since -04 - Change to Content-Type "vnd.gnupg.wkd" for servers announcing its support. - Require the existance of the Policy Flags file. - Re-title this I-D to Web Key Directory. diff --git a/tools/build-website.sh b/tools/build-website.sh index 2f8ceb9..6e2842d 100755 --- a/tools/build-website.sh +++ b/tools/build-website.sh @@ -1,334 +1,335 @@ #!/bin/sh # Build the gnupg.org website from a git working directory. # # This script requires two users # # webbuilder - the user to run this script # webbuild-x - the user used by this script to run emacs # webbuild-y - the user used by this script to run emacs (for preview) # # A certain directory layout is required with permissions setup # so that the webbuild-x has only write access to the stage area # and to its own home directory. The script checks the permissions. # # The trigger-website-build scripts is expected to be installed # as git post-merge hook. # # These cronjobs are required for user webbuilder: # --8<---------------cut here---------------start------------->8--- # # Pull the master branch of the web pages # */20 * * * * cd /home/webbuilder/gnupg-doc && git pull -q origin master # */18 * * * * cd /home/webbuilder/gnupg-doc-preview && git pull -q origin preview # # # In case of race conditions we try to build every few ours again. # 35 */7 * * * /home/webbuilder/bin/build-website.sh --cron # --8<---------------cut here---------------end--------------->8--- # # /etc/sudoers needs this: # --8<---------------cut here---------------start------------->8--- # # Let webbuilder run any command as user webbuild-x # webbuilder ALL = (webbuild-x,webbuild-y) NOPASSWD: ALL # --8<---------------cut here---------------end--------------->8--- # set -e pgm=build-website.sh mainuser=webbuilder workuser=webbuild-x workuser_pv=webbuild-y # We use a fixed HOME so that this script can be run here from other # accounts. HOME=$(awk &2; exit 1 fi reponame=gnupg-doc htdocs_web="/var/www/www/www.gnupg.org/htdocs" htdocs_preview="/var/www/www/preview.gnupg.org/htdocs" htdocs_blog="/var/www/www/www.gnupg.org/misc/blog" workuser_dir=$HOME/${workuser} workuser_pv_dir=$HOME/${workuser_pv} log_dir="$HOME/log" root_dir="$HOME/${reponame}" root_dir_pv="$HOME/${reponame}-preview" stage_dir="$HOME/${reponame}-stage" stage_dir_pv="$HOME/${reponame}-preview-stage" LOCKFILE="${log_dir}/${reponame}.lock" if [ x"$1" = x"--git" ]; then shift exec >>${log_dir}/"$reponame".log 2>&1 echo "$(date -u -Iseconds) gpgweb site build was git triggered" elif [ x"$1" = x"--cron" ]; then shift exec >>${log_dir}/"$reponame".log 2>&1 echo "$(date -u -Iseconds) gpgweb site build was cron triggered" fi if ! id $workuser >/dev/null 2>&1 ; then echo "$pgm: sudo user '${workuser}' not available" >&2; exit 1 fi if ! id $workuser_pv >/dev/null 2>&1 ; then echo "$pgm: sudo user '${workuser_pv}' not available" >&2; exit 1 fi # Check directories for f in "${workuser_dir}" "${root_dir}" "${stage_dir}" \ "${workuser_pv_dir}" "${root_dir_pv}" "${stage_dir_pv}"; do if [ ! -d "$f" ]; then echo "$pgm: directory '$f' missing" >&2; exit 1 fi done want="2775:${workuser}:${mainuser}" for f in "${workuser_dir}" "${stage_dir}"; do x=$(stat -c '%a:%U:%G' "$f") if [ x"$x" != x"$want" ]; then echo "$pgm: directory '$f' has wrong permissions" >&2 echo "$pgm: want: $want" >&2 echo "$pgm: have: $x" >&2 exit 1 fi done want="2775:${workuser_pv}:${mainuser}" for f in "${workuser_pv_dir}" "${stage_dir_pv}"; do x=$(stat -c '%a:%U:%G' "$f") if [ x"$x" != x"$want" ]; then echo "$pgm: directory '$f' has wrong permissions" >&2 echo "$pgm: want: $want" >&2 echo "$pgm: have: $x" >&2 exit 1 fi done cd "${root_dir}" # # Take a lock so that only one instance of this script runs. # if ! lockfile -l 7200 -r 2 $LOCKFILE; then echo "$pgm: another instance is still running" >&2 exit 0 fi trap "rm -f $LOCKFILE" 0 # These flags are set to the stage directory if a sync is required sync_web= sync_blog= sync_preview= # # Build main part # subdir=web revlastfile="${log_dir}/${reponame}.$(echo $subdir | tr / _).revlast" buildlog="${log_dir}/${reponame}.$(echo $subdir | tr / _).log" rev="$(git rev-parse --verify HEAD:$subdir)" if [ -z "$rev" ]; then echo "$pgm: No git revision found" >&2; exit 1 fi revlast="$(head -1 ${revlastfile} 2>/dev/null || true)" if [ x"$rev" = x"$revlast" ]; then echo "$pgm: No need to build $subdir" >&2; else echo "$(date -u -Iseconds) build started for $subdir" | tee ${buildlog} if [ ! -d ${stage_dir}/${subdir} ]; then sudo -u webbuild-x mkdir ${stage_dir}/${subdir} fi sudo 2>>${buildlog} -u webbuild-x emacs24 -q --batch \ --eval "(require 'assoc)" \ --eval "(require 'org)" \ --eval "(setq make-backup-files nil)" \ --eval "(setq gpgweb-root-dir \"${root_dir}/${subdir}/\")" \ --eval "(setq gpgweb-stage-dir \"${stage_dir}/${subdir}/\")" \ --eval "(require 'gpgweb (concat gpgweb-root-dir \"share/gpgweb.el\"))" \ --eval "(setq org-publish-use-timestamps-flag nil)" \ --eval "(setq org-export-html-toplevel-hlevel 1)" \ --eval "(setq org-export-html-coding-system 'utf-8)" \ --eval "(gpgweb-setup-project)" \ --eval "(org-publish-initialize-cache \"gpgweb\")" \ --eval "(message \"root=(%s)\" gpgweb-root-dir)" \ - --eval "(org-publish \"gpgweb\" t nil)" + --eval "(org-publish \"gpgweb\" t nil)" \ + --eval "(gpgweb-faq-to-txt \"gnupg-faq.org\")" echo "$rev" > ${revlastfile} sync_web=${stage_dir}/${subdir} echo "$(date -u -Iseconds) build finished for $subdir" | tee -a ${buildlog} fi # # Build blogs # subdir=misc/blog.gnupg.org revlastfile="${log_dir}/${reponame}.$(echo $subdir | tr / _).revlast" buildlog="${log_dir}/${reponame}.$(echo $subdir | tr / _).log" rev="$(git rev-parse --verify HEAD:$subdir)" if [ -z "$rev" ]; then echo "$pgm: No git revision found" >&2; exit 1 fi revlast="$(head -1 ${revlastfile} 2>/dev/null || true)" if [ x"$rev" = x"$revlast" ]; then echo "$pgm: No need to build $subdir" >&2; else echo "$(date -u -Iseconds) build started for $subdir" | tee ${buildlog} if [ ! -d ${stage_dir}/${subdir} ]; then sudo -u webbuild-x mkdir -p ${stage_dir}/${subdir} fi cd ${stage_dir}/${subdir} # We need to initialize that org cache to use our own publish function # despite that we do not use any org-publish feature echo "$pgm: Rendering blogs" >&2 sudo 2>>${buildlog} -u webbuild-x emacs24 -q --batch \ --eval "(require 'assoc)" \ --eval "(require 'org)" \ --eval "(setq gpgweb-root-dir \"${root_dir}/web/\")" \ --eval "(setq gpgweb-blog-dir \"${root_dir}/${subdir}/\")" \ --eval "(setq gpgweb-stage-dir \"${stage_dir}/${subdir}/\")" \ --eval "(require 'gpgweb (concat gpgweb-root-dir \"share/gpgweb.el\"))" \ --eval "(setq org-publish-use-timestamps-flag nil)" \ --eval "(setq org-export-html-toplevel-hlevel 1)" \ --eval "(setq org-export-html-coding-system 'utf-8)" \ --eval "(gpgweb-setup-project)" \ --eval "(org-publish-initialize-cache \"gpgweb\")" \ --eval "(message \"root=(%s)\" gpgweb-root-dir)" \ --eval "(gpgweb-publish-blogs)" echo "$pgm: Updating blog index" >&2 indexcreator="${root_dir}/${subdir}/update-index.sh" if [ ! -f $indexcreator ]; then echo "$pgm: $indexcreator not found" >&2 exit 1 fi sudo -u webbuild-x ${indexcreator} echo "$rev" > ${revlastfile} sync_blog=${stage_dir}/${subdir} echo "$(date -u -Iseconds) build finished for $subdir" | tee -a ${buildlog} fi # # Build the preview site (w/o blogs) # branch=preview subdir=web cd "${root_dir_pv}" revlastfile="${log_dir}/${reponame}.$branch.$(echo $subdir | tr / _).revlast" buildlog="${log_dir}/${reponame}.$branch.$(echo $subdir | tr / _).log" rev="$(git rev-parse --verify $branch:$subdir)" if [ -z "$rev" ]; then echo "$pgm: No git revision found" >&2; exit 1 fi revlast="$(head -1 ${revlastfile} 2>/dev/null || true)" if [ x"$rev" = x"$revlast" ]; then echo "$pgm: No need to build $branch:$subdir" >&2; else echo "$(date -u -Iseconds) build started for $branch:$subdir" | tee ${buildlog} if [ ! -d ${stage_dir_pv}/${subdir} ]; then sudo -u webbuild-y mkdir ${stage_dir_pv}/${subdir} fi sudo 2>>${buildlog} -u webbuild-y emacs24 -q --batch \ --eval "(require 'assoc)" \ --eval "(require 'org)" \ --eval "(setq make-backup-files nil)" \ --eval "(setq gpgweb-root-dir \"${root_dir_pv}/${subdir}/\")" \ --eval "(setq gpgweb-stage-dir \"${stage_dir_pv}/${subdir}/\")" \ --eval "(require 'gpgweb (concat gpgweb-root-dir \"share/gpgweb.el\"))" \ --eval "(setq org-publish-use-timestamps-flag nil)" \ --eval "(setq org-export-html-toplevel-hlevel 1)" \ --eval "(setq org-export-html-coding-system 'utf-8)" \ --eval "(gpgweb-setup-project)" \ --eval "(org-publish-initialize-cache \"gpgweb\")" \ --eval "(message \"root=(%s)\" gpgweb-root-dir)" \ --eval "(org-publish \"gpgweb\" t nil)" echo "$rev" > ${revlastfile} sync_preview=${stage_dir_pv}/${subdir} echo "$(date -u -Iseconds) build finished for $branch:$subdir" | tee -a ${buildlog} fi cd "${root_dir}" # # Sync to the webspace # cd "${root_dir}" any_sync= if [ -n "$sync_web" ]; then cd "$sync_web" rsync -rlt --exclude '*~' --exclude '*.tmp' \ . ${htdocs_web}/ touch ${htdocs_web}/donate/donors.dat cd ${htdocs_web} ln -sf ../../howtos.gnupg.org/htdocs howtos ln -sf software related_software ln -sf software/index.html features.html cd "$sync_web" any_sync=yes fi if [ -n "$sync_blog" ]; then cd "$sync_blog" rsync -rt --links --exclude '*~' --exclude '*.sh' \ --exclude '*tmp' --exclude '*.org' . ${htdocs_blog}/ cd "$root_dir/misc/blog.gnupg.org" rsync -rt --links --exclude '*~' --exclude '*.sh' \ --exclude '*tmp' --exclude '*.org' img data ${htdocs_blog}/ any_sync=yes fi if [ -n "$sync_preview" ]; then cd "$sync_preview" rsync -rlt --exclude '*~' --exclude '*.tmp' \ . ${htdocs_preview}/ $HOME/bin/mkkudos.sh --verbose --force --test fi cd "${root_dir}" if [ "$any_sync" = yes ]; then $HOME/bin/mkkudos.sh --verbose --force fi # # Print warnings when the scripts are out of date # (For security reasons the scripts need to be installed manually.) # for f in trigger-website-build build-website.sh mkkudos.sh \ append-to-donors.sh ; do if ! cmp -s ${HOME}/bin/$f tools/$f ; then echo "$pgm: Warning: A newer version of $f is available" >&2; fi done exit 0 diff --git a/web/copying.org b/web/copying.org index cb556c1..705f2d6 100644 --- a/web/copying.org +++ b/web/copying.org @@ -1,54 +1,55 @@ #+TITLE: GnuPG - Copying #+STARTUP: showall #+SETUPFILE: "share/setup.inc" * Copying #+index: Copying Except when noted otherwise, these web pages are copyrighted by /The GnuPG Project/. Given that such a legal entity does not exist, that name should be considered a placeholder for the list of the actual authors: #+begin_verse - \copy 1998--2013 Werner Koch + \copy 1998--2018 Werner Koch \copy 2000--2002 Nils Ellmenreich \copy 2001--2002 Mike Ashley \copy 2002--2005 Lorenzo Cappelletti \copy 2006--2006 David Shaw + \copy 2017--2018 Ben McGinnes #+end_verse # The Aegypten pages are under a different license - there authors are # \copy 2001--2004 Bernhard Reiter # \copy 2001--2005 Jan-Oliver Wagner You can redistribute these pages and/or modify them under the terms of the [[http://creativecommons.org/licenses/by-sa/3.0/][Creative Commons Attribution-ShareAlike 3.0 Unported License]] or alternatively under the terms of the [[http://www.gnu.org/licenses/][GNU General Public License]] as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. If you wish to allow the use of your version of these pages only under the terms of one of these licenses, indicate your decision by deleting the respective above paragraph. ** Remarks For many years we maintained translation of these pages to French, German, Italian, and Spanish. A big thank you to the translators: Jean-Francois Paris, Walter Koch, Cristian Rigamonti, and Noel David Torres Taño. Because we didn’t always managed to keep those translation up to date, we decided in 2013 to abandon them. In case translations are again demanded by users and sufficient resources are available, the tentative plan is to setup individual sites per language with language or country specific information. Former version of these web pages have been marked as copyrighted by the /Free Software Foundation/. However, a formal act to transfer the copyright to them has never been conducted. Thus in 2013 these notices have been replaced by a reference to the list of individual copyright holders. diff --git a/web/documentation/howtos.org b/web/documentation/howtos.org index 5be52f8..0df53a8 100644 --- a/web/documentation/howtos.org +++ b/web/documentation/howtos.org @@ -1,105 +1,132 @@ #+TITLE: GnuPG - HOWTOs #+STARTUP: showall #+SETUPFILE: "../share/setup.inc" * HOWTOs There are several HOWTOs available. ** GnuPG MiniHOWTO You may get the best overview about the GnuPG system by reading the mini HOWTO available in several formats: - as on-line browsable HTML files ( [[../howtos/ca/GPGMiniHowto.html][ca]] · [[../howtos/de/index.html][de]] · [[http://www.dewinter.com/gnupg_howto/english/GPGMiniHowto.html][en]] · [[http://www.dewinter.com/gnupg_howto/spanish/index.html][es]] · [[../howtos/fr/index.html][fr]] · [[../howtos/it/GPGMiniHowto.html][it]] · [[../howtos/tr/GPGMinikNasil.html][tr]] · [[../howtos/vn/index.htm][vn]] · [[../howtos/zh/index.html][zh]] ) - as one big HTML file ( [[../howtos/ca/GPGMiniHowto_big.html][ca]] · [[../howtos/it/GPGMiniHowto_big.html][it]] ) - as PDF ( [[../howtos/ca/GPGMiniHowto.pdf][ca]] · [[../howtos/de/GPGMiniHowto.pdf][de]] · [[../howtos/it/GPGMiniHowto.pdf][it]] · [[../howtos/vn/GPGMiniHowto.pdf][vn]] ) - in postscript format ( [[../howtos/ca/GPGMiniHowto.ps][ca]] · [[http://www.dewinter.com/gnupg_howto/english/GPGMiniHowto.ps][en]] · [[../howtos/de/GPGMiniHowto.ps][de]] ) - as DVI file ( [[../howtos/ca/GPGMiniHowto.dvi][ca]] ) - in RTF format ( [[../howtos/ca/GPGMiniHowto.rtf][ca]] ) - as plain text ( [[../howtos/ca/GPGMiniHowto.txt][ca]] · [[http://www.dewinter.com/gnupg_howto/english/GPGMiniHowto.txt][en]] · [[../howtos/it/GPGMiniHowto.txt][it]] ) - as SGML ( [[../howtos/ca/GPGMiniHowto.sgml][ca]] · [[../howtos/de/GPGMiniHowto.sgml][de]] · [[http://www.dewinter.com/gnupg_howto/english/GPGMiniHowto.sgml][en]] · [[../howtos/it/GPGMiniHowto.sgml][it]] · [[../howtos/tr/GPGMinikNasil.sgml.gz][tr]] ) - as gzipped tarball of them all ( [[../howtos/ca/GPGMiniHowto.tar.gz][ca]] ) ** GnuPG SmartcardHOWTO GnuPG supports the use of smartcards. This HOWTO explains how to install and work with these cards. - as on-line browsable HTML files ( [[../howtos/card-howto/en/smartcard-howto.html][en]] ) - as one big HTML file ( [[../howtos/card-howto/en/smartcard-howto-single.html][en]] ) - as plain text ( [[../howtos/card-howto/en/smartcard-howto.txt][en]] ) This smartcard howto is also available in the [[../download/git.org][source repository]]. ** GnuPG Keysigning Party HOWTO Once you get familiar with GnuPG's mechanisms, you surely wouldn't miss one of its funnest (and useful) aspects: to meet your Internet buddies and get your key signed by as many of them as possible. But having to check tens or even hundreds of keys at a meeting may become quite frustrating. Here it is where this HOWTO by V. Alex Brennen comes in handy. It is a guide to understanding and organizing a PGP keysigning party. Keysigning parties help build and strengthen the web of trust which serves to make the use of GnuPG more secure. This HOWTO is available: - as an on-line browsable set of HTML files ( [[http://www.cryptnet.net/fdp/crypto/gpg-party/gpg-party.de.html][de]] · [[http://www.cryptnet.net/fdp/crypto/keysigning_party/en/keysigning_party.html][en]] · [[../howtos/es/gpg-party.html][es]] · [[../howtos/it/keysigning_party.html][it]] · [[http://www.cypherpunks.ru/KSP.html][ru]] · [[http://www.cryptnet.net/fdp/crypto/gpg-party/gpg-party.si.html][si]] · [[http://www.cryptnet.net/fdp/crypto/gpg-party/gpg-party.zh-TW.html.big5][zh-TW.big5]] · [[http://www.cryptnet.net/fdp/crypto/gpg-party/gpg-party.zh-TW.html.euc-tw][zh-TW.euc-tw]] ) ** Mutt-GnuPG HOWTO Firstly, because everyone should be using encryption and signatures in their email. Secondly, because there are absolutely no reason for you not to be using PGP-compatible software. Thirdly, because documentation is mostly geared toward someone who is already familiar with PGP. Fourtly, because we like to promote both GnuPG and Mutt as free software project, for use in everyday communications. Lastly, because Justin R. Miller likes writing tutorials. For all these reasons, you can find below a link to Justin's HOWTO on how to send and receive cryptographically signed and/or encrypted email with GnuPG and the [[http://www.mutt.org/][Mutt mail reader]]. This HOWTO is available: - as plain text ( [[http://codesorcery.net/old/mutt/][en]] ) + +** PHP-GnuPG HOWTO + + With the preponderance of javascript based OpenPGP solutions to + various functions on the web, the desire to perform certain types + of server side functions on a PHP driven website also has its + merits. + + While PHP support for GPGME is either lacking, or too arcane for + most developers to decipher, or both; Piotr Masełkowski at + [[https://maslosoft.com/][Maslosoft]] has an alternative guide using the CLI programs. + + This HOWTO is available: + + - as an online HTML article ( [[https://maslosoft.com/blog/2017/09/12/using-gpg-with-php-on-server/][en]] ) + +** GPGME Python Bindings HOWTO + + Written "in house" by the GnuPG Project core team, the GPGME Python + Bindings HOWTO provides detailed instructions and examples for + using the Python bindings of the GPGME API with Python 3 code. + + This HOWTO is available: + + - in its original Emacs Org Mode source form in the GPGME repository ( [[https://dev.gnupg.org/source/gpgme/browse/master/lang/python/docs/GPGMEpythonHOWTOen.org][en]] ) + - as a single HTML file ( [[http://files.au.adversary.org/crypto/GPGMEpythonHOWTOen.html][en]] ) + - as a single HTML file with dark background and light text ( [[http://files.au.adversary.org/crypto/GPGMEpythonHOWTOen-dark.html][en]] ) diff --git a/web/faq/gnupg-faq.org b/web/faq/gnupg-faq.org index da30a0d..b30a64f 100644 --- a/web/faq/gnupg-faq.org +++ b/web/faq/gnupg-faq.org @@ -1,2192 +1,2220 @@ # gpgfaq.org -*- coding: utf-8; -*- #+TITLE: GnuPG Frequently Asked Questions #+EMAIL: gnupg-doc@gnupg.org #+AUTHOR: Robert J. Hansen et al. #+LANGUAGE: en #+LINK: gnupgweb https://www.gnupg.org/ #+LINK: roundup https://bugs.gnupg.org/gnupg/issue #+OPTIONS: H:3 num:2 toc:nil \n:nil @:t ::t |:t ^:{} -:t f:t *:t TeX:t LaTeX:t skip:nil d:nil tags:not-in-toc #+HTML_HEAD: #+STARTUP: overview indent * Foreword :PROPERTIES: :CUSTOM_ID: foreword :END: Welcome to the GnuPG Frequently Asked Questions (FAQ)! Before we begin, there’s just a few things that need to be addressed. It’s regrettable these things have to be included, but society has become very litigious. ** Trademark notice :PROPERTIES: :CUSTOM_ID: trademarks :END: - Linux is a trademark of Linus Torvalds. - GNU is a trademark of the Free Software Foundation. - Macintosh, OS X, macOS, and Mac OS X are all trademarks of the Apple Corporation. - PGP is a trademark of Symantec Corporation. - Solaris is a trademark of Oracle Corporation. - UNIX is a trademark of The Open Group. - Windows is a trademark of the Microsoft Corporation. - Some cryptographic algorithms mentioned in this FAQ may be trademarked. The use of these, or any other, marks is solely for identification purposes. ** Licensing :PROPERTIES: :CUSTOM_ID: documentation_license :END: -This document is © 2012-2017, Robert J. Hansen <[[mailto:rjh@sixdemonbag.org?subject=The%20GnuPG%20FAQ][rjh@sixdemonbag.org]]> and +This document is © 2012-2018, Robert J. Hansen <[[mailto:rjh@sixdemonbag.org?subject=The%20GnuPG%20FAQ][rjh@sixdemonbag.org]]> and A.M. Kuchling <[[mailto:amk@amk.ca?subject=The%20GnuPG%20FAQ][amk@amk.ca]]>. You are free to make use of this document in accordance with the [[https://creativecommons.org/licenses/by-sa/3.0/][Creative Commons Attribution-ShareAlike 3.0 license]]; alternately, you may make use of it under terms of the GNU General Public License (version 3 or, at your discretion, any later version). #+HTML: ** Disclaimer of liability :PROPERTIES: :CUSTOM_ID: liability :END: Although the contents of this document are believed to be correct, the author(s) cannot promise it is error-free and cannot assume liability for any errors. # We want the TOC to appear after the foreword. #+TOC: headlines 2 * Welcome :PROPERTIES: :CUSTOM_ID: welcome :END: Welcome to the official GnuPG FAQ. Like all FAQs, this is a work in progress. If you have questions that you think should be on it but aren’t, please feel free to email the FAQ maintainer (Rob Hansen, [[mailto:rjh@sixdemonbag.org?subject=The%20GnuPG%20FAQ][rjh@sixdemonbag.org]]) or bring your suggestion up on GnuPG-Users. ** Is this available in other languages? :PROPERTIES: :CUSTOM ID: translations :END: Thanks to the Free Software Foundation, this FAQ is also available in [[https://www.gnu.org/server/standards/translations/ru/gnupg/gnupg-faq.ru.html][Russian]]. ** How do I get help? :PROPERTIES: :CUSTOM_ID: gethelp :END: First, please don’t send emails directly to people in GnuPG. While we will try to help to people who send email directly to us, those emails quickly accumulate. Helping just six people a day can take an hour of time, and that’s an hour less we have to work on making GnuPG better. Please reach out to the GnuPG community via the [[https://lists.gnupg.org/mailman/listinfo/gnupg-users][GnuPG-Users mailing list]], not individual people within GnuPG. Second, tell us your operating environment. Be as specific as possible. What operating system are you using? Which version of GnuPG are you using? Where did you get GnuPG from? If your problem is related to email, which email client are you using? Which version number? Is GnuPG supported natively, or is there a plugin? If so, what’s the version number of that? Third, tell us your problem. Be as specific as possible. Do this, and you might be surprised at how quickly your problem is solved. An example of a good question would be, “I’m running GnuPG 1.4.14 on an Ubuntu 15.04 x64 box. I’m using Thunderbird with Enigmail. Everything was fine until I did a software update. Ever since then I can’t use GnuPG with email. What happened?” This question gives us enough to work with, and in short order someone will have an answer for you. A bad question would be, “How do I uninstall GnuPG?” We can’t help you at all; you’ve not given us any of the information we need to answer your question. ** Who maintains this FAQ? :PROPERTIES: :CUSTOM_ID: maintainer :END: [[mailto:rjh@sixdemonbag.org?subject%3DThe%20GnuPG%20FAQ][Rob Hansen]]. Please feel free to contact me should there be an error in this FAQ, whether typographical, grammatical, or factual. When writing, the editorial “we” refers to the general consensus of the GnuPG community. This consensus is hammered out on the GnuPG-Users mailing list. All members of the GnuPG community are invited to participate. Individual people within the community may give their own editorial comments: these will be set off by square brackets, italicized, and initialed by their author. The different editors are: - wk: Werner Koch <[[mailto:wk@gnupg.org?subject%3DThe%20GnuPG%20FAQ][wk@gnupg.org]]> - rjh: Robert J. Hansen <[[mailto:rjh@sixdemonbag.org?subject=The%20GnuPG%20FAQ][rjh@sixdemonbag.org]]> ** Is this the official GnuPG FAQ? :PROPERTIES: :CUSTOM_ID: is_it_official :END: Yes. ** When was this FAQ last checked for accuracy? :PROPERTIES: :CUSTOM_ID: last_checked :END: October 2017. * General questions :PROPERTIES: :CUSTOM_ID: general :END: ** What’s GnuPG? :PROPERTIES: :CUSTOM_ID: whats_gnupg :END: -GnuPG is cryptographic software that helps people ensure the -confidentiality, integrity and assurance of their data. Let’s try -that again: GnuPG is… +GnuPG is free cryptographic software from the GNU Project which helps +people ensure the confidentiality, integrity and assurance of their +data. Let’s try that again: GnuPG is… +- /Free./ When we say “free” we mean [[https://gnu.org/philosophy/free-sw.html][liberty, not price]]. You’re free + to use it, modify it, share it, tinker with it, and learn from it. + Software is meant to be used by people, and people deserve freedom. - /Cryptographic./ The word “cryptography” is derived from two Greek words, κρυπτός (pronounced “kryptos,” meaning “hidden”) and γράφω - (pronounced “graphein,” meaning “writing”). Cryptography is the + (pronounced “grapho,” meaning “writing”). Cryptography is the mathematical study of codes and ciphers. - /Software./ This one should already be obvious. +- /GNU Project./ The [[https://www.gnu.org][GNU Project]] is a group that aims to give people + the ability to do all their computing with free software. - /Confidentiality./ No one except authorized parties should be able to read your data. - /Integrity./ It shouldn’t be possible to tamper with a message unnoticeably. - /Assurance./ An assurance is not a guarantee. There are no guarantees in life, and software is no different. An assurance just means there is good reason to be confident of something — here, it means that when GnuPG is correctly used, people may be confident the data is confidential and/or possesses integrity. GnuPG may be used by itself as a command-line application (i.e., to be run at a Terminal prompt or a Windows command prompt), or integrated into popular email clients. It’s also used by some instant messaging clients, such as Psi. ** How do I pronounce GnuPG? :PROPERTIES: :CUSTOM_ID: pronunciation :END: -“guh-NEW-pee-gee.” +“GNU”, followed by the letters “P” and “G”. To learn how to pronounce +GNU, you may want to +[[https://www.gnu.org/gnu/pronunciation.en.html][listen to a recording]]. ** Is it compatible with Symantec’s PGP? :PROPERTIES: :CUSTOM_ID: compatible :END: Largely, yes. It can be made to interoperate with anything from PGP 5 and onwards, and has excellent interoperability with the most recent releases. *** Does it support Diffie-Hellman? :PROPERTIES: :CUSTOM_ID: pgp_dh :END: Yes. “Diffie-Hellman” is what PGP calls the Elgamal encryption algorithm. If your PGP-generated keypair uses a Diffie-Hellman encryption subkey, it will appear in GnuPG as an Elgamal subkey. The correct name, incidentally, is Elgamal. *** Does it support SHA-2-256 and SHA-2-512? :PROPERTIES: :CUSTOM_ID: pgp_sha2 :END: Yes. SHA-256 and SHA-512 belong to a group of hashes known collectively as “SHA-2”. PGP calls SHA-256 and SHA-512 by the non-standard names “SHA-2-256” and “SHA-2-512”, but they are the same algorithms. + ** Which operating systems does it run on? :PROPERTIES: :CUSTOM_ID: oses :END: Too many to list! It’s known to run on Microsoft Windows, Mac OS X, the various free Unixes, AIX, Solaris, HPUX, OpenVMS, and more. People are even working on porting it to smartphones such as Android. ** How much does it cost? :PROPERTIES: :CUSTOM_ID: free_as_in_beer :END: There is no fixed price. Many sites on the internet offer legal downloads of it for free. ** From where can I download it… :PROPERTIES: :CUSTOM_ID: get_gnupg :END: Lots of different places, but no one site hosts binaries for all operating systems. *** … for Microsoft Windows? :PROPERTIES: :CUSTOM_ID: get_gnupg_win32 :END: A convenient Windows installer is available from [[https://www.gpg4win.org][GPG4WIN]]. *** … for Mac OS X? :PROPERTIES: :CUSTOM_ID: get_gnupg_osx :END: The [[https://www.gpgtools.org][GPGtools project]] has everything needed to get started. Another excellent resources is the [[http://sourceforge.net/projects/gpgosx/][GnuPG for OS X]] project on SourceForge. Finally, [[https://brew.sh][Homebrew]], [[http://www.finkproject.org/][Fink]], and [[https://www.macports.org/][MacPorts]] all have it in their repositories. *** … for the free Unixes? :PROPERTIES: :CUSTOM_ID: get_gnupg_linux :END: There are as many ways to install it as there are free Unix systems. **** … for Debian GNU/Linux or Ubuntu? :PROPERTIES: :CUSTOM_ID: get_gnupg_debian :END: At a terminal window type =sudo apt-get install gnupg2=. **** … for OpenSUSE? :PROPERTIES: :CUSTOM_ID: get_gnupg_opensuse :END: At a terminal window type =sudo zypper install gnupg2=. **** … for Fedora, CentOS, or RHEL? :PROPERTIES: :CUSTOM_ID: get_gnupg_fedora :END: For Fedora 22 and later: at a terminal window type =sudo dnf install gnupg2=. For Fedora 21 and earlier, CentOS, or RHEL: at a terminal window type =sudo yum install gnupg2=. **** … for Slackware? :PROPERTIES: :CUSTOM_ID: get_gnupg_slack :END: Install the =gnupg= package for GnuPG 1.4, or the =gnupg2= package for GnuPG 2.0. **** … for Gentoo? :PROPERTIES: :CUSTOM_ID: get_gnupg_gentoo :END: To install GnuPG on Gentoo, run the following command as root: =emerge gnupg= The Gentoo documentation includes a [[https://www.gentoo.org/doc/en/gnupg-user.xml][GnuPG User Guide]]. **** … for FreeBSD? :PROPERTIES: :CUSTOM_ID: get_gnupg_freebsd :END: GnuPG is included in the ports collection. To install it, run the following commands as root: #+begin_example cd /usr/ports/security/gnupg make install clean #+end_example Alternatively, you can install GnuPG using a package manager: #+begin_example sudo pkg_add -r gnupg #+end_example +Or with this variation for the package manager: + +#+begin_example +sudo pkg install gnupg +#+end_example + *** … for VMS? :PROPERTIES: :CUSTOM_ID: get_gnupg_vms :END: A port to *VMS* is maintained by Steven M. Schweda at [[http://www.antinode.info/dec/sw/gnupg.html][antinode.info]]. ** Is source code available? :PROPERTIES: :CUSTOM_ID: source_code :END: Yes! The person, business or group that provided you with the GnuPG binary is required to give you the source code upon your request. ** What’s Free Software, and why does it matter? :PROPERTIES: :CUSTOM_ID: gpl :END: The word “free” should evoke ideas of liberty, not price. An awful lot of the software industry does not [[https://gnu.org/philosophy/free-software-even-more-important.html][respect your freedoms]]: your freedom to use the software for any purpose, your freedom to study and learn from how it works, your freedom to share it with others who might benefit from it, and more. Free Software is the antithesis of -this: Free Software is meant to respect your rights. You may use the +this: Free Software is meant to respect your freedoms. You may use the software for any purpose: you may inspect and modify the source code: you may share the software and/or your modifications with others. +GnuPG works with many operating systems, including ones that don’t +respect your freedoms. If you’d like to make the shift to a free +operating system, [[https://www.gnu.org/distros/free-distros.html][you have many choices]]. ** How can I donate money to the GnuPG project? :PROPERTIES: :CUSTOM_ID: donate :END: The best way is to visit the [[https://gnupg.org/donate/][donation page]]. ** How can I help with GnuPG development? :PROPERTIES: :CUSTOM_ID: develop :END: Development discussion takes place on the gnupg-devel mailing list. Go to the [[https://www.gnupg.org/documentation/mailing-lists.en.html][GnuPG mailing list page]] for links to subscribe and to the list’s archives. The [[https://bugs.gnupg.org/gnupg/][GnuPG project’s bug tracker]] is also publicly available. - * Where can I get more information? :PROPERTIES: :CUSTOM_ID: more_info :END: The good news is the internet is a treasure trove of information. The bad news is that the internet is a festering sewer of misinformation, conspiracy theories, and half-informed speculations all masquerading as informed commentary. The following mailing lists and web pages are generally known for having a strong signal-to-noise ratio. Nevertheless, we strongly urge you to keep a skeptical mind at all times. ** Help! I lost my passphrase. :PROPERTIES: :CUSTOM_ID: lost_passphrase :END: Unfortunately, we can’t help you. If you lose your passphrase, you’ll be unable to use that certificate to sign any new documents or decrypt any existing documents. You can still use it to verify signatures, though. (Technically you could encrypt documents, too, but without the passphrase there’s really not much point: how would you ever decrypt them?) If you can’t remember your passphrase, the best thing to do is use your pre-made revocation certificate to revoke your old certificate, upload the revocation to the keyserver network, and start anew with a fresh certificate. ** How can I spot the charlatans? :PROPERTIES: :CUSTOM_ID: fraudsters :END: First, beware of all absolutes. Almost every question in either the fields of computer security or cryptography can honestly be answered with, “it depends.” Real experts will avoid giving blanket yes-or-no answers except to the simplest and most routine of questions. They will instead hem and haw and explain the several different factors that must be weighed. Hucksters will promise you absolute truth. Second, the experts really don’t care whether you take their advice. Hucksters often want to be seen as authorities, and if you fail to take their advice they may harangue you about how you’re taking chances with your data, how you’re acting irresponsibly, and so on. Third, experts genuinely don’t want you to trust them. An expert will instead point to the published literature (usually in a dead-tree edition with the imprimatur of a reputable publishing house) and tell you what the reference books say. They want you to trust the reference books, not them. Hucksters will go on about their extensive personal experience or refer to papers that have only ever been self-published on websites. Fourth, experts try not to scare people. The world is a scary enough place without it being made moreso. Hucksters will try to scare you, in order to keep you listening to them and dependent on them for information on how to be ‘safe.’ Fifth, experts will quickly admit when they are wrong and give credit to the person bringing the error to their attention. Hucksters tend to take challenges as personal affronts. ** What are some useful mailing lists? :PROPERTIES: :CUSTOM_ID: mailing_lists :END: There are many excellent mailing lists out there. The following is a list of just some of them that we’ve found to be high-quality. There are undoubtedly many more that we’ve missed. *** The GnuPG-Users mailing list :PROPERTIES: :CUSTOM_ID: gnupg-users_list :END: - Subscribing :: visit the [[https://lists.gnupg.org/mailman/listinfo/gnupg-users][GnuPG-Users webpage]] - Unsubscribing :: see above - List moderator :: <[[mailto:gnupg-users-owner@gnupg.org?subject%3DThe%20GnuPG-Users%20list][gnupg-users-owner@gnupg.org]]> - Supports PGP/MIME? :: Yes - Languages supported :: English GnuPG-Users is home to the largest community of GnuPG users on the net. The list is very lightly moderated and somewhat freewheeling, but overall it has an excellent signal-to-noise ratio. The level of technical discussion is sometimes a little daunting for the newcomer, but on the whole it’s a wonderful resource. *** The Enigmail mailing list :PROPERTIES: :CUSTOM_ID: enigmail_list :END: - Subscribing :: Visit the [[https://admin.hostpoint.ch/mailman/listinfo/enigmail-users_enigmail.net][Enigmail mailing list page]] - Unsubscribing :: See above - List moderator(s) :: - John Clizbe <[[mailto:john@enigmail.net?subject=The%20Enigmail%20list][john@enigmail.net]]> - Olav Seyfarth <[[mailto:olav@enigmail.net?subject=The%20Enigmail%20list][olav@enigmail.net]]> - Patrick Brunschwig <[[mailto:patrick@enigmail.net?subject=The%20Enigmail%20list][patrick@enigmail.net]]> - Ludwig Hügelschäfer <[[mailto:ludwig@enigmail.net?subject=The%20Enigmail%20list][ludwig@enigmail.net]]> - Daniele Raffo <[[mailto:dan@enigmail.net?subject=The%20Enigmail%20list][dan@enigmail.net]]> - Robert J. Hansen <[[mailto:rob@enigmail.net?subject=The%20Enigmail%20list][rob@enigmail.net]]> - Supports PGP/MIME :: Yes - Languages supported :: English, Deutsch, Schwyzerdütsch, Español Enigmail integrates GnuPG with [[https://www.getthunderbird.com][Mozilla Thunderbird]] and/or [[https://www.seamonkey-project.org/][Mozilla Seamonkey]]. It’s one of the most popular ways to use GnuPG, and the mailing list provides a friendly place to learn how it works and get started using it. The list is lightly moderated. *** PGPNET :PROPERTIES: :CUSTOM_ID: pgpnet_list :END: - Subscribing :: visit the [[http://tech.groups.yahoo.com/group/PGPNET][PGPNET page]] - Unsubscribing :: see above - List moderator(s) :: Paul Kapaldo <[[mailto:pjkapaldo@yahoo.com?subject=PGPNET][pjkapaldo@yahoo.com]]> - Supports PGP/MIME? :: Yes - Languages supported :: Unknown PGPNET exists to provide people with the opportunity to practice sending and receiving encrypted, signed, and encrypted-and-signed traffic in a group environment. ** What are some useful webpages? :PROPERTIES: :CUSTOM_ID: webpages :END: As a general rule, the huckster quotient of webpages at-large is fairly high. That said, there are some web resources we recommend. They can be broken up into homepages for specific GnuPG-related projects, and sites of general interest. *** Where can I find the homepage for… :PROPERTIES: :CUSTOM_ID: homepages :END: Many of the projects associated with GnuPG maintain their own websites. If you have problems with an associated project, please check their website first: they might be able to give you faster and better help than the GnuPG community can. **** … GnuPG? :PROPERTIES: :CUSTOM_ID: gnupg_homepage :END: GnuPG’s homepage can be found at [[https://www.gnupg.org][https://www.gnupg.org]]. It is also available in the [[https://torproject.org][Tor]] network as =ic6au7wa3f6naxjq.onion=. **** … Enigmail? :PROPERTIES: :CUSTOM_ID: enigmail_homepage :END: Enigmail, a plugin for Mozilla Thunderbird that adds strong GnuPG support, can be found at [[https://enigmail.net][https://enigmail.net]]. **** … GPGTools? :PROPERTIES: :CUSTOM_ID: gpgtools_homepage :END: Mac OS X users may wish to visit the GPGTools project at [[https://www.gpgtools.org][https://www.gpgtools.org]]. **** … GPG4WIN? :PROPERTIES: :CUSTOM_ID: gpg4win_homepage :END: GPG4WIN, the Windows port of GnuPG, maintains a homepage at [[https://www.gpg4win.org][https://www.gpg4win.org]]. *** Where can I find webpages covering… :PROPERTIES: :CUSTOM_ID: pages_about :END: Although the GnuPG community generally finds these websites to be useful, your mileage may significantly vary. There are wide differences of opinion about some of them. They’re worth visiting and worth reading, but make sure to read skeptically. **** … an easy introduction to cryptography? :PROPERTIES: :CUSTOM_ID: pages_about_introduction_to_crypto :END: There is no such thing as an easy introduction to cryptography. However, PGP Corporation has a well-regarded [[http://www.cs.unibo.it/babaoglu/courses/security/resources/documents/intro-to-crypto.pdf][/Introduction to Cryptography/]]. **** … the deeper mathematics of cryptography? :PROPERTIES: :CUSTOM_ID: pages_about_cryptographic_mathematics :END: The maintainer of this list also keeps a gentle(-ish) [[http://sixdemonbag.org/cryptofaq.xhtml][introduction to the mathematics and computer science of cryptography]]. **** … best practices for using GnuPG? :PROPERTIES: :CUSTOM_ID: pages_about_best_practices :END: At present, there are no reputable web pages detailing GnuPG best practices. **** … the politics of cryptography? :PROPERTIES: :CUSTOM_ID: pages_about_politics :END: The inclusion of a site on this list is not an endorsement of that site’s political leanings. Probably the best-known organization is the [[https://www.eff.org][Electronic Frontier Foundation]], which has been at the vanguard of electronic civil liberties for over twenty years. The [[https://www.fsf.org][Free Software Foundation]] is also deeply involved in these matters, although in a different way than the EFF. * What email clients support GnuPG on… :PROPERTIES: :CUSTOM_ID: email_clients :END: Many email clients offer strong GnuPG integration. The column “Active” in the tables below indicate whether the software is actively developed. ** … Microsoft Windows? :PROPERTIES: :CUSTOM_ID: email_clients_win32 :END: | Name | Plugins | see | |-------------+----------------+-----| | Thunderbird | yes (Enigmail) | (1) | | Kontact | native | (2) | | Claws-Mail | yes (internal) | (3) | (1) With the Enigmail plugin, Thunderbird becomes one of the most popular GnuPG-aware email clients. It’s under active development and is compatible with the latest Thunderbird releases, with a friendly and welcoming user community. (2) Kontact is KDE’s integrated personal information manager of KDE. It runs anywhere that KDE does, and even on some mobile devices as Kontact Touch. (3) Claws-Mail for Windows is included in the [[https://www.gpg4win.org][Gpg4win]] installer. ** … Mac OS X? :PROPERTIES: :CUSTOM_ID: email_clients_osx :END: | Name | Plugins | see | |-------------+----------------+-----| | Thunderbird | yes (Enigmail) | (1) | | Gnus | yes ([[https://www.emacswiki.org/emacs/EasyPG][EasyPG]]) | (2) | | Mutt | native | (3) | +| Neomutt | native | (3) | | Apple Mail | yes ([[https://www.gpgtools.org][GPGtools]]) | (4) | (1) With the Enigmail plugin, Thunderbird becomes one of the most - popular GnuPG-aware email clients. it’s under active development + popular GnuPG-aware email clients. It’s under active development and is compatible with the latest Thunderbird releases, with a friendly and welcoming user community. -(2) EasyPG is part of Emacs 23, proper. Thus there is no more need to - install the plugin. See the Gnus manual for configuration hints. +(2) EasyPG is part of Emacs 23, proper as EPA and the underlying EPG. + Thus there is no more need to install the plugin. See the Gnus + manual for configuration hints. Both EPA and EPG can be + customized with the customize-group command and using either the + =epa= or =epg= groups. -(3) For best experience make sure to put ~set crypt_use_gpgme~ in your - =~/.muttrc= file. +(3) For the best experience make sure to put ~set crypt_use_gpgme~ in + your =~/.muttrc= file. Note that this requires installing Mutt or + Neomutt compiled with GPGME support, refer to the Mutt or Neomutt + documentation for details. (4) As of this writing, Apple Mail is incompatible with PGP/MIME. This is a known bug and people are working on it. ** … Free UNIX systems? :PROPERTIES: :CUSTOM_ID: email_clients_free_unix :END: | Name | Plugins | see | |-------------+----------------+-----| | Thunderbird | yes (Enigmail) | (1) | | Gnus | yes ([[https://www.emacswiki.org/emacs/EasyPG][EasyPG]]) | (2) | | Mutt | native | (3) | +| Neomutt | native | (3) | | Kontact | native | (4) | | Evolution | native | | | Claws-Mail | yes (internal) | | (1) With the Enigmail plugin, Thunderbird becomes one of the most - popular GnuPG-aware email clients. it’s under active development + popular GnuPG-aware email clients. It’s under active development and is compatible with the latest Thunderbird releases, with a friendly and welcoming user community. -(2) EasyPG is part of Emacs 23, proper. Thus there is no more need to - install the plugin. See the Gnus manual for configuration hints. +(2) EasyPG is part of Emacs 23, proper as EPA and the underlying EPG. + Thus there is no more need to install the plugin. See the Gnus + manual for configuration hints. Both EPA and EPG can be + customized with the customize-group command and using either the + =epa= or =epg= groups. -(3) For best experience make sure to put ~set crypt_use_gpgme~ in your - =~/.muttrc= file. +(3) For the best experience make sure to put ~set crypt_use_gpgme~ in + your =~/.muttrc= file. Note that this requires installing Mutt or + Neomutt compiled with GPGME support, refer to the Mutt or Neomutt + documentation for details. (4) Kontact is KDE’s integrated personal information manager of KDE. It runs anywhere that KDE does, and even on some mobile devices as Kontact Touch. * Is GnuPG available as a ‘portable app’? :PROPERTIES: :CUSTOM_ID: portable_app :END: Yes, but we don’t recommend it. Sharing a USB token between lots of random computers is a great way to get infested with malware, and that’s not something you want to happen to the token you’re using for secure email. If you’re going to do this, please show caution with respect to which computers you use the portable app on. That said, Windows users should check [[http://portableapps.com/apps/internet/thunderbird_portable][PortableApps]]. Or, to build your own, use the /mkportable/ tool which comes with [[https://www.gpg4win.org][Gpg4win]]. * What do all these strange words mean? :PROPERTIES: :CUSTOM_ID: glossary :END: Cryptography tends to use a whole lot of specialized language and jargon. In this section some of it will be deciphered. ** What’s ‘public-key cryptography’? :PROPERTIES: :CUSTOM_ID: define_asymc :END: In the 1970s new ideas came to the forefront of the cryptanalytic world. One of the most important was the development of asymmetric cryptography (also often called “public-key cryptography”). Asymmetric cryptography is built around problems that are very hard in one direction, and very easy in another. Consider the number 2,701. If you were to be asked for its prime factors, you would find it a daunting challenge. If you were to be given the numbers 37 and 73, though, it wouldn’t take but a minute to discover the answer was 2,701. Multiplying two numbers to yield a third number is easy: finding those two numbers, given the third, is hard. Asymmetric cryptography uses these asymmetric problems as the building-blocks of cryptography. It’s easy to create an encrypted message which neither you nor anyone else save the intended recipient can decrypt. To continue the metaphor, you and everyone else get to wrestle with the hard problem (“factor 2,701”). The intended recipient knows a secret piece of information which makes the problem easy (“factor 2,701, given that one of the factors is 73”). This manages to overcome the major flaw with symmetric cryptography. Your public key can be shared with the entire world, even your enemies, and your communications will still be secure. Compare this to symmetric cryptography, where as soon as the key became public knowledge the entire system was broken. ** What’s ‘symmetric cryptography’? :PROPERTIES: :CUSTOM_ID: define_symc :END: One of the earliest ciphers was the shift cipher, which was allegedly used by Julius Caesar in his campaign against the Gauls. He took his plaintext and shifted each letter three positions up in the alphabet, wrapping around once he reached the end (so that ‘Z’ would become ‘C’). His correspondents would reverse the process: by moving each letter in the encrypted text down three letters the original message would be recovered. Knowing how to encrypt the text also gave the knowledge of how to decrypt the text: the process wasn’t identical (one shifted up, the other shifted down), but knowing one process the other one could trivially be discovered. This trait, that of encryption and decryption being two sides of the same coin, is the defining trait of symmetric cryptography. Modern-day symmetric ciphers are much more complex than Caesar’s scheme, but they still work in fundamentally the same way. Knowledge of how to encrypt reveals knowledge of how to decrypt, and vice-versa. The symmetry between those two operations leads to the name “symmetric cryptography”. Symmetric cryptography is fast, well-studied, and safe. It has one critical drawback, though: you have to have a secure communications channel by which you can share the key with someone. If you already have a secure communications channel, though, do you really need cryptography? ** What’s a ‘key’? :PROPERTIES: :CUSTOM_ID: define_key :END: The word ‘key’ is unfortunately ambiguous. It can either refer to the mathematical structures that allow encryption, decryption, signing and verification to occur, or to the rather large blobs of data that contain those mathematical structures as well as information about the person associated with it, additional subkeys, and so forth. With respect to the large blobs of data, it is preferable to call them ‘certificates’, so that the word ‘key’ may be unambiguously recognized as meaning just the mathematical structures. Unfortunately, this is a custom that seems to be honored mostly in the breach. ** What’s a ‘certificate’? :PROPERTIES: :CUSTOM_ID: define_certificate :END: A certificate is a large data structure that contains one or more [[#define_keys][keys]], and optionally information that identifies the user, designated revokers, who has vouched for this certificate, and so on. ** What’s a ‘keyserver’? :PROPERTIES: :CUSTOM_ID: define_keyserver :END: A keyserver is a service that publishes public-key certificates and makes them searchable. You can upload your certificate to a keyserver so that other users can find it. There are distributed networks of keyservers that share keys, so you only need to upload your key once to that network. One widely-used keyserver network is [[https://www.sks-keyservers.net/][sks-keyservers.net]]. SKS stands for “Synchronizing Key Server”. You can use this network by supplying the =--keyserver pool.sks-keyservers.net= option. ** What’s RSA? :PROPERTIES: :CUSTOM_ID: define_rsa :END: RSA is the world’s premier [[#define_asymc][asymmetric cryptographic algorithm]], and is built on the difficulty of factoring extremely large composites. GnuPG supports RSA with [[#define_key][key]] sizes of between 1024 and 4096 bits. ** What’s DSA? :PROPERTIES: :CUSTOM_ID: define_dsa :END: The United States’ National Institute for Standards and Technology ([[http://www.nist.gov][NIST]]) established the Digital Signature Algorithm (DSA) as a government standard for digital signatures. Originally, it supported key lengths between 512 and 1024 bits. Recently, NIST has declared 512-bit keys obsolete: now, DSA is available in 1024, 2048 and 3072-bit lengths. DSA belongs to the Elgamal family of algorithms, and is very well-regarded. ** What’s Elgamal? :PROPERTIES: :CUSTOM_ID: define_elgamal :END: Elgamal may refer to either a family of cryptographic algorithms built around the difficulty of computing discrete logarithms in a finite field, or one particular [[#define_asymc][asymmetric encryption algorithm]] based on that problem. The former is normally referred to as “the Elgamal family,” and the latter is normally referred to as simply “Elgamal.” GnuPG supports the Elgamal asymmetric encryption algorithm in [[#define_key][key]] lengths ranging from 1024 to 4096 bits. There is also an Elgamal signature algorithm, which GnuPG no longer supports. ** What’s AES? :PROPERTIES: :CUSTOM_ID: define_aes :END: Leading up to the year 2000, it was obvious that the old Data Encryption Standard (DES) was on its last legs and needed to be replaced. 3DES was available as a stopgap measure, but there was a lot of pressure to make a new encryption standard that made use of the last few decades of cryptologic research. The United States National Institute of Standards and Technology ([[http://www.nist.gov][NIST]]) held an open competition to select the new encryption standard. In the summer of 2000, a cipher named Rijndael (pronounced “RAIN-doll”) was selected as the new Advanced Encryption Standard, or AES. AES is a thoroughly modern cipher design and may be used with confidence. ** What are Twofish and Blowfish? :PROPERTIES: :CUSTOM_ID: define_fish :END: Blowfish and Twofish are well-regarded symmetric ciphers. Blowfish should not be used to encrypt files larger than 4Gb in size, but Twofish has no such restrictions. These algorithms are modern, and may be used with confidence. ** What’s 3DES? :PROPERTIES: :CUSTOM_ID: define_3des :END: In the 1970s, IBM developed a new symmetric cipher called the Data Encryption Standard (DES). They overdesigned it horribly: even after three decades, the only way to break DES is by brute force. Unfortunately, standard DES has a small enough keyspace to be susceptible to brute-forcing. A new variant of DES was needed. 3DES, which is made of three DES algorithms running together with three independent keys, was the result. 3DES is ungainly, ugly, slow, and has all the aesthetics of a Soviet workers’ housing bloc. It has also withstood three decades of cryptanalysis and is still going strong. Due to its 1970s-era 64-bit block size, it should not be used to encrypt more than about 4Gb of data. Beyond that, though, it is solid as a rock, and very few GnuPG users will ever notice a problem with it. Provided you’re not encrypting more than 4Gb of data you may use 3DES with confidence. ** What are CAST, CAST5, and CAST5-128? :PROPERTIES: :CUSTOM_ID: define_cast :END: Carlisle Adams and Stafford Tavares (the “CA” and the “ST” in “CAST”) developed the CAST algorithm in 1996. It was later approved for Canadian government use. CAST has many names: CAST, CAST5, CAST5-128 and CAST-128 all refer to the same algorithm. Internally, CAST is distinctly similar to Blowfish, another well-respected algorithm. Like 3DES, its 64-bit block size means it should not be used to encrypt files larger than 4Gb in size. With that said, though, CAST is a modern cipher and may be used with confidence. ** What’s Camellia? :PROPERTIES: :CUSTOM_ID: define_camellia :END: During roughly the same time period that [[http://www.nist.gov][NIST]] was running the Advanced Encryption Standard trials, Japan’s [[http://www.cryptrec.jp/english/][CRYPTREC]] and the European Union’s [[http://www.cryptonessie.org/][NESSIE]] were running their own similar trials. Camellia is the cipher that won the NESSIE and CRYPTREC trials, much in the same way that Rijndael won the United States’ AES trials. Camellia is a thoroughly modern cipher design and may be used with confidence. ** What are SHA-1, SHA-224, SHA-256, SHA-384, SHA-512 and SHA-3? :PROPERTIES: :CUSTOM_ID: define_sha :END: The Secure Hash Algorithms are cryptographic hash functions originally devised by the United States’ National Security Agency. The algorithms have been made publicly available and have been subjected to an astonishing amount of peer review. - *SHA* and/or *SHA-0*: the original Secure Hash Algorithm, generating 160-bit outputs. Flaws were discovered in it almost immediately. SHA-0 never gained much traction in the cryptologic community, and it is not present in GnuPG. - *SHA-1*: This is SHA-0 with the flaws fixed, and not much else in the way of changes. It still generates 160-bit outputs. SHA-1 has not aged well. Although it is still believed to be safe, it would be advisable to use another, different hash function if possible. - *SHA-224, 256, 384, or 512*: This is a massively-overhauled SHA-1 which generates larger hashes (224, 256, 384, or 512 bits). Right now, these are the strongest hashes in GnuPG. - *SHA-3*: SHA-3 is a completely new hash algorithm that makes a clean break with the previous SHAs. It is believed to be safe, with no warnings about its usage. It hasn’t yet been officially introduced into the OpenPGP standard, and for that reason GnuPG doesn’t support it. However, SHA-3 will probably be incorporated into the spec, and GnuPG will support it as soon as it does. ** What’s MD5? :PROPERTIES: :CUSTOM_ID: define_md5 :END: MD5 is a 128-bit cryptographic hash function invented by Ron Rivest (the ‘R’ of ‘RSA’) in the early 1990s. For many years it was one of the standard algorithms of the field, but is now completely obsolete. For that reason, MD5 is not supported by GnuPG. ** What are ZLIB, ZIP and BZIP? :PROPERTIES: :CUSTOM_ID: define_compress :END: ZLIB, ZIP and BZIP refer to different kinds of compression algorithms. GnuPG will use one of these three algorithms to compress your data before encrypting it, unless GnuPG can see the data is already compressed. ** What’s a ‘revocation certificate’? :PROPERTIES: :CUSTOM_ID: define_rev_cert :END: A revocation certificate is a [[#define_certificate][certificate]] that possesses the information necessary to mark another certificate as unusable. This is called ‘revoking’ the certificate. We recommended you create a revocation certificate immediately after generating a new GnuPG certificate. Store it somewhere safe. Consult [[#generate_revocation_certificate][the FAQ instructions]] on how to do this. ** What’s a ‘designated revoker’? :PROPERTIES: :CUSTOM_ID: define_desig_revkr :END: A designated revoker is a person, identified by a certificate, that has the authority to revoke another certificate held by a different person. For instance, if you were using GnuPG in a corporate environment the IT staff might be listed as a designated revoker for your certificate, so that when you left the company the IT staff could revoke your certificate. ** What does ‘validity’ mean? :PROPERTIES: :CUSTOM_ID: define_validity :END: Although a certificate makes certain assertions about identity, these assertions cannot be blindly trusted. (Consider, for instance, whether you should trust a certificate that claims to belong to =obama@whitehouse.gov=.) If you trust the certificate’s assertions, you are said to have ‘validated’ the certificate. Validation can be done by fiat or as the result of a process. For instance, you validate your own certificate by fiat: “this certificate says it belongs to me, and I trust it.” Validating other certificates, though, should probably have a little more rigor involved. How much rigor will depend entirely on your own particular needs and the threats you face. ** What does ‘trust’ mean? :PROPERTIES: :CUSTOM_ID: define_trust :END: ‘Trust’ refers to how thoroughly a certificate has been [[#define_validity][validated]]. The terms are used somewhat interchangeably. ** What does ‘ownertrust’ mean? :PROPERTIES: :CUSTOM_ID: define_ownertrust :END: If a certificate has been [[#define_validity][validated]], and if you trust the person owning that certificate to do proper validation of certificates, you can tell GnuPG “I am willing to trust this person’s validations as if they were my own.” For instance: Alice has fully validated Bob’s certificate. She further believes, based on her knowledge of Bob, that he will be as careful as she is about the certificates he validates. Alice declares she has ownertrust in Bob. Now, any certificates that Bob validates will appear to Alice as valid, too. * How do I start using GnuPG? :PROPERTIES: :CUSTOM_ID: starting_out :END: The very first thing is to join the [[#gnupg-users_list][GnuPG-Users mailing list]]. You’ll find it to be a welcoming community that’s friendly to newcomers and is eager to help out. ** Does GnuPG need to be ‘tuned’ before use? :PROPERTIES: :CUSTOM_ID: tuning :END: No. GnuPG has sensible defaults right out of the box. You don’t need to tune GnuPG before you can use it. ** How large should my key be? :PROPERTIES: :CUSTOM_ID: new_key_size :END: The overwhelming majority of users will be well-served by generating 2048-bit RSA keys. This is the default behavior for GnuPG. ** What algorithm should I use? :PROPERTIES: :CUSTOM_ID: new_key_algo :END: The overwhelming majority of users will be well-served by generating 2048-bit RSA keys. This is the default behavior for GnuPG. ** Why does it take so long to generate a certificate? :PROPERTIES: :CUSTOM_ID: new_key_generate_time :END: The short answer is, “your computer is doing a lot of work.” But don’t worry: although generating new certificates can take a while, actually using them once they’re made is quite fast. ** What should I do after making my certificate? :PROPERTIES: :CUSTOM_ID: new_key_after_generation :END: Generate a revocation certificate, and store it in a safe place. Alternately, you may wish to appoint [[#define_desig_revkr][a designated revoker]]. *** How do I appoint a designated revoker? :PROPERTIES: :CUSTOM_ID: appoint_revoker :END: A designated revoker is someone whom you trust to revoke your certificates on your behalf. This person may revoke your certificates without needing a revocation certificate. For instance, you may wish to appoint your lawyer as your designated revoker so that, in the event of your untimely death, your lawyer may revoke your certificates. To add a revoker, use the following command line: =gpg --edit-key= /[your key ID here]/ =addrevoker= When prompted, enter the key ID of the person whom you wish to appoint as a revoker. The revoker’s key must be fully validated. *** How do I generate a revocation certificate? :PROPERTIES: :CUSTOM_ID: generate_revocation_certificate :END: A [[#define_rev_cert][revocation certificate]] marks another certificate as unusable. To generate a revocation certificate for your key, do: =gpg --armor --output revoke.asc --gen-revoke= /[your key ID]/ Copy =revoke.asc= to a safe place. *** How do I send my certificate to the keyserver network? :PROPERTIES: :CUSTOM_ID: send_to_keyservers :END: =gpg --keyserver pool.sks-keyservers.net --send-key= /[your certificate ID]/ You should only upload your own certificates to the keyservers, or obtain the certificate holder’s permission before doing so. In some circles it’s considered rude to upload someone else’s certificate; not everyone wants to publish their key publicly. ** Where does GnuPG look for configuration options? :PROPERTIES: :CUSTOM_ID: location_gpg_conf_file :END: GnuPG looks at a file called =gpg.conf= to determine various runtime parameters. On UNIX systems this file can be found in =~/.gnupg=. On Windows systems open Explorer and go to =%APPDATA%\Roaming\GnuPG=. ** What options should I put in my configuration file? :PROPERTIES: :CUSTOM_ID: new_user_gpg_conf :END: The good news is, you really shouldn’t need to. That said, the following is Rob Hansen’s =gpg.conf= file. #+begin_example # Tell GnuPG that I want maximum OpenPGP conformance. openpgp # Disable a few messages from GnuPG that I know I don’t need. no-greeting no-secmem-warning # Don’t include a version number or a comment in my output. no-emit-version no-comments # Use full 16-character key IDs, not short 8-character key IDs. keyid-format long # Use the global keyserver network for certificate lookups. # Further, whenever I send or receive something to/from the # keyserver network, clean up what I get or send. keyserver pool.sks-keyservers.net keyserver-options import-clean-sigs import-clean-uids export-clean-sigs export-clean-uids # If I don’t explicitly state which certificate to use, use this one. default-key 1DCBDC01B44427C7 # Always include signatures from these two certificates. local-user 1DCBDC01B44427C7 # Always add these two certificates to my recipients list. encrypt-to 1DCBDC01B44427C7 # Turn "From" into "> From", in order to play nice with UNIX mailboxes. escape-from-lines # Prefer strong hashes whenever possible. personal-digest-preferences SHA256 SHA384 SHA512 SHA224 RIPEMD160 # Prefer more modern ciphers over older ones. personal-cipher-preferences CAMELLIA256 AES256 TWOFISH CAMELLIA192 AES192 CAMELLIA128 AES BLOWFISH CAST5 3DES # Turn up the compression level and prefer BZIP2 over ZIP and ZLIB. bzip2-compress-level 9 compress-level 9 personal-compress-preferences BZIP2 ZIP ZLIB #+end_example ** Is there any particular keyserver I should use? :PROPERTIES: :CUSTOM_ID: new_user_default_keyserver :END: Many people have had excellent luck with =pool.sks-keyservers.net=. On OS X, some people have needed to use =ipv4.pool.sks-keyservers.net= instead. ** What’s the difference between an ‘option’ and a ‘command’? :PROPERTIES: :CUSTOM_ID: diff_option_commands :END: Commands tell GnuPG what to do: options tell GnuPG how to do it. For instance, =encrypt= is a command, and =armor= is an option that tells GnuPG to ensure the output contains only printable characters. ** What are the most commonly used options? :PROPERTIES: :CUSTOM_ID: common_options :END: Some of the most commonly used options are: Produce more output explaining what GnuPG is doing: =-v=, =--verbose= Make no changes; this is useful for testing a command line that will modify keys or generate output: =-n=, =--dry-run= Send output to the named file: =-o= /FILE/, =--output= /FILE/ Create ASCII-armored output that can be safely e-mailed, instead of binary output: =-a=, =--armor= When encrypting a message, you will usually supply at least one recipient ID with the recipient option. This option can be supplied multiple times to encrypt a message to multiple recipients: =-r= /KEYID/, =--recipient= /KEYID=/ /specify a recipient ID/ ** What are the most commonly used commands? :PROPERTIES: :CUSTOM_ID: common_commands :END: GnuPG’s primary functions are to encrypt and decrypt messages, and to sign and verify them. It’s possible to sign without encrypting or encrypt without signing. Signing a file’s content is done with the =-s= or =--sign= commands. A variation is =-b= or =--detach-sign=, which produces a separate signature without including the file’s content; this is useful for signing a software archive or other large file. The key to use for the signature can be specified with the =local-user= setting in your =gpg.conf= file, or with the =-u=, =--local-user= options. Encrypting a file’s content is done with the =-e= or =--encrypt= commands. Recipients are specified with the =-r= or =--recipient= options. GnuPG’s default action is to decrypt and verify its input file, writing the contents to standard output or to the filename specified by the =-o= or =--output= options. The =--verify= command will only verify the signature without writing the file’s contents anywhere. These commands are the most commonly used. GnuPG has many more commands, largely for managing your keyring containing your private keys and the certificates of others. ** How do I use another person’s certificate? :PROPERTIES: :CUSTOM_ID: using_certificates :END: In order to send an encrypted message or verify a signature, you must obtain the certificate for the recipient’s/signer’s public key. Occasionally you might obtain the certificate physically, by meeting the certificate holder face-to-face and exchanging the certificate on some storage medium such as a USB stick, memory card, or portable disk. Or you might download a copy of the certificate from the holder’s web site. Once obtained in one of these ways, you can add the certificate to your collection of public keys by doing: =gpg --import certificate.txt= More commonly, you’ll download a correspondent’s certificate from a keyserver. *** How do I search the keyserver for someone’s certificate? :PROPERTIES: :CUSTOM_ID: searching_keyservers :END: There is also a network of public keyservers, accessible under the collective hostname =pool.sks-keyservers.net=. GnuPG users can upload their certificates to the keyservers, and other users can then search for and download them. =gpg --keyserver pool.sks-keyservers.net --search= /[email address, name, key ID, etc.]/ GnuPG will list matching certificates and prompt you to select which ones you wish to download and add to your keyring. People will obtain new signatures for their certificates from time to time. =gpg --refresh-keys= will recheck all of the certificates on your public key and download any new signatures for those keys. *** How do I retrieve a certificate if I already know its fingerprint? :PROPERTIES: :CUSTOM_ID: retrieving_by_fingerprint :END: =gpg --keyserver pool.sks-keyservers.net --recv-key= /[fingerprint]/ *** Why do I need to validate certificates? :PROPERTIES: :CUSTOM_ID: why_validate :END: If you were to receive a letter in the mail that claimed to be from the President of the United States, would you believe it? Probably not, because anyone can put together official-looking letterhead: you’d insist on doing some kind of checking to make sure that no one was fooling with you. The same applies to email. A certificate can claim to be from anyone. You have to make sure that the certificate really belongs to whom it claims it belongs to. That process of making sure is called ‘validation’. *** How do I validate certificates? :PROPERTIES: :CUSTOM_ID: how_to_validate :END: *This advice is controversial.* It’s controversial for a simple reason: every Tom, Dick and Harry has their own idea about the “right way” to validate certificates. Some of these people are well-informed and some of them are just plain unhinged. In the end, you are responsible for making your own decisions. That said, the following is generally agreed upon as being a reasonable procedure: 1. Meet the certificate holder face-to-face. 2. Ask to see two forms of government-issued identification. 3. Upon verifying the person really is who they claim to be, ask this person to provide their certificate’s fingerprint, their email address, and where you can obtain a copy of their certificate. (Example: “My fingerprint is =4541 BB01 8EA4 8F99 19CA 3701 2380 6BE5 D6B9 8E10=, and you can find it on =pool.sks-keyservers.net=.”) 4. On your own computer, retrieve the person’s certificate from the specified location. Check to make sure the email address they gave you is one that’s also listed on the certificate. Check to make sure the fingerprint of the certificate you’ve downloaded matches the fingerprint the person gave you. 5. =gpg --edit-key= /[their certificate ID]/ =sign= 6. Once signed, =gpg --armor --output signed_cert.asc --export= /[their certificate ID]/ 7. Send the file =signed_cert.asc= to the address they gave you By following this process you first ensure that you’re speaking to the right person. By comparing the fingerprints of the certificate you have against the fingerprint they specified, you’re ensuring that you have the right certificate. Checking to make sure the email address they gave you is also listed on the certificate is one more check to make sure. Once that’s done, presto, Bob’s your uncle: there’s nothing left to do except sign it and return the newly-signed certificate to the other person. ** Why can’t I read emails I’ve sent, and how do I fix it? :PROPERTIES: :CUSTOM_ID: encrypt_to_self :END: You encrypted a message to Alice, which means that it requires Alice’s private key to read it. Only Alice has her private key. That’s why you can’t read encrypted traffic you generated: only Alice can read it. To get around this, add yourself as a recipient (=--recipient= /[your certificate ID]/). ** How do I encrypt a file for multiple recipients? :PROPERTIES: :CUSTOM_ID: multiple_recipients :END: Use multiple =--recipient= options. Remember, options come before commands! ** How do I sign a file with multiple certificates? :PROPERTIES: :CUSTOM_ID: multiple_signers :END: Use multiple =--local-user= options. Remember, options come before commands! ** How do I combine encryption with signing? :PROPERTIES: :CUSTOM_ID: encrypt_and_sign :END: =gpg --armor --recipient= /[first recipient’s key ID]/ =--local-user= /[your key ID]/ =--sign --encrypt= /[filename]/ ** How do I force GnuPG to make printable-text output? :PROPERTIES: :CUSTOM_ID: ascii_armor :END: Normally, computers use eight-bit binary code. This often presents trouble for email, which often requires that only printable (seven-bit) characters may be used. By using the =--armor= flag, GnuPG will generate output containing only printable characters. ** How do I create an ‘inline signature’? :PROPERTIES: :CUSTOM_ID: generate_inline_signature :END: An inline signature wraps a textual header and footer around the text to be signed, leaving the text readable without running GnuPG. This doesn’t conceal the text at all and therefore provides no secrecy, but if someone edits the text GnuPG will report that the signature is bad. To generate an inline signature, run =gpg --armor --output signed_file.asc --local-user= /[your key ID]/ =--clearsign message_file.txt= To verify the resulting file, simply invoke GnuPG with the filename of the signed file: =gpg signed_file.asc= ** How can I use GnuPG to verify a file I’ve downloaded? :PROPERTIES: :CUSTOM_ID: how_do_i_verify_signed_packages :END: 1. Get a copy of the author’s public certificate and import it to your keyring. It’s important to get the author’s certificate through a trusted source. On the internet, anyone can be pretend to be anyone. Particularly, be careful if the certificate you have doesn’t match the one used for prior code releases. 2. Once you’re confident you have the correct certificate, give it a local signature. Assuming you want to locally sign certificate 1DCBDC01B44427C7, you’d type: =gpg --edit-key 1DCBDC01B44427C7 lsign= 3. Download the software package. Let’s assume it’s called “foo.zip”. 4. Download the detached signature for the package. Let’s assume it’s called “foo.zip.asc”. 5. Run: =gpg foo.zip.asc= GnuPG will assume the original file is in foo.zip. (If GnuPG can’t find foo.zip, GnuPG will prompt you for the name of the original package.) If all goes well, GnuPG will report good signatures and you may be confident you’ve received the package as the author intended. Please note that a good signature doesn’t mean a piece of software is trustworthy, reliable, or bug-free. It just means nobody tampered with it and you’re receiving it as the author intends. Keep a healthy dose of skepticism, and remember that cryptography cannot save us from our own foolishness. ** How can I use GnuPG in an automated environment? :PROPERTIES: :CUSTOM_ID: automated_use :END: You should use the =--batch= option. Don’t bother to use a passphrase because there’s usually no way to store it more securely than on the secret keyring itself. The suggested way to create keys for an automated environment is as follows. First, on a secure machine: 1. If you want to do automatic signing, create a signing subkey for your key. Use the interactive key editing menu by issuing the command: =gpg --edit-key= /keyID/ Enter “addkey” and choose whichever key type best suits your needs. (If you don’t know which one is best, choose RSA.) 2. Make sure that you use a passphrase; this is required by the current implementation to let you export the secret key. 3. Run: =gpg --export-secret-subkeys --no-comment= /newsubkeyID/ => secring.auto= 4. Copy =secring.auto= and the public keyring to a test directory. 5. Change to the test directory. 6. Run the command: =gpg --homedir . --edit= /newsubkeyID/ Use the sub-command =passwd= to remove the passphrase from the subkeys. You may also want to remove all unused subkeys by doing =key N= and then =delkey= for each subkey. 7. Copy =secring.auto= to the target box somehow. On the target machine, install =secring.auto= as the secret keyring and begin writing scripts that invoke GnuPG. It’s a good idea to install an intrusion detection system so that you will get notice of a successful intrusion. If that happens, you can revoke all the subkeys installed on that machine and install new subkeys once the machine is secured again. ** I’m a programmer and I need a GnuPG library. Is there one? :PROPERTIES: :CUSTOM_ID: yes_gpgme :END: Check out [[https://www.gnupg.org/software/gpgme/][GPGME (GnuPG Made Easy)]]. ** I’m a programmer and I need a way to call GnuPG internals directly. Is there a library for this? :PROPERTIES: :CUSTOM_ID: keep_dreaming :END: No, nor will there be. * What common problems come up? :PROPERTIES: :CUSTOM_ID: common_problems :END: ** Why is GnuPG warning me this certificate might not belong to whom I think it does? :PROPERTIES: :CUSTOM_ID: you_need_to_validate :END: If you received an email claiming to be from a Nigerian oil tycoon, would you believe it? Or would you insist on doing some kind of verification first, in order to make sure that you’re not being scammed or swindled? The same principle applies here. If you’re using a certificate that claims to belong to Alice, but there’s no evidence it actually belongs to Alice, GnuPG will warn you that you’re using an untrusted certificate. You probably want to validate the certificate; see [[#how_to_validate][this FAQ’s instructions]]. ** Why is GnuPG warning me about using insecure memory? :PROPERTIES: :CUSTOM_ID: insecure_memory :END: GnuPG tries to lock memory so that no other process can see it and so that the memory will not be written to swap. If for some reason it’s not able to do this (for instance, certain platforms don’t support this kind of memory locking), GnuPG will warn you that it’s using insecure memory. While it’s almost always better to use secure memory, it’s not necessarily a bad thing to use insecure memory. If you own the machine and you’re confident it’s not harboring malware, then this warning can probably be ignored. ** Why is GnuPG changing my message? :PROPERTIES: :CUSTOM_ID: escaped_dashes :END: GnuPG uses special lines to denote the beginning of a message, the beginning of a signature, and so forth. These lines start with “=----- BEGIN=…”. If your text contains a line beginning with a dash, that line will be slightly mangled in order to prevent GnuPG from misinterpreting your data as one of its special lines. * What are some common best practices? :PROPERTIES: :CUSTOM_ID: best_practices :END: It’s very hard to give advice on this subject, because everyone will have their own opinion. That said, here are some good guidelines: - *Join the community.* Join [[gnupg-users_list][GnuPG-Users]] and get involved in the discussions. The conversation is wide-ranging and you’ll encounter a great variety of thoughts and opinions. Reading GnuPG-Users is one of the best ways to educate yourself. - *Practice.* If you don’t practice these skills before they become necessary, you won’t be able to use these skills effectively. - *Generate a revocation certificate and keep it safe.* - *Use a strong passphrase.* - *Keep your computer free of malware.* - *Validate certificates correctly.* ** How can I choose a strong passphrase? :PROPERTIES: :CUSTOM_ID: strong_passphrase :END: If someone manages to obtain your secret key, the only thing protecting the key will be your passphrase. A passphrase should be 1) difficult to guess for someone who knows you, and 2) difficult to brute-force by trying every possible combination of characters. To meet requirement 1), the passphrase shouldn’t be based on publicly-available information about you: your birthday, your spouse’s name, your school’s motto, a line of text from a book, etc. To meet requirement 2), the passphrase should be long: commercially available hardware can try 2.8 billion passwords in a day, which is sufficient to crack a 10-letter all-lowercase password. One simple approach that produces easy-to-remember passphrases is to generate four to six random words, as illustrated by the XKCD cartoon [[http://xkcd.com/936/][“Correct, horse! Battery staple!”]]. ** How can I keep my revocation certificate safe? :PROPERTIES: :CUSTOM_ID: keep_rev_cert_safe :END: Good places include safe deposit boxes, kept on file with your lawyer, placed in a fireproof safe, and so forth. It should be treated as an important document that needs to be kept safe. ** How can I keep my computer safe from malware? :PROPERTIES: :CUSTOM_ID: malware :END: Although there is no guaranteed way of keeping your system free of malware, you can reduce your risk quite a lot by following some basic rules. 1. Keep your system up-to-date. Always apply the latest patches. 2. Stop using old versions of Internet Explorer. If possible, use [[https://www.getfirefox.com][Mozilla Firefox]] or [[https://download-chromium.appspot.com/][Chromium]]. 3. Don’t open email attachments unless they are expected and come from someone you know. 4. Don’t click on email links unless they are expected and come from someone you know. 5. Be suspicious of requests for personal information, especially if it’s more detail than is strictly necessary to solve a problem. ** Should I use encrypted disk software like TrueCrypt, BitLocker or FileVault? :PROPERTIES: :CUSTOM_ID: disk_encryption :END: You can if you want, but it won’t make your private key any more secure. Your private key is already encrypted: your passphrase is the key used to decrypt your private key. * Advanced topics :PROPERTIES: :CUSTOM_ID: advanced_topics :END: These topics are ‘advanced’ in the sense that you really don’t need to understand them in order to safely and correctly use GnuPG. That said, if you have a more technical question about GnuPG, you may find some of the answers in this section. ** Which ciphers are recommended, and why? :PROPERTIES: :CUSTOM_ID: recommended_ciphers :END: Although all the ciphers in GnuPG are believed strong, they are not all equally recommended. For asymmetric ciphers we recommend RSA over DSA and/or Elgamal; for symmetric ciphers we recommend AES, Camellia, and/or Twofish over all the others. With respect to our RSA recommendation, there is no reason to believe RSA is any better or worse than DSA and/or Elgamal in a cryptographic sense. However, if you ever want to migrate your certificate to a smart card or other cryptographic token, you’ll find RSA is much better supported. With respect to our symmetric cipher recommendations, we have to explain a little bit about cryptanalysis. First, ciphers are deterministic: given the same inputs, they generate the same outputs. Second, ciphers don’t operate on individual bytes. They work on blocks of data, either eight or sixteen bytes large, depending on the cipher. Third, the OpenPGP standard requires that ciphers run in what’s called a “feedback mode.” In feedback mode, a cipher has two inputs: the random session key used for the message, and the output of the previous block. Put it all together and imagine what would happen if, within the same message, two identical ciphertext blocks were created. Since the cipher is deterministic (always generates the same output for the same inputs), and since the key and the previous block are the same, the output of this block would be the same. This repetition creates a distinctive pattern which a cryptanalyst might be able to potentially exploit. For a cipher with an eight-byte block size, you’ll probably repeat a block after about 32 gigabytes of data. This means if you encrypt a single message larger than 32 gigabytes, it’s pretty much a statistical guarantee you’ll have a repeated block. That’s bad. For this reason, we recommend you not use ciphers with eight-byte data blocks if you’re going to be doing bulk encryption. It’s very unlikely you’ll have any problems if you keep your messages under 4 gigabytes in size. For a cipher with a sixteen-byte block size, you’d need to encrypt a single message that contained more data than is found in the entire internet. In other words, it’s no longer an issue. Twofish, AES, and Camellia all operate on sixteen bytes at a time. The others all operate on eight bytes at a time. ** Why does GnuPG default to 2048 bit RSA-2048? :PROPERTIES: :CUSTOM_ID: default_rsa2048 :END: At the time the decision was made, 2048-bit RSA was thought to provide reasonable security for the next decade or more while still being compatible with the overwhelming majority of the OpenPGP ecosystem. *** Is that still the case? Largely, yes. According to NIST Special Publication 800-57, published in July 2012, 2048-bit RSA is believed safe until 2030. At present, no reputable cryptographer or research group has cast doubt on the safety of RSA-2048. That said, many are suggesting shifting to larger keys, and GnuPG will be making such a shift in the near future. *** What do other groups have to say about 2048-bit RSA? In 2014, the German Bundesnetzagentur fuer Elektrizitaet, Gas, Telekommunikation, Post und Eisenbahnen recommended using RSA-2048 for long-term security in electronic signatures. In 2012, ECRYPT-II published their “Yearly Report on Algorithms and Keysizes” wherein they expressed their belief RSA-1776 will suffice until at least 2020, and RSA-2432 until 2030. In 2010, France’s Agence Nationale de la Securite des Systems d’Information stated they had confidence in RSA-2048 until at least 2020. *** Is there a general recommendation that 3072-bit keys be used for new applications? No, although some respected people and groups within the cryptographic community have made such recommendations. Some even recommend 4096-bit keys. *** Will GnuPG ever support RSA-3072 or RSA-4096 by default? Probably not. The future is elliptical-curve cryptography, which will bring a level of safety comparable to RSA-16384. Every minute we spend arguing about whether we should change the defaults to RSA-3072 or more is one minute the shift to ECC is delayed. Frankly, we think ECC is a really good idea and we’d like to see it deployed as soon as humanly possible. *** I think I need larger key sizes. By all means, feel free to generate certificates with larger keys. GnuPG supports up to 4096-bit keys. ** Do other high-security applications use RSA-2048? :PROPERTIES: :CUSTOM_ID: rsa2048_in_the_real_world :END: 2048-bit RSA is commonly used to secure SSL root signing certificates. It’s also used to sign operating system patches, Authenticode signatures, Java applets and more. RSA-2048 is believed to be safe against attack until at least the year 2030, so use it with confidence. ** Why doesn’t GnuPG default to using RSA-4096? :PROPERTIES: :CUSTOM_ID: no_default_of_rsa4096 :END: Because it gives us almost nothing, while costing us quite a lot. Breaking an RSA-10 key requires you to try each prime number between two and one hundred. There are twenty-five of these, meaning RSA-10 is equivalent to about a 5-bit symmetric cipher. Breaking an RSA-20 key requires you to try each prime number between two and one thousand: there are 168 of them, meaning RSA-20 is equivalent to about an 8-bit cipher. Doubling the keylength (from RSA-10 to RSA-20) didn’t give us the benefit that we naively expected. Each additional bit gives correspondingly less in the way of additional security, and we quickly reach a point of diminishing returns. That point of diminishing returns happens around RSA-2048. Once you move past RSA-2048, you’re really not gaining very much. At the same time, moving past RSA-2048 means you lose the ability to migrate your certificate to a smartcard, or to effectively use it on some mobile devices, or to interoperate with other OpenPGP applications that don’t handle large keys gracefully. If you really want a 4096-bit RSA key there’s nothing stopping you: but we sincerely believe the overwhelming majority of users will be well-served with RSA-2048. ** Why do people advise against using RSA-4096? :PROPERTIES: :CUSTOM_ID: please_use_ecc :END: Almost always when people use 4096-bit RSA they’re doing so because they believe RSA-4096 to be much stronger than it is. The United States’ National Institute of Standards and Technology ([[http://www.nist.gov][NIST]]) states that RSA-2048 gives roughly 112 bits of security and RSA-3072 gives roughly 128. There is no formal recommendation on where RSA-4096 lies, but the general consensus is that it would come in somewhere around 140 bits — 28 bits of improvement over RSA-2048. This is an improvement so marginal that it’s really not worth mentioning. If you need more security than RSA-2048 offers, the way to go would be to switch to elliptical curve cryptography — not to continue using RSA. ** Why does GnuPG support RSA-4096 if it’s such a bad idea? :PROPERTIES: :CUSTOM_ID: not_a_bad_idea_just_unnecessary :END: RSA-4096 is not a bad idea: it’s just, generally speaking, unnecessary. You gain very little in the way of additional resistance to brute-forcing and cryptanalysis. ** Can any of the ciphers in GnuPG be brute-forced? :PROPERTIES: :CUSTOM_ID: brute_force :END: No. The laws of physics require that a certain amount of heat be used in computation. This is a consequence of the Second Law of Thermodynamics, and may not be violated under our current understanding of the laws of physics. Further, physics requires that a certain amount of time be used in computation. This is a consequence of the Heisenberg Uncertainty Principle, and may not be violated under our current understanding of the laws of physics. Using these two principles (the [[https://en.wikipedia.org/wiki/Landauer_bound][Landauer bound]] and the [[https://en.wikipedia.org/wiki/Margolus%E2%80%93Levitin_theorem][Margolus–Levitin limit]]), we can determine quite accurately how much heat would be released by a computer that brute-forced a 128-bit cipher. The results are profoundly silly: it’s enough to boil the oceans and leave the planet as a charred, smoking ruin. This is not to say that GnuPG cannot be successfully attacked. It is only to say that none of the ciphers in GnuPG are susceptible to brute-forcing. ** Has GnuPG ever been successfully attacked? :PROPERTIES: :CUSTOM_ID: successful_attacks :END: This depends entirely on what is meant by “successful attack.” If you mean, “has GnuPG traffic ever been successfully cryptanalyzed?”, the answer is a flat ‘no’. We are unaware of any credible reports of any of the ciphers used in GnuPG having ever been successfully cryptanalyzed. If you mean, “have people figured out ways to obtain the plaintext anyway?”, the answer is an emphatic ‘yes.’ In [[http://news.cnet.com/8301-10784_3-9741357-7.html][a 2007 Drug Enforcement Administration case]], a keylogger was installed on a suspect’s computer. GnuPG protects your traffic against cryptanalysis, but it is not magic fairy dust that can be sprinkled over your data to make it safe against all threats. ** Should I use PGP/MIME for my emails? :PROPERTIES: :CUSTOM_ID: use_pgpmime :END: Almost certainly. In the past this was a controversial question, but recently there’s come to be a consensus: use PGP/MIME whenever possible. The reason for this is that it’s possible to armor email headers and metadata with PGP/MIME, but sending messages inline leaves this data exposed. As recent years have taught us, the metadata is often as sensitive as the contents of the message. PGP/MIME can protect metadata; inline can’t. However, please be aware that not all mail servers handle PGP/MIME properly. Some mailing lists are incompatible with it (PGP-Basics, for instance). Some mailing list software mangles PGP/MIME (old versions of Mailman, for instance). If you have any problems with PGP/MIME, consider carefully whether you need metadata protection. If you don’t, then fall back to inline. ** What are the best algorithms in GnuPG? :PROPERTIES: :CUSTOM_ID: no_best_algo :END: MD5 and SHA-1 should be avoided if possible, and for bulk encryption it’s best to use Camellia, Twofish, or AES. Beyond that guidance there is no “best algorithm” in GnuPG. It’s sort of like asking whether Godzilla or King Kong is better at terrorizing urban cities: there is no clear-cut winner. This is not to say you shouldn’t have preferences, though. It is only to say that GnuPG’s algorithms are so well-designed for what they do that there is no single “best”. There’s just a lot of personal, subjective choice. ** Why is my DSA key limited to 3072 bits? :PROPERTIES: :CUSTOM_ID: no_dsa4096 :END: The United States’ National Institute of Standards and Technology ([[http://www.nist.gov][NIST]]) is responsible for the DSA specification. NIST has not published a 4096-bit DSA variant, and thus GnuPG doesn’t offer it. ** Why does my DSA-1024 key use a different digest algorithm than my DSA-2048 or DSA-3072 key? :PROPERTIES: :CUSTOM_ID: hash_widths_in_dsa :END: The DSA algorithm has gone through several revisions. GnuPG’s original implementation of DSA supported 1024-bit keys that used either SHA-1 or RIPEMD-160 as hashes. When the United States’ National Institute of Standards and Technology ([[http://www.nist.gov][NIST]]) revised the specification to support 2048- and 3072-bit keys, they also required longer hashes be used. DSA-2048 required a 224-bit hash (SHA-224, or a longer hash cut down to 224 bits), and DSA-3072 required a 256-bit hash (SHA-256, or a longer hash cut down to 256 bits). They also now allowed for stronger hashes to be used for DSA-1024: if they were more than 160 bits, they would simply be cut down. So, depending on how you have GnuPG configured, GnuPG might be forced to use SHA-1 and/or RIPEMD-160 with DSA-1024; GnuPG might be able to use any of the longer SHAs with DSA-1024; GnuPG might use SHA-224, -256, -384 or -512 for DSA-2048; GnuPG might use SHA-256, SHA-384 or SHA-512 for DSA-3072. ** Why can’t I decrypt things I encrypted twenty years ago with PGP 2.6? :PROPERTIES: :CUSTOM_ID: pgp_26 :END: PGP 2.6 was released almost twenty-five years ago and is now completely obsolete. We strongly advise against using PGP 2.6 if you have any choice in the matter. Due to PGP 2.6 being obsolete, GnuPG dropped support for it years ago in the GnuPG 2.0 series. If you absolutely must have PGP 2.6 support, we recommend you use GnuPG's oldest supported version, 1.4, which can still handle PGP 2.6 traffic. We still urge you to migrate your documents to OpenPGP, as we will not be supporting GnuPG 1.4 for much longer. * COMMENT HTML style specifications #+begin_src emacs-lisp (defun org-faq-make-target () "Make hard target for current headline." (interactive) (if (not (org-on-heading-p)) (error "Not on a headline")) (let ((h (org-trim (org-get-heading 'no-tags)))) (if (string-match "[ \t]*\\?\\'" h) (setq h (replace-match "" t t h))) (while (string-match "[ \t]+" h) (setq h (replace-match "-" t t h))) (setq h (downcase h)) (org-entry-put nil "CUSTOM_ID" h))) #+end_src diff --git a/web/faq/gpgme-faq.org b/web/faq/gpgme-faq.org index 814d12c..e991a83 100644 --- a/web/faq/gpgme-faq.org +++ b/web/faq/gpgme-faq.org @@ -1,34 +1,63 @@ #+TITLE: GPGME FAQ --- GnuPG.org * GPGME FAQ GnuPG Made Easy (GPGME) is a library designed to make access to GnuPG easier for applications. It provides a High-Level Crypto API for encryption, decryption, signing, signature verification and key management. * Frequently Asked Questions ** Why does the function =gpgme_data_seek= not work? You probably did not compile the program with largefile support. GPGME is compiled with largefile support by default, so off_t is a 64-bit data type. Because =gpgme_data_seek= uses =off_t= as a parameter type, you have to compile your program with largefile support as well, so that the data types used by GPGME and by your program match. Note that you have to compile your program with largefile support even if you do not use =gpgme_data_seek=, because file descriptors are exchanged between the program and GPGME. The GPGME documentation contains much more information on the subject. See section 2.3 Largefile support of the GPGME Reference Manual. +** Why don't the Python bindings announced in 2016 work? + + The Python bindings have been undergoing continual improvement and + fine tuning since the initial announcement. To obtain the most + accurate bindings it is recommended to install the bindings shipped + with GPGME itself rather than older versions available on PyPI. + + The Python module has been renamed from =pyme= or =pyme3= and is + now simply called =gpg=. Otherwise the function remains similar + and example code is included with the source. + + A basic decryption operation to take an encrypted file and decrypt + it with a key in your secret keys would look something like this: + + #+begin_example + import gpg + + ciphertext = open("filename.txt.asc", "rb") + plaintext = gpg.Context().decrypt(ciphertext) + ciphertext.close() + f = open("filename.txt", "wb") + f.write(plaintext[0]) + f.close() + del plaintext + #+end_example + + # Copyright (C) 2002-2004 Free Software Foundation, Inc. +# Copyright (C) 2006-2018 The GnuPG Project. # # Written by Werner Koch (2006-04-27 12:50:00). +# Ammended by Ben McGinnes (2018-02-14 08:21:32 UTC). diff --git a/web/index.org b/web/index.org index 6cb1d1f..610be3a 100644 --- a/web/index.org +++ b/web/index.org @@ -1,279 +1,144 @@ #+TITLE: The GNU Privacy Guard #+STARTUP: showall #+SETUPFILE: "share/setup.inc" #+GPGWEB-NEED-SWDB #+HTML_HEAD_EXTRA: * The GNU Privacy Guard #+index: GnuPG #+index: GPG #+index: PGP #+index: Gpg4win GnuPG is a complete and free implementation of the OpenPGP standard as defined by [[https://www.ietf.org/rfc/rfc4880.txt][RFC4880]] (also known as /PGP/). GnuPG allows you to encrypt and sign your data and communications; it features a versatile key management system, along with access modules for all kinds of public key directories. GnuPG, also known as /GPG/, is a command line tool with features for easy integration with other applications. A wealth of [[file:software/frontends.html][frontend applications]] and [[file:software/libraries.html][libraries]] are available. GnuPG also provides support for S/MIME and Secure Shell (ssh). Since its introduction in 1997, GnuPG is [[https://www.gnu.org/philosophy/free-sw.html][Free Software]] (meaning that it respects your freedom). It can be freely used, modified and distributed under the terms of the [[https://www.gnu.org/copyleft/gpl.html][GNU General Public License]] . The current version of GnuPG is {{{gnupg22_ver}}}. See the [[file:download/index.org][download]] page for other maintained versions. [[https://www.gpg4win.org][Gpg4win]] is a Windows version of GnuPG featuring a context menu tool, a crypto manager, and an Outlook plugin to send and receive standard PGP/MIME mails. The current version of Gpg4win is {{{gpg4win_ver}}}. * Reconquer your privacy #+begin_quote Arguing that you don't care about the right to privacy because you have nothing to hide is no different from saying you don't care about free speech because you have nothing to say. \ndash\nbsp{}Edward\nbsp{}Snowden #+end_quote Using encryption helps to protect your privacy and the privacy of the people you communicate with. Encryption makes life difficult for bulk surveillance systems. GnuPG is one of the tools that Snowden used to uncover the secrets of the NSA. Please visit the [[https://emailselfdefense.fsf.org][Email Self-Defense]] site to learn how and why you should use GnuPG for your electronic communication. If you need printed leaflets check out [[https://fsfe.org/contribute/spreadtheword.html#gnupg-leaflet][FSFE’s GnuPG leaflet]]. * News #+index: News The latest blog entries: #+begin_html #+end_html The latest release news:\\ ([[file:news.org][all news]]) # For those of you who like reading world’s news with an RSS reader, # GnuPG's latest news are available as [[http://feedvalidator.org/check.cgi?url%3Dhttps://www.gnupg.org/news.en.rss][RSS 2.0 compliant]] feed. Just # point or paste the [[news.en.rss][RSS file]] into your aggregator. +** GnuPG Made Easy 1.11.0 released (2018-04-18) + +[[file:software/gpgme/index.org][GPGME]] is a library that allows to add support for cryptography to a +program. {[[https://lists.gnupg.org/pipermail/gnupg-announce/2018q2/000422.html][more]]} + +** GnuPG 2.2.6 released (2018-04-09) + +We are pleased to announce the availability of GnuPG version 2.2.6. +This is a maintenance release fixing a few problems. {[[https://lists.gnupg.org/pipermail/gnupg-announce/2018q2/000421.html][more]]} + +Update (2018-04-16): In case you run into problems with [[file:software/gpgme/index.org][GPGME]] and this +or a later version of GnuPG, please apply this [[https://lists.gnupg.org/pipermail/gnupg-users/attachments/20180413/e2c8e5d5/attachment-0001.patch][patch]] to GPGME or use +GPGME version 1.11.0 which will soon be released. + +** GnuPG 2.2.5 released (2018-02-22) + +We are pleased to announce the availability of GnuPG version 2.2.5. +This is a maintenance release fixing a few problems. {[[https://lists.gnupg.org/pipermail/gnupg-announce/2018q1/000420.html][more]]} + ** 20 Years of GnuPG (2017-12-20) Exactly 20 years ago the first public version of GnuPG was released under the name "g10". Today we are pleased to announce the availability of GnuPG version 2.2.4. This is a maintenance release fixing a few minor bugs. {[[https://lists.gnupg.org/pipermail/gnupg-announce/2017q4/000419.html][more]]} ** GnuPG Made Easy 1.10.0 released (2017-12-12) [[file:software/gpgme/index.org][GPGME]] is a library that allows to add support for cryptography to a program. {[[https://lists.gnupg.org/pipermail/gnupg-announce/2017q4/000418.html][more]]} ** GnuPG 2.2.3 released (2017-11-21) We are pleased to announce the availability of GnuPG version 2.2.3. This is a maintenance release mainly fixing a bug on Windows. The Windows installer [[https://gpg4win.org][Gpg4win]] 3.0.1 already includes this version of GnuPG. {[[https://lists.gnupg.org/pipermail/gnupg-announce/2017q4/000417.html][more]]} ** GnuPG 2.2.2 released (2017-11-07) We are pleased to announce the availability of GnuPG version 2.2.2. This is a maintenance release fixing a few bugs. {[[https://lists.gnupg.org/pipermail/gnupg-announce/2017q4/000416.html][more]]} ** GnuPG 2.2.1 released (2017-09-19) We are pleased to announce the availability of GnuPG version 2.2.1. This is a maintenance release fixing a few minor bugs. {[[https://lists.gnupg.org/pipermail/gnupg-announce/2017q3/000415.html][more]]} ** Libgcrypt 1.8.1 released (2017-08-31) :important: We are pleased to announce the availability of [[file:software/libgcrypt/index.org][Libgcrypt]] version 1.8.1 and 1.7.9. These releases fix a local side-channel attack on Curve25519 encryption dubbed "May the Fourth be With You" [CVE-2017-0379]. Read {[[https://lists.gnupg.org/pipermail/gnupg-announce/2017q3/000414.html][more]]}... ** GnuPG 2.2.0 released (2017-08-28) The GnuPG team is pleased to announce the availability of a new GnuPG release: version 2.2.0. Read {[[https://lists.gnupg.org/pipermail/gnupg-announce/2017q3/000413.html][more]]} for details. This release marks the start of a new long term support series to replace the 2.0.x series which will reach end-of-life on 2017-12-31. -** GnuPG 2.1.23 released (2017-08-09) - -A new version of GnuPG has been released. Please read the full -[[https://lists.gnupg.org/pipermail/gnupg-announce/2017q3/000412.html][announcement mail]] for details. This version is intended as a release -candidate for 2.2.0 which will mark a new long term stable branch. - -** GnuPG 2.1.22 released (2017-07-28) - -A new version of GnuPG has been released. Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2017q3/000411.html][announcement -mail]] for details. - -Update 2017-07-31: We fixed a problem with keyserver access in the -Windows versions. A fixed installer has been uploaded; the [[../../download/index.org::binary][download]] -section has the links. - -** GnuPG 1.4.22 released (2017-07-19) - -Although GnuPG 1.4 is of limited use today we did a maintenance -release to address the recently published local side channel attack -CVE-2017-7526. See the [[../../download/index.org][download]] section on how to get this version. - -** Libgcrypt 1.8.0 released (2017-07-18) - -We are pleased to announce the availability of [[file:software/libgcrypt/index.org][Libgcrypt]] version -1.8.0. This is a new stable version with full API and ABI -compatibility to the 1.7 series. Its main features are support for -the hash algorithm [[https://en.wikipedia.org/wiki/BLAKE_(hash_function)][Blake-2]], the addition of [[https://en.wikipedia.org/wiki/Disk_encryption_theory][XTS]] mode, an improved -random number generator, and performance improvements for the [[https://en.wikipedia.org/wiki/ARM_architecture][ARM]] -architecture. See the [[https://lists.gnupg.org/pipermail/gnupg-announce/2017q3/000410.html][announcement mail]] for details. - -** Scute 1.5.0 released (2017-07-14) - -Scute is a PKCS#11 module built around the GnuPG Agent and the GnuPG -Smart Card Daemon. It allows you to use your OpenPGP smart card for TLS -client authentication and S/MIME mail and document signing. -Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2017q3/000409.html][announcement mail]] for details. - -** Libgcrypt 1.7.8 released (2017-06-29) :important: - -We are pleased to announce the availability of [[file:software/libgcrypt/index.org][Libgcrypt]] version -1.7.8. This release fixes a local side-channel attack -(CVE-2017-7526). See the [[https://lists.gnupg.org/pipermail/gnupg-announce/2017q2/000408.html][announcement mail]] for details. - -** GnuPG 2.1.21 released (2017-05-15) :important: - -A new version of GnuPG has been released. This release fixes a -pubring.gpg corruption bug introduced with 2.1.20. Read the full -[[https://lists.gnupg.org/pipermail/gnupg-announce/2017q2/000405.html][announcement mail]] for details. - -** GnuPG 2.1.20 released (2017-04-03) - -A new version of GnuPG has been released. Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2017q2/000404.html][announcement -mail]] for details. - -** New installer for GnuPG 2.1.19 (2017-03-28) - -An updated Windows [[https://gnupg.org/ftp/gcrypt/binary/gnupg-w32-2.1.19_20170328.exe][installer]] for GnuPG 2.1.19 is now available. This -installer fixes problems retrieving keys for [[https://posteo.de][Posteo]] accounts and other -servers with limited set of TLS algorithms. - -** GnuPG Made Easy 1.9.0 released (2017-03-28) - -[[file:software/gpgme/index.org][GPGME]] is a library that allows to add support for cryptography to a -program. {[[https://lists.gnupg.org/pipermail/gnupg-announce/2017q1/000403.html][more]]} - - -** GnuPG 2.1.19 released (2017-03-01) - -A new version of GnuPG has been released. Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2017q1/000402.html][announcement -mail]] for details. - -** GnuPG 2.1.18 released (2017-01-23) - -A new version of GnuPG has been released. Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2017q1/000401.html][announcement -mail]] for details. - -** Libgcrypt 1.7.6 released (2017-01-18) - -We are pleased to announce the availability of Libgcrypt version -1.7.6. This is a maintenance release for the stable version of -[[file:software/libgcrypt/index.org][Libgcrypt]] with a few bug fixes. - -** GnuPG 2.1.17 released (2016-12-20) - -A new version of GnuPG has been released. Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2016q4/000400.html][announcement -mail]] for details. - -** Libgcrypt 1.7.5 released (2016-12-15) - -We are pleased to announce the availability of Libgcrypt version -1.7.5. This is a maintenance release for the stable version of -[[file:software/libgcrypt/index.org][Libgcrypt]] with a few bug fixes. [[https://lists.gnupg.org/pipermail/gnupg-announce/2016q4/000399.html][{more}]] - -** Pinentry 1.0.0 released (2016-11-22) - -After 14 years is was time to bump up the version of [[file:software/pinentry/index.org][Pinentry]] to 1.0. -This new release fixes a couple of minor bugs and introduces features -to better diagnose problems. See the [[../../download/index.org::pinentry][download]] section on how to get -Pinentry. - -** GPA 0.9.10 released (2016-11-19) - -A maintenance release of the [[file:software/gpa/index.org][GNU Privacy Assistant]] is now available. -Note that some of the changes are only available when build with the -latest [[file:software/gpgme/index.org][GPGME]] version and used with GnuPG 2.1.16 or later. - -** GnuPG 2.1.16 released (2016-11-18) - -It has been 3 months since the last GnuPG /modern/ release and thus it -was time for a new one: Version 2.1.16 is now available. Read the -full [[https://lists.gnupg.org/pipermail/gnupg-announce/2016q4/000398.html][announcement mail]] for details. - -** GnuPG Made Easy (GPGME) 1.7.0 released (2016-09-21) - -[[file:software/gpgme/index.org][GPGME]] is a library that allows to add support for cryptography to a -program. Highlights in this release are Python and C++ language -bindings as well as support for GnuPG 2.1 features. {[[https://lists.gnupg.org/pipermail/gnupg-announce/2016q3/000397.html][more]]} - -** GnuPG 2.1.15 released (2016-08-18) - -A new version of the /modern/ branch of GnuPG has been released. -Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2016q3/000396.html][announcement mail]] for details. - -** Security fixes for Libgcrypt and GnuPG 1.4 (2016-08-17) :important: - -A bug in the random number generator of Libgcrypt and in GnuPG 1.4 has -been found. Updating the software is highly suggested. Please read -this [[https://lists.gnupg.org/pipermail/gnupg-announce/2016q3/000395.html][mail]] for details. Note that the CVE id in that mail is not -correct, the correct one is CVE-2016-6313. - - -* A big Thanks to all supporters - -Due to this [[http://www.propublica.org/article/the-worlds-email-encryption-software-relies-on-one-guy-who-is-going-broke][ProPublica article]] we received more than 120,000 \euro of -individual donations on a single day. There was even more: The [[https://www.linuxfoundation.org/programs/core-infrastructure-initiative][Core -Infrastructure Initiative]] granted 60,000 $ for 2015. Our payment -service [[https://twitter.com/stripe/status/563449352635432960][Stripe]] and [[https://www.facebook.com/notes/protect-the-graph/supporting-gnu-privacy-guard/1564591893780956][Facebook]] will each give 50,000 $ to the project. -And finally the [[https://www.wauland.de/en/donation.html#61][Wau Holland Stiftung]] is collecting tax deductible -funds for GnuPG (19000 \euro plus 57 BTC). - -As the main author of GnuPG, I like to thank everyone for supporting -the project, be it small or large individual donations, helping users, -providing corporate sponsorship, working on the software, and for all -the encouraging words. - -GnuPG does not stand alone: there are many other projects, often -unknown to most people, which are essential to keep the free Internet -running. Many of them are run by volunteers who spend a lot of unpaid -time on them. They need our support as well. - -/--- Werner, 2015-02-06/ - -(see also this [[https://gnupg.org/blog/20150310-gnupg-in-february.html][blog]] entry) - * COMMENT This is the publishing info used for the GnuPG pages #+begin_src emacs-lisp (progn (setq gpgweb-root-dir (file-name-directory (buffer-file-name))) (setq gpgweb-stage-dir (concat gpgweb-root-dir "../stage")) (require 'gpgweb (concat gpgweb-root-dir "share/gpgweb.el")) (setq org-publish-use-timestamps-flag nil) (setq org-export-html-toplevel-hlevel 1) (setq org-export-html-coding-system 'utf-8) (gpgweb-setup-project)) #+end_src diff --git a/web/mirrors.org b/web/mirrors.org index 99d7727..b3f9df6 100644 --- a/web/mirrors.org +++ b/web/mirrors.org @@ -1,40 +1,39 @@ #+TITLE: GnuPG - WWW Mirrors #+STARTUP: showall #+SETUPFILE: "share/setup.inc" * WWW Mirrors The primary HTTP site [[https://www.gnupg.org/][GnuPG.org]] is mirrored at several sites. Note that some features of this site will not work on the mirrors. If you are seeking mirrors for source or binary packages, please consult the [[https://www.gnupg.org/download/mirrors.html][FTP mirror page]] under the [[download/index.html][Download]] section. | Country | Organisation | Links | Sync | |----------------+-----------------------+-----------+--------| | | | | | |----------------+-----------------------+-----------+--------| | The Americas | | | | |----------------+-----------------------+-----------+--------| | Canada | [[http://www.gnupg.ca/][GnuPG.ca]] | [[http://www.gnupg.ca/][http]] | 2/day | | | [[http://www.raffsoftware.com/][RaffSoftware]] | [[http://gnupg.raffsoftware.com/][http]] | daily | - | | [[http://www.parentinginformed.com/][parentinginformed]] | [[http://gnupg.parentinginformed.com/][http]] | 2/day | | | | | | |----------------+-----------------------+-----------+--------| | Asia | | | | |----------------+-----------------------+-----------+--------| | Korea | [[http://www.snu.ac.kr/][SNU]] | [[http://musicone.snu.ac.kr/webmirror/gnupg/][http]] | weekly | | | | | | |----------------+-----------------------+-----------+--------| | Europe | | | | |----------------+-----------------------+-----------+--------| | Austria | [[http://gd.tuwien.ac.at/][TU Wien]] | [[http://gd.tuwien.ac.at/www.gnupg.org/][http]] | | | Czechia | [[http://www.gnupg.cz/][GnuPG.cz]] | [[http://www.gnupg.cz/][http]] | | | Denmark | [[http://www.gnupg.dk/][GnuPG.dk]] | [[http://www.gnupg.dk/][http]] | | | France | [[http://mirror.cict.fr/][CICT Mirror, Toulouse]] | [[http://gnupg.cict.fr/][http]] | daily | | Hungary | [[http://www.crysys.hu/][CrySyS Lab., Bute]] | [[http://gnupg.mirrors.crysys.hu/][http]] | daily | | Portugal | [[http://5coluna.com][5ª Coluna]] | [[http://mirror.gnupg.pt/][http]] | 2/day | | United Kingdom | [[http://mirror.tje.me.uk/][mirror.tje.me.uk]] | [[http://mirror.tje.me.uk/pub/mirrors/www.gnupg.org/][http]] [[ftp://mirror.tje.me.uk/pub/mirrors/www.gnupg.org][ftp]] | 4/day | | | [[http://www.mirrorservice.org/][UK Mirror Service]] | [[http://www.mirrorservice.org/sites/www.gnupg.org/][http]] | | | | | | | |----------------+-----------------------+-----------+--------| diff --git a/web/news.org b/web/news.org index 5f85932..b78040c 100644 --- a/web/news.org +++ b/web/news.org @@ -1,1659 +1,1790 @@ #+TITLE: GnuPG - All News #+STARTUP: showall * All News On this page you'll find all the news of previous years in reverse chronological order. News for the current year are found at the [[index][main page]]. + +** GnuPG 2.1.23 released (2017-08-09) + +A new version of GnuPG has been released. Please read the full +[[https://lists.gnupg.org/pipermail/gnupg-announce/2017q3/000412.html][announcement mail]] for details. This version is intended as a release +candidate for 2.2.0 which will mark a new long term stable branch. + +** GnuPG 2.1.22 released (2017-07-28) + +A new version of GnuPG has been released. Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2017q3/000411.html][announcement +mail]] for details. + +Update 2017-07-31: We fixed a problem with keyserver access in the +Windows versions. A fixed installer has been uploaded; the [[../../download/index.org::binary][download]] +section has the links. + +** GnuPG 1.4.22 released (2017-07-19) + +Although GnuPG 1.4 is of limited use today we did a maintenance +release to address the recently published local side channel attack +CVE-2017-7526. See the [[../../download/index.org][download]] section on how to get this version. + +** Libgcrypt 1.8.0 released (2017-07-18) + +We are pleased to announce the availability of [[file:software/libgcrypt/index.org][Libgcrypt]] version +1.8.0. This is a new stable version with full API and ABI +compatibility to the 1.7 series. Its main features are support for +the hash algorithm [[https://en.wikipedia.org/wiki/BLAKE_(hash_function)][Blake-2]], the addition of [[https://en.wikipedia.org/wiki/Disk_encryption_theory][XTS]] mode, an improved +random number generator, and performance improvements for the [[https://en.wikipedia.org/wiki/ARM_architecture][ARM]] +architecture. See the [[https://lists.gnupg.org/pipermail/gnupg-announce/2017q3/000410.html][announcement mail]] for details. + +** Scute 1.5.0 released (2017-07-14) + +Scute is a PKCS#11 module built around the GnuPG Agent and the GnuPG +Smart Card Daemon. It allows you to use your OpenPGP smart card for TLS +client authentication and S/MIME mail and document signing. +Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2017q3/000409.html][announcement mail]] for details. + +** Libgcrypt 1.7.8 released (2017-06-29) :important: + +We are pleased to announce the availability of [[file:software/libgcrypt/index.org][Libgcrypt]] version +1.7.8. This release fixes a local side-channel attack +(CVE-2017-7526). See the [[https://lists.gnupg.org/pipermail/gnupg-announce/2017q2/000408.html][announcement mail]] for details. + +** GnuPG 2.1.21 released (2017-05-15) :important: + +A new version of GnuPG has been released. This release fixes a +pubring.gpg corruption bug introduced with 2.1.20. Read the full +[[https://lists.gnupg.org/pipermail/gnupg-announce/2017q2/000405.html][announcement mail]] for details. + +** GnuPG 2.1.20 released (2017-04-03) + +A new version of GnuPG has been released. Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2017q2/000404.html][announcement +mail]] for details. + +** New installer for GnuPG 2.1.19 (2017-03-28) + +An updated Windows [[https://gnupg.org/ftp/gcrypt/binary/gnupg-w32-2.1.19_20170328.exe][installer]] for GnuPG 2.1.19 is now available. This +installer fixes problems retrieving keys for [[https://posteo.de][Posteo]] accounts and other +servers with limited set of TLS algorithms. + +** GnuPG Made Easy 1.9.0 released (2017-03-28) + +[[file:software/gpgme/index.org][GPGME]] is a library that allows to add support for cryptography to a +program. {[[https://lists.gnupg.org/pipermail/gnupg-announce/2017q1/000403.html][more]]} + + +** GnuPG 2.1.19 released (2017-03-01) + +A new version of GnuPG has been released. Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2017q1/000402.html][announcement +mail]] for details. + +** GnuPG 2.1.18 released (2017-01-23) + +A new version of GnuPG has been released. Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2017q1/000401.html][announcement +mail]] for details. + +** Libgcrypt 1.7.6 released (2017-01-18) + +We are pleased to announce the availability of Libgcrypt version +1.7.6. This is a maintenance release for the stable version of +[[file:software/libgcrypt/index.org][Libgcrypt]] with a few bug fixes. + +** GnuPG 2.1.17 released (2016-12-20) + +A new version of GnuPG has been released. Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2016q4/000400.html][announcement +mail]] for details. + +** Libgcrypt 1.7.5 released (2016-12-15) + +We are pleased to announce the availability of Libgcrypt version +1.7.5. This is a maintenance release for the stable version of +[[file:software/libgcrypt/index.org][Libgcrypt]] with a few bug fixes. [[https://lists.gnupg.org/pipermail/gnupg-announce/2016q4/000399.html][{more}]] + +** Pinentry 1.0.0 released (2016-11-22) + +After 14 years is was time to bump up the version of [[file:software/pinentry/index.org][Pinentry]] to 1.0. +This new release fixes a couple of minor bugs and introduces features +to better diagnose problems. See the [[../../download/index.org::pinentry][download]] section on how to get +Pinentry. + +** GPA 0.9.10 released (2016-11-19) + +A maintenance release of the [[file:software/gpa/index.org][GNU Privacy Assistant]] is now available. +Note that some of the changes are only available when build with the +latest [[file:software/gpgme/index.org][GPGME]] version and used with GnuPG 2.1.16 or later. + +** GnuPG 2.1.16 released (2016-11-18) + +It has been 3 months since the last GnuPG /modern/ release and thus it +was time for a new one: Version 2.1.16 is now available. Read the +full [[https://lists.gnupg.org/pipermail/gnupg-announce/2016q4/000398.html][announcement mail]] for details. + +** GnuPG Made Easy (GPGME) 1.7.0 released (2016-09-21) + +[[file:software/gpgme/index.org][GPGME]] is a library that allows to add support for cryptography to a +program. Highlights in this release are Python and C++ language +bindings as well as support for GnuPG 2.1 features. {[[https://lists.gnupg.org/pipermail/gnupg-announce/2016q3/000397.html][more]]} + +** GnuPG 2.1.15 released (2016-08-18) + +A new version of the /modern/ branch of GnuPG has been released. +Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2016q3/000396.html][announcement mail]] for details. + +** Security fixes for Libgcrypt and GnuPG 1.4 (2016-08-17) :important: + +A bug in the random number generator of Libgcrypt and in GnuPG 1.4 has +been found. Updating the software is highly suggested. Please read +this [[https://lists.gnupg.org/pipermail/gnupg-announce/2016q3/000395.html][mail]] for details. Note that the CVE id in that mail is not +correct, the correct one is CVE-2016-6313. + ** GnuPG 2.1.14 released (2016-07-14) A new version of the /modern/ branch of GnuPG has been released. Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2016q3/000393.html][announcement mail]] for details. ** Libgcrypt 1.7.2 released (2016-07-14) We are pleased to announce the availability of Libgcrypt version 1.7.2. This is a maintenance release for the stable version of [[file:software/libgcrypt/index.org][Libgcrypt]] with a few bug fixes. [[https://lists.gnupg.org/pipermail/gnupg-announce/2016q3/000392.html][{more}]] ** GnuPG 2.1.13 released (2016-06-16) A new version of the /modern/ branch of GnuPG has been released. Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2016q2/000390.html][announcement mail]] for details. ** Libgcrypt 1.7.1 released (2016-06-15) We are pleased to announce the availability of Libgcrypt version 1.7.1. This is a maintenance release for the stable version of [[file:software/libgcrypt/index.org][Libgcrypt]] with a few bug fixes. [[https://lists.gnupg.org/pipermail/gnupg-announce/2016q2/000389.html][{more}]] ** First OpenPGP conference (2016-05-20) If you are a user or implementer of OpenPGP related software, you may join us at [[https://gnupg.org/conf/][OpenPGP.conf]] in Cologne on September 8 and 9, 2016. ** GnuPG 2.1.12 released (2016-05-04) A new version of the /modern/ branch of GnuPG has been released. Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2016q2/000387.html][announcement mail]] for details. ** Libgcrypt 1.7.0 released (2016-04-15) We are pleased to announce the availability of Libgcrypt version 1.7.0. This is a new stable version of [[file:software/libgcrypt/index.org][Libgcrypt]] with full API and ABI compatibiliy to the 1.6 series. Its main features are new algorithms, curves, and performance improvements. [[https://lists.gnupg.org/pipermail/gnupg-announce/2016q2/000386.html][{more}]] ** GnuPG 2.0.30 released (2016-03-31) GnuPG 2.0.30 is now available. This release fixes a few minor bugs; users of GnuPG 2.0.x may want to update to this version. [[https://lists.gnupg.org/pipermail/gnupg-announce/2016q1/000385.html][{more}]] ** Libgcrypt 1.6.5 released (2016-02-09) :important: Libgcrypt version 1.6.5 and an updated Windows installer for GnuPG 2.1.11 has been released to mitigate a new side-channel attack. [[https://lists.gnupg.org/pipermail/gnupg-announce/2016q1/000384.html][{more}]] ** GnuPG 2.1.11 released (2016-01-26) A new version of the /modern/ branch of GnuPG has been released. Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2016q1/000383.html][announcement mail]] for details. ** GnuPG 1.4.20 released (2015-12-20) 18 years after the first GnuPG release version 1.4.20 has been released today. This release from the /classic/ branch of GnuPG now also rejects the insecure MD5 signatures created by PGP-2 (unless the =--pgp2= option is used). [[https://lists.gnupg.org/pipermail/gnupg-announce/2015q4/000382.html][{more}]] ** GnuPG 2.1.10 released (2015-12-04) A new version of the /modern/ branch of GnuPG has been released. The main features of this release are support for [[https://en.wikipedia.org/wiki/Trust_on_first_use][TOFU]] and anonymous key retrieval via [[https://www.torproject.org][Tor]]. Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2015q4/000381.html][announcement mail]] for details. ** GnuPG 2.1.9 released (2015-10-09) A new version of the /modern/ branch of GnuPG has been released. Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2015q4/000380.html][announcement mail]] for details. ** GnuPG 2.1.8 released (2015-09-10) A new version of the /modern/ branch of GnuPG has been released. Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2015q3/000379.html][announcement mail]] for details. ** GPA 0.9.9 released (2015-09-09) A new version of [[file:software/gpa/index.org][GPA]], the graphical frontend for GnuPG, is now available. This release fixes a couple of bugs and has been changed to show the clipboard view on startup. [[https://lists.gnupg.org/pipermail/gnupg-announce/2015q3/000378.html][{more}]] ** GnuPG 2.0.29 released (2015-09-08) GnuPG 2.0.29 is now available. This release fixes a couple of bugs; users of GnuPG 2.0.x may want to update to this version. [[https://lists.gnupg.org/pipermail/gnupg-announce/2015q3/000376.html][{more}]] ** Libgcrypt 1.6.4 released (2015-09-08) Libgcrypt version 1.6.4 has been released to fix a few minor bugs and a crash on newer Windows versions. [[https://lists.gnupg.org/pipermail/gnupg-announce/2015q3/000375.html][{more}]] ** Libassuan 2.3.0 released (2015-08-28) [[file:software/libassuan/index.org][Libassuan]] is a generic [[https://en.wikipedia.org/wiki/Inter-process_communication][IPC]] library used by GnuPG, GPGME, and a few other packages. This release fixes two bugs and introduces new support functions for the socket wrappers. See [[https://lists.gnupg.org/pipermail/gnupg-announce/2015q3/000374.html][here]] for details. ** GPGME 1.6.0 and Libgpg-error 1.20 released (2015-08-26) GPGME 1.6.0 is now available. This release introduce a mode to export sceret keys, improves the error return codes, and is prepared to make use of the GnuPG 2.1 Windows installer. See this full [[https://lists.gnupg.org/pipermail/gnupg-announce/2015q3/000372.html][announcement]]. An update of Libgpg-error to fix a problem in Windows has also been released; see this [[https://lists.gnupg.org/pipermail/gnupg-announce/2015q3/000373.html][announcement]]. ** GnuPG 2.1.7 released (2015-08-11) A new version of the /modern/ branch of GnuPG has been released. Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2015q3/000371.html][announcement mail]] for details. ** GnuPG 2.1.6 released (2015-07-01) A new version of the /modern/ branch of GnuPG has been released. Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2015q3/000370.html][announcement mail]] for details. ** GnuPG 2.1.5 released (2015-06-11) A new version of the /modern/ branch of GnuPG has been released. Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2015q2/000369.html][announcement mail]] for details. ** GPGME 1.5.5 released (2015-06-08) GPGME 1.5.5 is now available. This release fixes a crash due to malformed user ids and a regression when gpgsm < 2.1 is used. See the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2015q2/000368.html][{announcement}]] mail. ** GnuPG 2.0.28 released (2015-06-02) GnuPG 2.0.28 is now available. This release fixes a couple of bugs; users of GnuPG 2.0.x should update to this version. [[https://lists.gnupg.org/pipermail/gnupg-announce/2015q2/000367.html][{more}]] ** GnuPG 2.1.4 released (2015-05-12) A new version of the /modern/ branch of GnuPG has been released. Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2015q2/000366.html][announcement mail]] for details. ** GnuPG 2.1.3 released (2015-04-11) This is another release of the /modern/ branch of GnuPG. It fixes a lot of bugs. Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2015q2/000365.html][announcement mail]]. ** GnuPG 1.4.19 released (2015-02-27) :important: GnuPG 1.4.19 is now available. This release mitigates two new of side channel attack methods as well as a couple of other bugs. [[https://lists.gnupg.org/pipermail/gnupg-announce/2015q1/000363.html][{more}]] ** Libgcrypt 1.6.3 released (2015-02-27) :important: Libgcrypt version 1.6.3 has been released to mitigate two new side channel attack methods. [[https://lists.gnupg.org/pipermail/gnupg-announce/2015q1/000364.html][{more}]] ** GnuPG 2.0.27 released (2015-02-18) GnuPG 2.0.27 is now available. This release fixes a couple of bugs; users of GnuPG 2.0.x should update to this version. [[https://lists.gnupg.org/pipermail/gnupg-announce/2015q1/000362.html][{more}]] ** GnuPG 2.1.2 released (2015-02-11) This is the third release of the /modern/ branch of GnuPG. It fixes a lot of bugs. Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2015q1/000361.html][announcement mail]]. ** GnuPG 2.1.1 released (2014-12-16) This is the second release of the /modern/ branch of GnuPG. It fixes a lot of bugs and brings some new features. Read more about 2.1 at the [[file:faq/whats-new-in-2.1.org][feature overview]] page and in the [[https://lists.gnupg.org/pipermail/gnupg-announce/2014q4/000360.html][announcement]] mail. ** Libksba 1.3.2 released (2014-11-25) :important: This is a security fix release and all users of Libksba should update to this version. Note that *GnuPG 2.x* makes use of Libksba and thus all user of GnuPG 2.x need to install this new version of Libksba and restart the dirmngr process. Read the full [[https://lists.gnupg.org/pipermail/gnupg-announce/2014q4/000359.html][announcement]]. ** GnuPG 2.1.0 with ECC support released (2014-11-06) This is the first release of the new /modern/ branch of GnuPG. It features a lot of new things including support for ECC. Read more at the [[file:faq/whats-new-in-2.1.org][feature overview]] page and in the [[https://lists.gnupg.org/pipermail/gnupg-announce/2014q4/000358.html][announcement]] mail. ** A beta for GnuPG 2.1.0 released (2014-10-03) A beta release for the forthcoming GnuPG 2.1 version is now available. [[https://lists.gnupg.org/pipermail/gnupg-announce/2014q4/000357.html][{more}]] ** GPA 0.95 released GPA is the GNU Privacy Assistant, a frontend to GnuPG. This new release has support for ECC keys and improves on the UI server feature. [[https://lists.gnupg.org/pipermail/gnupg-announce/2014q3/000356.html][{more}]] ** GnuPG 2.0.26 released (2014-08-12) GnuPG 2.0.26 is now available. This is a maintenance release. [[https://lists.gnupg.org/pipermail/gnupg-announce/2014q3/000353.html][{more}]] ** Libgcrypt 1.5.4 security fix release :important: Using any Libgcrypt version less than 1.5.4 with GnuPG 2.0.x and Elgamal encryption keys is vulnerable to the /Get Your Hands Off My Laptop/ attack. Please update to the newly released Libgcrypt 1.5.4 or a 1.6 version. [[https://lists.gnupg.org/pipermail/gnupg-announce/2014q3/000352.html][{more}]] ** Get Your Hands Off My Laptop (2014-08-07) Daniel Genkin, Itamar Pipman, and Eran Tromer latest side channel attack targets an /older version/ of GnuPG. If your GnuPG and Libgcrypt versions are up-to-date you are safe. [[https://lists.gnupg.org/pipermail/gnupg-announce/2014q3/000349.html][{more}]] ** GPGME 1.5.1 and 1.4.4 released (2014-08-07) :important: A security fix release for the GPGME library is available. It is suggested to update to one of these version. [[https://lists.gnupg.org/pipermail/gnupg-announce/2014q3/000350.html][{more}]] ** GnuPG 2.0.25 and 1.4.18 released (2014-06-30) To fix a minor regression in the previous releases we released today new versions of GnuPG-1 and GnuPG-2: [[https://lists.gnupg.org/pipermail/gnupg-announce/2014q2/000346.html][{2.0.25}]], [[https://lists.gnupg.org/pipermail/gnupg-announce/2014q2/000347.html][{1.4.18}]] ** GnuPG 2.0.24 released (2014-06-24) :important: GnuPG 2.0.24 is now available. This GnuPG-2 release features a fix for a denial of service attack and a few other changes. [[https://lists.gnupg.org/pipermail/gnupg-announce/2014q2/000345.html][{more}]] ** GnuPG 1.4.17 released (2014-06-23) :important: GnuPG 1.4.17 is now available. This GnuPG-1 release features a fix for a denial of service attack and a few other minor changes. [[https://lists.gnupg.org/pipermail/gnupg-announce/2014q2/000344.html][{more}]] ** GnuPG 2.0.23 released (2014-06-03) We are pleased to announce the availability of GnuPG 2.0.23. This is a maintenance release with a few new features. [[https://lists.gnupg.org/pipermail/gnupg-announce/2014q2/000342.html][{more}]] ** Goteo campaign: preliminary results (2014-05-12) The blog has a report on the current status of the campaign including an overview of the financial results. [[https://www.gnupg.org/blog/20140512-rewards-sent.html][{read here}]] ** Mission complete: campaign ends, closing stats (2014-02-06) After 50 days of crowdfunding, the GnuPG campaign for new website and infrastructure will close tomorrow. That means rewards for backers can now be ordered and preparations for dispatch can begin. Here are the results so far. [[https://www.gnupg.org/blog/20140206-crowdfunding-complete.html][{more}]] ** 16 Years of protecting privacy (2013-12-20) Today marks 16 years since the first release of GnuPG. In that time the project has grown from being a hacker’s hobby into one of the world’s most critical anti-surveillance tools. Today GnuPG stands at the front line of the battle between invasive surveillance and civil liberties. [[https://www.gnupg.org/blog/20131220-gnupg-turned-0x10.html][{more}]] ** GnuPG launches crowdfunding campaign (2013-12-19) Today GNU Privacy Guard (GnuPG) has launched its first [[http://goteo.org/project/gnupg-new-website-and-infrastructure][crowdfunding campaign]] with the aim of building a new website and long term infrastructure. [[https://lists.gnupg.org/pipermail/gnupg-announce/2013q4/000338.html][{more}]] [[https://www.gnupg.org/blog/20131219-gnupg-launches-crowfunding.de.html][{deutsch}]] [[https://www.gnupg.org/blog/20131219-gnupg-launches-crowfunding.fr.html][{francaise}]] ** GnuPG 1.4.16 released (2013-12-18) :important: Along with the publication of an interesting new [[http://www.cs.tau.ac.il/~tromer/acoustic/][side channel attack]] by Genkin, Shamir, and Tromer we announce the availability of a new stable GnuPG release to relieve this bug: Version 1.4.16 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2013q4/000337.html][{more}]] ** Blog: Getting Goteo crowdfunding approval (2013-12-18) The targets are set, the rewards are prepared, the press release has been edited and translated, and now we're waiting for approval from the crowdfunding platform Goteo ... [[https://www.gnupg.org/blog/20131218-getting-goteo-approval.html][{more}]] ** GnuPG 1.4.16 released (2013-12-18) :important: Along with the publication of an interesting new [[http://www.cs.tau.ac.il/~tromer/acoustic/][side channel attack]] by Genkin, Shamir, and Tromer we announce the availability of a new stable GnuPG release to relieve this bug: Version 1.4.16 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2013q4/000337.html][{more}]] ** Libgcrypt 1.6.0 released (2013-10-16) The GNU project is pleased to announce the availability of Libgcrypt version 1.6.0. This is the new stable version of Libgcrypt with the API being mostly compatible to previous versions. Due to the removal of certain long deprecated functions this version introduces an ABI change. The main features of this version are performance improvements, better support for elliptic curves, new algorithms and modes, as well as API and internal cleanups. [[https://lists.gnupg.org/pipermail/gnupg-announce/2013q4/000336.html][{more}]] ** Blog: Preparing for launch (2013-12-13) Mid December, giving season, and nearly time for the GnuPG Crowdfunding to commence. We've been working hard on preparations ... [[https://www.gnupg.org/blog/index.html][{more}]] ** Blog: Friends tell friends they love GnuPG (2013-11-13) Using GnuPG for email encryption takes two to tango. That's why we're asking users to share their stories using #iloveGPG ... [[https://www.gnupg.org/blog/index.html][{more}]] ** New website infrastructure (2013-11-12) After more than a decade we switched from the legacy WML based website system to a new [[http://org-mode.org][org-mode]] based one. The old WML code was not anymore maintainable and building the website took way to long. The new system uses plain text files and will make it way easier to keep information up to date. Unfortunately the translations are gone for now --- most of them have not been updated for many years anyway. ** Blog: Securing the future of GPG (2013-11-05) We have a plan for securing the long term stability of GnuPG development by giving more to our users, and asking more from them in return ... [[https://www.gnupg.org/blog/index.html][{more}]] ** Security update for GnuPG (2013-10-05) :important: We are pleased to announce the availability of a new stable GnuPG release: Version 2.0.22 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2013q4/000333.html][{more}]] ** Security update for GnuPG (2013-10-05) :important: We are pleased to announce the availability of a new stable GnuPG release: Version 1.4.15 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2013q4/000334.html][{more}]] ** GnuPG 2.0.21 released (2013-08-19) We are pleased to announce the availability of GnuPG 2.0.21. ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2013q3/000332.html][{more}]] ** Security update for GnuPG (2013-07-25) :important: We are pleased to announce the availability of a new stable GnuPG release: Version 1.4.14 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2013q3/000329.html][{more}]] ** Security update for Libgcrypt (2013-07-25) :important: We are pleased to announce the availability of a new stable Libgcrypt release: Version 1.5.3 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2013q3/000329.html][{more}]] ** GnuPG 2.0.20 released (2013-05-10 18:59:01) We are pleased to announce the availability of GnuPG 2.0.20. ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2013q2/000328.html][{more}]] ** GnuPG 1.4.13 released (2012-12-20 21:51:56) We are pleased to announce the availability of a new stable GnuPG release: Version 1.4.13 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2012q4/000319.html][{more}]] ** GnuPG 2.0.19 released (2012-03-27 11:22:13) We are pleased to announce the availability of GnuPG 2.0.19. ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2012q1/000314.html][{more}]] ** GnuPG 1.4.12 released (2012-01-30 17:39:22) We are pleased to announce the availability of a new stable GnuPG release: Version 1.4.12 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2012q1/000313.html][{more}]] ** GnuPG 1.4.13 released (2012-12-20 21:51:56) Wir freuen uns, Ihnen die Verfügbarkeit von GnuPG 1.4.13 bekannt zu geben. [[https://lists.gnupg.org/pipermail/gnupg-announce/2012q4/000319.html][{more}]] ** GnuPG 2.0.19 released (2012-03-27 11:22:13) We are pleased to announce the availability of GnuPG 2.0.19. ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2012q1/000314.html][{more}]] ** GnuPG 1.4.12 released (2012-01-30 17:39:22) We are pleased to announce the availability of a new stable GnuPG release: Version 1.4.12. ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2012q1/000313.html][{more}]] ** STEED project announced (2011-10-17 20:15:22) STEED - Usable end-to-end encryption ... [[https://lists.gnupg.org/pipermail/gnupg-devel/2011-October/026264.html][{more}]] ** GnuPG 2.0.18 released (2011-08-04 18:19:36) We are pleased to announce the availability of GnuPG 2.0.18. ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2011q3/000312.html][{more}]] ** Libgcrypt 1.5.0 released (2011-06-29 12:21:39) We are pleased to announce the availability of Libgcrypt 1.5.0. This is the new stable version of Libgcrypt and upward compatible with the 1.4 series. ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2011q2/000307.html][{more}]] ** GnuPG 2.0.17 released (2011-01-13 17:20:12) We are pleased to announce the availability of GnuPG 2.0.17. ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2011q1/000305.html][{more}]] ** GnuPG 1.4.11 released (2010-10-18 13:36:14) We are pleased to announce the availability of a new stable GnuPG release: Version 1.4.11 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2010q4/000303.html][{more}]] ** Important security update for GnuPG (2010-07-23 14:38:50) While trying to import a server certificate for a CDN service, a segv bug was found in GnuPG's GPGSM tool. It is likely that this bug is exploitable by sending a special crafted signed message and having a user verify the signature. A simple patch is available ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2010q3/000302.html][{more}]] ** GnuPG 2.0.16 released (2010-07-19 10:44:59) We are pleased to announce the availability of GnuPG 2.0.16. ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2010q3/000301.html][{more}]] ** GnuPG 2.0.15 released (2010-03-09 11:44:13) We are pleased to announce the availability of GnuPG 2.0.15. ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2010q1/000299.html][{more}]] ** GnuPG 2.0.14 released (2009-12-21 19:03:26) We are pleased to announce the availability of GnuPG 2.0.14. ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2009q4/000296.html][{more}]] ** Libgcrypt 1.4.5 released (2009-12-11 17:51:12) We are pleased to announce the availability of Libgcrypt 1.4.5. This is the new stable version of Libgcrypt and upward compatible with the 1.2 series. ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2009q4/000295.html][{more}]] ** GnuPG 2.0.13 released (2009-09-04 19:12:01) We are pleased to announce the availability of GnuPG 2.0.13. ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2009q3/000294.html][{more}]] ** GnuPG 1.4.10 released (2009-09-02 19:27:55) We are pleased to announce the availability of a new stable GnuPG release: Version 1.4.10 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2009q3/000291.html][{more}]] ** GnuPG 2.0.12 released (2009-06-17 13:19:26) We are pleased to announce the availability of GnuPG 2.0.12. ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2009q2/000288.html][{more}]] ** GnuPG 2.0.11 released (2009-03-03 13:02:51) We are pleased to announce the availability of GnuPG 2.0.11 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2009q1/000287.html][{more}]] ** Libgcrypt 1.4.4 released (2009-01-22 20:08:24) We are pleased to announce the availability of Libgcrypt 1.4.4. This is the new stable version of Libgcrypt and upward compatible with the 1.2 series. ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2009q1/000285.html][{more}]] ** GnuPG 2.0.10 released (2009-01-12 10:59:05) We are pleased to announce the availability of GnuPG 2.0.10 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2009q1/000284.html][{more}]] ** Signing key updated! (2009-01-09 12:58:02) The expiration date of the key used to sign GnuPG distributions has been prolonged for another year. Please update the key ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2009q1/000282.html][{more}]] ** GnuPG's 10th birthday! (2007-12-20 12:10:30) It has been a decade since the very first version of the GNU Privacy Guard was released ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2007q4/000268.html][{more}]] ** GnuPG 2.0.8 released (2007-12-20 12:09:30) We are pleased to announce the availability of GnuPG 2.0.8 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2007q4/000267.html][{more}]] ** GnuPG 1.4.8 released (2007-12-20 12:09:03) We are pleased to announce the availability of a new stable GnuPG release: Version 1.4.8. ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2007q4/000266.html][{more}]] ** Libgcrypt 1.4.0 released (2007-12-10 20:10:34) We are pleased to announce the availability of Libgcrypt 1.4.0. This is the new stable version of Libgcrypt and upward compatible with the 1.2 series. ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2007q4/000263.html][{more}]] ** New OpenPGP standard (2007-11-02 17:54:26) The new OpenPGP standard has been published. It was assigned RFC number 4880. ... [[https://lists.gnupg.org/pipermail/gnupg-users/2007-November/031994.html][{more}]] ** GnuPG 2.0.7 released (2007-09-10 19:18) We are pleased to announce the availability of GnuPG 2.0.7 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2007q3/000259.html][{more}]] ** GnuPG 2.0.6 released (2007-08-16 17:48) We are pleased to announce the availability of GnuPG 2.0.6 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2007q3/000258.html][{more}]] ** GnuPG 2.0.5 released (2007-07-06 12:46) We are pleased to announce the availability of GnuPG 2.0.5 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2007q3/000255.html][{more}]] ** Manual pages online (2007-05-11 11:45:30) The manuals of GnuPG and some related software are now available online. Check out the navigation bar or go directly to the [[https://www.gnupg.org/documentation/manuals.html][overview page]] . ** GnuPG 2.0.4 released (2007-05-09 13:02) We are pleased to announce the availability of GnuPG 2.0.4 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2007q2/000254.html][{more}]] ** GnuPG 2.0.3 released (2007-03-08 16:55:25) We are pleased to announce the availability of GnuPG 2.0.3 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2007q1/000252.html][{more}]] ** Multiple Messages Problem in GnuPG and GPGME (2007-03-06 09:31:21) A common usage problem of gpg has been identified. Instead of requiring a fix for all these applications, GnuPG and GPGME have been changed to provide the necessary protection. ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2007q1/000251.html][{more}]] ** Important security update for GnuPG(2006-12-06 17:18:35) Tavis Ormandy of the Gentoo security team identified a severe and exploitable bug in the processing of encrypted packets in GnuPG. Updating is highly suggested. A new version of GnuPG (1.4.6) as well has a patch to 2.0.1 has been released. ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2006q4/000246.html][{more}]] ** Announcing the winner of the logo contest (2006-12-02 19:37:04) And the winner is: Thomas Wittek ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2006q4/000244.html][{more}]] ** GnuPG 2.0.1 released (2006-11-29 15:14:13) We are pleased to announce the availability of GnuPG 2.0.1 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2006q4/000242.html][{more}]] ** Dirmngr 1.0.0 released (2006-11-29 15:14:13) We are pleased to announce the availability of Dirmngr 1.0.0 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2006q4/000243.html][{more}]] ** GnuPG 2.0 released (2006-11-13 12:43:16) We are pleased to announce the availability of GnuPG 2.0.0 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2006q4/000239.html][{more}]] ** GnuPG 1.9.92 released (2006-10-11 13:43:29) We are pleased to announce the availability of GnuPG 1.9.92 - one of the last steps towards a 2.0 release. ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2006q4/000236.html][{more}]] ** GnuPG Logo contest (2006-09-19 14:43:08) After 8 years the time has come to modernize the GnuPG Logo and to work on a new layout of the website ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2006q3/000235.html][{more}]] ** Gpg4win 1.0.6 released (2006-08-29 09:52:50) We are pleased to announce the availibility of Gpg4win, version 1.0.6 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2006q3/000232.html][{more}]] ** Libgcrypt 1.2.3 released (2006-08-29 09:49:39) We are pleased to announce the availability of Libgcrypt 1.2.3. Since this is a bugfix release, it does not include any new features... [[https://lists.gnupg.org/pipermail/gnupg-announce/2006q3/000231.html][{more}]] ** GnuPG 1.4.5 released (2006-08-01 17:42:11) We are pleased to announce the availability of a new stable GnuPG release: Version 1.4.5 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2006q3/000229.html][{more}]] ** GnuPG 1.4.4 released (2006-06-25 15:57:40) We are pleased to announce the availability of a new stable GnuPG release: Version 1.4.4 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2006q2/000226.html][{more}]] ** Gpg4win 1.0.1 released (2006-04-26 13:29:58) We are pleased to announce the availibility of Gpg4win, version 1.0.1 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2006q2/000224.html][{more}]] ** Gpg4win released (2006-04-03 14:28:36) After struggling for 6 month with Windows pecularities, we are finally pleased to announce the first stable release of Gpg4win, version 1.0.0... [[https://lists.gnupg.org/pipermail/gnupg-announce/2006q2/000223.html][{more}]] ** GnuPG 1.4.3 released (2006-04-03 14:28:36) We are pleased to announce the availability of a new stable GnuPG release: Version 1.4.3 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2006q2/000222.html][{more}]] ** GnuPG does not detect injection of unsigned data (2006-03-09 20:02:28) In the aftermath of the false positive signature verification bug more thorough testing of the fix has been done and another vulnerability has been detected. This new problem affects the use of gpg for verification of signatures which are not detached signatures. The problem also affects verification of signatures embedded in encrypted messages; i.e. standard use of gpg for mails. Update GnuPG as soon as possible to version 1.4.2.2! [[https://lists.gnupg.org/pipermail/gnupg-announce/2006q1/000216.html][{more}]] ** False positive signature verification in GnuPG (2006-02-15 12:43:54) The Gentoo project identified a security related bug in GnuPG. When using any current version of GnuPG for unattended signature verification (e.g. by scripts and mail programs), false positive signature verification of detached signatures may occur. This problem affects the tool *gpgv*, as well as using "gpg --verify" to imitate gpgv, if only the exit code of the process is used to decide whether a detached signature is valid. [[https://lists.gnupg.org/pipermail/gnupg-announce/2006q1/000211.html][{more}]] ** GnuPG 1.9.20 (S/MIME and gpg-agent) released (2005-12-20 12:56:31) We are pleased to announce the availability of GnuPG 1.9.20 - the branch of GnuPG featuring the S/MIME... [[https://lists.gnupg.org/pipermail/gnupg-announce/2005q4/000209.html][{more}]] ** Libgcrypt 1.2.2 released (2005-10-05 15:34:42) We are pleased to announce the availability of Libgcrypt 1.2.2. Since this is a bugfix release, it does not include any new features... [[https://lists.gnupg.org/pipermail/gnupg-announce/2005q4/000205.html][{more}]] ** GnuPG 1.9.19 (S/MIME and gpg-agent) released (2005-09-12 15:29:20) We are pleased to announce the availability of GnuPG 1.9.19 - the branch of GnuPG featuring the S/MIME... [[https://lists.gnupg.org/pipermail/gnupg-announce/2005q3/000204.html][{more}]] ** GnuPG Explorer Extension (GPGee) version 1.2.1 released (2005-09-08 14:41:58) Version 1.2.1 of GPGee has now been released and is available at... [[https://lists.gnupg.org/pipermail/gnupg-announce/2005q3/000203.html][{more}]] ** GnuPG Explorer Extension (GPGee) version 1.2.0 released (2005-09-06 16:09:57) Version 1.2.0 of GPGee has been released - head to the homepage at... [[https://lists.gnupg.org/pipermail/gnupg-announce/2005q3/000202.html][{more}]] ** GPGee version 1.1.2 - Important Security Update (2005-07-30 00:29:18) Version 1.1.2 of GPGee has been released. This release fixes a newly identified security issue... [[https://lists.gnupg.org/pipermail/gnupg-announce/2005q3/000201.html][{more}]] ** GnuPG 1.4.2 released (2005-07-27 09:53:27) We are pleased to announce the availability of a new stable GnuPG release: Version 1.4.2 ... [[https://lists.gnupg.org/pipermail/gnupg-announce/2005q3/000200.html][{more}]] ** GPGee (GnuPG Explorer Extension) version 1.1.1 (2005-07-18 04:58:16) I have released version 1.1.1 of GPGee. This is a minor update to 1.1 to answer a couple user... [[https://lists.gnupg.org/pipermail/gnupg-announce/2005q3/000199.html][{more}]] ** Second release candidate for GnuPG 1.4.2 available (2005-06-21 16:44:35 CET) We are pleased to announce the availability of another release candidate for the forthcoming 1.4.2 version of gnupg... [[https://lists.gnupg.org/pipermail/gnupg-announce/2005q2/000198.html][{more}]] ** GnuPG 1.9.17 (S/MIME and gpg-agent) released (2005-06-20 21:58:24 CET) We are pleased to announce the availability of GnuPG 1.9.17; the development branch of GnuPG featuring the S/MIME protocol... [[https://lists.gnupg.org/pipermail/gnupg-announce/2005q2/000196.html][{more}]] ** First release candidate for GnuPG 1.4.2 available (2005-05-31 14:27:33 CET) We are pleased to announce the availability of a release candidate for the forthcoming 1.4.2 version of gnupg... [[https://lists.gnupg.org/pipermail/gnupg-announce/2005q2/000195.html][{more}]] ** GnuPG 1.9.16 (S/MIME) released (2005-04-21 17:23:56 CET) We are pleased to announce the availability of GnuPG 1.9.16; the development branch of GnuPG featuring the S/MIME protocol... [[https://lists.gnupg.org/pipermail/gnupg-announce/2005q2/000194.html][{more}]] ** GnuPG 1.4.1 News (2005-03-15 17:53:36 CET) We are pleased to announce the availability of a new stable GnuPG release: Version 1.4.1... [[https://lists.gnupg.org/pipermail/gnupg-announce/2005q2/000192.html][{more}]] ** Smartcard daemon and gpg's S/MIME cousin gpgsm (2005-02-23 12:43:27 CET) The design is different to the previous versions and we may not support all ancient... [[https://lists.gnupg.org/pipermail/gnupg-announce/2005q2/000177.html][{more}]] ** Attack against OpenPGP encryption (2005-02-11 02:00:17 CET) Last night, Serge Mister and Robert Zuccherato published a paper reporting on an attack against OpenPGP symmetric encryption... [[https://lists.gnupg.org/pipermail/gnupg-announce/2005q1/000191.html][{more}]] ** Libgcrypt 1.2.1 released (2005-01-09 15:03:22 CET) We are pleased to announce the availability of Libgcrypt 1.2.1. Since this is a bugfix release, it does not include any new features... [[https://lists.gnupg.org/pipermail/gnupg-announce/2005q1/000189.html][{more}]] ** GnuPG 1.2.7 released (2004-12-28 11:54:32 CET) As promised in the announcement of GnuPG 1.4.0, we are now pleased to announce the availability GnuPG 1.2.7... [[https://lists.gnupg.org/pipermail/gnupg-announce/2004q4/000188.html][{more}]] ** Updated GnuPG 1.4.0 Windows binary (2004-12-16 22:17:10 CET) A couple of hours ago we announced GnuPG 1.4.0, claiming that a compiled version for MS Windows is also available. Unfortunately that Windows version... [[https://lists.gnupg.org/pipermail/gnupg-announce/2004q4/000187.html][{more}]] ** GnuPG stable 1.4 released (2004-12-16 18:24:48 CET) We are pleased to announce the availability of the new stable GnuPG series. This first release is version 1.4.0... [[https://lists.gnupg.org/pipermail/gnupg-announce/2004q4/000186.html][{more}]] ** GnuPG 1.3.93 released (2004-12-14 11:06:45 CET) The latest and hopefully last release candidate for GnuPG 1.4 is ready for public consumption. We strongly encourage people to try this release candidate... [[https://lists.gnupg.org/pipermail/gnupg-announce/2004q4/000185.html][{more}]] ** sha1sum for MS Windows released (2004-12-09 17:16:22 CET) In the light of the recently found weaknesses in the MD5 hash function we won't anymore accompany software announcements with MD5 checksums. Instead SHA-1 checksums will be given... [[https://lists.gnupg.org/pipermail/gnupg-announce/2004q4/000184.html][{more}]] ** News available as in RSS 2.0 format (2004-11-25 22:49:58 CET) As of today, the latest ten news from GnuPG's are available as RSS 2.0 compliant feed. Just point or paste the [[news.en.rss][RSS file]] into your aggregator. ** GnuPG 1.3.92 released (development) (2004-10-28 14:30:58 CEST) The latest release from the development branch of GnuPG is ready for public consumption. This is a branch to create what will extremely soon become the new stable release of... [[https://lists.gnupg.org/pipermail/gnupg-announce/2004q4/000183.html][{more}]] ** GPGME 1.0.1 released (2004-10-22 21:27:47 CEST) We are pleased to announce version 1.0.1 of GnuPG Made Easy, a library designed to make access to GnuPG easier for... [[https://lists.gnupg.org/pipermail/gnupg-announce/2004q4/000181.html][{more}]] ** GnuPG 1.3.91 released (development) (2004-10-16 14:46:21 CEST) The latest release from the development branch of GnuPG is ready for public consumption. This is a branch to create what will extremely soon become the new stable release of... [[https://lists.gnupg.org/pipermail/gnupg-announce/2004q4/000180.html][{more}]] ** Building GnuPG for Win32 using MinGW (2004-10-12) A new link to Carlo Luciano Bianco's page has been added under the [[download/index][download section]] . The detailed document is dedicated to Windows users and explains how to build GnuPG using MinGW. ** GnuPG Subkeys MiniHOWTO (2004-10-11) With GnuPG and the possibility of having multiple subkeys, you can have only one key, but still retain the security feature that you do not have to revoke your primary key (and lose all signatures on it) if the key at the office is compromised... [[documentation/howtos.en.html#GnuPG-Subkeys][{more}]] ** GnuPG 1.3.90 released (development) (2004-10-02 15:47:23 CEST) The latest release from the development branch of GnuPG is ready for public consumption. This is a branch to create what will... [[https://lists.gnupg.org/pipermail/gnupg-announce/2004q4/000179.html][{more}]] ** GPGME 1.0.0 released (2004-09-30 18:07:54 CEST) We are pleased to announce version 1.0.0 of GnuPG Made Easy, a library designed to make access to GnuPG easier for... [[https://lists.gnupg.org/pipermail/gnupg-announce/2004q3/000178.html][{more}]] ** GnuPG 1.2.6 released (2004-08-26 12:07:34 CEST) We are pleased to announce the availability of a new stable GnuPG release: Version 1.2.6. The GNU Privacy Guard (GnuPG) is... [[https://lists.gnupg.org/pipermail/gnupg-announce/2004q3/000176.html][{more}]] ** GnuPG 1.2.5 build instruction update (2004-07-27) Due to a problem with the gettext installation on the build machine a little annoying bug will disturb... [[https://lists.gnupg.org/pipermail/gnupg-announce/2004q3/000173.html][{more}]] ** GnuPG 1.2.5 released (2004-07-27) We are pleased to announce the availability of a new stable GnuPG release: Version 1.2.5. The GNU Privacy Guard (GnuPG) is... [[https://lists.gnupg.org/pipermail/gnupg-announce/2004q3/000171.html][{more}]] ** GnuPG 1.2.5 second release candidate (2004-06-16) We are pleased to announce the availability of the second release candidate for GnuPG 1.2.5... [[https://lists.gnupg.org/pipermail/gnupg-announce/2004q2/000169.html][{more}]] ** GnuPG 1.3.6 released (development) (2004-05-22 18:07:54 CEST) The latest release from the development branch of GnuPG is ready for public consumption. This is a branch to create what will eventually become GnuPG 1.4. It will change with greater frequency... [[https://lists.gnupg.org/pipermail/gnupg-announce/2004q2/000168.html][{more}]] ** First U.S. mirror available (2004-05-06) We are proud to enlist on our [[download/mirrors.en.html][mirror page]] the first mirror located in the United States of America. This is the first tangible effort that we have logged since the rule relaxation by the U.S. Department of Commerce about [[http://www.crypto.com/exports/][exporting cryptography]] and we hope that more mirrors will follow. ** Libgcrypt 1.2.0 released (2004-04-16) We are pleased to announce the availability of Libgcrypt 1.2.0, which is the first stable release of this general purpose crypto library... [[https://lists.gnupg.org/pipermail/gnupg-announce/2004q2/000167.html][{more}]] ** GnuPG 1.2.5 first release candidate (2004-03-29) We are pleased to announce the availability of the first release candidate for GnuPG 1.2.5... [[https://lists.gnupg.org/pipermail/gnupg-announce/2004q1/000166.html][{more}]] ** GnuPG 1.3.5 released (development) (2004-02-26) The latest release from the development branch of GnuPG is ready for public consumption. This is a branch to create what will... [[https://lists.gnupg.org/pipermail/gnupg-announce/2004q1/000165.html][{more}]] ** GnuPG 1.2.4 released (2003-12-24) We are pleased to announce the availability of a new stable GnuPG release: Version 1.2.4. The GNU Privacy Guard (GnuPG) is... [[https://lists.gnupg.org/pipermail/gnupg-announce/2003q4/][{more}]] ** GnuPG 1.3.4 released (development) (2003-11-27) The latest release from the development branch of GnuPG is ready for public consumption. This is a branch to create what will... [[https://lists.gnupg.org/pipermail/gnupg-announce/2003q4/][{more}]] ** GnuPG 1.2.3 patch to remove ElGamal signing keys (2003-11-27) David Shaw wrote a patch against GnuPG 1.2.3 to disable the ability to create signatures using the ElGamal sign+encrypt... [[https://lists.gnupg.org/pipermail/gnupg-announce/2003q4/][{more}]] ** GnuPG's ElGamal signing keys compromised (2003-11-27) A severe problem with ElGamal sign+encrypt keys has been found. This leads to a full compromise of the private key. Fortunately... [[https://lists.gnupg.org/pipermail/gnupg-announce/2003q4/][{more}]] ** Libgcrypt 1.1.44 released (2003-11-01) We are pleased to announce version 1.1.44 of Libgcrypt, a general purpose cryptography library based on... [[https://lists.gnupg.org/pipermail/gnupg-announce/2003q4/][{more}]] ** RISC OS port (2003-10-28) The [[download][Download section]] now includes a link to Stefan Bellon's page who ported GnuPG to the RISC OS platform. ** GPA 0.7.0 released (2003-10-22) We are pleased to announce the release of GPA 0.7.0. GPA is a graphical frontend for the GNU Privacy Guard... [[https://lists.gnupg.org/pipermail/gnupg-announce/2003q4/][{more}]] ** GnuPG 1.3.3 released (development) (2003-10-10) The latest release from the development branch of GnuPG is ready for public consumption. This is a branch... [[https://lists.gnupg.org/pipermail/gnupg-announce/2003q4/][{more}]] ** HTTP access to FTP server dismissed (2003-09-22) Because the HTTP protocol has a couple of problems compared to FTP when transmitting large files, we decided to dismiss this service for our server. All the files are thus only available from [[ftp://ftp.gnupg.org/]] via FTP. ** A Practical Introduction to GPG in Windows (2003-08-22) The documentation section now contains a [[documentation/guides.en.html#GPG-Win][new guide]] from Brendan Kidwell which will hopefully help out Windows users who couldn't get the thing to work. ** GnuPG one-two-three released (2003-08-22) We are pleased to announce the availability of a new stable GnuPG release: Version 1.2.3... [[https://lists.gnupg.org/pipermail/gnupg-announce/2003q3/][{more}]] ** Libgcrypt 1.1.42 released (2003-07-31) We are pleased to announce version 1.1.42 of Libgcrypt, a general purpose cryptography library... [[https://lists.gnupg.org/pipermail/gnupg-announce/2003q3/][{more}]] ** GnuPG 1.2.3 second release candidate (2003-07-30) We are pleased to announce the availability of the second release candidate for GnuPG 1.2.3... [[https://lists.gnupg.org/pipermail/gnupg-announce/2003q3/][{more}]] ** OpenPGP Smartcards (2003-07-07) The new OpenPGP smartcards for GnuPG will be shown the first time at the [[http://www.linuxtag.de/2003/en/index.html][LinuxTag]] , Europe's largest GNU/Linux exhibition (booth G24). ** GnuPG Keysigning Party HOWTO (2003-06-16) Documentation section can now count a new entry among its HOWTOs. It is a valuable source of information for understanding and organizing a [[documentation/howtos.en.html#GnuPG-Keysigning-Party][GnuPG keysigning party]] . ** GnuPG 1.3.2 released (2003-05-27) The latest release from the development branch of GnuPG is ready for public consumption. The more GnuPG-familiar user is encouraged try this release... [[https://lists.gnupg.org/pipermail/gnupg-announce/2003q2/000153.html][{more}]] ** Key validity bug in GnuPG 1.2.1 and earlier (2003-05-04) As part of the development of GnuPG 1.2.2, a bug was discovered in the key validation code. This bug causes keys with more than one user ID... [[https://lists.gnupg.org/pipermail/gnupg-announce/2003q2/][{more}]] ** GnuPG 1.2.2 released (2003-05-03) We are pleased to announce the availability of a new stable GnuPG release: Version 1.2.2... [[https://lists.gnupg.org/pipermail/gnupg-announce/2003q2/][{more}]] ** GnuPG.org/(it) 1.0 (2003-04-23) Version 1.0 of this site's Italian translation has been released. - È stata rilasciata la versione 1.0 della traduzione italiana di questo sito. ** New revision of GPH French translation (2003-04-17) Thanks to Jean-francois for the new French revision of [[documentation/guides.en.html#gph][The GNU Privacy Handbook]] . ** The No-War banner (2003-04-08) Recently, a no-war banner has been added to the site. Because not all of us at GnuPG.org agreed on it, we moved it to the bottom of the page. We invite you to read more on our mailing-list. [[https://lists.gnupg.org/pipermail/gpgweb-devel/2003q1/][{more}]] ** GnuPG.org/(es) 0.9 (2003-02-19) Ha visto la luz la versión 0.9 de la traducción al castellano de este sitio. - Version 0.9 of this site spanish translation has been released. ** GPA 0.6.1 released (2003-02-03) We are pleased to announce the release of GPA 0.6.1 [[https://lists.gnupg.org/pipermail/gnupg-announce/2003q1/][{more}]] ** Libgcrypt 1.1.12 released (2003-01-20) I am pleased to announce a new Beta version of Libgcrypt, GNU's implementation of basic crypto functions. Libgcrypt is a general... [[https://lists.gnupg.org/pipermail/gnupg-announce/2003q1/][{more}]] ** GPA 0.6.0 released (2002-12-24) We are pleased to announce the release of GPA 0.6.0. GPA is a graphical frontend for the GNU Privacy Guard... [[gpa-dev/2002-December/index][{more}]] ** GnuPG signature key update and X-Request-PGP (2002-12-23) The key used to sign GnuPG distributions would expire in a few days. I have extended the lifetime of this key for another... [[https://lists.gnupg.org/pipermail/gnupg-announce/2002q4/][{more}]] ** GPGME 0.4.0 released (2002-12-23) We are pleased to announce version 0.4.0 of GnuPG Made Easy, a library designed to make access to GnuPG easier for... [[gpa-dev/2002-December/index][{more}]] ** Libgcrypt 1.1.11 released (2002-12-22) I am pleased to announce the availability of libgcrypt version 1.1.11. Libgcrypt is a general purpose cryptographic library based on the code from GnuPG and... [[https://lists.gnupg.org/pipermail/gnupg-announce/2002q4/][{more}]] ** gnupg.org 1.1 released (2002-12-15) New site look has gained several positive critical comments since revision 1.0 was out, but many bugs were also reported. This revision tries to fix the most part of them. ** cryptplug 0.3.15 released (2002-12-05) Due to an error in the configuration system, the previous release had some problems. This has been fixed and a new version... [[gpa-dev/2002-December/index][{more}]] ** newpg 0.9.4 released (2002-12-04) I have just released newpg 0.9.4. NewPG is the S/MIME variant of GnuPG which does also include the gpg-agent, useful even for... [[gpa-dev/2002-December/index][{more}]] ** cryptplug 0.3.14 released (2002-12-04) We have just released the first standalone version of cryptplug. cryptplug is required for GnuPG and S/MIME support under KDE... [[gpa-dev/2002-December/index][{more}]] ** gpgme 0.3.14 released (2002-12-04) We have released gpgme 0.3.14. This version fixes a segv and a race condition with locales. gpgmeplug is not anymore included... [[gpa-dev/2002-December/index][{more}]] ** New look-and-feel site released to the public (2002-12-01) After about four months of WML coding (well, summer was on the way ;-), first revision of the new site look-and-feel was released today. Site is available in english only for now. ** OpenCDK 0.3.3 (2002-11-25) This is the first public announcement for OpenCDK. It is a library to provide some basic parts of the OpenPGP Message Format... [[https://lists.gnupg.org/pipermail/gnupg-announce/2002q4/][{more}]] ** Pyme -- Python OO interface to GPGME (2002-11-20) Today I am announcing the first release of Pyme, the brand-new Python bindings for GPGME.... [[https://lists.gnupg.org/pipermail/gnupg-announce/2002q4/][{more}]] ** GnuPG 1.3.1 released (development) (2002-11-12) The latest release from the development branch of GnuPG is ready for public consumption. This is a branch to create what will... ** GPGRemail v0.1 initial announcement (2002-11-06) GPGRemail is a minimalistic mailinglist software, meant for small, private, mailinglists that require strong cryptography via... ** RPMs (2002-10-28) I'm currently uploading RPMs packages for gnupg 1.2.1. At this moment I've uploaded src and mdk 9.0 packages. The latter... [[https://lists.gnupg.org/pipermail/gnupg-announce/2002q4/][{more}]] ** GnuPG 1.2.1 Windows update released (2002-10-26) Due to a bug in the recent mingw32/cpd toolkit the latest GnuPG binary for Windows did not work on Windows NT. I have build... [[https://lists.gnupg.org/pipermail/gnupg-announce/2002q4/][{more}]] ** GnuPG 1.2.1 has been released (2002-10-25) Please see this [[download/release_notes.en.html#news-2002-10-25][list of changes]] and then go to the [[download/index.en.html][download instructions]] . ** GnuPG 1.3.0 released (development) (2002-10-18) The first release from the new development branch of GnuPG is ready for public consumption. This is a branch to create what... [[https://lists.gnupg.org/pipermail/gnupg-announce/2002q4/][{more}]] ** GnuPG 1.2.0 released (2002-09-21) Far too many enhancements to be listed here, please see the [[https://lists.gnupg.org/pipermail/gnupg-announce/2002q3/000252.html][announcement mail]] . ** New site (2002-06-20) Developmenent of the site new look and feel has started. ** ftp.gnupg.org HTTP access (2002-05-08) [[http://ftp.gnupg.org][ftp.gnupg.org]] can now also be accessed by HTTP. ** GnuPG 1.0.7 released (2002-04-29) Far too many enhancements to be listed here, please see the [[https://lists.gnupg.org/pipermail/gnupg-announce/2002q2/000251.html][announcement mail]] . ** GPA 0.4.3 released (2002-01-14) [[software/gpa/index.en.html][GPA]] 0.4.3 has been released. ** GPA pages (2001-11-15) [[software/gpa/index.en.html][GPA pages]] reflect latest released version (gpa-0.4.2) now. ** GnuPG 1.0.6 released (2001-05-29) See the [[download/release_notes.en.html#news-2001-05-29][release note]]. ** GnuPG 1.0.5 for W32 released (2001-05-02) Released GnuPG 1.0.5 binary for W32. ** GnuPG 1.0.5 released (2001-04-29) - The semantics of --verify have changed. - Corrected hash calculation for input data larger than 512M. - Large File Support is now working. - A bunch of new options and commands. - Keyserver support for the W32 version. - Better handling of key expiration and subkeys. - Estonian and Turkish translation. - The usual fixes and other enhancements. ** New CVS access instructions (2001-04-18) Changed the instructions for CVS access and add a list of available modules. ** GnuPG Tools (2001-04-03) Add a new webpage about GnuPG tools. ** News about gnupg.de (2001-03-28) News flash about [[http://www.gnupg.de][www.gnupg.de]] . ** Link to Phil Zimmermann (2001-03-24) Add a link to [[http://web.mit.edu/~prz][Phil Zimmermann]] 's homepage. ** New page about GPGME (2001-02-22) Add a page about [[software/gpgme/index.en.html][GPGME]] . ** Patch for GnuPG 1.0.4 released (2000-11-30) Fixed a serious bug which could lead to false positives when checking detached signatures. ** New web design (2000-10-26) New design of these web pages. ** GnuPG 1.0.4 W32 released (2000-10-23) Pre-compiled version of [[download/index.en.html][GnuPG 1.0.4]] for Windows released. ** GnuPG 1.0.4 (2000-10-17) - Fixed a serious bug which could lead to false signature verification results when more than one signature is fed to gpg. - New utility gpgv which is a stripped down version of gpg to be used to verify signatures against a list of trusted keys. - Rijndael (AES) is now supported. ** German GPH (2000-10-06) Put the [[documentation/guides.en.html#gph][German version]] of the GPH online. ** Secure Telephony (2000-09-27) Add a link about secure telephony and a pointer to a Japanese translation of RFC2440. ** GnuPG 1.0.3 released (2000-09-20) - RSA support. - Supports the new MDC encryption packet. - Default options changed for better compatibility with PGP 7. - The usual fixes and other enhancements. ** FAQ (2000-09-06) Add a [[documentation/faqs.en.html][FAQ]] . ** Site improvements (2000-08-28) Add a short menu to the top of the docs page. Add a note about the PGP ARR problem. ** Links to GPH (2000-08-08) Put links to the GPH into the doc webpage. ** Italian web site (2000-08-02) Italian translation of the web pages. ** GnuPG 1.0.2 released (2000-07-12) A lot of fixes and enhancements. ** Pages about PGA (2000-06-29) Add some pages about the [[software/gpa/][GPA]]. ** Two new supported OSes (2000-03-20) Add 2 OSes to the list of supported systems. ** CVS access (2000-03-15) [[https://cvs.gnupg.org/][cvs.gnupg.org]] provides browsable access to the CVS tree of GnuPG and related projects. ** GnuPG 1.0.1 released (1999-12-16) Bug fixes and small enhancements. ** GnuPG 1.0.0 released (1999-09-07) Released the first production version. ** GnuPG 0.9.11 released (1999-09-03) Some more fixes and cleanups. ** GnuPG 0.9.10 released (1999-08-04) Minor bug fixes. ** GnuPG 0.9.9 released (1999-07-23) - Yet another chunk of options. - More bug fixes. ** GnuPG 0.9.8 released (1999-06-26) - A couple of new options. - Yet another workaround for PGP2. - Other bug fixes. ** GnuPG 0.9.7 released (1999-05-23) - Workarounds for a couple of PGP2 bugs. - Other bug fixes. ** GnuPG 0.9.6 released (1999-05-06) - Bug fixes. - Subkey and signature revocations. ** GnuPG 0.9.5 released (1999-03-20) - Bug fixes. - --recv-keys command ** GnuPG 0.9.4 released (1999-03-08) Bug fixes. ** GnuPG 0.9.3 released (1999-02-19) - Bug fixes. - Some new options. ** GnuPG 0.9.2 released (1999-01-20) - Bug fixes. - HKP keyserver support. ** GnuPG 0.9.1 released (1999-01-01) - Fixed some serious bugs. - Some internal redesign. - Polish language support. - Setup a anonymous rsync server. ** GnuPG 0.9.0 released (1998-12-23) - Option to dash-escape "From" in clear text messages. - Better support for unices without /dev/random. - Fixed some bugs. ** GnuPG 0.4.5 released (1998-12-08) - Brazilian translation. - Improved key import. - Loadable random gathering stuff. - Files are now locked during updates. ** GnuPG 0.4.4 released (1998-11-20) - Spanish translation. - Fixed the way expiration dates are stored. - Key validation is now much faster and some more bugs fixed. - New feature to support signed patch files. ** GnuPG 0.4.3 released (1998-11-08) - Russian translation. - Now lists all matching names. - Experimental support for keyrings store in GDBM files. - Many bug fixes. ** GnuPG 0.4.1 released (1998-10-07) - Fixed a couple of bugs and add some more features. - Checked OpenPGP compliance. - PGP 5 passphrase are now working. ** GnuPG 0.4.0 released (1998-09-18) - Fixed a serious Bug in 0.3.5. - Added 3DES. ** GnuPG 0.3.5 released (1998-09-14) - Do not use this version! - Anonymous enciphered messages. - Building in another directory now work better. - Blowfish weak key detection mechanism. ** GnuPG 0.3.4 released (1998-08-11) Relased revision 0.3.4. ** GnuPG 0.3.3 released (1998-08-08) - Alternate user IDs. - A menu to sign, add, remove user ids and other tasks. - [[http://www.counterpane.com/twofish.html][Twofish]] as a new experimental cipher algorithm. - Ability to run as a coprocess; this is nice for frontends. ** GnuPG 0.3.2 released (1998-07-09) Bug fixes. ** GnuPG 0.3.1 released (1998-07-06) - Bug fixes. - More in compliance with OpenPGP. ** GnuPG 0.3.0 released (1998-06-25) - Major enhancements. - More complete v4 key support: Preferences and expiration time is set into the self signature. - Key generation defaults to DSA/ElGamal keys, so that new keys are interoperable with pgp5. - Support for dynamic loading of new algorithms. ** GnuPG 0.2.19 released (1998-05-29) - Tiger has now the OpenPGP assigned number 6. Because the OID has changed, old signatures using this algorithm can't be verified. - GnuPG now encrypts the compressed packed and not any longer in the reverse order; anyway it can decrypt both versions. - =--add-key= works and you are now able to generate subkeys. - It is now possible to generate ElGamal keys in v4 packets to create valid OpenPGP keys. - Some new features for better integration into MUAs. ** GnuPG 0.2.18 released (1998-05-15) - Add key generation for DSA and v4 signatures. - Fixed a small bug in the key generation. - New option =--compress-algo 1= to allow the creation of compressed messages which are readable by PGP. ** GnuPG 0.2.17 released (1998-05-04) - More stuff for OpenPGP: Blowfish is now type 20, comment packets moved to a private type, packet type 3 now prepends conventional encryption packets. - Fixed a passphrase bug and some others. ** GnuPG 0.2.16 released (1998-04-28) - Experimental support for TIGER/192. - Standard cipher is now Blowfish with 128 bit key in OpenPGP's CFB mode. ** GnuPG 0.2.15 released (1998-04-09) - Fixed a bug with the old checksum calculation for secret keys. - CAST5 works (using PGP's strange CFB mode). ** GnuPG 0.0.0 released (1997-12-20) First release. diff --git a/web/people/ben.png b/web/people/ben.png new file mode 100644 index 0000000..6d8b0c1 Binary files /dev/null and b/web/people/ben.png differ diff --git a/web/people/index.org b/web/people/index.org index ea3e484..0438a17 100644 --- a/web/people/index.org +++ b/web/people/index.org @@ -1,144 +1,168 @@ #+TITLE: GnuPG - People #+STARTUP: showall #+SETUPFILE: "../share/setup.inc" * The People behind GnuPG As with all technical things in the world, people and not machines - created them are responsible to keep them running. Software and - thus GnuPG is not different. Although software is build using a lot - of other software and thus the work of many thousand people, you may - be interested to see who is working on GnuPG. Here is a list of + created them and are responsible to keep them running. Software and + thus GnuPG is no different. Although software is built using a lot + of other software and thus the work of many thousands of people, you + may be interested to see who is working on GnuPG. Here is a list of some of them: #+HTML:
** Werner Koch #+HTML:
#+HTML:

#+HTML:
/Core components maintainer/ Werner started GnuPG in 1997 and still puts most of his working time into the development and maintenance of GnuPG. He has 29 years experience in commercial software development on systems ranging from CP/M systems to mainframes, languages from assembler to Smalltalk and applications from drivers to financial analysis systems. Werner is a long time free software supporter and co-founder of the [[http://fsfe.org][FSFE]]. With the support of his brother he founded [[https://g10code.com][g10^code]] GmbH in 2001 to make GnuPG development his profession. Werner is full time employed by g10^code. He is a founding member and the current chairperson of the [[../verein/index.org][GnuPG e.V.]] #+HTML:

** David Shaw #+HTML:

#+HTML:

#+HTML:
/Master of the classic branch/ David approached the GnuPG Project in 2002 after the relaxing of the US crypto regulation allowed the participation of US based hackers on international crypto projects. One of his first achievements was a much improved Web-of-Trust implementation. Today he mainly takes responsibility for the keyserver access and the classic GnuPG 1.x branch. #+HTML:

** Marcus Brinkmann #+HTML:

#+HTML:

#+HTML:
/Hacker/ Marcus is part of the free software community since 1997, when he joined the [[http://www.debian.org][Debian]] project. Probably best known for his past work on GNU/Hurd, he also has a diploma degree in mathematics, and was part and full time employed by [[https://g10code.com][g10^code]] to work on GnuPG and related software from 2001 to 2012 and for 7 months in 2017. He was a founding member of the [[../verein/index.org][GnuPG e.V.]] #+HTML:

** NIIBE Yutaka #+HTML:

#+HTML:

#+HTML:
/Smartcards and Libgcrypt/ Niibe is a long time free software hacker who joined the GnuPG project in 2011 and soon took over the development of the smartcard related code. He is also the person behind the [[http://www.fsij.org/gnuk/][Gnuk Token]] and the [[http://www.gniibe.org/memo/development/gnuk/rng/please-more-and-more-mep.html][MEP game]]. Niibe’s work on GnuPG is financially supported by g10^code. He is a founding member of the [[../verein/index.org][GnuPG e.V.]] #+HTML:

** Jussi Kivilinna #+HTML:

#+HTML:

#+HTML:
/Optimization/ Jussi joined the GnuPG project in 2012 and worked since then on assembler optimized code for cryptographic algorithms in Libgcrypt. #+HTML:

** Neal Walfied #+HTML:

#+HTML:

#+HTML:
/Core components hacker/ Neal started to work on GnuPG in 2015 to support maintenance and development in all areas. We was full time employed by g10^code from 2015 to 2017. He is a founding member of the [[../verein/index.org][GnuPG e.V.]] #+HTML:

** Kai Michaelis #+HTML:

#+HTML:

#+HTML:
/Enigmail hacker/ Kai is working on the [[https://enigmail.net][Enigmail]] project since 2015. He was part time employed by g10^code from 2015 to 2017. He is a founding member of the [[../verein/index.org][GnuPG e.V.]] #+HTML:

** Justus Winter #+HTML:

#+HTML:

#+HTML:
/Core components hacker/ Justus started to work on GnuPG in 2015 to support maintenance and - development in all areas. We was full time employed by g10^code + development in all areas. He was full time employed by g10^code from 2015 to 2017. He is a founding member of the [[../verein/index.org][GnuPG e.V.]] #+HTML:

+** Ben McGinnes + + #+HTML:

+ #+HTML:

+ #+HTML:
+ + /GPGME python hacker/ + + Ben started working on GPGME in 2015 with the initial port of PyME + from Python 2 to Python 3. Then returned to take over stewardship + of Justus' enhanced version of that port from late 2017 onward. In + conjunction with with continuing work on documentation and + developing XML schemas for the XML format included in GPGME. + + He is a co-founder of the original CryptoParty movement in + Melbourne, Australia, a founding member of Pirate Party Australia + and actively advocating for civil and human rights since the '90s. + Ben can sometimes be found on freenode IRC using the handle + =Hasimir= and, of course, on the GnuPG mailing lists. + + [[https://sks-keyservers.net/pks/lookup?op=get&search=0xDB4724E6FA4286C92B4E55C4321E4E2373590E5D][GPG key DB4724E6FA4286C92B4E55C4321E4E2373590E5D]] + + #+HTML:

+ * COMMENT # eof diff --git a/web/service.org b/web/service.org index ee061b1..07f533a 100644 --- a/web/service.org +++ b/web/service.org @@ -1,107 +1,115 @@ #+TITLE: GnuPG - Support #+STARTUP: showall #+SETUPFILE: "share/setup.inc" * Commercial support As part of the GNU project, GnuPG is community developed, and everyone is welcome to contribute under certain conditions. Some companies are offering paid services to meet specific needs. This page contains links to companies that wishes to announce their interest in working with GnuPG and related software. The information on this page comes from companies who asked to be listed; we do not include any information we know to be false, but we cannot check out any of the information; we are transmitting it to you as it was given to us and do not promise it is correct. Also, this is not an endorsement of the people listed here. We have no opinions and usually no information about the abilities of any specific person. We provide this list to enable you to contact service providers. ** Privacy training The companies listed here provide mainly non-technical training and consulting on secure communication. - /none so far/ + - [[https://laboussole.coop][La Boussole]], Ile-de-France, France :: La Boussole is a cooperative + organization based in France. It brings together academic + scholars and trainers who run training sessions on digital + issues (privacy protection, environmental impact, social and + political insights of IT, and the promotion of commons), but + also on media, cooperative teamwork, and fight against + discrimination. Our pedagogy is rooted in non-formal education + (so-called "éducation populaire"), which aims at accompanying + individuals and groups towards emancipation. ** Technical support The companies listed here provide mainly technical support and consulting. - [[http://g10code.com][g10 Code GmbH]], Düsseldorf, Germany :: Offers customized development, porting to new platforms, help with integrating GnuPG into your own projects, code audits, and more. g10 Code is owned and run by GnuPG's principal author. - [[http://josefsson.org/][Simon Josefsson Datakonsult]], Stockholm, Sweden :: Offers integration of OpenPGP technology in TLS, Kerberos, e-mail, and SASL. Does customized development, porting to new platforms, and more. Simon Josefsson Datakonsult is owned and run by the principal author of Shishi and GNU SASL, and the maintainer of [[http://www.gnu.org/software/gnutls/][GnuTLS]] . - [[http://www.intevation.net][Intevation GmbH]], Osnabrück, Germany :: Offers management of development or deployment projects based on or including GnuPG and related tools. Sample references are project "Ägypten" which developed a S/MIME solution and "Gpg4win" which developed a easy-to-use Windows Installer für E-Mail encryption tools. Intevation takes over project and quality management. We usually team up with g10 Code who perform all developments. Intevation offers this type of management for any type of Free Software application and has a long record of doing so. - [[http://www.iktech.net][IKTech]], Vienna, Austria :: Offers independent consultancy and systems integration services for PGP-based PKIs & architectures, OpenPGP, GnuPG and integration with X.509v3 PKIs. IKTech also provides legal expertise and expert witness testimony regarding the legal implications of PGP deployments and use in the context of European Union electronic signature legislation. # Disabled 2017-03-22 (no connection for a long time): # - [[https://www.encryptioncorp.com][EncryptionCorp]], Toronto, Canada :: EncryptionCorp located in # Ontario, Canada is both Toronto and Peterborough's leading-edge # encryption consulting firms. We train and consult for companies # as well as their employees on much more than just how to use # encryption. Our small yet powerful organization is able to # train staff on the safest and fastest ways to handle an # organization's data, without cross contamination. We teach # everything from the simplest methods of password management to # quantum encryption. We do all this in little more than 3 hours # (including 4 breaks) with our non-invasive easy to understand # media. # Disabled 2017-03-22 (website points to a random github repo): # - [[http://lsupport.net][Linux Support LLC]], Kiev, Ukraine :: Linux Support LLC provides # consulting services using GnuPG and related tools, integrated # security for individuals, soho and enterprise in Ukraine. # Disabled 2017-03-22 (domain is for sale): # - [[https://5coluna.com/][5ª Coluna]], Portugal :: Offers GNU/Linux support and consulting for # helpdesk/ticketing software, discussion lists, backup and # small and medium sized companies, including GnuPG services like # disaster recovery using GnuPG and the OpenPGP card, as well as # general GnuPG implementations on Microsoft Windows and # Linux-based systems. ** How to get listed Before we will list your name on this page, we ask that you agree informally to the following terms: 1. You will not restrict (except by copyleft) the use or distribution of any software, documentation, or other technical information you supply anyone in the course of modifying, extending, or supporting free software. This includes any information specifically designed to ameliorate the use of free software. 2. You will not take advantage of contact made through this page to advertise an unrelated business (e.g. sales of proprietary information). You may spontaneously mention your availability for general consulting, but you should not promote a specific unrelated business unless the client asks. To have your information added to this list, please send mail to service-listing at gnupg.org. The entries are listed in the order we receive requests. We might eventually divide the list up by geographic location or type of service. diff --git a/web/share/gpgweb.el b/web/share/gpgweb.el index 6539206..9f14d1c 100644 --- a/web/share/gpgweb.el +++ b/web/share/gpgweb.el @@ -1,527 +1,543 @@ ;;; gpgweb.el --- elisp helper code for the GnuPG web pages (if (< (string-to-number emacs-version) 24) (require 'org-exp)) ;; makeindex disabled because the generated file is created in the ;; source directory. (defun gpgweb-setup-project () "Set up an org-publish project for the gnupg.org website." (progn (require 'ox-gpgweb (concat gpgweb-root-dir "share/ox-gpgweb.el")) (aput 'org-publish-project-alist "gpgweb-org" `(:base-directory ,gpgweb-root-dir :base-extension "org" :language "en" :html-extension "html" :recursive t :publishing-directory ,gpgweb-stage-dir :publishing-function gpgweb-org-to-html :body-only t :section-numbers nil :tags nil :with-toc nil :makeindex nil :auto-sitemap nil :sitemap-title "GnuPG - Sitemap" :sitemap-sort-folders "last" :sitemap-file-entry-format "%t @@html:@@(%d)@@html:@@" :style-include-default nil :timestamp-file nil :html-head "" :html-head-include-scripts nil)) (aput 'org-publish-project-alist "gpgweb-other" `(:base-directory ,gpgweb-root-dir :base-extension "jpg\\|png\\|css\\|txt\\|rss\\|lst\\|sig\\|js\\|map\\|eot\\|ttf\\|woff\\|woff2\\|svg" :recursive t :publishing-directory ,gpgweb-stage-dir :publishing-function org-publish-attachment :completion-function gpgweb-upload)) (aput 'org-publish-project-alist "gpgweb" '(:components ("gpgweb-org" "gpgweb-other"))) (add-hook 'org-export-before-processing-hook 'gpgweb-preprocess))) (defun gpgweb-preprocess (backend) "Insert certain stuff before processing." (let () (goto-char (point-min)) (when (re-search-forward "^#\\+GPGWEB-NEED-SWDB\\b" 2048 t) (beginning-of-line) (kill-line 1) (insert (org-file-contents (concat gpgweb-root-dir "swdb.mac") 'noerror))))) (defun gpgweb-insert-header (title committed-at custom) "Insert the header. COMMITTED-AT is the commit date string of the source file or nil if not available. If CUSTOM is true only a minimal header is set." (goto-char (point-min)) (insert " " title " ") (when (and committed-at (>= (length committed-at) 10)) (insert "\n")) (insert " ") (unless custom (insert " "))) (defconst gpgweb-gnupg-menu-alist '(("/index.html" "Home" (("/index.html" "Home") ("/news.html" "News") ("/people/index.html" "People") ("/verein/index.html" "Verein") ("/documentation/sites.html" "Sites"))) ("/donate/index.html" "Donate" (("/donate/index.html" "Donate") ("/donate/kudos.html" "List of Donors"))) ("/software/index.html" "Software" (("/software/index.html" "GnuPG") ("/software/frontends.html" "Frontends") ("/software/tools.html" "Tools") ("/software/libraries.html" "Libraries") ("/software/swlist.html" "All"))) ("/download/index.html" "Download" (("/download/index.html" "Download") ("/download/integrity_check.html" "Integrity Check") ("/download/supported_systems.html" "Supported Systems") ("/download/release_notes.html" "Release Notes") ("/download/mirrors.html" "Mirrors") ("/download/git.html" "GIT"))) ("/documentation/index.html" "Documentation" (("/documentation/howtos.html" "HOWTOs") ("/documentation/manuals.html" "Manuals") ("/documentation/guides.html" "Guides") ("/documentation/faqs.html" "FAQs") ("/documentation/mailing-lists.html" "Mailing Lists") ("/service.html" "3rd Party Support") ("/documentation/bts.html" "Bug Tracker") ("/documentation/security.html" "Security"))) ("/blog/index.html" "Blog")) "The definition of the gnupg.org menu structure.") (defconst gpgweb-gnupg-bottom-menu-alist '(("/privacy-policy.html" "Privacy Policy" ()) ("/imprint.html" "Imprint" ()) ("/misc/index.html" "Archive" ()) ("/sitemap.html" "Sitemap" ()) ("/blog/index.html" "Blog" ()) ("/ftp/index.html" "Files" ())) "The definition of the gnupg.org bottom menu structure.") (defun gpgweb--any-selected-menu-p (menu selected-file) "Return t if any item in MENU has been selected." (let ((item (car menu)) res) (when menu (when item (when (string= (car item) selected-file) (setq res t)) (when (caddr item) (when (gpgweb--any-selected-menu-p (caddr item) selected-file) (setq res t)))) (when (gpgweb--any-selected-menu-p (cdr menu) selected-file) (setq res t))) res)) (defun gpgweb--selected-top-menu (menu selected-file) "Return the selected top menu or nil." (when menu (let ((item (car menu))) (if (and item (or (string= (car item) selected-file) (gpgweb--any-selected-menu-p (caddr item) selected-file))) menu (gpgweb--selected-top-menu (cdr menu) selected-file))))) (defun gpgweb--insert-menu (menu lvl selected-file) "Helper function to insert the menu." (when menu (let ((item (car menu))) (when item (dotimes (i (1+ lvl)) (insert " ")) (insert "

  • " (cadr item) "\n") (when (caddr item) (dotimes (i (1+ lvl)) (insert " ")) (insert " \n")) (dotimes (i (1+ lvl)) (insert " ")) (insert "
  • \n"))) (gpgweb--insert-menu (cdr menu) lvl selected-file))) (defun gpgweb--insert-submenu (menu selected-file) "Helper function to insert the sub-menu." (when menu (let ((item (car menu))) (when item (insert "
  • " (cadr item) "
  • \n"))) (gpgweb--insert-submenu (cdr menu) selected-file))) (defun gpgweb-insert-menu (selected-file) "Insert the menu structure into the HTML file." (goto-char (point-min)) (when (re-search-forward "^\n" nil t) (insert "
     
    ") (let ((m (caddr (car (gpgweb--selected-top-menu gpgweb-gnupg-menu-alist selected-file))))) (when m (insert "\n"))) (insert "
    "))) (defun gpgweb-blog-index (orgfile filelist) "Return the index of ORGFILE in FILELIST or nil if not found." (let (found (i 0)) (while (and filelist (not found)) (if (string= orgfile (car filelist)) (setq found i)) (setq i (1+ i)) (setq filelist (cdr filelist))) found)) (defun gpgweb-blog-prev (fileidx filelist) "Return the chronological previous file at FILEIDX from FILELIST with the suffixed replaced by \"html\"." (if (> fileidx 1) (concat (file-name-sans-extension (nth (1- fileidx) filelist)) ".html"))) (defun gpgweb-blog-next (orgfile filelist) "Return the chronological next file at FILEIDX from FILELIST with the suffixed replaced by \"html\"." (if (< fileidx (1- (length filelist))) (concat (file-name-sans-extension (nth (1+ fileidx) filelist)) ".html"))) (defun gpgweb-fixup-blog (info orgfile filelist) "Insert the blog specific content. INFO is the usual plist. ORGFILE is the name of the current source file without the directory part. If FILELIST is a list it has an ordered list of org filenames." (let ((authorstr (car (plist-get info :author))) (datestr (car (plist-get info :date)))) (goto-char (point-min)) (if (re-search-forward "^
    " nil t) (let* ((indexp (string= orgfile "index.org")) (fileidx (if (listp filelist) (if indexp (1- (length filelist)) (gpgweb-blog-index orgfile filelist)))) (prevfile (if fileidx (gpgweb-blog-prev fileidx filelist))) (nextfile (if (and fileidx (not indexp)) (gpgweb-blog-next fileidx filelist)))) (move-beginning-of-line nil) (insert "\n"))) (if (and datestr authorstr) (if (re-search-forward "^

    Posted " datestr " by " authorstr "

    \n"))))) (defun gpgweb-insert-footer (htmlfile committed-at blogmode) "Insert the footer. HTMLFILE is HTML file name and COMMITTED-AT is the commit date string of the source file or nil if not available." (let ((srcfile (concat "https://git.gnupg.org/cgi-bin/gitweb.cgi?" "p=gnupg-doc.git;a=blob;f=" (if blogmode "misc/blog.gnupg.org" "web/") ;; The replace below is a hack to cope with ;; blogmode where HTMLFILE is like "./foo.html". (replace-regexp-in-string "^\\./" "/" (file-name-sans-extension htmlfile) t) ".org")) (changed (if (and committed-at (>= (length committed-at) 10)) (substring committed-at 0 10) "[unknown]"))) (goto-char (point-max)) (insert "

      ") (gpgweb--insert-menu gpgweb-gnupg-bottom-menu-alist 0 nil) (insert "
    ") (insert "
    \"Traueranzeige:

    ") (goto-char (point-min)) (unless (search-forward "" nil t) (goto-char (point-max)) (if (string-prefix-p "verein/" htmlfile) (insert "
    \"CC  This web page is - Copyright 2017 GnuPG e.V. and licensed under a + Copyright 2018 GnuPG e.V. and licensed under a Creative Commons Attribution-ShareAlike 4.0 International License. See copying for details. Page source last changed on " changed ".
    \n") (insert "
    \"CC  These web pages are - Copyright 1998--2017 The GnuPG Project and licensed under a + Copyright 1998--2018 The GnuPG Project and licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See copying for details. Page source last changed on " changed ".
    \n"))) (goto-char (point-max)) (insert "
    "))) (defun gpgweb-publish-find-title (file &optional reset) "Find the title of FILE in project. This is a copy of org-publish-find-title which switches the buffer into read-write mode so that it works with read-only files." (or (and (not reset) (org-publish-cache-get-file-property file :title nil t)) (let* ((org-inhibit-startup t) (visiting (find-buffer-visiting file)) (buffer (or visiting (find-file-noselect file)))) (with-current-buffer buffer (toggle-read-only 0) (let ((title (let ((property (plist-get ;; protect local variables in open buffers (if visiting (org-export-with-buffer-copy (org-export-get-environment)) (org-export-get-environment)) :title))) (if property (org-no-properties (org-element-interpret-data property)) (file-name-nondirectory (file-name-sans-extension file)))))) (unless visiting (kill-buffer buffer)) (org-publish-cache-set-file-property file :title title) title))))) (defun gpgweb-want-custom-page-p () "Return true if the current buffer indicated that it wants to be a custom page." (let ((savepoint (point)) (result)) (goto-char (point-min)) (setq result (not (not (search-forward "" nil t)))) (goto-char savepoint) result)) (defun gpgweb-postprocess-html (plist orgfile htmlfile blogmode) "Post-process the generated HTML file - Insert header and footer - Insert \"class=selected\" into the active menu entry - Fixup sitemap. If blogmode is not nil the output is rendered as a blog. BLOGMODE may then contain an ordered list of org file names which are used to create the previous and Next links for an entry." (let* ((visitingp (find-buffer-visiting htmlfile)) (work-buffer (or visitingp (find-file-noselect htmlfile))) (committed-at (shell-command-to-string (concat "git" (if blogmode (concat " -C " gpgweb-blog-dir)) " log -1 --format='%ci' -- " orgfile)))) (prog1 (with-current-buffer work-buffer (let ((fname (file-name-nondirectory htmlfile)) (fname-2 (replace-regexp-in-string ".*/gnupg-doc-stage/web/\\(.*\\)$" "\\1" htmlfile t)) (title (gpgweb-publish-find-title orgfile)) (custom (gpgweb-want-custom-page-p))) ;; Insert header, menu, and footer. (gpgweb-insert-header title committed-at custom) (unless custom (goto-char (point-min)) (unless (search-forward "" nil t) (gpgweb-insert-menu fname-2)) (if blogmode (gpgweb-fixup-blog plist (file-name-nondirectory orgfile) blogmode)) (gpgweb-insert-footer fname-2 committed-at blogmode)) ; Fixup the sitemap (when (string-equal fname "sitemap.html") (goto-char (point-min)) (while (re-search-forward "^.*
  • .*>\\(GnuPG - \\).* and ; attributes. (goto-char (point-min)) (when (search-forward "" nil t) (goto-char (point-min)) (while (re-search-forward "^ ;; Jambunathan K ;; Keywords: outlines, hypermedia, calendar, wp ;; This file is part of GNU Emacs. ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . ;;; Commentary: ;; This library implements a HTML back-end for Org generic exporter. ;; See Org manual for more information. This is a simplified version ;; of the standard HTML backend to be used for the gnupg.org website. ;;; Code: ;;; Dependencies (require 'ox) (require 'ox-publish) (require 'format-spec) (eval-when-compile (require 'cl) (require 'table nil 'noerror)) ;;; Function Declarations (declare-function htmlize-region "ext:htmlize" (beg end)) ;;; Define Back-End (org-export-define-backend 'gpgweb '((bold . org-gpgweb-bold) (center-block . org-gpgweb-center-block) (clock . org-gpgweb-clock) (code . org-gpgweb-code) (drawer . org-gpgweb-drawer) (dynamic-block . org-gpgweb-dynamic-block) (entity . org-gpgweb-entity) (example-block . org-gpgweb-example-block) (export-block . org-gpgweb-export-block) (export-snippet . org-gpgweb-export-snippet) (fixed-width . org-gpgweb-fixed-width) (footnote-definition . org-gpgweb-footnote-definition) (footnote-reference . org-gpgweb-footnote-reference) (headline . org-gpgweb-headline) (horizontal-rule . org-gpgweb-horizontal-rule) (inline-src-block . org-gpgweb-inline-src-block) (inlinetask . org-gpgweb-inlinetask) (inner-template . org-gpgweb-inner-template) (italic . org-gpgweb-italic) (item . org-gpgweb-item) (keyword . org-gpgweb-keyword) (latex-environment . org-gpgweb-latex-environment) (latex-fragment . org-gpgweb-latex-fragment) (line-break . org-gpgweb-line-break) (link . org-gpgweb-link) (node-property . org-gpgweb-node-property) (paragraph . org-gpgweb-paragraph) (plain-list . org-gpgweb-plain-list) (plain-text . org-gpgweb-plain-text) (planning . org-gpgweb-planning) (property-drawer . org-gpgweb-property-drawer) (quote-block . org-gpgweb-quote-block) (radio-target . org-gpgweb-radio-target) (section . org-gpgweb-section) (special-block . org-gpgweb-special-block) (src-block . org-gpgweb-src-block) (statistics-cookie . org-gpgweb-statistics-cookie) (strike-through . org-gpgweb-strike-through) (subscript . org-gpgweb-subscript) (superscript . org-gpgweb-superscript) (table . org-gpgweb-table) (table-cell . org-gpgweb-table-cell) (table-row . org-gpgweb-table-row) (target . org-gpgweb-target) (timestamp . org-gpgweb-timestamp) (underline . org-gpgweb-underline) (verbatim . org-gpgweb-verbatim) (verse-block . org-gpgweb-verse-block)) :export-block "HTML" :filters-alist '((:filter-final-output . org-gpgweb-final-function)) :menu-entry '(?G "Export for http://gnupg.org" ((?H "As HTML buffer" org-gpgweb-export-as-html) (?h "As HTML file" org-gpgweb-export-to-html) (?o "As HTML file and open" (lambda (a s v b) (if a (org-gpgweb-export-to-html t s v b) (org-open-file (org-gpgweb-export-to-html nil s v b))))))) :options-alist '( (:html-html5-fancy nil "html5-fancy" org-gpgweb-html5-fancy) (:html-link-home "HTML_LINK_HOME" nil org-gpgweb-link-home) (:html-link-up "HTML_LINK_UP" nil org-gpgweb-link-up) (:html-mathjax "HTML_MATHJAX" nil "" space) (:html-html5-fancy nil "html5-fancy" org-gpgweb-html5-fancy) (:html-checkbox-type nil nil org-gpgweb-checkbox-type) (:html-extension nil nil org-gpgweb-extension) (:html-home/up-format nil nil org-gpgweb-home/up-format) (:html-inline-image-rules nil nil org-gpgweb-inline-image-rules) (:html-link-org-files-as-html nil nil org-gpgweb-link-org-files-as-html) (:html-mathjax-options nil nil org-gpgweb-mathjax-options) (:html-mathjax-template nil nil org-gpgweb-mathjax-template) (:html-table-align-individual-fields nil nil org-gpgweb-table-align-individual-fields) (:html-table-caption-above nil nil org-gpgweb-table-caption-above) (:html-table-data-tags nil nil org-gpgweb-table-data-tags) (:html-table-header-tags nil nil org-gpgweb-table-header-tags) (:html-table-use-header-tags-for-first-column nil nil org-gpgweb-table-use-header-tags-for-first-column) (:html-tag-class-prefix nil nil org-gpgweb-tag-class-prefix) (:html-todo-kwd-class-prefix nil nil org-gpgweb-todo-kwd-class-prefix) (:html-toplevel-hlevel nil nil org-gpgweb-toplevel-hlevel) (:html-inline-images nil nil org-gpgweb-inline-images) (:html-table-attributes nil nil org-gpgweb-table-default-attributes) (:html-table-row-tags nil nil org-gpgweb-table-row-tags) (:html-xml-declaration nil nil org-gpgweb-xml-declaration) ;; Redefine regular options. (:with-latex nil "tex" org-gpgweb-with-latex) ;; Retrieve LaTeX header for fragments. (:latex-header "LATEX_HEADER" nil nil newline))) ;;; Internal Variables (defvar org-gpgweb-format-table-no-css) (defvar htmlize-buffer-places) ; from htmlize.el (defvar org-gpgweb--pre/postamble-class "status" "CSS class used for pre/postamble") (defconst org-gpgweb-html5-elements '("article" "aside" "audio" "canvas" "details" "figcaption" "figure" "footer" "header" "menu" "meter" "nav" "output" "progress" "section" "video") "New elements in html5. For blocks that should contain headlines, use the HTML_CONTAINER property on the headline itself.") (defconst org-gpgweb-special-string-regexps '(("\\\\-" . "­") ; shy ("---\\([^-]\\)" . "—\\1") ; mdash ("--\\([^-]\\)" . "–\\1") ; ndash ("\\.\\.\\." . "…")) ; hellip "Regular expressions for special string conversion.") ;;; User Configuration Variables ;;;; Headline (defconst org-gpgweb-toplevel-hlevel 2 "The level for level 1 headings in HTML export. This is also important for the classes that will be wrapped around headlines and outline structure. If this variable is 1, the top-level headlines will be

    , and the corresponding classes will be outline-1, section-number-1, and outline-text-1. If this is 2, all of these will get a 2 instead. The default for this variable is 2, because we use

    for formatting the document title.") ;;;; LaTeX (defconst org-gpgweb-with-latex org-export-with-latex "Non-nil means process LaTeX math snippets. When set, the exporter will process LaTeX environments and fragments. This option can also be set with the +OPTIONS line, e.g. \"tex:mathjax\". Allowed values are: nil Ignore math snippets. `verbatim' Keep everything in verbatim `dvipng' Process the LaTeX fragments to images. This will also include processing of non-math environments. `imagemagick' Convert the LaTeX fragments to pdf files and use imagemagick to convert pdf files to png files. `mathjax' Do MathJax preprocessing and arrange for MathJax.js to be loaded. t Synonym for `mathjax'.") ;;;; Links :: Generic (defconst org-gpgweb-link-org-files-as-html t "Non-nil means make file links to `file.org' point to `file.html'. When `org-mode' is exporting an `org-mode' file to HTML, links to non-html files are directly put into a href tag in HTML. However, links to other Org-mode files (recognized by the extension `.org.) should become links to the corresponding html file, assuming that the linked `org-mode' file will also be converted to HTML. When nil, the links still point to the plain `.org' file.") ;;;; Links :: Inline images (defconst org-gpgweb-inline-images t "Non-nil means inline images into exported HTML pages. This is done using an tag. When nil, an anchor with href is used to link to the image.") (defconst org-gpgweb-inline-image-rules '(("file" . "\\.\\(jpeg\\|jpg\\|png\\|gif\\|svg\\)\\'") ("http" . "\\.\\(jpeg\\|jpg\\|png\\|gif\\|svg\\)\\'") ("https" . "\\.\\(jpeg\\|jpg\\|png\\|gif\\|svg\\)\\'")) "Rules characterizing image files that can be inlined into HTML. A rule consists in an association whose key is the type of link to consider, and value is a regexp that will be matched against link's path.") ;;;; Plain Text (defvar org-gpgweb-protect-char-alist '(("&" . "&") ("<" . "<") (">" . ">")) "Alist of characters to be converted by `org-gpgweb-protect'.") ;;;; Src Block (defconst org-gpgweb-htmlize-output-type nil "Output type to be used by htmlize when formatting code snippets. Choices are `css' to export the CSS selectors only,`inline-css' to export the CSS attribute values inline in the HTML or `nil' to export plain text.") (defconst org-gpgweb-htmlize-font-prefix "org-" "The prefix for CSS class names for htmlize font specifications.") ;;;; Table (defconst org-gpgweb-table-default-attributes '(:border "2" :cellspacing "0" :cellpadding "6" :rules "groups" :frame "hsides") "Default attributes and values which will be used in table tags. This is a plist where attributes are symbols, starting with colons, and values are strings. When exporting to HTML5, these values will be disregarded.") (defconst org-gpgweb-table-header-tags '("" . "") "The opening and ending tags for table header fields. This is customizable so that alignment options can be specified. The first %s will be filled with the scope of the field, either row or col. The second %s will be replaced by a style entry to align the field. See also the variable `org-gpgweb-table-use-header-tags-for-first-column'. See also the variable `org-gpgweb-table-align-individual-fields'.") (defconst org-gpgweb-table-data-tags '("" . "") "The opening and ending tags for table data fields. This is customizable so that alignment options can be specified. The first %s will be filled with the scope of the field, either row or col. The second %s will be replaced by a style entry to align the field. See also the variable `org-gpgweb-table-align-individual-fields'.") (defconst org-gpgweb-table-row-tags '("" . "") "The opening and ending tags for table rows. This is customizable so that alignment options can be specified. Instead of strings, these can be Lisp forms that will be evaluated for each row in order to construct the table row tags. During evaluation, these variables will be dynamically bound so that you can reuse them: `row-number': row number (0 is the first row) `rowgroup-number': group number of current row `start-rowgroup-p': non-nil means the row starts a group `end-rowgroup-p': non-nil means the row ends a group `top-row-p': non-nil means this is the top row `bottom-row-p': non-nil means this is the bottom row For example: \(setq org-gpgweb-table-row-tags (cons '(cond (top-row-p \"\") (bottom-row-p \"\") (t (if (= (mod row-number 2) 1) \"\" \"\"))) \"\")) will use the \"tr-top\" and \"tr-bottom\" classes for the top row and the bottom row, and otherwise alternate between \"tr-odd\" and \"tr-even\" for odd and even rows.") (defconst org-gpgweb-table-align-individual-fields t "Non-nil means attach style attributes for alignment to each table field. When nil, alignment will only be specified in the column tags, but this is ignored by some browsers (like Firefox, Safari). Opera does it right though.") (defconst org-gpgweb-table-use-header-tags-for-first-column nil "Non-nil means format column one in tables with header tags. When nil, also column one will use data tags.") (defconst org-gpgweb-table-caption-above t "When non-nil, place caption string at the beginning of the table. Otherwise, place it near the end.") ;;;; Tags (defconst org-gpgweb-tag-class-prefix "" "Prefix to class names for TODO keywords. Each tag gets a class given by the tag itself, with this prefix. The default prefix is empty because it is nice to just use the keyword as a class name. But if you get into conflicts with other, existing CSS classes, then this prefix can be very useful.") ;;;; Template :: Generic (defconst org-gpgweb-extension "html" "The extension for exported HTML files.") (defconst org-gpgweb-xml-declaration '(("html" . "") ("php" . "\"; ?>")) "The extension for exported HTML files. %s will be replaced with the charset of the exported file. This may be a string, or an alist with export extensions and corresponding declarations. This declaration only applies when exporting to XHTML.") (defconst org-gpgweb-doctype "xhtml-strict" "Document type definition to use for exported HTML files.") (defconst org-gpgweb-html5-fancy nil "Non-nil means using new HTML5 elements. This variable is ignored for anything other than HTML5 export. For compatibility with Internet Explorer, it's probably a good idea to download some form of the html5shiv (for instance https://code.google.com/p/html5shiv/) and add it to your HTML_HEAD_EXTRA, so that your pages don't break for users of IE versions 8 and below.") (defconst org-gpgweb-container-element "div" "HTML element to use for wrapping top level sections.") (defconst org-gpgweb-checkbox-types '((unicode . ((on . "☑") (off . "☐") (trans . "☐"))) (ascii . ((on . "[X]") (off . "[ ]") (trans . "[-]"))) (html . ((on . "") (off . "") (trans . "")))) "Alist of checkbox types. The cdr of each entry is an alist list three checkbox types for HTML export: `on', `off' and `trans'. The choices are: `unicode' Unicode characters (HTML entities) `ascii' ASCII characters `html' HTML checkboxes Note that only the ascii characters implement tri-state checkboxes. The other two use the `off' checkbox for `trans'.") (defconst org-gpgweb-checkbox-type 'ascii "The type of checkboxes to use for HTML export. See `org-gpgweb-checkbox-types' for for the values used for each option.") ;;;; Template :: Mathjax (defconst org-gpgweb-mathjax-options '((path "http://orgmode.org/mathjax/MathJax.js") (scale "100") (align "center") (indent "2em") (mathml nil)) "Options for MathJax setup. path The path where to find MathJax scale Scaling for the HTML-CSS backend, usually between 100 and 133 align How to align display math: left, center, or right indent If align is not center, how far from the left/right side? mathml Should a MathML player be used if available? This is faster and reduces bandwidth use, but currently sometimes has lower spacing quality. Therefore, the default is nil. When browsers get better, this switch can be flipped. You can also customize this for each buffer, using something like #+MATHJAX: scale:\"133\" align:\"right\" mathml:t path:\"/MathJax/\"") (defconst org-gpgweb-mathjax-template " " "The MathJax setup for XHTML files.") (defconst org-gpgweb-link-up "" "Where should the \"UP\" link of exported HTML pages lead?") (defconst org-gpgweb-link-home "" "Where should the \"HOME\" link of exported HTML pages lead?") (defconst org-gpgweb-home/up-format "" "Snippet used to insert the HOME and UP links. This is a format string, the first %s will receive the UP link, the second the HOME link. If both `org-gpgweb-link-up' and `org-gpgweb-link-home' are empty, the entire snippet will be ignored.") ;;;; Todos (defconst org-gpgweb-todo-kwd-class-prefix "" "Prefix to class names for TODO keywords. Each TODO keyword gets a class given by the keyword itself, with this prefix. The default prefix is empty because it is nice to just use the keyword as a class name. But if you get into conflicts with other, existing CSS classes, then this prefix can be very useful.") ;;; Internal Functions (defun org-gpgweb-xhtml-p (info) (member org-gpgweb-doctype '("xhtml-strict" "xhtml" "xhtml5"))) (defun org-gpgweb-html5-p (info) (member org-gpgweb-doctype '("html5" "xhtml5" ""))) (defun org-gpgweb-close-tag (tag attr info) (concat "<" tag " " attr (if (org-gpgweb-xhtml-p info) " />" ">"))) (defun org-gpgweb--make-attribute-string (attributes) "Return a list of attributes, as a string. ATTRIBUTES is a plist where values are either strings or nil. An attributes with a nil value will be omitted from the result." (let (output) (dolist (item attributes (mapconcat 'identity (nreverse output) " ")) (cond ((null item) (pop output)) ((symbolp item) (push (substring (symbol-name item) 1) output)) (t (let ((key (car output)) (value (replace-regexp-in-string "\"" """ (org-gpgweb-encode-plain-text item)))) (setcar output (format "%s=\"%s\"" key value)))))))) (defun org-gpgweb--wrap-image (contents info &optional caption label) "Wrap CONTENTS string within an appropriate environment for images. INFO is a plist used as a communication channel. When optional arguments CAPTION and LABEL are given, use them for caption and \"id\" attribute." (let ((html5-fancy (and (org-gpgweb-html5-p info) (plist-get info :html-html5-fancy)))) (format (if html5-fancy "\n%s%s\n" "\n%s%s\n") ;; ID. (if (not (org-string-nw-p label)) "" (format " id=\"%s\"" (org-export-solidify-link-text label))) ;; Contents. (format "\n

    %s

    " contents) ;; Caption. (if (not (org-string-nw-p caption)) "" (format (if html5-fancy "\n
    %s
    " "\n

    %s

    ") caption))))) (defun org-gpgweb--format-image (source attributes info) "Return \"img\" tag with given SOURCE and ATTRIBUTES. SOURCE is a string specifying the location of the image. ATTRIBUTES is a plist, as returned by `org-export-read-attribute'. INFO is a plist used as a communication channel." (if (string= "svg" (file-name-extension source)) (org-gpgweb--svg-image source attributes info) (org-gpgweb-close-tag "img" (org-gpgweb--make-attribute-string (org-combine-plists (list :src source :alt (if (string-match-p "^ltxpng/" source) (org-gpgweb-encode-plain-text (org-find-text-property-in-string 'org-latex-src source)) (file-name-nondirectory source))) attributes)) info))) (defun org-gpgweb--svg-image (source attributes info) "Return \"object\" appropriate for embedding svg file SOURCE with assoicated ATTRIBUTES. INFO is a plist used as a communication channel. The special attribute \"fallback\" can be used to specify a fallback image file to use if the object embedding is not supported." (let ((fallback (plist-get attributes :fallback)) (attrs (org-gpgweb--make-attribute-string (plist-put attributes :fallback nil)))) (format "\n%s" source attrs (if fallback (org-gpgweb-close-tag "img" (format "src=\"%s\" %s" fallback attrs) info) "Sorry, your browser does not support SVG.")))) (defun org-gpgweb--textarea-block (element) "Transcode ELEMENT into a textarea block. ELEMENT is either a src block or an example block." (let* ((code (car (org-export-unravel-code element))) (attr (org-export-read-attribute :attr_html element))) (format "

    \n\n

    " (or (plist-get attr :width) 80) (or (plist-get attr :height) (org-count-lines code)) code))) (defun org-gpgweb--has-caption-p (element &optional info) "Non-nil when ELEMENT has a caption affiliated keyword. INFO is a plist used as a communication channel. This function is meant to be used as a predicate for `org-export-get-ordinal' or a value to `org-gpgweb-standalone-image-predicate'." (org-element-property :caption element)) ;;;; Table (defun org-gpgweb-htmlize-region-for-paste (beg end) "Convert the region between BEG and END to HTML, using htmlize.el. This is much like `htmlize-region-for-paste', only that it uses the settings define in the org-... variables." (let* ((htmlize-output-type org-gpgweb-htmlize-output-type) (htmlize-css-name-prefix org-gpgweb-htmlize-font-prefix) (htmlbuf (htmlize-region beg end))) (unwind-protect (with-current-buffer htmlbuf (buffer-substring (plist-get htmlize-buffer-places 'content-start) (plist-get htmlize-buffer-places 'content-end))) (kill-buffer htmlbuf)))) (defun org-gpgweb--make-string (n string) "Build a string by concatenating N times STRING." (let (out) (dotimes (i n out) (setq out (concat string out))))) (defun org-gpgweb-fix-class-name (kwd) ; audit callers of this function "Turn todo keyword KWD into a valid class name. Replaces invalid characters with \"_\"." (save-match-data (while (string-match "[^a-zA-Z0-9_]" kwd) (setq kwd (replace-match "_" t t kwd)))) kwd) (defun org-gpgweb-footnote-section (info) "Format the footnote section. INFO is a plist used as a communication channel." (let* ((fn-alist (org-export-collect-footnote-definitions (plist-get info :parse-tree) info)) (fn-alist (loop for (n type raw) in fn-alist collect (cons n (if (eq (org-element-type raw) 'org-data) (org-trim (org-export-data raw info)) (format "

    %s

    " (org-trim (org-export-data raw info)))))))) (when fn-alist (format "

    %s:

    %s
    " (org-gpgweb--translate "Footnotes" info) (format "\n%s\n" (mapconcat (lambda (fn) (let ((n (car fn)) (def (cdr fn))) (format "
    %s %s
    \n" (format "%s" (org-gpgweb--anchor (format "fn.%d" n) n (format " class=\"footnum\" href=\"#fnr.%d\"" n) info)) def))) fn-alist "\n")))))) ;;; Template (defun org-gpgweb--build-meta-info (info) "Return meta tags for exported document. INFO is a plist used as a communication channel." (let ((protect-string (lambda (str) (replace-regexp-in-string "\"" """ (org-gpgweb-encode-plain-text str)))) (title (org-export-data (plist-get info :title) info)) (author (and (plist-get info :with-author) (let ((auth (plist-get info :author))) (and auth ;; Return raw Org syntax, skipping non ;; exportable objects. (org-element-interpret-data (org-element-map auth (cons 'plain-text org-element-all-objects) 'identity info)))))) (description (plist-get info :description)) (keywords (plist-get info :keywords)) (charset (or (and (fboundp 'coding-system-get) (coding-system-get 'utf-8 'mime-charset)) "iso-8859-1"))) (concat (format "%s\n" title) (when (plist-get info :time-stamp-file) (format-time-string (concat "\n"))) (format (if (org-gpgweb-html5-p info) (org-gpgweb-close-tag "meta" " charset=\"%s\"" info) (org-gpgweb-close-tag "meta" " http-equiv=\"Content-Type\" content=\"text/html;charset=%s\"" info)) charset) "\n" (org-gpgweb-close-tag "meta" " name=\"generator\" content=\"Org-mode\"" info) "\n" (and (org-string-nw-p author) (concat (org-gpgweb-close-tag "meta" (format " name=\"author\" content=\"%s\"" (funcall protect-string author)) info) "\n")) (and (org-string-nw-p description) (concat (org-gpgweb-close-tag "meta" (format " name=\"description\" content=\"%s\"\n" (funcall protect-string description)) info) "\n")) (and (org-string-nw-p keywords) (concat (org-gpgweb-close-tag "meta" (format " name=\"keywords\" content=\"%s\"" (funcall protect-string keywords)) info) "\n"))))) (defun org-gpgweb--build-mathjax-config (info) "Insert the user setup into the mathjax template. INFO is a plist used as a communication channel." (when (and (memq (plist-get info :with-latex) '(mathjax t)) (org-element-map (plist-get info :parse-tree) '(latex-fragment latex-environment) 'identity info t)) (let ((template (plist-get info :html-mathjax-template)) (options (plist-get info :html-mathjax-options)) (in-buffer (or (plist-get info :html-mathjax) "")) name val (yes " ") (no "// ") x) (mapc (lambda (e) (setq name (car e) val (nth 1 e)) (if (string-match (concat "\\<" (symbol-name name) ":") in-buffer) (setq val (car (read-from-string (substring in-buffer (match-end 0)))))) (if (not (stringp val)) (setq val (format "%s" val))) (if (string-match (concat "%" (upcase (symbol-name name))) template) (setq template (replace-match val t t template)))) options) (setq val (nth 1 (assq 'mathml options))) (if (string-match (concat "\\%s" attributes (or desc "")))) ;;;; Todo (defun org-gpgweb--todo (todo info) "Format TODO keywords into HTML." (when todo (format "%s" (if (member todo org-done-keywords) "done" "todo") (plist-get info :html-todo-kwd-class-prefix) (org-gpgweb-fix-class-name todo) todo))) ;;;; Tags (defun org-gpgweb--tags (tags info) "Format TAGS into HTML. INFO is a plist containing export options." (when tags (format "%s" (mapconcat (lambda (tag) (format "%s" (concat (plist-get info :html-tag-class-prefix) (org-gpgweb-fix-class-name tag)) tag)) tags " ")))) ;;;; Src Code (defun org-gpgweb-fontify-code (code lang) "Color CODE with htmlize library. CODE is a string representing the source code to colorize. LANG is the language used for CODE, as a string, or nil." (when code (cond ;; Case 1: No lang. Possibly an example block. ((not lang) ;; Simple transcoding. (org-gpgweb-encode-plain-text code)) ;; Case 2: No htmlize or an inferior version of htmlize ((not (and (require 'htmlize nil t) (fboundp 'htmlize-region-for-paste))) ;; Emit a warning. (message "Cannot fontify src block (htmlize.el >= 1.34 required)") ;; Simple transcoding. (org-gpgweb-encode-plain-text code)) ;; Case 3: plain text explicitly set ((not org-gpgweb-htmlize-output-type) ;; Simple transcoding. (org-gpgweb-encode-plain-text code)) (t ;; Map language (setq lang (or (assoc-default lang org-src-lang-modes) lang)) (let* ((lang-mode (and lang (intern (format "%s-mode" lang))))) (cond ;; Case 1: Language is not associated with any Emacs mode ((not (functionp lang-mode)) ;; Simple transcoding. (org-gpgweb-encode-plain-text code)) ;; Case 2: Default. Fontify code. (t ;; htmlize (setq code (with-temp-buffer ;; Switch to language-specific mode. (funcall lang-mode) ;; Disable fci-mode if present (when (and (fboundp 'fci-mode) (require 'fill-column-indicator nil 'noerror)) (fci-mode -1)) (insert code) ;; Fontify buffer. (font-lock-ensure) ;; Remove formatting on newline characters. (save-excursion (let ((beg (point-min)) (end (point-max))) (goto-char beg) (while (progn (end-of-line) (< (point) end)) (put-text-property (point) (1+ (point)) 'face nil) (forward-char 1)))) (org-src-mode) (set-buffer-modified-p nil) ;; Htmlize region. (org-gpgweb-htmlize-region-for-paste (point-min) (point-max)))) ;; Strip any enclosing
     tags.
     	  (let* ((beg (and (string-match "\\`]*>\n*" code) (match-end 0)))
     		 (end (and beg (string-match "\\'" code))))
     	    (if (and beg end) (substring code beg end) code)))))))))
     
     (defun org-gpgweb-do-format-code
       (code &optional lang refs retain-labels num-start)
       "Format CODE string as source code.
     Optional arguments LANG, REFS, RETAIN-LABELS and NUM-START are,
     respectively, the language of the source code, as a string, an
     alist between line numbers and references (as returned by
     `org-export-unravel-code'), a boolean specifying if labels should
     appear in the source code, and the number associated to the first
     line of code."
       (let* ((code-lines (org-split-string code "\n"))
     	 (code-length (length code-lines))
     	 (num-fmt
     	  (and num-start
     	       (format "%%%ds: "
     		       (length (number-to-string (+ code-length num-start))))))
     	 (code (org-gpgweb-fontify-code code lang)))
         (org-export-format-code
          code
          (lambda (loc line-num ref)
            (setq loc
     	     (concat
     	      ;; Add line number, if needed.
     	      (when num-start
     		(format "%s"
     			(format num-fmt line-num)))
     	      ;; Transcoded src line.
     	      loc
     	      ;; Add label, if needed.
     	      (when (and ref retain-labels) (format " (%s)" ref))))
            ;; Mark transcoded line as an anchor, if needed.
            (if (not ref) loc
     	 (format "%s"
     		 ref loc)))
          num-start refs)))
     
     (defun org-gpgweb-format-code (element info)
       "Format contents of ELEMENT as source code.
     ELEMENT is either an example block or a src block.  INFO is
     a plist used as a communication channel."
       (let* ((lang (org-element-property :language element))
     	 ;; Extract code and references.
     	 (code-info (org-export-unravel-code element))
     	 (code (car code-info))
     	 (refs (cdr code-info))
     	 ;; Does the src block contain labels?
     	 (retain-labels (org-element-property :retain-labels element))
     	 ;; Does it have line numbers?
     	 (num-start (case (org-element-property :number-lines element)
     		      (continued (org-export-get-loc element info))
     		      (new 0))))
         (org-gpgweb-do-format-code code lang refs retain-labels num-start)))
     
     
     ;;; Tables of Contents
     
     (defun org-gpgweb-toc (depth info)
       "Build a table of contents.
     DEPTH is an integer specifying the depth of the table.  INFO is a
     plist used as a communication channel.  Return the table of
     contents as a string, or nil if it is empty."
       (let ((toc-entries
     	 (mapcar (lambda (headline)
     		   (cons (org-gpgweb--format-toc-headline headline info)
     			 (org-export-get-relative-level headline info)))
     		 (org-export-collect-headlines info depth)))
     	(outer-tag (if (and (org-gpgweb-html5-p info)
     			    (plist-get info :html-html5-fancy))
     		       "nav"
     		     "div")))
         (when toc-entries
           (concat (format "<%s id=\"table-of-contents\">\n" outer-tag)
     	      (let ((top-level (plist-get info :html-toplevel-hlevel)))
     		(format "%s\n"
     			top-level
     			(org-gpgweb--translate "Table of Contents" info)
     			top-level))
     	      "
    " (org-gpgweb--toc-text toc-entries) "
    \n" (format "\n" outer-tag))))) (defun org-gpgweb--toc-text (toc-entries) "Return innards of a table of contents, as a string. TOC-ENTRIES is an alist where key is an entry title, as a string, and value is its relative level, as an integer." (let* ((prev-level (1- (cdar toc-entries))) (start-level prev-level)) (concat (mapconcat (lambda (entry) (let ((headline (car entry)) (level (cdr entry))) (concat (let* ((cnt (- level prev-level)) (times (if (> cnt 0) (1- cnt) (- cnt))) rtn) (setq prev-level level) (concat (org-gpgweb--make-string times (cond ((> cnt 0) "\n
      \n
    • ") ((< cnt 0) "
    • \n
    \n"))) (if (> cnt 0) "\n
      \n
    • " "
    • \n
    • "))) headline))) toc-entries "") (org-gpgweb--make-string (- prev-level start-level) "
    • \n
    \n")))) (defun org-gpgweb--format-toc-headline (headline info) "Return an appropriate table of contents entry for HEADLINE. INFO is a plist used as a communication channel." (let* ((headline-number (org-export-get-headline-number headline info)) (todo (and (plist-get info :with-todo-keywords) (let ((todo (org-element-property :todo-keyword headline))) (and todo (org-export-data todo info))))) (todo-type (and todo (org-element-property :todo-type headline))) (priority (and (plist-get info :with-priority) (org-element-property :priority headline))) (text (org-export-data-with-backend (org-export-get-alt-title headline info) ;; Create an anonymous back-end that will ignore any ;; footnote-reference, link, radio-target and target ;; in table of contents. (org-export-create-backend :parent 'gpgweb :transcoders '((footnote-reference . ignore) (link . (lambda (object c i) c)) (radio-target . (lambda (object c i) c)) (target . ignore))) info)) (tags (and (eq (plist-get info :with-tags) t) (org-export-get-tags headline info)))) (format "%s" ;; Label. (org-export-solidify-link-text (or (org-element-property :CUSTOM_ID headline) (concat "sec-" (mapconcat #'number-to-string headline-number "-")))) ;; Body. (concat (and (not (org-export-low-level-p headline info)) (org-export-numbered-headline-p headline info) (concat (mapconcat #'number-to-string headline-number ".") ". ")) (apply 'org-gpgweb-format-headline-function todo todo-type priority text tags :section-number nil))))) (defun org-gpgweb-list-of-listings (info) "Build a list of listings. INFO is a plist used as a communication channel. Return the list of listings as a string, or nil if it is empty." (let ((lol-entries (org-export-collect-listings info))) (when lol-entries (concat "
    \n" (let ((top-level (plist-get info :html-toplevel-hlevel))) (format "%s\n" top-level (org-gpgweb--translate "List of Listings" info) top-level)) "
    \n
      \n" (let ((count 0) (initial-fmt (format "%s" (org-gpgweb--translate "Listing %d:" info)))) (mapconcat (lambda (entry) (let ((label (org-element-property :name entry)) (title (org-trim (org-export-data (or (org-export-get-caption entry t) (org-export-get-caption entry)) info)))) (concat "
    • " (if (not label) (concat (format initial-fmt (incf count)) " " title) (format "%s %s" (org-export-solidify-link-text label) (format initial-fmt (incf count)) title)) "
    • "))) lol-entries "\n")) "\n
    \n
    \n
    ")))) (defun org-gpgweb-list-of-tables (info) "Build a list of tables. INFO is a plist used as a communication channel. Return the list of tables as a string, or nil if it is empty." (let ((lol-entries (org-export-collect-tables info))) (when lol-entries (concat "
    \n" (let ((top-level (plist-get info :html-toplevel-hlevel))) (format "%s\n" top-level (org-gpgweb--translate "List of Tables" info) top-level)) "
    \n
      \n" (let ((count 0) (initial-fmt (format "%s" (org-gpgweb--translate "Table %d:" info)))) (mapconcat (lambda (entry) (let ((label (org-element-property :name entry)) (title (org-trim (org-export-data (or (org-export-get-caption entry t) (org-export-get-caption entry)) info)))) (concat "
    • " (if (not label) (concat (format initial-fmt (incf count)) " " title) (format "%s %s" (org-export-solidify-link-text label) (format initial-fmt (incf count)) title)) "
    • "))) lol-entries "\n")) "\n
    \n
    \n
    ")))) ;;; Transcode Functions ;;;; Bold (defun org-gpgweb-bold (bold contents info) "Transcode BOLD from Org to HTML. CONTENTS is the text with bold markup. INFO is a plist holding contextual information." (format "%s" contents)) ;;;; Center Block (defun org-gpgweb-center-block (center-block contents info) "Transcode a CENTER-BLOCK element from Org to HTML. CONTENTS holds the contents of the block. INFO is a plist holding contextual information." (format "
    \n%s
    " contents)) ;;;; Clock (defun org-gpgweb-clock (clock contents info) "Transcode a CLOCK element from Org to HTML. CONTENTS is nil. INFO is a plist used as a communication channel." (format "

    %s %s%s

    " org-clock-string (org-translate-time (org-element-property :raw-value (org-element-property :value clock))) (let ((time (org-element-property :duration clock))) (and time (format " (%s)" time))))) ;;;; Code (defun org-gpgweb-code (code contents info) "Transcode CODE from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (format "%s" (org-gpgweb-encode-plain-text (org-element-property :value code)))) ;;;; Drawer (defun org-gpgweb-drawer (drawer contents info) "Transcode a DRAWER element from Org to HTML. CONTENTS holds the contents of the block. INFO is a plist holding contextual information." (funcall (lambda (name contents) contents) (org-element-property :drawer-name drawer) contents)) ;;;; Dynamic Block (defun org-gpgweb-dynamic-block (dynamic-block contents info) "Transcode a DYNAMIC-BLOCK element from Org to HTML. CONTENTS holds the contents of the block. INFO is a plist holding contextual information. See `org-export-data'." contents) ;;;; Entity (defun org-gpgweb-entity (entity contents info) "Transcode an ENTITY object from Org to HTML. CONTENTS are the definition itself. INFO is a plist holding contextual information." (org-element-property :html entity)) ;;;; Example Block (defun org-gpgweb-example-block (example-block contents info) "Transcode a EXAMPLE-BLOCK element from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (if (org-export-read-attribute :attr_html example-block :textarea) (org-gpgweb--textarea-block example-block) (format "
    \n%s
    " (org-gpgweb-format-code example-block info)))) ;;;; Export Snippet (defun org-gpgweb-export-snippet (export-snippet contents info) "Transcode a EXPORT-SNIPPET object from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (when (eq (org-export-snippet-backend export-snippet) 'html) (org-element-property :value export-snippet))) ;;;; Export Block (defun org-gpgweb-export-block (export-block contents info) "Transcode an EXPORT-BLOCK element from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (when (string= (org-element-property :type export-block) "HTML") (org-remove-indentation (org-element-property :value export-block)))) ;;;; Fixed Width (defun org-gpgweb-fixed-width (fixed-width contents info) "Transcode a FIXED-WIDTH element from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (format "
    \n%s
    " (org-gpgweb-do-format-code (org-remove-indentation (org-element-property :value fixed-width))))) ;;;; Footnote Reference (defun org-gpgweb-footnote-reference (footnote-reference contents info) "Transcode a FOOTNOTE-REFERENCE element from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (concat ;; Insert separator between two footnotes in a row. (let ((prev (org-export-get-previous-element footnote-reference info))) (when (eq (org-element-type prev) 'footnote-reference) ", ")) (let* ((n (org-export-get-footnote-number footnote-reference info)) (id (format "fnr.%d%s" n (if (org-export-footnote-first-reference-p footnote-reference info) "" ".100")))) (format "%s" (org-gpgweb--anchor id n (format " class=\"footref\" href=\"#fn.%d\"" n) info))))) ;;;; Headline (defun org-gpgweb-headline (headline contents info) "Transcode a HEADLINE element from Org to HTML. CONTENTS holds the contents of the headline. INFO is a plist holding contextual information." (let* ((numberedp (org-export-numbered-headline-p headline info)) (level (+ (org-export-get-relative-level headline info) (1- (plist-get info :html-toplevel-hlevel)))) (todo (and (plist-get info :with-todo-keywords) (let ((todo (org-element-property :todo-keyword headline))) (and todo (org-export-data todo info))))) (todo-type (and todo (org-element-property :todo-type headline))) (priority (and (plist-get info :with-priority) (org-element-property :priority headline))) (text (org-export-data (org-element-property :title headline) info)) (tags (and (plist-get info :with-tags) (org-export-get-tags headline info))) (full-text (org-gpgweb-format-headline-function todo todo-type priority text tags info)) (contents (or contents ""))) (cond + ;; Case 0: virtual headline: Just print the raw value. + ((member "html" (org-export-get-tags headline info)) + (format "%s\n" (org-element-property :raw-value headline))) ;; Case 1: This is a footnote section: ignore it. ((org-element-property :footnote-section-p headline) nil) ;; Case 2: This is a deep sub-tree: export it as a list item. ;; Also export as items headlines for which no section ;; format has been found. ((org-export-low-level-p headline info) ;; Build the real contents of the sub-tree. (let* ((type (if numberedp 'ordered 'unordered)) (itemized-body (org-gpgweb-format-list-item contents type nil info nil full-text))) (concat (and (org-export-first-sibling-p headline info) (org-gpgweb-begin-plain-list type)) itemized-body (and (org-export-last-sibling-p headline info) (org-gpgweb-end-plain-list type))))) ;; Case 3: Standard headline. Export it as a section. (t (let* ((numbers (org-export-get-headline-number headline info)) (section-number (mapconcat #'number-to-string numbers "-")) (ids (remq nil (list (org-element-property :CUSTOM_ID headline) (concat "sec-" section-number) (org-element-property :ID headline)))) (preferred-id (car ids)) (extra-ids (cdr ids)) - (extra-class (org-element-property :HTML_CONTAINER_CLASS headline)) + (outer-class (org-element-property :HTML_CONTAINER_CLASS headline)) + (header-class (org-element-property :HTML_CLASS headline)) (first-content (car (org-element-contents headline)))) - (format "%s%s\n%s\n" + (format "%s%s%s\n%s%s\n" + ; div class? + (if outer-class (concat "
    \n") "") ; h? level + ; header-class? + (if header-class (concat " class=\"" header-class "\"") "") ; id=? preferred-id ; insert anchors (mapconcat (lambda (x) (let ((id (org-export-solidify-link-text (if (org-uuidgen-p x) (concat "ID-" x) x)))) (org-gpgweb--anchor id nil nil info))) extra-ids "") ; text of header (concat (and numberedp (format "%s " level (mapconcat #'number-to-string numbers "."))) full-text) ; /h? level ; the content of the section - contents)))))) + contents + (if outer-class "
    " "") + )))))) (defun org-gpgweb-format-headline-function (todo todo-type priority text tags info) "Function to format headline text. This function will be called with six arguments: TODO the todo keyword (string or nil). TODO-TYPE the type of todo (symbol: `todo', `done', nil) PRIORITY the priority of the headline (integer or nil) TEXT the main headline text (string). TAGS the tags (string or nil). INFO the export options (plist). The function result will be used in the section format string." (let ((todo (org-gpgweb--todo todo info)) (tags (org-gpgweb--tags tags info))) (concat todo (and todo " ") text (and tags "   ") tags))) ;;;; Horizontal Rule (defun org-gpgweb-horizontal-rule (horizontal-rule contents info) "Transcode an HORIZONTAL-RULE object from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (org-gpgweb-close-tag "hr" nil info)) ;;;; Inline Src Block (defun org-gpgweb-inline-src-block (inline-src-block contents info) "Transcode an INLINE-SRC-BLOCK element from Org to HTML. CONTENTS holds the contents of the item. INFO is a plist holding contextual information." (let* ((org-lang (org-element-property :language inline-src-block)) (code (org-element-property :value inline-src-block))) (let ((lang (org-element-property :language inline-src-block)) (code (org-gpgweb-format-code inline-src-block info)) (label (let ((lbl (org-element-property :name inline-src-block))) (if (not lbl) "" (format " id=\"%s\"" (org-export-solidify-link-text lbl)))))) (format "%s" lang label code)))) ;;;; Inlinetask (defun org-gpgweb-inlinetask (inlinetask contents info) "Transcode an INLINETASK element from Org to HTML. CONTENTS holds the contents of the block. INFO is a plist holding contextual information." (let* ((todo (and (plist-get info :with-todo-keywords) (let ((todo (org-element-property :todo-keyword inlinetask))) (and todo (org-export-data todo info))))) (todo-type (and todo (org-element-property :todo-type inlinetask))) (priority (and (plist-get info :with-priority) (org-element-property :priority inlinetask))) (text (org-export-data (org-element-property :title inlinetask) info)) (tags (and (plist-get info :with-tags) (org-export-get-tags inlinetask info)))) (funcall org-gpgweb-format-inlinetask-function todo todo-type priority text tags contents))) (defun org-gpgweb-format-inlinetask-function (todo todo-type priority text tags contents info) "Function called to format an inlinetask in HTML code. The function must accept seven parameters: TODO the todo keyword, as a string TODO-TYPE the todo type, a symbol among `todo', `done' and nil. PRIORITY the inlinetask priority, as a string NAME the inlinetask name, as a string. TAGS the inlinetask tags, as a list of strings. CONTENTS the contents of the inlinetask, as a string. INFO the export options, as a plist The function should return the string to be exported." (format "
    \n%s%s\n%s
    " (org-gpgweb-format-headline-function todo todo-type priority text tags info) (org-gpgweb-close-tag "br" nil info) contents)) ;;;; Italic (defun org-gpgweb-italic (italic contents info) "Transcode ITALIC from Org to HTML. CONTENTS is the text with italic markup. INFO is a plist holding contextual information." (format "%s" contents)) ;;;; Item (defun org-gpgweb-checkbox (checkbox info) "Format CHECKBOX into HTML. INFO is a plist holding contextual information. See `org-gpgweb-checkbox-type' for customization options." (cdr (assq checkbox (cdr (assq (plist-get info :html-checkbox-type) org-gpgweb-checkbox-types))))) (defun org-gpgweb-format-list-item (contents type checkbox info &optional term-counter-id headline) "Format a list item into HTML." (let ((class (if checkbox (format " class=\"%s\"" (symbol-name checkbox)) "")) (checkbox (concat (org-gpgweb-checkbox checkbox info) (and checkbox " "))) (br (org-gpgweb-close-tag "br" nil info))) (concat (case type (ordered (let* ((counter term-counter-id) (extra (if counter (format " value=\"%s\"" counter) ""))) (concat (format "" class extra) (when headline (concat headline br))))) (unordered (let* ((id term-counter-id) (extra (if id (format " id=\"%s\"" id) ""))) (concat (format "" class extra) (when headline (concat headline br))))) (descriptive (let* ((term term-counter-id)) (setq term (or term "(no term)")) ;; Check-boxes in descriptive lists are associated to tag. (concat (format "%s" class (concat checkbox term)) "
    ")))) (unless (eq type 'descriptive) checkbox) contents (case type (ordered "

  • ") (unordered "") (descriptive ""))))) (defun org-gpgweb-item (item contents info) "Transcode an ITEM element from Org to HTML. CONTENTS holds the contents of the item. INFO is a plist holding contextual information." (let* ((plain-list (org-export-get-parent item)) (type (org-element-property :type plain-list)) (counter (org-element-property :counter item)) (checkbox (org-element-property :checkbox item)) (tag (let ((tag (org-element-property :tag item))) (and tag (org-export-data tag info))))) (org-gpgweb-format-list-item contents type checkbox info (or tag counter)))) ;;;; Keyword (defun org-gpgweb-keyword (keyword contents info) "Transcode a KEYWORD element from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (let ((key (org-element-property :key keyword)) (value (org-element-property :value keyword))) (cond ((string= key "HTML") value) ((string= key "TOC") (let ((value (downcase value))) (cond ((string-match "\\" value) (let ((depth (or (and (string-match "[0-9]+" value) (string-to-number (match-string 0 value))) (plist-get info :with-toc)))) (org-gpgweb-toc depth info))) ((string= "listings" value) (org-gpgweb-list-of-listings info)) ((string= "tables" value) (org-gpgweb-list-of-tables info)))))))) ;;;; Latex Environment (defun org-gpgweb-format-latex (latex-frag processing-type info) "Format a LaTeX fragment LATEX-FRAG into HTML. PROCESSING-TYPE designates the tool used for conversion. It is a symbol among `mathjax', `dvipng', `imagemagick', `verbatim' nil and t. See `org-gpgweb-with-latex' for more information. INFO is a plist containing export properties." (let ((cache-relpath "") (cache-dir "")) (unless (eq processing-type 'mathjax) (let ((bfn (or (buffer-file-name) (make-temp-name (expand-file-name "latex" temporary-file-directory)))) (latex-header (let ((header (plist-get info :latex-header))) (and header (concat (mapconcat (lambda (line) (concat "#+LATEX_HEADER: " line)) (org-split-string header "\n") "\n") "\n"))))) (setq cache-relpath (concat "ltxpng/" (file-name-sans-extension (file-name-nondirectory bfn))) cache-dir (file-name-directory bfn)) ;; Re-create LaTeX environment from original buffer in ;; temporary buffer so that dvipng/imagemagick can properly ;; turn the fragment into an image. (setq latex-frag (concat latex-header latex-frag)))) (with-temp-buffer (insert latex-frag) (org-format-latex cache-relpath cache-dir nil "Creating LaTeX Image..." nil nil processing-type) (buffer-string)))) (defun org-gpgweb-latex-environment (latex-environment contents info) "Transcode a LATEX-ENVIRONMENT element from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (let ((processing-type (plist-get info :with-latex)) (latex-frag (org-remove-indentation (org-element-property :value latex-environment))) (attributes (org-export-read-attribute :attr_html latex-environment))) (case processing-type ((t mathjax) (org-gpgweb-format-latex latex-frag 'mathjax info)) ((dvipng imagemagick) (let ((formula-link (org-gpgweb-format-latex latex-frag processing-type info))) (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link)) ;; Do not provide a caption or a name to be consistent with ;; `mathjax' handling. (org-gpgweb--wrap-image (org-gpgweb--format-image (match-string 1 formula-link) attributes info) info)))) (t latex-frag)))) ;;;; Latex Fragment (defun org-gpgweb-latex-fragment (latex-fragment contents info) "Transcode a LATEX-FRAGMENT object from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (let ((latex-frag (org-element-property :value latex-fragment)) (processing-type (plist-get info :with-latex))) (case processing-type ((t mathjax) (org-gpgweb-format-latex latex-frag 'mathjax info)) ((dvipng imagemagick) (let ((formula-link (org-gpgweb-format-latex latex-frag processing-type info))) (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link)) (org-gpgweb--format-image (match-string 1 formula-link) nil info)))) (t latex-frag)))) ;;;; Line Break (defun org-gpgweb-line-break (line-break contents info) "Transcode a LINE-BREAK object from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (concat (org-gpgweb-close-tag "br" nil info) "\n")) ;;;; Link (defun org-gpgweb-inline-image-p (link info) "Non-nil when LINK is meant to appear as an image. INFO is a plist used as a communication channel. LINK is an inline image when it has no description and targets an image file (see `org-gpgweb-inline-image-rules' for more information), or if its description is a single link targeting an image file." (if (not (org-element-contents link)) (org-export-inline-image-p link (plist-get info :html-inline-image-rules)) (not (let ((link-count 0)) (org-element-map (org-element-contents link) (cons 'plain-text org-element-all-objects) (lambda (obj) (case (org-element-type obj) (plain-text (org-string-nw-p obj)) (link (if (= link-count 1) t (incf link-count) (not (org-export-inline-image-p obj (plist-get info :html-inline-image-rules))))) (otherwise t))) info t))))) (defvar org-gpgweb-standalone-image-predicate) (defun org-gpgweb-standalone-image-p (element info) "Non-nil if ELEMENT is a standalone image. INFO is a plist holding contextual information. An element or object is a standalone image when - its type is `paragraph' and its sole content, save for white spaces, is a link that qualifies as an inline image; - its type is `link' and its containing paragraph has no other content save white spaces. Bind `org-gpgweb-standalone-image-predicate' to constrain paragraph further. For example, to check for only captioned standalone images, set it to: \(lambda (paragraph) (org-element-property :caption paragraph))" (let ((paragraph (case (org-element-type element) (paragraph element) (link (org-export-get-parent element))))) (and (eq (org-element-type paragraph) 'paragraph) (or (not (fboundp 'org-gpgweb-standalone-image-predicate)) (funcall org-gpgweb-standalone-image-predicate paragraph)) (catch 'exit (let ((link-count 0)) (org-element-map (org-element-contents paragraph) (cons 'plain-text org-element-all-objects) #'(lambda (obj) (when (case (org-element-type obj) (plain-text (org-string-nw-p obj)) (link (or (> (incf link-count) 1) (not (org-gpgweb-inline-image-p obj info)))) (otherwise t)) (throw 'exit nil))) info nil 'link) (= link-count 1)))))) (defun org-gpgweb-link (link desc info) "Transcode a LINK object from Org to HTML. DESC is the description part of the link, or the empty string. INFO is a plist holding contextual information. See `org-export-data'." (let* ((link-org-files-as-html-maybe (function (lambda (raw-path info) "Treat links to `file.org' as links to `file.html', if needed." (cond ((string= ".org" (downcase (file-name-extension raw-path "."))) (concat (file-name-sans-extension raw-path) "." org-gpgweb-extension)) (t raw-path))))) (type (org-element-property :type link)) (raw-path (org-element-property :path link)) ;; Ensure DESC really exists, or set it to nil. (desc (org-string-nw-p desc)) (path (cond ((member type '("http" "https" "ftp" "mailto")) ;(org-link-escape-browser ; (org-link-unescape (concat type ":" raw-path)))) (concat type ":" raw-path)) ((string= type "file") ;; Treat links to ".org" files as ".html". (setq raw-path (funcall link-org-files-as-html-maybe raw-path info)) ;; If file path is absolute, prepend it with protocol ;; component - "file:". ;(cond ; ((file-name-absolute-p raw-path) ; (setq raw-path (concat "file:" raw-path)))) ;; Add search option, if any. A search option can be ;; relative to a custom-id or a headline title. Append ;; a hash sign to any unresolved option, as it might point ;; to a target. (let ((option (org-element-property :search-option link))) (cond ((not option) raw-path) ((eq (aref option 0) ?#) (concat raw-path option)) (t (let ((destination (org-publish-resolve-external-fuzzy-link (org-element-property :path link) option))) (concat raw-path (if (not destination) (concat "#" option) (concat "#sec-" (mapconcat #'number-to-string destination "-"))))))))) (t raw-path))) ;; Extract attributes from parent's paragraph. HACK: Only do ;; this for the first link in parent (inner image link for ;; inline images). This is needed as long as attributes ;; cannot be set on a per link basis. (attributes-plist (let* ((parent (org-export-get-parent-element link)) (link (let ((container (org-export-get-parent link))) (if (and (eq (org-element-type container) 'link) (org-gpgweb-inline-image-p link info)) container link)))) (and (eq (org-element-map parent 'link 'identity info t) link) (org-export-read-attribute :attr_html parent)))) (attributes (let ((attr (org-gpgweb--make-attribute-string attributes-plist))) (if (org-string-nw-p attr) (concat " " attr) ""))) protocol) (cond ;; Image file. ((and (plist-get info :html-inline-images) (org-export-inline-image-p link (plist-get info :html-inline-image-rules))) (org-gpgweb--format-image path attributes-plist info)) ;; Radio target: Transcode target's contents and use them as ;; link's description. ((string= type "radio") (let ((destination (org-export-resolve-radio-link link info))) (when destination (format "%s" (org-export-solidify-link-text (org-element-property :value destination)) attributes desc)))) ;; Links pointing to a headline: Find destination and build ;; appropriate referencing command. ((member type '("custom-id" "fuzzy" "id")) (let ((destination (if (string= type "fuzzy") (org-export-resolve-fuzzy-link link info) (org-export-resolve-id-link link info)))) (case (org-element-type destination) ;; ID link points to an external file. (plain-text (let ((fragment (concat "ID-" path)) ;; Treat links to ".org" files as ".html", if needed. (path (funcall link-org-files-as-html-maybe destination info))) (format "%s" path fragment attributes (or desc destination)))) ;; Fuzzy link points nowhere. ((nil) (format "%s" (or desc (org-export-data (org-element-property :raw-link link) info)))) ;; Link points to a headline. (headline (let ((href ;; What href to use? (cond ;; Case 1: Headline is linked via it's CUSTOM_ID ;; property. Use CUSTOM_ID. ((string= type "custom-id") (org-element-property :CUSTOM_ID destination)) ;; Case 2: Headline is linked via it's ID property ;; or through other means. Use the default href. ((member type '("id" "fuzzy")) (format "sec-%s" (mapconcat 'number-to-string (org-export-get-headline-number destination info) "-"))) (t (error "Shouldn't reach here")))) ;; What description to use? (desc ;; Case 1: Headline is numbered and LINK has no ;; description. Display section number. (if (and (org-export-numbered-headline-p destination info) (not desc)) (mapconcat 'number-to-string (org-export-get-headline-number destination info) ".") ;; Case 2: Either the headline is un-numbered or ;; LINK has a custom description. Display LINK's ;; description or headline's title. (or desc (org-export-data (org-element-property :title destination) info))))) (format "%s" (org-export-solidify-link-text href) attributes desc))) ;; Fuzzy link points to a target or an element. (t (let* ((path (org-export-solidify-link-text path)) (org-gpgweb-standalone-image-predicate 'org-gpgweb--has-caption-p) (number (cond (desc nil) ((org-gpgweb-standalone-image-p destination info) (org-export-get-ordinal (org-element-map destination 'link 'identity info t) info 'link 'org-gpgweb-standalone-image-p)) (t (org-export-get-ordinal destination info nil 'org-gpgweb--has-caption-p)))) (desc (cond (desc) ((not number) "No description for this link") ((numberp number) (number-to-string number)) (t (mapconcat 'number-to-string number "."))))) (format "%s" path attributes desc)))))) ;; Coderef: replace link with the reference name or the ;; equivalent line number. ((string= type "coderef") (let ((fragment (concat "coderef-" path))) (format "%s" fragment (org-trim (format (concat "class=\"coderef\"" " onmouseover=\"CodeHighlightOn(this, '%s');\"" " onmouseout=\"CodeHighlightOff(this, '%s');\"") fragment fragment)) attributes (format (org-export-get-coderef-format path desc) (org-export-resolve-coderef path info))))) ;; Link type is handled by a special function. ((functionp (setq protocol (nth 2 (assoc type org-link-protocols)))) (funcall protocol (org-link-unescape path) desc 'gpgweb)) ;; External link with a description part. ((and path desc) (format "%s" path attributes desc)) ;; External link without a description part. (path (format "%s" path attributes path)) ;; No path, only description. Try to do something useful. (t (format "%s" desc))))) ;;;; Node Property (defun org-gpgweb-node-property (node-property contents info) "Transcode a NODE-PROPERTY element from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (format "%s:%s" (org-element-property :key node-property) (let ((value (org-element-property :value node-property))) (if value (concat " " value) "")))) ;;;; Paragraph (defun org-gpgweb-paragraph (paragraph contents info) "Transcode a PARAGRAPH element from Org to HTML. CONTENTS is the contents of the paragraph, as a string. INFO is the plist used as a communication channel." (let* ((parent (org-export-get-parent paragraph)) (parent-type (org-element-type parent)) (style '((footnote-definition " class=\"footpara\""))) (attributes (org-gpgweb--make-attribute-string (org-export-read-attribute :attr_html paragraph))) (extra (or (cadr (assoc parent-type style)) ""))) (cond ((and (eq (org-element-type parent) 'item) (= (org-element-property :begin paragraph) (org-element-property :contents-begin parent)) (not (org-element-map (org-export-get-parent parent) 'item (lambda (item) (let ((contents (org-element-contents item))) (and contents (or (cdr contents) (not (eq (org-element-type (car contents)) 'paragraph)))))) info 'first-match 'item))) ;; Leading paragraph in a list item have no tags if every ;; element of the containing list is only a single paragraph. contents) ((org-gpgweb-standalone-image-p paragraph info) ;; Standalone image. (let ((caption (let ((raw (org-export-data (org-export-get-caption paragraph) info)) (org-gpgweb-standalone-image-predicate 'org-gpgweb--has-caption-p)) (if (not (org-string-nw-p raw)) raw (concat "" (format (org-gpgweb--translate "Figure %d:" info) (org-export-get-ordinal (org-element-map paragraph 'link 'identity info t) info nil 'org-gpgweb-standalone-image-p)) " " raw)))) (label (org-element-property :name paragraph))) (org-gpgweb--wrap-image contents info caption label))) ;; Regular paragraph. (t (format "\n%s

    " (if (org-string-nw-p attributes) (concat " " attributes) "") extra contents))))) ;;;; Plain List ;; FIXME Maybe arg1 is not needed because
  • already sets ;; the correct value for the item counter (defun org-gpgweb-begin-plain-list (type &optional arg1) "Insert the beginning of the HTML list depending on TYPE. When ARG1 is a string, use it as the start parameter for ordered lists." (case type (ordered (format "" (if arg1 (format " start=\"%d\"" arg1) ""))) (unordered "
      ") (descriptive "
      "))) (defun org-gpgweb-end-plain-list (type) "Insert the end of the HTML list depending on TYPE." (case type (ordered "") (unordered "
    ") (descriptive ""))) (defun org-gpgweb-plain-list (plain-list contents info) "Transcode a PLAIN-LIST element from Org to HTML. CONTENTS is the contents of the list. INFO is a plist holding contextual information." (let* (arg1 ;; (assoc :counter (org-element-map plain-list 'item (type (org-element-property :type plain-list))) (format "%s\n%s%s" (org-gpgweb-begin-plain-list type) contents (org-gpgweb-end-plain-list type)))) ;;;; Plain Text (defun org-gpgweb-convert-special-strings (string) "Convert special characters in STRING to HTML." (let ((all org-gpgweb-special-string-regexps) e a re rpl start) (while (setq a (pop all)) (setq re (car a) rpl (cdr a) start 0) (while (string-match re string start) (setq string (replace-match rpl t nil string)))) string)) (defun org-gpgweb-encode-plain-text (text) "Convert plain text characters from TEXT to HTML equivalent. Possible conversions are set in `org-gpgweb-protect-char-alist'." (mapc (lambda (pair) (setq text (replace-regexp-in-string (car pair) (cdr pair) text t t))) org-gpgweb-protect-char-alist) text) (defun org-gpgweb-plain-text (text info) "Transcode a TEXT string from Org to HTML. TEXT is the string to transcode. INFO is a plist holding contextual information." (let ((output text)) ;; Protect following characters: <, >, &. (setq output (org-gpgweb-encode-plain-text output)) ;; Handle smart quotes. Be sure to provide original string since ;; OUTPUT may have been modified. (when (plist-get info :with-smart-quotes) (setq output (org-export-activate-smart-quotes output :html info text))) ;; Handle special strings. (when (plist-get info :with-special-strings) (setq output (org-gpgweb-convert-special-strings output))) ;; Handle break preservation if required. (when (plist-get info :preserve-breaks) (setq output (replace-regexp-in-string "\\(\\\\\\\\\\)?[ \t]*\n" (concat (org-gpgweb-close-tag "br" nil info) "\n") output))) ;; Return value. output)) ;; Planning (defun org-gpgweb-planning (planning contents info) "Transcode a PLANNING element from Org to HTML. CONTENTS is nil. INFO is a plist used as a communication channel." (let ((span-fmt "%s %s")) (format "

    %s

    " (mapconcat 'identity (delq nil (list (let ((closed (org-element-property :closed planning))) (when closed (format span-fmt org-closed-string (org-translate-time (org-element-property :raw-value closed))))) (let ((deadline (org-element-property :deadline planning))) (when deadline (format span-fmt org-deadline-string (org-translate-time (org-element-property :raw-value deadline))))) (let ((scheduled (org-element-property :scheduled planning))) (when scheduled (format span-fmt org-scheduled-string (org-translate-time (org-element-property :raw-value scheduled))))))) " ")))) ;;;; Property Drawer (defun org-gpgweb-property-drawer (property-drawer contents info) "Transcode a PROPERTY-DRAWER element from Org to HTML. CONTENTS holds the contents of the drawer. INFO is a plist holding contextual information." (and nil (org-string-nw-p contents) (format "
    \n%s
    " contents))) ;;;; Quote Block (defun org-gpgweb-quote-block (quote-block contents info) "Transcode a QUOTE-BLOCK element from Org to HTML. CONTENTS holds the contents of the block. INFO is a plist holding contextual information." (format "
    \n%s
    " contents)) ;;;; Section (defun org-gpgweb-section (section contents info) "Transcode a SECTION element from Org to HTML. CONTENTS holds the contents of the section. INFO is a plist holding contextual information." (let ((parent (org-export-get-parent-headline section))) ;; Before first headline: no container, just return CONTENTS. (if (not parent) contents ;; Get div's class and id references. (let* ((class-num (+ (org-export-get-relative-level parent info) (1- (plist-get info :html-toplevel-hlevel)))) (section-number (mapconcat 'number-to-string (org-export-get-headline-number parent info) "-"))) ;; Build return value. (format "
    \n%s
    " class-num (or (org-element-property :CUSTOM_ID parent) section-number) contents))))) ;;;; Radio Target (defun org-gpgweb-radio-target (radio-target text info) "Transcode a RADIO-TARGET object from Org to HTML. TEXT is the text of the target. INFO is a plist holding contextual information." (let ((id (org-export-solidify-link-text (org-element-property :value radio-target)))) (org-gpgweb--anchor id text nil info))) ;;;; Special Block (defun org-gpgweb-special-block (special-block contents info) "Transcode a SPECIAL-BLOCK element from Org to HTML. CONTENTS holds the contents of the block. INFO is a plist holding contextual information." (if (org-export-raw-special-block-p special-block info) (org-remove-indentation (org-element-property :raw-value special-block)) (let* ((block-type (downcase (org-element-property :type special-block))) (contents (or contents "")) (html5-fancy (and (org-gpgweb-html5-p info) (plist-get info :html-html5-fancy) (member block-type org-gpgweb-html5-elements))) (attributes (org-export-read-attribute :attr_html special-block))) (unless html5-fancy (let ((class (plist-get attributes :class))) (setq attributes (plist-put attributes :class (if class (concat class " " block-type) block-type))))) (setq attributes (org-gpgweb--make-attribute-string attributes)) (when (not (equal attributes "")) (setq attributes (concat " " attributes))) (if html5-fancy (format "<%s%s>\n%s" block-type attributes contents block-type) (format "\n%s\n" attributes contents))))) ;;;; Src Block (defun org-gpgweb-src-block (src-block contents info) "Transcode a SRC-BLOCK element from Org to HTML. CONTENTS holds the contents of the item. INFO is a plist holding contextual information." (if (org-export-read-attribute :attr_html src-block :textarea) (org-gpgweb--textarea-block src-block) (let ((lang (org-element-property :language src-block)) (caption (org-export-get-caption src-block)) (code (org-gpgweb-format-code src-block info)) (label (let ((lbl (org-element-property :name src-block))) (if (not lbl) "" (format " id=\"%s\"" (org-export-solidify-link-text lbl)))))) (if (not lang) (format "
    \n%s
    " label code) (format "
    \n%s%s\n
    " (if (not caption) "" (format "" (org-export-data caption info))) (format "\n
    %s
    " lang label code)))))) ;;;; Statistics Cookie (defun org-gpgweb-statistics-cookie (statistics-cookie contents info) "Transcode a STATISTICS-COOKIE object from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (let ((cookie-value (org-element-property :value statistics-cookie))) (format "%s" cookie-value))) ;;;; Strike-Through (defun org-gpgweb-strike-through (strike-through contents info) "Transcode STRIKE-THROUGH from Org to HTML. CONTENTS is the text with strike-through markup. INFO is a plist holding contextual information." (format "%s" contents)) ;;;; Subscript (defun org-gpgweb-subscript (subscript contents info) "Transcode a SUBSCRIPT object from Org to HTML. CONTENTS is the contents of the object. INFO is a plist holding contextual information." (format "%s" contents)) ;;;; Superscript (defun org-gpgweb-superscript (superscript contents info) "Transcode a SUPERSCRIPT object from Org to HTML. CONTENTS is the contents of the object. INFO is a plist holding contextual information." (format "%s" contents)) ;;;; Table Cell (defun org-gpgweb-table-cell (table-cell contents info) "Transcode a TABLE-CELL element from Org to HTML. CONTENTS is nil. INFO is a plist used as a communication channel." (let* ((table-row (org-export-get-parent table-cell)) (table (org-export-get-parent-table table-cell)) (cell-attrs (if (not (plist-get info :html-table-align-individual-fields)) "" (format (if (and (boundp 'org-gpgweb-format-table-no-css) org-gpgweb-format-table-no-css) " align=\"%s\"" " class=\"%s\"") (org-export-table-cell-alignment table-cell info))))) (when (or (not contents) (string= "" (org-trim contents))) (setq contents " ")) (cond ((and (org-export-table-has-header-p table info) (= 1 (org-export-table-row-group table-row info))) (let ((header-tags (plist-get info :html-table-header-tags))) (concat "\n" (format (car header-tags) "col" cell-attrs) contents (cdr header-tags)))) ((and (plist-get info :html-table-use-header-tags-for-first-column) (zerop (cdr (org-export-table-cell-address table-cell info)))) (let ((header-tags (plist-get info :html-table-header-tags))) (concat "\n" (format (car header-tags) "row" cell-attrs) contents (cdr header-tags)))) (t (let ((data-tags (plist-get info :html-table-data-tags))) (concat "\n" (format (car data-tags) cell-attrs) contents (cdr data-tags))))))) ;;;; Table Row (defun org-gpgweb-table-row (table-row contents info) "Transcode a TABLE-ROW element from Org to HTML. CONTENTS is the contents of the row. INFO is a plist used as a communication channel." ;; Rules are ignored since table separators are deduced from ;; borders of the current row. (when (eq (org-element-property :type table-row) 'standard) (let* ((rowgroup-number (org-export-table-row-group table-row info)) (row-number (org-export-table-row-number table-row info)) (start-rowgroup-p (org-export-table-row-starts-rowgroup-p table-row info)) (end-rowgroup-p (org-export-table-row-ends-rowgroup-p table-row info)) ;; `top-row-p' and `end-rowgroup-p' are not used directly ;; but should be set so that `org-gpgweb-table-row-tags' can ;; use them (see the docstring of this variable.) (top-row-p (and (equal start-rowgroup-p '(top)) (equal end-rowgroup-p '(below top)))) (bottom-row-p (and (equal start-rowgroup-p '(above)) (equal end-rowgroup-p '(bottom above)))) (rowgroup-tags (cond ;; Case 1: Row belongs to second or subsequent rowgroups. ((not (= 1 rowgroup-number)) '("" . "\n")) ;; Case 2: Row is from first rowgroup. Table has >=1 rowgroups. ((org-export-table-has-header-p (org-export-get-parent-table table-row) info) '("" . "\n")) ;; Case 2: Row is from first and only row group. (t '("" . "\n"))))) (concat ;; Begin a rowgroup? (when start-rowgroup-p (car rowgroup-tags)) ;; Actual table row (concat "\n" (eval (car (plist-get info :html-table-row-tags))) contents "\n" (eval (cdr (plist-get info :html-table-row-tags)))) ;; End a rowgroup? (when end-rowgroup-p (cdr rowgroup-tags)))))) ;;;; Table (defun org-gpgweb-table-first-row-data-cells (table info) "Transcode the first row of TABLE. INFO is a plist used as a communication channel." (let ((table-row (org-element-map table 'table-row (lambda (row) (unless (eq (org-element-property :type row) 'rule) row)) info 'first-match)) (special-column-p (org-export-table-has-special-column-p table))) (if (not special-column-p) (org-element-contents table-row) (cdr (org-element-contents table-row))))) (defun org-gpgweb-table--table.el-table (table info) "Format table.el tables into HTML. INFO is a plist used as a communication channel." (when (eq (org-element-property :type table) 'table.el) (require 'table) (let ((outbuf (with-current-buffer (get-buffer-create "*org-export-table*") (erase-buffer) (current-buffer)))) (with-temp-buffer (insert (org-element-property :value table)) (goto-char 1) (re-search-forward "^[ \t]*|[^|]" nil t) (table-generate-source 'html outbuf)) (with-current-buffer outbuf (prog1 (org-trim (buffer-string)) (kill-buffer) ))))) (defun org-gpgweb-table (table contents info) "Transcode a TABLE element from Org to HTML. CONTENTS is the contents of the table. INFO is a plist holding contextual information." (case (org-element-property :type table) ;; Case 1: table.el table. Convert it using appropriate tools. (table.el (org-gpgweb-table--table.el-table table info)) ;; Case 2: Standard table. (t (let* ((label (org-element-property :name table)) (caption (org-export-get-caption table)) (number (org-export-get-ordinal table info nil 'org-gpgweb--has-caption-p)) (attributes (org-gpgweb--make-attribute-string (org-combine-plists (and label (list :id (org-export-solidify-link-text label))) (and (not (org-gpgweb-html5-p info)) (plist-get info :html-table-attributes)) (org-export-read-attribute :attr_html table)))) (alignspec (if (and (boundp 'org-gpgweb-format-table-no-css) org-gpgweb-format-table-no-css) "align=\"%s\"" "class=\"%s\"")) (table-column-specs (function (lambda (table info) (mapconcat (lambda (table-cell) (let ((alignment (org-export-table-cell-alignment table-cell info))) (concat ;; Begin a colgroup? (when (org-export-table-cell-starts-colgroup-p table-cell info) "\n") ;; Add a column. Also specify it's alignment. (format "\n%s" (org-gpgweb-close-tag "col" (concat " " (format alignspec alignment)) info)) ;; End a colgroup? (when (org-export-table-cell-ends-colgroup-p table-cell info) "\n")))) (org-gpgweb-table-first-row-data-cells table info) "\n"))))) (format "\n%s\n%s\n%s" (if (equal attributes "") "" (concat " " attributes)) (if (not caption) "" (format (if (plist-get info :html-table-caption-above) "%s" "%s") (concat "" (format (org-gpgweb--translate "Table %d:" info) number) " " (org-export-data caption info)))) (funcall table-column-specs table info) contents))))) ;;;; Target (defun org-gpgweb-target (target contents info) "Transcode a TARGET object from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (let ((id (org-export-solidify-link-text (org-element-property :value target)))) (org-gpgweb--anchor id nil nil info))) ;;;; Timestamp (defun org-gpgweb-timestamp (timestamp contents info) "Transcode a TIMESTAMP object from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (let ((value (org-gpgweb-plain-text (org-timestamp-translate timestamp) info))) (format "%s" (replace-regexp-in-string "--" "–" value)))) ;;;; Underline (defun org-gpgweb-underline (underline contents info) "Transcode UNDERLINE from Org to HTML. CONTENTS is the text with underline markup. INFO is a plist holding contextual information." (format "%s" contents)) ;;;; Verbatim (defun org-gpgweb-verbatim (verbatim contents info) "Transcode VERBATIM from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." (format "%s" (org-gpgweb-encode-plain-text (org-element-property :value verbatim)))) ;;;; Verse Block (defun org-gpgweb-verse-block (verse-block contents info) "Transcode a VERSE-BLOCK element from Org to HTML. CONTENTS is verse block contents. INFO is a plist holding contextual information." ;; Replace each newline character with line break. Also replace ;; each blank line with a line break. (setq contents (replace-regexp-in-string "^ *\\\\\\\\$" (format "%s\n" (org-gpgweb-close-tag "br" nil info)) (replace-regexp-in-string "\\(\\\\\\\\\\)?[ \t]*\n" (format "%s\n" (org-gpgweb-close-tag "br" nil info)) contents))) ;; Replace each white space at beginning of a line with a ;; non-breaking space. (while (string-match "^[ \t]+" contents) (let* ((num-ws (length (match-string 0 contents))) (ws (let (out) (dotimes (i num-ws out) (setq out (concat out " ")))))) (setq contents (replace-match ws nil t contents)))) (format "

    \n%s

    " contents)) ;;; Filter Functions (defun org-gpgweb-final-function (contents backend info) "Filter to indent the HTML and convert HTML entities." (with-temp-buffer (insert contents) (buffer-substring-no-properties (point-min) (point-max)))) ;;; End-user functions ;;;###autoload (defun org-gpgweb-export-as-html (&optional async subtreep visible-only body-only ext-plist) "Export current buffer to an HTML buffer. If narrowing is active in the current buffer, only export its narrowed part. If a region is active, export that region. A non-nil optional argument ASYNC means the process should happen asynchronously. The resulting buffer should be accessible through the `org-export-stack' interface. When optional argument SUBTREEP is non-nil, export the sub-tree at point, extracting information from the headline properties first. When optional argument VISIBLE-ONLY is non-nil, don't export contents of hidden elements. The optional argument BODY-ONLY is ignored. EXT-PLIST, when provided, is a property list with external parameters overriding Org default settings, but still inferior to file-local settings. Export is done in a buffer named \"*Org HTML Export*\", which will be displayed when `org-export-show-temporary-export-buffer' is non-nil." (interactive) (org-export-to-buffer 'gpgweb "*Org GPGWEB Export*" async subtreep visible-only t ext-plist (lambda () (set-auto-mode t)))) ;;;###autoload (defun org-gpgweb-convert-region-to-html () "Assume the current region has org-mode syntax, and convert it to HTML. This can be used in any buffer. For example, you can write an itemized list in org-mode syntax in an HTML buffer and use this command to convert it." (interactive) (org-export-replace-region-by 'gpgweb)) ;;;###autoload (defun org-gpgweb-export-to-html (&optional async subtreep visible-only body-only ext-plist) "Export current buffer to a HTML file. If narrowing is active in the current buffer, only export its narrowed part. If a region is active, export that region. A non-nil optional argument ASYNC means the process should happen asynchronously. The resulting file should be accessible through the `org-export-stack' interface. When optional argument SUBTREEP is non-nil, export the sub-tree at point, extracting information from the headline properties first. When optional argument VISIBLE-ONLY is non-nil, don't export contents of hidden elements. When optional argument BODY-ONLY is non-nil, only write code between \"\" and \"\" tags. EXT-PLIST, when provided, is a property list with external parameters overriding Org default settings, but still inferior to file-local settings. Return output file's name." (interactive) (let* ((extension (concat "." (or (plist-get ext-plist :html-extension) org-gpgweb-extension "html"))) (file (org-export-output-file-name extension subtreep)) (org-export-coding-system 'utf-8)) (org-export-to-file 'gpgweb file async subtreep visible-only body-only ext-plist))) ;;;###autoload (defun org-gpgweb-publish-to-html (plist filename pub-dir) "Publish an org file to HTML. FILENAME is the filename of the Org file to be published. PLIST is the property list for the given project. PUB-DIR is the publishing directory. Return output file name." (org-publish-org-to 'gpgweb filename (concat "." (or (plist-get plist :html-extension) org-gpgweb-extension "html")) plist pub-dir)) (provide 'ox-gpgweb) ;; Local variables: ;; generated-autoload-file: "org-loaddefs.el" ;; End: ;;; ox-gpgweb.el ends here diff --git a/web/swdb.mac b/web/swdb.mac index 2f87b99..2e91d61 100644 --- a/web/swdb.mac +++ b/web/swdb.mac @@ -1,227 +1,218 @@ # Version information # Please run make in this directory after changing this file. # # Primary FTP server base directory # #+macro: ftp_base ftp://ftp.gnupg.org/gcrypt #+macro: ftp_loc_base /ftp/gcrypt # # GnuPG-2.2 # -#+macro: gnupg22_ver 2.2.4 -#+macro: gnupg22_date 2017-12-20 -#+macro: gnupg22_size 6417k -#+macro: gnupg22_sha1 732266e8888c6f41c084d043c7a0058332ff3580 -#+macro: gnupg22_sha2 401a3e64780fdfa6d7670de0880aa5c9d589b3db7a7098979d7606cec546f2ec +#+macro: gnupg22_ver 2.2.6 +#+macro: gnupg22_date 2018-04-09 +#+macro: gnupg22_size 6450k +#+macro: gnupg22_sha1 295298debcc2c12f02a2f2fdf04aecb6d6aae396 +#+macro: gnupg22_sha2 e64d8c5fa2d05938a5080cb784a98ac21be0812f2a26f844b18f0d6a0e711984 #+macro: gnupg22_branch STABLE-BRANCH-2-2 -#+macro: gnupg22_w32_ver 2.2.4_20171220 -#+macro: gnupg22_w32_date 2017-12-20 -#+macro: gnupg22_w32_size 3817k -#+macro: gnupg22_w32_sha1 d06a1413fd901c51eba14164ddb28d99ab9f84df -#+macro: gnupg22_w32_sha2 2030f00548ec175cac4996a8128ed71393c156429d95f3e6c2f53194b2f4d885 - - -# temporary keep it as "gnupg21". In the future we will use the name of -# the stable branch even for the development versions. -#+macro: gnupg21_ver 2.2.4 -#+macro: gnupg21_date 2017-12-20 -#+macro: gnupg21_size 6417k -#+macro: gnupg21_sha1 732266e8888c6f41c084d043c7a0058332ff3580 -#+macro: gnupg21_sha2 401a3e64780fdfa6d7670de0880aa5c9d589b3db7a7098979d7606cec546f2ec -#+macro: gnupg21_branch STABLE-BRANCH-2-2 -#+macro: gnupg21_w32_ver 2.2.4_20171220 -#+macro: gnupg21_w32_date 2017-12-20 -#+macro: gnupg21_w32_size 3817k -#+macro: gnupg21_w32_sha1 d06a1413fd901c51eba14164ddb28d99ab9f84df -#+macro: gnupg21_w32_sha2 2030f00548ec175cac4996a8128ed71393c156429d95f3e6c2f53194b2f4d885 +#+macro: gnupg22_w32_ver 2.2.6_20180409 +#+macro: gnupg22_w32_date 2018-04-09 +#+macro: gnupg22_w32_size 3837k +#+macro: gnupg22_w32_sha1 c9fe66788ea40bc57a189aa13e7c83add9baec40 +#+macro: gnupg22_w32_sha2 5d426b19d9cc3d7d3c0db0dfb58af1b6a36f4ea1cfd55901bb6864e865fcccc6 # # GnuPG 2.0 (end-of-life) # #+macro: gnupg20_ver 2.0.31 #+macro: gnupg20_date 2017-12-29 #+macro: gnupg20_size 4324k #+macro: gnupg20_sha1 a7d5021a6a39dd67942e00a1239e37063edb00f0 #+macro: gnupg20_sha2 095558cfbba52fba582963e97b0c016889570b4712d6b871abeef2cf93e62293 #+macro: gnupg20_branch STABLE-BRANCH-2-0 # # GnuPG-1 # #+macro: gnupg1_ver 1.4.22 #+macro: gnupg1_date 2017-07-19 #+macro: gnupg1_size 3658k #+macro: gnupg1_sha1 4bad84fba712626cbbd5adf20988788028c5a5a6 #+macro: gnupg1_sha2 9594a24bec63a21568424242e3f198b9d9828dea5ff0c335e47b06f835f930b4 # #+macro: gnupg1_w32cli_ver 1.4.22 #+macro: gnupg1_w32cli_size 2372k #+macro: gnupg1_w32cli_sha1 27b8069872d6d2b271222ffb9322dbd6197b0b89 # # Gpg4win # -#+macro: gpg4win_ver 3.0.2 -#+macro: gpg4win_date 2017-12-08 -#+macro: gpg4win_src_size 5226k -#+macro: gpg4win_src_sha1 53f1690b4377e2d7c9931977630a05caa8fafe14 -#+macro: gpg4win_src_sha2 eda921939189648ad01156a153545941916457c0b94bff19026df3c296e326ab -#+macro: gpg4win_exe_size 26343k -#+macro: gpg4win_exe_sha1 a2dabaf0a65f3ef30c60e7522f3459c81120098e -#+macro: gpg4win_exe_sha2 c4c4e5724e9581fdcf00241b33d18eee363a1fb6cc6a737d8cb2877e3b4f9298 -#+macro: gpg4win_isrc_size 220262k -#+macro: gpg4win_isrc_sha1 51494bb278720bbe83d4fbc47543f0a1e374826b -#+macro: gpg4win_isrc_sha2 7a162a875676857d2b9927b1bbd611e24d4d670b43a25e1b6a8c771ac3253408 +#+macro: gpg4win_ver 3.1.0 +#+macro: gpg4win_date 2018-04-13 +#+macro: gpg4win_src_size 5292k +#+macro: gpg4win_src_sha1 d0a0c7665d4bc724a5f1a83763c526754be47024 +#+macro: gpg4win_src_sha2 6d697372ec4c75a29c6daa6aca00060455825966c079efac6370140929b2c4f8 +#+macro: gpg4win_exe_size 27592k +#+macro: gpg4win_exe_sha1 fb9f39199d7b096d1397dad4aa0719de5ff05b31 +#+macro: gpg4win_exe_sha2 a416aca375a80eada7edc69efdf3757988310a2f1723cd6190d9e3113d787301 +#+macro: gpg4win_isrc_size 222756k +#+macro: gpg4win_isrc_sha1 23e9a6bc7fb1eceda7ece3a6655a09789c673ef5 +#+macro: gpg4win_isrc_sha2 ca40ade2dcb55f08d412d768f7946f9199a28edc189c4dc430dcd990b2fb8315 # # GPA # #+macro: gpa_ver 0.9.10 #+macro: gpa_date 2016-11-19 #+macro: gpa_size 745k #+macro: gpa_sha1 c629348725c1bf5dafd57f8a70187dc89815ce60 #+macro: gpa_sha2 c3b9cc36fd9916e83524930f99df13b1d5f601f4c0168cb9f5d81422e282b727 # # PINENTRY # #+macro: pinentry_ver 1.1.0 #+macro: pinentry_date 2017-12-03 #+macro: pinentry_size 456k #+macro: pinentry_sha1 693bdf9f48dfb3e040d92f50b1bb464e268b9fb0 #+macro: pinentry_sha2 68076686fa724a290ea49cdf0d1c0c1500907d1b759a3bcbfbec0293e8f56570 # # GPGME # -#+macro: gpgme_ver 1.10.0 -#+macro: gpgme_date 2017-12-12 -#+macro: gpgme_size 1338k -#+macro: gpgme_sha1 77d3390887da25ed70b7ac04392360efbdca501f -#+macro: gpgme_sha2 1a8fed1197c3b99c35f403066bb344a26224d292afc048cfdfc4ccd5690a0693 +#+macro: gpgme_ver 1.11.0 +#+macro: gpgme_date 2018-04-18 +#+macro: gpgme_size 1381k +#+macro: gpgme_sha1 17772bf86eef70ab0c77cbb6df0b90f002af0030 +#+macro: gpgme_sha2 5b03adbafadab74474ded30b74c882de28d3c5c3b9ee3016ef24023d4c35d492 # # LIBGCRYPT # #+macro: libgcrypt_ver 1.8.2 #+macro: libgcrypt_date 2017-12-13 #+macro: libgcrypt_size 2897k #+macro: libgcrypt_sha1 ab8aae5d7a68f8e0988f90e11e7f6a4805af5c8d #+macro: libgcrypt_sha2 c8064cae7558144b13ef0eb87093412380efa16c4ee30ad12ecb54886a524c07 # # LIBKSBA # #+macro: libksba_ver 1.3.5 #+macro: libksba_date 2016-08-22 #+macro: libksba_size 606k #+macro: libksba_sha1 a98385734a0c3f5b713198e8d6e6e4aeb0b76fde #+macro: libksba_sha2 41444fd7a6ff73a79ad9728f985e71c9ba8cd3e5e53358e70d5f066d35c1a340 # # DirMngr (not any longer needed) # #+macro: dirmngr_ver 1.1.1 #+macro: dirmngr_date 2013-04-26 #+macro: dirmngr_size 554k #+macro: dirmngr_sha1 e708d4aa5ce852f4de3f4b58f4e4f221f5e5c690 # # LIBGPG-ERROR # -#+macro: libgpg_error_ver 1.27 -#+macro: libgpg_error_date 2017-02-28 -#+macro: libgpg_error_size 794k -#+macro: libgpg_error_sha1 a428758999ff573e62d06892e3d2c0b0f335787c -#+macro: libgpg_error_sha2 4f93aac6fecb7da2b92871bb9ee33032be6a87b174f54abf8ddf0911a22d29d2 +#+macro: libgpg_error_ver 1.29 +#+macro: libgpg_error_date 2018-04-11 +#+macro: libgpg_error_size 873k +#+macro: libgpg_error_sha1 a56241d60bb7d810fdb478463b1732b134a52a19 +#+macro: libgpg_error_sha2 ece926fa5719d17a7ad8da618712cfa2f8a796ab2f2af9d544c5bb093383b1ea +#+macro: gpgrt_ver 1.29 +#+macro: gpgrt_date 2018-04-11 +#+macro: gpgrt_size 873k +#+macro: gpgrt_sha1 a56241d60bb7d810fdb478463b1732b134a52a19 +#+macro: gpgrt_sha2 ece926fa5719d17a7ad8da618712cfa2f8a796ab2f2af9d544c5bb093383b1ea # # LIBASSUAN # #+macro: libassuan_ver 2.5.1 #+macro: libassuan_date 2017-12-07 #+macro: libassuan_size 551k #+macro: libassuan_sha1 c8432695bf1daa914a92f51e911881ed93d50604 #+macro: libassuan_sha2 47f96c37b4f2aac289f0bc1bacfa8bd8b4b209a488d3d15e2229cb6cc9b26449 # # NTBTLS # #+macro: ntbtls_ver 0.1.2 #+macro: ntbtls_date 2017-09-19 #+macro: ntbtls_size 334k #+macro: ntbtls_sha1 05cf57cd8400b338b94bdce7287397c24315ac49 #+macro: ntbtls_sha2 8240db84e50c2351b19eb8064bdfd4d25e3c157d37875c62e335df237d7bdce7 # # nPth # #+macro: npth_ver 1.5 #+macro: npth_date 2017-06-02 #+macro: npth_size 292k #+macro: npth_sha1 93ddf1a3bdbca00fb4cf811498094ca61bbb8ee1 #+macro: npth_sha2 294a690c1f537b92ed829d867bee537e46be93fbd60b16c04630fbbfcd9db3c2 # # GpgEX # -#+macro: gpgex_ver 1.0.4 -#+macro: gpgex_date 2016-03-30 -#+macro: gpgex_size 286k -#+macro: gpgex_sha1 a1521fd86b6a1c5d5865d864e5700e98f4e99dcb -#+macro: gpgex_sha2 aea2232d026219072491f1bf5b2f189a15552f66377ff4dd3b11c0f069379206 +#+macro: gpgex_ver 1.0.6 +#+macro: gpgex_date 2018-04-10 +#+macro: gpgex_size 297k +#+macro: gpgex_sha1 443270219d542f97b6f124d2101ae8d803c6dbe2 +#+macro: gpgex_sha2 d69898d1022400bd09bb684080edc95be554af736ae9c014df73543f34f7481b + # # GpgOL # -#+macro: gpgol_ver 2.0.5 -#+macro: gpgol_date 2017-12-08 -#+macro: gpgol_size 750k -#+macro: gpgol_sha1 2f7eb7453ad5c6e811823be5348eec4c78f97695 -#+macro: gpgol_sha2 8fa5d4d13edfb344ec75a0e9dce3e633e6ce81e92cd388b73e2d34a14c78d46e +#+macro: gpgol_ver 2.1.0 +#+macro: gpgol_date 2018-04-12 +#+macro: gpgol_size 775k +#+macro: gpgol_sha1 4b581ec9b8efdd02f2222c5a68934b0decef72c2 +#+macro: gpgol_sha2 3193fc5c85f7ef8cddca97c537831daf7a51f56c244f3d33ce2c3fcc01437764 # # ADNS # #+macro: adns_ver 1.4-g10-7 #+macro: adns_date 2015-11-20 #+macro: adns_sha1 d2e089d98d3faed6cad009477cc0bc030b35c646 # # zlib (mirrored at our server) # #+macro: zlib_ver 1.2.8 #+macro: zlib_sha1_gz a4d316c404ff54ca545ea71a27af7dbc29817088 # # bzip2 (mirrored and stripped down version) # #+macro: bzip2_ver 1.0.6-g10 #+macro: bzip2_sha1_gz 6e38be3377340a21a1f13ff84b5e6adce97cd1d4 # # SQLite (mirrored at our server) # #+macro: sqlite_ver 3120200 #+macro: sqlite_sha1_gz b43c2e7238e54c50b95fbbd85c48792f4f39af8c # --- end of swdb.mac --- diff --git a/web/verein/finances.org b/web/verein/finances.org index 6c33f48..a25de6e 100644 --- a/web/verein/finances.org +++ b/web/verein/finances.org @@ -1,47 +1,61 @@ #+TITLE: Finances of the GnuPG e.V #+STARTUP: showall indent #+SETUPFILE: "../share/setup.inc" #+macro: atgit [[https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg-verein.git;a=blob_plain;f=$1][$2]] * Financial Overview This page gives an overview on the financial state of the GnuPG e.V. Note that in general the name of a donor is not public; for larger donations we will however publish the name. If you have any - questions on certain transactions, please write to board@. + questions on certain transactions, please write to board@. For the + annual accounts see [[*Annual%20Accounts][below]]. -** Euro transaction +** Transactions in 2017 - Here are the transactions on our bank account. +Here are the transactions on our bank account in 2017 | Date | Debit | Credit | Balance | Description | |------------+----------+--------+-----------+--------------------------| | 2017-06-23 | 200.00 | | 200.00 | Donation: g10 Code | | 2017-06-30 | | 2.23 | 197.77 | Bank fees | | 2017-07-10 | 2000.00 | | 2197.77 | Donation: German company | | 2017-07-25 | 59005.30 | | 61203.07 | Transfer from WHS | -| 2017-07-31 | | 5.80 | 61198.27 | Bank fees | +| 2017-07-31 | | 5.80 | 61197.27 | Bank fees | | 2017-08-31 | | 5.00 | 61192.27 | Bank fees | | 2017-09-07 | 3615.64 | | 64807.91 | Exchange of 1 BTC | | 2017-09-11 | 38650.36 | | 103458.27 | Exchange of 10 BTC | | 2017-09-14 | 35868.08 | | 139326.35 | Exchange of 10 BTC | | 2017-09-19 | | 119.00 | 139207.35 | Design postcards | | 2017-09-29 | | 12.00 | 139195.35 | Banking card | -| 2017-09-29 | | 6.30 | 139190.05 | Bank fees | +| 2017-09-29 | | 6.30 | 139189.05 | Bank fees | | 2017-10-06 | 18197.53 | | 157386.58 | Exchange of 5 BTC | | 2017-10-12 | 220.00 | | 157606.58 | Donation kernel-recipes | | 2017-10-12 | 310.00 | | 157916.58 | Donation kernel-recipes | +| 2017-10-28 | | 6.20 | 157910.38 | Bank fees | +| 2017-11-30 | | 5.00 | 157905.38 | Bank fees | +| 2017-12-29 | | 5.00 | 157900.38 | Bank fees | +|------------+----------+--------+-----------+--------------------------| The 59.000 € from the Wau Holland Stiftung have been collected by them for the GnuPG project since 2013. After the Verein reached charitable state they were able to transfer that money. Many thanks to them. -We have produced two postcards to be used as giveaways at shows and -other opportunities. Our account has not yet been charged for -printing costs. +As of 2018-01-02 we own 0.4608 confirmed BTC. 26 BTC have been +transferred to our Euro account in September/October 2017 (see above). + +We produced two kinds of postcards to be used as giveaways at shows +and other opportunities. + +** Transactions in 2018 + +| Date | Debit | Credit | Balance | Description | +|------------+---------+--------+-----------+--------------------------| +| 2018-01-16 | 1000.00 | | 158900.38 | Donation: German company | + + -** Bitcoin transactions +* Annual Accounts - As of 2017-10-06 we own 0.12 BTC. 26 BTC have been - transferred to our Euro account (see above). +- Annual accounts for 2017: [[https://gnupg.org/ftp/verein/annual-accounts-2017.pdf][pdf]] ([[https://gnupg.org/ftp/verein/annual-accounts-2017.pdf.sig][sig]]) [[https://gnupg.org/ftp/verein/annual-accounts-2017.html][html]] ([[https://gnupg.org/ftp/verein/annual-accounts-2017.html.sig][sig]]) [[https://gnupg.org/ftp/verein/annual-accounts-2017.de.pdf][pdf (German)]] ([[https://gnupg.org/ftp/verein/annual-accounts-2017.de.pdf.sig][sig]]) diff --git a/web/verein/index.org b/web/verein/index.org index 8ef7350..8569107 100644 --- a/web/verein/index.org +++ b/web/verein/index.org @@ -1,36 +1,32 @@ #+TITLE: GnuPG e.V. #+STARTUP: showall #+SETUPFILE: "../share/setup.inc" #+macro: atgit [[https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg-verein.git;a=blob_plain;f=$1][$2]] * The GnuPG e.V. -In February 2017 several GnuPG developer came together for a 3 day -hackathon. While having some beer in the [[http://www.bilkinfo.de/kneipen/tigges.html][Tigges]] on one evening the -lingering plan for setting up a legal entity was finally agreed upon. -Work on the constitution started right away and the founding assembly -commenced on the next day at 13:37. - -The 7 founding members are: Andre Heinecke, Justus Winter, Kai -Michaelis, Marcus Brinkmann, Neal Walfied, Werner Koch, and Yutaka -Niibe. The elected chair is Werner, the vice Andre, and the cashier -Marcus. Marcus resigned on 2017-08-02; a new cashier needs to be -elected soon. - -The rules on how to apply for membership will soon be posted. The -registration number is /VR11482/ at /Amtsgericht Düsseldorf/. The tax -office Düsseldorf-Altstadt confirmed our charitable state on -2017-04-03. +The GnuPG e.V. is a charitable legal person (a German “Verein”) to +improve data protection, data sovereignty and customer protection in +in our supranational networked society. To achieve these goals the +Verein seeks for international cooperation with people and +organizations and supports the development and distribution of Free +and Open Source software. + +The Verein was founded on February 8, 2017 by 7 active GnuPG +developers. Its registration number is /VR11482/ at /Amtsgericht +Düsseldorf/. The tax office Düsseldorf-Altstadt has confirmed the +charitable state. As of 2018-02-02 the Verein has 15 regular members +represented by its board: Werner Koch (chairperson), Martin +Gollowitzer (vice-chair) and Andre Heinecke (treasurer). ** Menu - [[file:members.org][Members]] - [[file:finances.org][Financial overview]] - {{{atgit(legal/constitution.de.pdf,constitution)}}} [German] - {{{atgit(legal/constitution.en.pdf,constitution)}}} [English translation] - {{{atgit(legal/founding-protocol-20170208.txt,Founding protocol)}}} [German] - - +- [[https://gnupg.org/ftp/verein/beitragsordnung.en.pdf][Membership fee regulations (English)]] [[https://gnupg.org/ftp/verein/beitragsordnung.de.pdf][(German)]] # eof diff --git a/web/verein/members.org b/web/verein/members.org index 93c34d7..4d88133 100644 --- a/web/verein/members.org +++ b/web/verein/members.org @@ -1,34 +1,39 @@ #+TITLE: Members of the GnuPG e.V #+STARTUP: showall #+SETUPFILE: "../share/setup.inc" * List of GnuPG e.V Members. -To apply for membership please write to board@. We expect that you -have a more than average interest in GnuPG or OpenPGP and that you are -active in development or in evangelizing end-to-end encryption. +To apply for membership please write to board at gnupg dot org. For +regular members we expect that you have a more than average interest +in GnuPG and that you are active in development or in evangelizing +end-to-end encryption. It is also possible to support the Verein by +applying as a supporting member. See the membership regulations +([[https://gnupg.org/ftp/verein/beitragsordnung.en.pdf][English]], [[https://gnupg.org/ftp/verein/beitragsordnung.de.pdf][German]]) for details. + ** The regular members - Andre Heinecke - Bernhard Reiter - Damien Goutte-Gattat - Daniel Kahn Gillmor + - Guilhem Moulin - Holger Smolinski - Justus Winter - Kai Michaelis - Kristian Fiskerstrand - Martin Gollowitzer - Maurice Kemmann - Neal Walfied - Phil Pennock - Werner Koch - Yutaka Niibe *** Former members - Marcus Brinkmann ** The supporting members - /none so far - we still need to setup rules/ + /none so far/