From 64c5886132aceefc9d9600a3a6dbbbf404b95b81 Mon Sep 17 00:00:00 2001 From: Ben McGinnes Date: Mon, 19 Mar 2018 10:00:44 +1100 Subject: [PATCH] doc: python bindings howto * Replaced the single encryption methods with one main way (i.e. cut the low level stuff involving SEEK_SET instructions). --- lang/python/docs/GPGMEpythonHOWTOen.org | 153 ++++++++---------------- 1 file changed, 53 insertions(+), 100 deletions(-) diff --git a/lang/python/docs/GPGMEpythonHOWTOen.org b/lang/python/docs/GPGMEpythonHOWTOen.org index c0606dd9..a9608304 100644 --- a/lang/python/docs/GPGMEpythonHOWTOen.org +++ b/lang/python/docs/GPGMEpythonHOWTOen.org @@ -436,6 +436,7 @@ section we will look at how to programmatically encrypt data, decrypt it, sign it and verify signatures. + ** Encryption :PROPERTIES: :CUSTOM_ID: howto-basic-encryption @@ -446,85 +447,35 @@ the second example the message will be encrypted to multiple recipients. + *** Encrypting to one key :PROPERTIES: :CUSTOM_ID: howto-basic-encryption-single :END: - The text is then encapsulated in a GPGME Data object as =plain= and - the =cipher= object is created with another Data object. Then we - create the Context as =c= and set it to use the ASCII armoured - OpenPGP format. In later examples there will be alternative - methods of setting the OpenPGP output to be ASCII armoured. + 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. - Next we prepare a keylist object in our Context and follow it with - specifying the recipients as =r=. Note that the configuration in - one's =gpg.conf= file is honoured, so if you have the options set - to encrypt to one key or to a default key, that will be included - with this operation. - - This is followed by a quick check to be sure that the recipient is - actually selected and that the key is available. Assuming it is, - the encryption can proceed, but if not a message will print stating - the key was not found. - - The encryption operation is invoked within the Context with the - =c.op_encrypt= function, loading the recipients (=r=), the message - (=plain=) and the =cipher=. The =cipher.seek= uses =os.SEEK_SET= - to set the data to the correct byte format for GPGME to use it. - - At this point we no longer need the plaintext material, so we - delete both the =text= and the =plain= objects. Then we write the - encrypted data out to a file, =secret_plans.txt.asc=. - - #+begin_src python - import gpg - import os - - rkey = "0x12345678DEADBEEF" - text = """ - Some plain text to test with. Obtained from any input source Python can read. - - It makes no difference whether it is string or bytes, but the bindings always - produce byte output data. Which is useful to know when writing out either the - encrypted or decrypted results. - - """ - - plain = gpg.core.Data(text) - cipher = gpg.core.Data() - c = gpg.core.Context() - c.set_armor(1) - - c.op_keylist_start(rkey, 0) - r = c.op_keylist_next() - - if r == None: - print("""The key for user "{0}" was not found""".format(rkey)) - else: - try: - c.op_encrypt([r], 1, plain, cipher) - cipher.seek(0, os.SEEK_SET) - with open("secret_plans.txt.asc", "wb") as afile: - afile.write(cipher.read()) - except gpg.errors.GPGMEError as ex: - print(ex.getstring()) - #+end_src - -*** Encrypting to one key using the second method - :PROPERTIES: - :CUSTOM_ID: howto-basic-encryption-monogamous - :END: - - This example re-creates the first encryption example except it - uses the same =encrypt= method used in the subsequent examples - instead of the =op_encrypt= method. This means that, unlike the - =op_encrypt= method, it /must/ use byte literal input data. + 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=). #+begin_src python import gpg - rkey = "0x12345678DEADBEEF" + a_key = "0x12345678DEADBEEF" text = b"""Some text to test with. Since the text in this case must be bytes, it is most likely that @@ -534,56 +485,51 @@ """ c = gpg.Context(armor=True) - rpattern = list(c.keylist(pattern=rkey, secret=False)) - logrus = [] - - for i in range(len(rpattern)): - if rpattern[i].can_encrypt == 1: - logrus.append(rpattern[i]) - - cipher = c.encrypt(text, recipients=logrus, sign=False, always_trust=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(cipher[0]) + afile.write(ciphertext) #+end_src - With one or two exceptions, this method will probably prove to be - easier to implement than the first method and thus it is the - recommended encryption method. Though it is even more likely to - be used like this: + 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 import gpg - rkey = "0x12345678DEADBEEF" + a_key = "0x12345678DEADBEEF" - afile = open("secret_plans.txt", "rb") - text = afile.read() - afile.close() + with open("secret_plans.txt", "rb") as afile: + text = afile.read() c = gpg.Context(armor=True) - rpattern = list(c.keylist(pattern=rkey, secret=False)) - logrus = [] - - for i in range(len(rpattern)): - if rpattern[i].can_encrypt == 1: - logrus.append(rpattern[i]) - - cipher = c.encrypt(text, recipients=logrus, sign=False, always_trust=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(cipher[0]) + afile.write(ciphertext) #+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 callback registered with the =Context()= then + an out-of-band prompt for the passphrase via pinentry will be + invoked. + + *** Encrypting to multiple keys :PROPERTIES: :CUSTOM_ID: howto-basic-encryption-multiple :END: - Encrypting to multiple keys, in addition to a default key or a key - configured to always encrypt to, is a little different and uses a - slightly different call to the =op_encrypt= call demonstrated in the - previous section. + 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,[fn:3] but does /not/ encrypt @@ -711,7 +657,8 @@ :CUSTOM_ID: howto-basic-signing :END: - The following sections demonstrate how to specify + The following sections demonstrate how to specify keys to sign with. + *** Signing key selection :PROPERTIES: @@ -743,6 +690,7 @@ bytes or None and not a list. A string with two fingerprints won't match any single key. + *** Normal or default signing messages or files :PROPERTIES: :CUSTOM_ID: howto-basic-signing-normal @@ -798,6 +746,7 @@ afile.write(signed[0]) #+end_src + *** Detached signing messages and files :PROPERTIES: :CUSTOM_ID: howto-basic-signing-detached @@ -840,6 +789,7 @@ afile.write(signed[0]) #+end_src + *** Clearsigning messages or text :PROPERTIES: :CUSTOM_ID: howto-basic-signing-clear @@ -1307,6 +1257,7 @@ :CUSTOM_ID: cheats-and-hacks :END: + ** Group lines :PROPERTIES: :CUSTOM_ID: group-lines @@ -1357,6 +1308,7 @@ :CUSTOM_ID: copyright-and-license :END: + ** Copyright (C) The GnuPG Project, 2018 :PROPERTIES: :CUSTOM_ID: copyright @@ -1364,6 +1316,7 @@ Copyright © The GnuPG Project, 2018. + ** License GPL compatible :PROPERTIES: :CUSTOM_ID: license