docs: python bindings howto
* Fixed and tested the changes necessary for org-mode to correctly parse pythonic (Python 3) indentation. * Updated the source blocks to recommended upper case for BEGIN_SRC and END_SRC. * Tested and confirmed XHTML output matches correct examples. * Tested against pseudo-control output via exporting from org-mode to org-mode and then exporting that to XHTML. Remaining differences appear to be discarding the custom tags used to provide X[HT]ML id elements to each section which does not appear to offer any benefit. * Exporting directly to XHTML or other HTML output should no longer cause problems, but if there are any then the first step should be exporting from org-to-org and then exporting that to XHTML. Tested-by: Ben McGinnes <ben@adversary.org> Signed-off-by: Ben McGinnes <ben@adversary.org>
This commit is contained in:
parent
d7c5366d58
commit
4d1642b11e
@ -340,41 +340,41 @@ pattern is upper or lower case.
|
||||
|
||||
So this is the best method:
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
|
||||
k = gpg.Context().keylist(pattern="258E88DCBD3CD44D8E7AB43F6ECB6AF0DEADBEEF")
|
||||
keys = list(k)
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
This is passable and very likely to be common:
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
|
||||
k = gpg.Context().keylist(pattern="0x6ECB6AF0DEADBEEF")
|
||||
keys = list(k)
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
And this is a really bad idea:
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
|
||||
k = gpg.Context().keylist(pattern="0xDEADBEEF")
|
||||
keys = list(k)
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
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:
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
|
||||
ncsc = gpg.Context().keylist(pattern="ncsc.mil")
|
||||
nsa = list(ncsc)
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
|
||||
*** Counting keys
|
||||
@ -386,7 +386,7 @@ 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.
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
|
||||
c = gpg.Context()
|
||||
@ -403,7 +403,7 @@ print("""
|
||||
Number of secret keys: {0}
|
||||
Number of public keys: {1}
|
||||
""".format(secnum, pubnum))
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
|
||||
** Get key
|
||||
@ -424,22 +424,22 @@ 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:
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
|
||||
fingerprint = "80615870F5BAD690333686D0F2AD85AC1E42B367"
|
||||
key = gpg.Context().get_key(fingerprint)
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
Whereas this example demonstrates selecting the author's current key
|
||||
with the =secret= key word argument set to =True=:
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
|
||||
fingerprint = "DB4724E6FA4286C92B4E55C4321E4E2373590E5D"
|
||||
key = gpg.Context().get_key(fingerprint, secret=True)
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
It is, of course, quite possible to select expired, disabled and
|
||||
revoked keys with this function, but only to effectively display
|
||||
@ -463,7 +463,7 @@ keyservers via the web using the requests module. Since requests
|
||||
returns the content as a bytes literal object, we can then use that
|
||||
directly to import the resulting data into our keybox.
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
import os.path
|
||||
import requests
|
||||
@ -500,11 +500,10 @@ elif result is not None and hasattr(result, "considered") is True:
|
||||
""".format(num_keys, new_revs, new_sigs, new_subs, new_uids, new_scrt,
|
||||
nochange))
|
||||
for i in range(num_keys):
|
||||
print(result.imports[i].fpr)
|
||||
print("")
|
||||
print("{0}\n".format(result.imports[i].fpr))
|
||||
else:
|
||||
pass
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
*NOTE:* When searching for a key ID of any length or a fingerprint
|
||||
(without spaces), the SKS servers require the the leading =0x=
|
||||
@ -538,7 +537,7 @@ alternative, the =key_export_minimal()= method, will do the same thing
|
||||
except producing a minimised output with extra signatures and third
|
||||
party signatures or certifications removed.
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
import os.path
|
||||
import sys
|
||||
@ -586,14 +585,14 @@ if result is not None:
|
||||
f.write(result)
|
||||
else:
|
||||
pass
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
It is important to note that the result will only return =None= when a
|
||||
pattern has been entered for =logrus=, but it has not matched any
|
||||
keys. When the search pattern itself is set to =None= this triggers
|
||||
the exporting of the entire public keybox.
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
import os.path
|
||||
import sys
|
||||
@ -641,7 +640,7 @@ if result is not None:
|
||||
f.write(result)
|
||||
else:
|
||||
pass
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
|
||||
*** Exporting secret keys
|
||||
@ -657,7 +656,7 @@ The following example exports the secret key to a file which is then
|
||||
set with the same permissions as the output files created by the
|
||||
command line secret key export options.
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
import os
|
||||
import os.path
|
||||
@ -709,7 +708,7 @@ if result is not None:
|
||||
os.chmod(keyfile, 0o600)
|
||||
else:
|
||||
pass
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
Alternatively the approach of the following script can be used. This
|
||||
longer example saves the exported secret key(s) in files in the GnuPG
|
||||
@ -718,7 +717,7 @@ readable and writable by the user. It also exports the secret key(s)
|
||||
twice in order to output both GPG binary (=.gpg=) and ASCII armoured
|
||||
(=.asc=) files.
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
import os
|
||||
import os.path
|
||||
@ -803,7 +802,7 @@ if b_result is not None:
|
||||
os.chmod(gpgfile, 0o600)
|
||||
else:
|
||||
pass
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
|
||||
* Basic Functions
|
||||
@ -850,7 +849,7 @@ trust model settings for recipient keys (defaults to =False=);
|
||||
=expect_sign=, prepare for signing (defaults to =False=); =compress=,
|
||||
compresses the plaintext prior to encryption (defaults to =True=).
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
|
||||
a_key = "0x12345678DEADBEEF"
|
||||
@ -867,14 +866,14 @@ ciphertext, result, sign_result = c.encrypt(text, recipients=rkey, sign=False)
|
||||
|
||||
with open("secret_plans.txt.asc", "wb") as afile:
|
||||
afile.write(ciphertext)
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
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:
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
|
||||
a_key = "0x12345678DEADBEEF"
|
||||
@ -890,7 +889,7 @@ ciphertext, result, sign_result = c.encrypt(text, recipients=rkey, sign=True,
|
||||
|
||||
with open("secret_plans.txt.asc", "wb") as afile:
|
||||
afile.write(ciphertext)
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
If the =recipients= paramater is empty then the plaintext is encrypted
|
||||
symmetrically. If no =passphrase= is supplied as a parameter or via a
|
||||
@ -911,7 +910,7 @@ email address on the =gnupg.org= domain,[fn:3] but does /not/ encrypt
|
||||
to a default key or other key which is configured to normally encrypt
|
||||
to.
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
|
||||
text = b"""Oh look, another test message.
|
||||
@ -940,17 +939,17 @@ ciphertext, result, sign_result = c.encrypt(text, recipients=logrus,
|
||||
|
||||
with open("secret_plans.txt.asc", "wb") as afile:
|
||||
afile.write(ciphertext)
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
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:
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
ciphertext, result, sign_result = c.encrypt(text, recipients=logrus,
|
||||
always_trust=True,
|
||||
add_encrypt_to=True)
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
The only keyword arguments requiring modification are those for which
|
||||
the default values are changing. The default value of =sign= is
|
||||
@ -962,7 +961,7 @@ 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:
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
|
||||
with open("secret_plans.txt.asc", "rb") as afile:
|
||||
@ -994,7 +993,7 @@ for i in range(len(rpattern)):
|
||||
afile.write(ciphertext)
|
||||
except:
|
||||
pass
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
This will attempt to encrypt to all the keys searched for, then remove
|
||||
invalid recipients if it fails and try again.
|
||||
@ -1014,7 +1013,7 @@ 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.
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
|
||||
ciphertext = input("Enter path and filename of encrypted file: ")
|
||||
@ -1032,7 +1031,7 @@ with open(ciphertext, "rb") as cfile:
|
||||
nfile.write(plaintext)
|
||||
else:
|
||||
pass
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
The data available in =plaintext= in this example is the decrypted
|
||||
content as a byte object, the recipient key IDs and algorithms in
|
||||
@ -1059,13 +1058,13 @@ 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.
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
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)
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
The signing examples in the following sections include the explicitly
|
||||
designated =signers= parameter in two of the five examples; once where
|
||||
@ -1100,7 +1099,7 @@ multiple keys are involved; from the preferences saved into the key
|
||||
itself or by comparison with the preferences with all other keys
|
||||
involved.
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
|
||||
text0 = """Declaration of ... something.
|
||||
@ -1113,14 +1112,14 @@ 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())
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
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.
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
|
||||
with open("/path/to/statement.txt", "rb") as tfile:
|
||||
@ -1131,7 +1130,7 @@ 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)
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
|
||||
*** Detached signing messages and files
|
||||
@ -1143,7 +1142,7 @@ 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).
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
|
||||
text0 = """Declaration of ... something.
|
||||
@ -1156,12 +1155,12 @@ 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())
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
As with normal signatures, detached signatures are best handled as
|
||||
byte literals, even when the output is ASCII armoured.
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
|
||||
with open("/path/to/statement.txt", "rb") as tfile:
|
||||
@ -1172,7 +1171,7 @@ 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)
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
|
||||
*** Clearsigning messages or text
|
||||
@ -1184,7 +1183,7 @@ 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.
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
|
||||
text0 = """Declaration of ... something.
|
||||
@ -1197,12 +1196,12 @@ 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())
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
In spite of the appearance of a clear-signed message, the data handled
|
||||
by GPGME in signing it must still be byte literals.
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
|
||||
with open("/path/to/statement.txt", "rb") as tfile:
|
||||
@ -1213,7 +1212,7 @@ 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)
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
|
||||
** Signature verification
|
||||
@ -1229,7 +1228,7 @@ 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:
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
import time
|
||||
|
||||
@ -1256,12 +1255,12 @@ made at {2}
|
||||
time.ctime(sign.timestamp)))
|
||||
else:
|
||||
pass
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
Whereas this next example, which is almost identical would work with
|
||||
normal ASCII armoured files and with clear-signed files:
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
import time
|
||||
|
||||
@ -1288,13 +1287,13 @@ made at {2}
|
||||
time.ctime(sign.timestamp)))
|
||||
else:
|
||||
pass
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
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:
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
with open(filename, "rb") as afile:
|
||||
text = afile.read()
|
||||
|
||||
@ -1302,7 +1301,7 @@ if text == data:
|
||||
print("Good signature.")
|
||||
else:
|
||||
pass
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
The following two examples, however, deal with detached signatures.
|
||||
With his method of verification the data that was signed does not get
|
||||
@ -1310,7 +1309,7 @@ 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.
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
import time
|
||||
|
||||
@ -1337,9 +1336,9 @@ made at {2}
|
||||
time.ctime(sign.timestamp)))
|
||||
else:
|
||||
pass
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
import time
|
||||
|
||||
@ -1366,7 +1365,7 @@ made at {2}
|
||||
time.ctime(sign.timestamp)))
|
||||
else:
|
||||
pass
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
|
||||
* Creating keys and subkeys
|
||||
@ -1387,7 +1386,7 @@ 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:
|
||||
|
||||
#+begin_src conf
|
||||
#+BEGIN_SRC conf
|
||||
expert
|
||||
allow-freeform-uid
|
||||
allow-secret-key-import
|
||||
@ -1400,7 +1399,7 @@ preferences contains the following configuration parameters:
|
||||
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
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
|
||||
** Primary key
|
||||
@ -1423,7 +1422,7 @@ 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=.
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
|
||||
c = gpg.Context()
|
||||
@ -1433,7 +1432,7 @@ userid = "Danger Mouse <dm@secret.example.net>"
|
||||
|
||||
dmkey = c.create_key(userid, algorithm="rsa3072", expires_in=31536000,
|
||||
sign=True, certify=True)
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
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
|
||||
@ -1451,7 +1450,7 @@ already set and the correct directory and file permissions.
|
||||
The successful generation of the key can be confirmed via the returned
|
||||
=GenkeyResult= object, which includes the following data:
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
print("""
|
||||
Fingerprint: {0}
|
||||
Primary Key: {1}
|
||||
@ -1461,12 +1460,12 @@ print("""
|
||||
User IDs: {5}
|
||||
""".format(dmkey.fpr, dmkey.primary, dmkey.pubkey, dmkey.seckey, dmkey.sub,
|
||||
dmkey.uid))
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
Alternatively the information can be confirmed using the command line
|
||||
program:
|
||||
|
||||
#+begin_src shell
|
||||
#+BEGIN_SRC shell
|
||||
bash-4.4$ gpg --homedir ~/.gnupg-dm -K
|
||||
~/.gnupg-dm/pubring.kbx
|
||||
----------------------
|
||||
@ -1475,7 +1474,7 @@ program:
|
||||
uid [ultimate] Danger Mouse <dm@secret.example.net>
|
||||
|
||||
bash-4.4$
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
As with generating keys manually, to preconfigure expanded preferences
|
||||
for the cipher, digest and compression algorithms, the =gpg.conf= file
|
||||
@ -1483,7 +1482,7 @@ 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:
|
||||
|
||||
#+begin_src shell
|
||||
#+BEGIN_SRC shell
|
||||
bash-4.4$ gpg --homedir ~/.gnupg-dm --edit-key 177B7C25DB99745EE2EE13ED026D2F19E99E63AA showpref quit
|
||||
Secret key is available.
|
||||
|
||||
@ -1499,7 +1498,7 @@ file in order to be able to generate this:
|
||||
Features: MDC, Keyserver no-modify
|
||||
|
||||
bash-4.4$
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
|
||||
** Subkeys
|
||||
@ -1518,7 +1517,7 @@ 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.
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
|
||||
c = gpg.Context()
|
||||
@ -1527,11 +1526,11 @@ 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)
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
As with the primary key, the results here can be checked with:
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
print("""
|
||||
Fingerprint: {0}
|
||||
Primary Key: {1}
|
||||
@ -1541,11 +1540,11 @@ print("""
|
||||
User IDs: {5}
|
||||
""".format(dmsub.fpr, dmsub.primary, dmsub.pubkey, dmsub.seckey, dmsub.sub,
|
||||
dmsub.uid))
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
As well as on the command line with:
|
||||
|
||||
#+begin_src shell
|
||||
#+BEGIN_SRC shell
|
||||
bash-4.4$ gpg --homedir ~/.gnupg-dm -K
|
||||
~/.gnupg-dm/pubring.kbx
|
||||
----------------------
|
||||
@ -1555,7 +1554,7 @@ As well as on the command line with:
|
||||
ssb rsa3072 2018-03-15 [E] [expires: 2018-09-13]
|
||||
|
||||
bash-4.4$
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
|
||||
** User IDs
|
||||
@ -1574,7 +1573,7 @@ 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=.
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
|
||||
c = gpg.Context()
|
||||
@ -1585,11 +1584,11 @@ key = c.get_key(dmfpr, secret=True)
|
||||
uid = "Danger Mouse <danger.mouse@secret.example.net>"
|
||||
|
||||
c.key_add_uid(key, uid)
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
Unsurprisingly the result of this is:
|
||||
|
||||
#+begin_src shell
|
||||
#+BEGIN_SRC shell
|
||||
bash-4.4$ gpg --homedir ~/.gnupg-dm -K
|
||||
~/.gnupg-dm/pubring.kbx
|
||||
----------------------
|
||||
@ -1600,7 +1599,7 @@ Unsurprisingly the result of this is:
|
||||
ssb rsa3072 2018-03-15 [E] [expires: 2018-09-13]
|
||||
|
||||
bash-4.4$
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
|
||||
*** Revokinging User IDs
|
||||
@ -1611,7 +1610,7 @@ Unsurprisingly the result of this is:
|
||||
Revoking a user ID is a fairly similar process, except that it uses
|
||||
the =key_revoke_uid= method.
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
|
||||
c = gpg.Context()
|
||||
@ -1622,7 +1621,7 @@ key = c.get_key(dmfpr, secret=True)
|
||||
uid = "Danger Mouse <danger.mouse@secret.example.net>"
|
||||
|
||||
c.key_revoke_uid(key, uid)
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
|
||||
** Key certification
|
||||
@ -1651,7 +1650,7 @@ 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:
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
|
||||
c = gpg.Context()
|
||||
@ -1660,7 +1659,7 @@ 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)
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
|
||||
* Miscellaneous work-arounds
|
||||
@ -1682,7 +1681,7 @@ MUAs readily.
|
||||
The following code, however, provides a work-around for obtaining this
|
||||
information in Python.
|
||||
|
||||
#+begin_src python -i
|
||||
#+BEGIN_SRC python -i
|
||||
import subprocess
|
||||
|
||||
lines = subprocess.getoutput("gpgconf --list-options gpg").splitlines()
|
||||
@ -1704,7 +1703,7 @@ for i in range(len(groups)):
|
||||
|
||||
for i in range(len(group_lists)):
|
||||
group_lists[i][1] = group_lists[i][1].split()
|
||||
#+end_src
|
||||
#+END_SRC
|
||||
|
||||
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]=
|
||||
|
Loading…
Reference in New Issue
Block a user