aboutsummaryrefslogtreecommitdiffstats
path: root/lang/python/docs/dita/howto/part04
diff options
context:
space:
mode:
Diffstat (limited to 'lang/python/docs/dita/howto/part04')
-rw-r--r--lang/python/docs/dita/howto/part04/basic-functions.dita12
-rw-r--r--lang/python/docs/dita/howto/part04/clear-signing.dita42
-rw-r--r--lang/python/docs/dita/howto/part04/decryption.dita31
-rw-r--r--lang/python/docs/dita/howto/part04/default-signing.dita51
-rw-r--r--lang/python/docs/dita/howto/part04/detached-signing.dita42
-rw-r--r--lang/python/docs/dita/howto/part04/encrypt-to-many.dita100
-rw-r--r--lang/python/docs/dita/howto/part04/encrypt-to-one.dita83
-rw-r--r--lang/python/docs/dita/howto/part04/encryption.dita12
-rw-r--r--lang/python/docs/dita/howto/part04/signing-key-selection.dita28
-rw-r--r--lang/python/docs/dita/howto/part04/signing.dita11
-rw-r--r--lang/python/docs/dita/howto/part04/verification.dita150
11 files changed, 562 insertions, 0 deletions
diff --git a/lang/python/docs/dita/howto/part04/basic-functions.dita b/lang/python/docs/dita/howto/part04/basic-functions.dita
new file mode 100644
index 00000000..a0c64b56
--- /dev/null
+++ b/lang/python/docs/dita/howto/part04/basic-functions.dita
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE dita PUBLIC "-//OASIS//DTD DITA Composite//EN" "ditabase.dtd">
+<dita>
+ <topic id="topic_w5f_zpy_5db">
+ <title>Basic Functions</title>
+ <body>
+ <p>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.</p>
+ </body>
+ </topic>
+</dita>
diff --git a/lang/python/docs/dita/howto/part04/clear-signing.dita b/lang/python/docs/dita/howto/part04/clear-signing.dita
new file mode 100644
index 00000000..c6104922
--- /dev/null
+++ b/lang/python/docs/dita/howto/part04/clear-signing.dita
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE dita PUBLIC "-//OASIS//DTD DITA Composite//EN" "ditabase.dtd">
+<dita>
+ <topic id="topic_ydy_5qz_5db">
+ <title>Clear Signatures</title>
+ <body>
+ <p>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.</p>
+ <p>
+ <codeblock id="clrsig-1" outputclass="language-python">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())
+</codeblock>
+ </p>
+ <p>In spite of the appearance of a clear-signed message, the data handled by GPGME in signing
+ it must still be byte literals.</p>
+ <p>
+ <codeblock id="clrsig-2" outputclass="language-python">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)
+</codeblock>
+ </p>
+ </body>
+ </topic>
+</dita>
diff --git a/lang/python/docs/dita/howto/part04/decryption.dita b/lang/python/docs/dita/howto/part04/decryption.dita
new file mode 100644
index 00000000..e3918c55
--- /dev/null
+++ b/lang/python/docs/dita/howto/part04/decryption.dita
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE dita PUBLIC "-//OASIS//DTD DITA Composite//EN" "ditabase.dtd">
+<dita>
+ <topic id="topic_vqx_tqy_5db">
+ <title>Decryption</title>
+ <body>
+ <p>Decrypting something encrypted to a key in one's secret keyring is fairly straight
+ forward.</p>
+ <p>In this example code, however, preconfiguring either <codeph>gpg.Context()</codeph> or
+ <codeph>gpg.core.Context()</codeph> as <codeph>c</codeph> 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.</p>
+ <p>
+ <codeblock id="decry-1" outputclass="language-python">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)
+</codeblock>
+ </p>
+ <p>The data available in <codeph>plaintext</codeph> in this example is the decrypted content
+ as a byte object, the recipient key IDs and algorithms in <codeph>result</codeph> and the
+ results of verifying any signatures of the data in <codeph>verify_result</codeph>.</p>
+ </body>
+ </topic>
+</dita>
diff --git a/lang/python/docs/dita/howto/part04/default-signing.dita b/lang/python/docs/dita/howto/part04/default-signing.dita
new file mode 100644
index 00000000..d3a227b5
--- /dev/null
+++ b/lang/python/docs/dita/howto/part04/default-signing.dita
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE dita PUBLIC "-//OASIS//DTD DITA Composite//EN" "ditabase.dtd">
+<dita>
+ <topic id="topic_ntx_sqz_5db">
+ <title>Default Signatures</title>
+ <body>
+ <p>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.</p>
+ <p>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
+ <codeph>gpg.Context().armor</codeph>.</p>
+ <p>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.</p>
+ <p>
+ <codeblock id="defsig-1" outputclass="language-python">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())
+</codeblock>
+ </p>
+ <p>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.</p>
+ <p>
+ <codeblock id="defsig-2" outputclass="language-python">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)
+</codeblock>
+ </p>
+ </body>
+ </topic>
+</dita>
diff --git a/lang/python/docs/dita/howto/part04/detached-signing.dita b/lang/python/docs/dita/howto/part04/detached-signing.dita
new file mode 100644
index 00000000..38406eff
--- /dev/null
+++ b/lang/python/docs/dita/howto/part04/detached-signing.dita
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE dita PUBLIC "-//OASIS//DTD DITA Composite//EN" "ditabase.dtd">
+<dita>
+ <topic id="topic_rfg_5qz_5db">
+ <title>Detached Signatures</title>
+ <body>
+ <p>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).</p>
+ <p>
+ <codeblock id="detsig-1" outputclass="language-python">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())
+</codeblock>
+ </p>
+ <p>As with normal signatures, detached signatures are best handled as byte literals, even when
+ the output is ASCII armoured.</p>
+ <p>
+ <codeblock id="detsig-2" outputclass="language-python">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)
+</codeblock>
+ </p>
+ </body>
+ </topic>
+</dita>
diff --git a/lang/python/docs/dita/howto/part04/encrypt-to-many.dita b/lang/python/docs/dita/howto/part04/encrypt-to-many.dita
new file mode 100644
index 00000000..df3454f8
--- /dev/null
+++ b/lang/python/docs/dita/howto/part04/encrypt-to-many.dita
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE dita PUBLIC "-//OASIS//DTD DITA Composite//EN" "ditabase.dtd">
+<dita>
+ <topic id="topic_wmg_tjz_5db">
+ <title>Encrypting to Multiple Keys</title>
+ <body>
+ <p>Encrypting to multiple keys essentially just expands upon the key selection process
+ and the recipients from the previous examples.</p>
+ <p>The following example encrypts a message (<codeph>text</codeph>) to everyone with an email
+ address on the <codeph>gnupg.org </codeph>domain,<fn>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.</fn> but does <i>not</i> encrypt to a default key or other
+ key which is configured to normally encrypt to.</p>
+ <p>
+ <codeblock id="enc2-1" outputclass="language-python">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 f:
+ f.write(ciphertext)
+</codeblock>
+ </p>
+ <p>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 <codeph>c.encrypt</codeph>
+ line to this:</p>
+ <p>
+ <codeblock id="enc2-2" outputclass="language-python">ciphertext, result, sign_result = c.encrypt(text, recipients=logrus,
+ always_trust=True,
+ add_encrypt_to=True)
+</codeblock>
+ </p>
+ <p>The only keyword arguments requiring modification are those for which the default values
+ are changing. The default value of <codeph>sign</codeph> is <codeph>True</codeph>, the
+ default of <codeph>always_trust</codeph> is <codeph>False</codeph>, the default of
+ <codeph>add_encrypt_to</codeph> is <codeph>False</codeph>.</p>
+ <p>If <codeph>always_trust</codeph> is not set to <codeph>True</codeph> 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:</p>
+ <p>
+ <codeblock id="enc2-3" outputclass="language-python">import gpg
+
+with open("secret_plans.txt.asc", "rb") as f:
+ text = f.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 f:
+ f.write(ciphertext)
+</codeblock>
+ </p>
+ <p>This will attempt to encrypt to all the keys searched for, then remove invalid recipients
+ if it fails and try again.</p>
+ </body>
+ </topic>
+</dita>
diff --git a/lang/python/docs/dita/howto/part04/encrypt-to-one.dita b/lang/python/docs/dita/howto/part04/encrypt-to-one.dita
new file mode 100644
index 00000000..2abbe06a
--- /dev/null
+++ b/lang/python/docs/dita/howto/part04/encrypt-to-one.dita
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE dita PUBLIC "-//OASIS//DTD DITA Composite//EN" "ditabase.dtd">
+<dita>
+ <topic id="topic_dkk_sjz_5db">
+ <title>Encrypting to One Key</title>
+ <body>
+ <p>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
+ <codeph>gpg.Context().encrypt()</codeph> method.</p>
+ <p>Those keyword arguments are:</p>
+ <p>
+ <ul id="ul_cmt_3kz_5db">
+ <li><codeph>recipients</codeph>, a list of keys encrypted to (covered in greater detail in
+ the following section);</li>
+ <li><codeph>sign</codeph>, whether or not to sign the plaintext data, see subsequent
+ sections on signing and verifying signatures below (defaults to
+ <codeph>True</codeph>);</li>
+ <li><codeph>sink</codeph>, to write results or partial results to a secure sink instead of
+ returning it (defaults to <codeph>None</codeph>);</li>
+ <li><codeph>passphrase</codeph>, only used when utilising symmetric encryption (defaults
+ to <codeph>None</codeph>);</li>
+ <li><codeph>always_trust</codeph>, used to override the trust model settings for recipient
+ keys (defaults to <codeph>False</codeph>);</li>
+ <li><codeph>add_encrypt_to</codeph>, utilises any preconfigured encrypt-to or default-key
+ settings in the user's <filepath>gpg.conf</filepath> file (defaults to
+ <codeph>False</codeph>);</li>
+ <li><codeph>prepare</codeph>, prepare for encryption (defaults to
+ <codeph>False</codeph>);</li>
+ <li><codeph>expect_sign</codeph>, prepare for signing (defaults to
+ <codeph>False</codeph>);</li>
+ <li><codeph>compress</codeph>, compresses the plaintext prior to encryption (defaults to
+ <codeph>True</codeph>).</li>
+ </ul>
+ </p>
+ <p>
+ <codeblock id="enc1-1" outputclass="language-python">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 f:
+ f.write(ciphertext)
+</codeblock>
+ </p>
+ <p>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
+ <filepath>gpg.conf</filepath> file:</p>
+ <p>
+ <codeblock id="enc1-2" outputclass="language-python">import gpg
+
+a_key = "0x12345678DEADBEEF"
+
+with open("secret_plans.txt", "rb") as f:
+ text = f.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 f:
+ f.write(ciphertext)
+</codeblock>
+ </p>
+ <p>If the <codeph>recipients</codeph> paramater is empty then the plaintext is encrypted
+ symmetrically. If no <codeph>passphrase</codeph> is supplied as a parameter or via a
+ callback registered with the <codeph>Context()</codeph> then an out-of-band prompt for the
+ passphrase via pinentry will be invoked.</p>
+ </body>
+ </topic>
+</dita>
diff --git a/lang/python/docs/dita/howto/part04/encryption.dita b/lang/python/docs/dita/howto/part04/encryption.dita
new file mode 100644
index 00000000..572cc9d2
--- /dev/null
+++ b/lang/python/docs/dita/howto/part04/encryption.dita
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE dita PUBLIC "-//OASIS//DTD DITA Composite//EN" "ditabase.dtd">
+<dita>
+ <topic id="topic_on2_nqy_5db">
+ <title>Encryption</title>
+ <body>
+ <p>Encrypting is very straight forward. In the first example below the message,
+ <codeph>text</codeph>, is encrypted to a single recipient's key. In the second example the
+ message will be encrypted to multiple recipients.</p>
+ </body>
+ </topic>
+</dita>
diff --git a/lang/python/docs/dita/howto/part04/signing-key-selection.dita b/lang/python/docs/dita/howto/part04/signing-key-selection.dita
new file mode 100644
index 00000000..34d02b4a
--- /dev/null
+++ b/lang/python/docs/dita/howto/part04/signing-key-selection.dita
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE dita PUBLIC "-//OASIS//DTD DITA Composite//EN" "ditabase.dtd">
+<dita>
+ <topic id="topic_dpb_fqz_5db">
+ <title>Signing Key Selection</title>
+ <body>
+ <p>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.</p>
+ <p>
+ <codeblock id="sigkey-1" outputclass="language-python">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)
+</codeblock>
+ </p>
+ <p>The signing examples in the following sections include the explicitly designated
+ <codeph>signers</codeph> parameter in two of the five examples; once where the resulting
+ signature would be ASCII armoured and once where it would not be armoured.</p>
+ <p>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.</p>
+ </body>
+ </topic>
+</dita>
diff --git a/lang/python/docs/dita/howto/part04/signing.dita b/lang/python/docs/dita/howto/part04/signing.dita
new file mode 100644
index 00000000..289e3742
--- /dev/null
+++ b/lang/python/docs/dita/howto/part04/signing.dita
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE dita PUBLIC "-//OASIS//DTD DITA Composite//EN" "ditabase.dtd">
+<dita>
+ <topic id="topic_nqk_vqy_5db">
+ <title>Signing Text and Files</title>
+ <body>
+ <p>The following sections demonstrate how to specify keys to sign with and the types of
+ signatures which can be made.</p>
+ </body>
+ </topic>
+</dita>
diff --git a/lang/python/docs/dita/howto/part04/verification.dita b/lang/python/docs/dita/howto/part04/verification.dita
new file mode 100644
index 00000000..d50482a8
--- /dev/null
+++ b/lang/python/docs/dita/howto/part04/verification.dita
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE dita PUBLIC "-//OASIS//DTD DITA Composite//EN" "ditabase.dtd">
+<dita>
+ <topic id="topic_p3g_yqy_5db">
+ <title>Signature Verification</title>
+ <body>
+ <p>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.</p>
+ <p>The following example is intended for use with the default signing method where the file
+ was not ASCII armoured:</p>
+ <p>
+ <codeblock id="verify-1" outputclass="language-python">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
+</codeblock>
+ </p>
+ <p>Whereas this next example, which is almost identical would work with normal ASCII armoured
+ files and with clear-signed files:</p>
+ <p>
+ <codeblock id="verify-2" outputclass="language-python">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
+</codeblock>
+ </p>
+ <p>In both of the previous examples it is also possible to compare the original data that was
+ signed against the signed data in <codeph>data</codeph> to see if it matches with something
+ like this:</p>
+ <p>
+ <codeblock id="verify-3" outputclass="language-python">with open(filename, "rb") as afile:
+ text = afile.read()
+
+if text == data:
+ print("Good signature.")
+else:
+ pass
+</codeblock>
+ </p>
+ <p>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 <codeph>c.verify</codeph>. So
+ <codeph>data</codeph> is <codeph>None</codeph> and only the information in
+ <codeph>result</codeph> is available.</p>
+ <p>
+ <codeblock id="verify-4" outputclass="language-python">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
+</codeblock>
+ </p>
+ <p>
+ <codeblock id="verify-5" outputclass="language-python">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
+</codeblock>
+ </p>
+ </body>
+ </topic>
+</dita>