How to do PGP in Python (generate keys, encrypt/decrypt)
Asked Answered
P

10

44

I'm making a program in Python to be distributed to windows users via an installer.

The program needs to be able to download a file every day encrypted with the user's public key and then decrypt it.

So I need to find a Python library that will let me generate public and private PGP keys, and also decrypt files encrypted with the public key.

Is this something pyCrypto will do (documentation is nebulous)? Are there other pure Python libraries? How about a standalone command line tool in any language?

All I saw so far was GNUPG but installing that on Windows does stuff to the registry and throws dll's everywhere, and then I have to worry about whether the user already has this installed, how to backup their existing keyrings, etc. I'd rather just have a python library or command line tool and mange the keys myself.

Update: pyME might work but it doesn't seem to be compatible with Python 2.4 which I have to use.

Poker answered 19/6, 2009 at 22:28 Comment(1)
Please check this article - medium.com/@almirx101/…Drumlin
P
44

You don't need PyCrypto or PyMe, fine though those packages may be - you will have all kinds of problems building under Windows. Instead, why not avoid the rabbit-holes and do what I did? Use gnupg 1.4.9. You don't need to do a full installation on end-user machines - just gpg.exe and iconv.dll from the distribution are sufficient, and you just need to have them somewhere in the path or accessed from your Python code using a full pathname. No changes to the registry are needed, and everything (executables and data files) can be confined to a single folder if you want.

There's a module GPG.py which was originally written by Andrew Kuchling, improved by Richard Jones and improved further by Steve Traugott. It's available here, but as-is it's not suitable for Windows because it uses os.fork(). Although originally part of PyCrypto, it is completely independent of the other parts of PyCrypto and needs only gpg.exe/iconv.dll in order to work.

I have a version (gnupg.py) derived from Traugott's GPG.py, which uses the subprocess module. It works fine under Windows, at least for my purposes - I use it to do the following:

  • Key management - generation, listing, export etc.
  • Import keys from an external source (e.g. public keys received from a partner company)
  • Encrypt and decrypt data
  • Sign and verify signatures

The module I've got is not ideal to show right now, because it includes some other stuff which shouldn't be there - which means I can't release it as-is at the moment. At some point, perhaps in the next couple of weeks, I hope to be able to tidy it up, add some more unit tests (I don't have any unit tests for sign/verify, for example) and release it (either under the original PyCrypto licence or a similar commercial-friendly license). If you can't wait, go with Traugott's module and modify it yourself - it wasn't too much work to make it work with the subprocess module.

This approach was a lot less painful than the others (e.g. SWIG-based solutions, or solutions which require building with MinGW/MSYS), which I considered and experimented with. I've used the same (gpg.exe/iconv.dll) approach with systems written in other languages, e.g. C#, with equally painless results.

P.S. It works with Python 2.4 as well as Python 2.5 and later. Not tested with other versions, though I don't foresee any problems.

Prow answered 27/6, 2009 at 22:12 Comment(10)
Thanks that sounds perfect. I had no idea I could just pull the exe out of gpg. Where will it put the keyring? Will this method cause any problems if the user already has gpg installed? Any chance I could just see how your code does key generation, and key imports?Poker
Also be sure to update us here when you release your final code.Poker
When you call gpg, specify the path where you want the keyrings to be stashed using the --homedir argument. (This is already done for you using Traugott's module - there's a GPG class whose constructor takes a gnupghome parameter which you can set to this directory.) The pubring.gpg, secring.gpg and trustdb.gpg are created in the folder specified by --homedir. I don't believe this will cause a problem if the user has gpg already installed - the --homedir argument should override any values in the registry.Prow
Just make sure that the gpg which gets executed is your bundled copy - another installed copy (which might be on the path) may be a different version which would be wise to avoid just as a precautionary measure to head off any interoperability issues.Prow
See paste.pocoo.org/show/125608 for an excerpts from the unit tests for the module. This shows key generation and key importing. Thanks for accepting the answer. I'll be sure to post a comment here when I release the code.Prow
@VinaySajip Hi there Vinay, thanks for your work on gnupg. Could you comment on the relationship between this module and the python-gnupg project on github? Considering this answer is about 7 years old now - what's current, and which should a new user prefer? (both projects seem well maintained and well documented, so the choice is not obvious)Backtrack
@Backtrack The other module is a fork (without any discussion with me) by another developer, and not a drop-in replacement. Obviously, I would recommend my project as "the original and best"! The other project is GPLv3, my project is BSD. The other project cites a shell=True vulnerability which has not been in my project for a long time. To decide which to use, pick some features you need, and see which project has those/makes them easy to use.Prow
The provided link within the answer is stale.Magistrate
how do i go about using GPG.py, just drop it in my project folder and I can make reference to it?Warrantee
@Warrantee you can now install using pip install python-gnupg and then import gnupg etc,Prow
M
40

After a LOT of digging, I found a package that worked for me. Although it is said to support the generation of keys, I didn't test it. However I did manage to decrypt a message that was encrypted using a GPG public key. The advantage of this package is that it does not require a GPG executable file on the machine, and is a Python based implementation of the OpenPGP (rather than a wrapper around the executable). I created the private and public keys using GPG4win and kleopatra for windows See my code below.

import pgpy
emsg = pgpy.PGPMessage.from_file(<path to the file from the client that was encrypted using your public key>)
key,_  = pgpy.PGPKey.from_file(<path to your private key>)
with key.unlock(<your private key passpharase>):
    print (key.decrypt(emsg).message)

Although the question is very old. I hope this helps future users.

Music answered 10/10, 2017 at 11:41 Comment(5)
Thank you for the info. Can this actually perform encryption using the public key ? Also, a link to the package maybe helpful.Miltiades
Thank you @Roee Anuar. Already used it to build a PGP based password protection program. Appreciate the help.Miltiades
Is there an equivalent example where I can encrypt file using public key (pgpy) ?Hebrew
Added an answer with code sample for pgpy and gpg to use just the public key exported file.Woodworm
@Miltiades here is the documentation that includes capabilities and installation instructions. pgpy.readthedocs.io/en/latest/index.htmlRounding
E
7

PyCrypto supports PGP - albeit you should test it to make sure that it works to your specifications.

Although documentation is hard to come by, if you look through Util/test.py (the module test script), you can find a rudimentary example of their PGP support:

if verbose: print '  PGP mode:',
obj1=ciph.new(password, ciph.MODE_PGP, IV)
obj2=ciph.new(password, ciph.MODE_PGP, IV)
start=time.time()
ciphertext=obj1.encrypt(str)
plaintext=obj2.decrypt(ciphertext)
end=time.time()
if (plaintext!=str):
    die('Error in resulting plaintext from PGP mode')
print_timing(256, end-start, verbose)
del obj1, obj2

Futhermore, PublicKey/pubkey.py provides for the following relevant methods:

def encrypt(self, plaintext, K)
def decrypt(self, ciphertext):
def sign(self, M, K):
def verify (self, M, signature):
def can_sign (self):
    """can_sign() : bool
    Return a Boolean value recording whether this algorithm can
    generate signatures.  (This does not imply that this
    particular key object has the private information required to
    to generate a signature.)
    """
    return 1
Eighty answered 24/6, 2009 at 8:30 Comment(3)
I don't see a way to generate keys, or accept another party's public key to encrypt data with. Any ideas?Poker
No, MODE_PGP in PyCrypto is legacy, experimental code that probably never worked right. (See bugs.launchpad.net/pycrypto/+bug/996814). Don't use it. We'll be removing it from PyCrypto soon anyway.Voluminous
Then what do you suggest, @dlitz?Equinox
C
3

PyMe does claim full compatibility with Python 2.4, and I quote:

The latest version of PyMe (as of this writing) is v0.8.0. Its binary distribution for Debian was compiled with SWIG v1.3.33 and GCC v4.2.3 for GPGME v1.1.6 and Python v2.3.5, v2.4.4, and v2.5.2 (provided in 'unstable' distribution at the time). Its binary distribution for Windows was compiled with SWIG v1.3.29 and MinGW v4.1 for GPGME v1.1.6 and Python v2.5.2 (although the same binary get installed and works fine in v2.4.2 as well).

I'm not sure why you say "it doesn't seem to be compatible with Python 2.4 which I have to use" -- specifics please?

And yes it does exist as a semi-Pythonic (SWIGd) wrapper on GPGME -- that's a popular way to develop Python extensions once you have a C library that basically does the job.

PyPgp has a much simpler approach -- that's why it's a single, simple Python script: basically it does nothing more than "shell out" to command-line PGP commands. For example, decryption is just:

def decrypt(data):
    "Decrypt a string - if you have the right key."
    pw,pr = os.popen2('pgpv -f')
    pw.write(data)
    pw.close()
    ptext = pr.read()
    return ptext

i.e., write the encrypted cyphertext to the standard input of pgpv -f, read pgpv's standard output as the decrypted plaintext.

PyPgp is also a very old project, though its simplicity means that making it work with modern Python (e.g., subprocess instead of now-deprecated os.popen2) would not be hard. But you still do need PGP installed, or PyPgp won't do anything;-).

Cataplasia answered 24/6, 2009 at 16:3 Comment(2)
PyMe was this issue: #1030797Poker
Yeah, theit claim that I quoted (about Windows, specifically) is ill-founded (in Windows, only, extensions need to be compiled for specific versions of Python, so one compiled for 2.5 will not work for 2.4). All you need is to recompile (which requires MSVC 6.0).Cataplasia
T
3

M2Crypto has PGP module, but I have actually never tried to use it. If you try it, and it works, please let me know (I am the current M2Crypto maintainer). Some links:

Update: The PGP module does not provide ways to generate keys, but presumably these could be created with the lower level RSA, DSA etc. modules. I don't know PGP insides, so you'd have to dig up the details. Also, if you know how to generate these using openssl command line commands, it should be reasonably easy to convert that to M2Crypto calls.

Tungstite answered 25/6, 2009 at 4:10 Comment(2)
Hmm, it looked promising but I don't see how to generate keys.Poker
You might be able to generate the keys with the lower level RSA, DSA etc. modules.Tungstite
M
3

As other have noted, PyMe is the canonical solution for this, since it's based on GpgME, which is part of the GnuPG ecosystem.

For Windows, I strongly recommend to use Gpg4win as the GnuPG distribution, for two reasons:

It's based on GnuPG 2, which, among other things, includes gpg2.exe, which can (finally, I might add :) start gpg-agent.exe on-demand (gpg v1.x can't).

And secondly, it's the only official Windows build by the GnuPG developers. E.g. it's entirely cross-compiled from Linux to Windows, so not a iota of non-free software was used in preparing it (quite important for a security suite :).

Moyers answered 31/7, 2009 at 18:26 Comment(0)
O
3

Here's a full script that will:

  1. Attempt to decrypt all the files in a given folder that were encrypted with your public key.
  2. Write the new files to a specified folder.
  3. Move the encrypted files to a specified folder.

The script also has everything you need to create and store your own private and public keys, check out the "First time set up" section below.

The idea is that you can schedule this script to run as often as you like, and it'll automatically decrypt data found and store it for you.

I hope this helps someone, this was a tricky project to figure out.

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~ Introduction, change log and table of contents
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Purpose: This script is used to encrypt and decrypt files using the PGP (Pretty Good Privacy) standard..
#
# Change date   Changed by      Description
# 2022-10-03    Ryan Bradley    Initial draft
# 2022-10-12    Ryan Bradley    Cleaned up some comments and table of contents. 
#
# Table of Contents
# [1.0] Hard-coded variables
# [1.1] Load packages and custom functions
# [1.3] First time set up
# [1.4] Define custom functions
# [2.0] Load keys and decrypt files
#
# Sources used to create this script, and for further reading:
# https://github.com/SecurityInnovation/PGPy/
# https://mcmap.net/q/370399/-how-to-do-pgp-in-python-generate-keys-encrypt-decrypt
# https://pypi.org/project/PGPy/
# https://betterprogramming.pub/creating-a-pgp-encryption-tool-with-python-19bae51b7fd
# https://pgpy.readthedocs.io/en/latest/examples.html

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~ [1.1] Load packages 
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import glob
import pgpy
import shutil
import io

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~ [1.2] Hard-coded variables
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# Define the paths to public and private keys
path_public_key = r'YOUR PATH HERE'
path_private_key = r'YOUR PATH HERE'

# Define paths to files you want to try decrypting
path_original_files = r'YOUR PATH HERE'
path_decrypted_files = r'YOUR PATH HERE'
path_encrypted_files= r'YOUR PATH HERE'

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~ [1.3] First time set up
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# IMPORTANT WARNINGS!!!!
#  - Do NOT share your private key with anyone else. 
#  - You MUST have the associated private key that is is generated along with a public key 
#       if you want to be able to decrypt anything that is encryped with that public key. Do
#       not overwrite the existing keys unless you will never need any of the previously 
#       encryped data. 
#   - Do not generate new public and private keys unless you have a good reason to. 
#
# The following steps will walk you through how to create and write public and private keys to
# a network location. Be very careful where you store this information. Anyone with access
# to your private key can decrypt anything that was encryped with your public key.
#
# These steps only need to be performed one time when the script is first being 
# created. They are commented out intentionally, as they shouldn't need to be performed 
# every time the script is ran. 
# 
# Here's the a link to the documentation on this topic:
# https://pgpy.readthedocs.io/en/latest/examples.html

# # Load the extra things we need to define a new key
# from pgpy.constants import PubKeyAlgorithm, KeyFlags, HashAlgorithm, SymmetricKeyAlgorithm, CompressionAlgorithm
 
# # Gerate a new a primary key. For this example, we'll use RSA, but it could be DSA or ECDSA as well
# key = pgpy.PGPKey.new(PubKeyAlgorithm.RSAEncryptOrSign, 4096)

# # Define a new user 
# uid = pgpy.PGPUID.new('USER_NAME', comment='Generic user', email='YOUR_EMAIL')

# # Add the new user id to the key, and define all the key preferences.
# key.add_uid(uid, usage={KeyFlags.Sign, KeyFlags.EncryptCommunications, KeyFlags.EncryptStorage},
#             hashes=[HashAlgorithm.SHA256, HashAlgorithm.SHA384, HashAlgorithm.SHA512, HashAlgorithm.SHA224],
#             ciphers=[SymmetricKeyAlgorithm.AES256, SymmetricKeyAlgorithm.AES192, SymmetricKeyAlgorithm.AES128],
#             compression=[CompressionAlgorithm.ZLIB, CompressionAlgorithm.BZ2, CompressionAlgorithm.ZIP, CompressionAlgorithm.Uncompressed]
#             , is_compressed = True)

# # Write the ASCII armored public key to a network location.
# text_file = open(path_public_key, 'w')
# text_file.write(str(key.pubkey))
# text_file.close()

# # Write the ASCII armored private key to a network location.
# text_file = open(path_private_key, 'w')
# text_file.write(str(key))
# text_file.close()

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~ [1.4] Define custom functions
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

def file_encrypt(path_original_file, path_encrypted_file, key_public):
    """
    A function that encrypts the content of a file at the given path and 
    creates an ecryped version file at the new location using the specified
    public key.
    """
    
    # Create a PGP file, compressed with ZIP DEFLATE by default unless otherwise specified
    pgp_file = pgpy.PGPMessage.new(path_original_file, file=True)
    
    # Encrypt the data with the public key
    encrypted_data = key_public.encrypt(pgp_file) 
    
    # Write the encryped data to the encrypted destination
    text_file = open(path_encrypted_file, 'w')
    text_file.write(str(encrypted_data))
    text_file.close()
   
def file_decrypt(path_encrypted_file, path_decrypted_file, key_private):
    """
    A function that decrypts the content of a file at path path and 
    creates a decrypted file at the new location using the given 
    private key.
    """

    # Load a previously encryped message from a file
    pgp_file = pgpy.PGPMessage.from_file(path_encrypted_file)
    
    # Decrypt the data with the given private key
    decrypted_data = key_private.decrypt(pgp_file).message
   
    # Read in the bytes of the decrypted data
    toread = io.BytesIO()
    toread.write(bytes(decrypted_data))  
    toread.seek(0)  # reset the pointer 
   
    # Write the data to the location
    with open(path_decrypted_file, 'wb') as f:
        shutil.copyfileobj(toread, f)
        f.close()
      
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~ [2.0] Load keys and decrypt files
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# Load your pre-generated public key from the network
key_public, _ = pgpy.PGPKey.from_file(path_public_key)

# Load your pre-generated public key from the network
key_private, _ = pgpy.PGPKey.from_file(path_private_key)

# Find and process any encrypted files in the landing folder
for file in glob.glob(path_original_files + '\*.pgp'):
    
    # Get the path to the file we need to decrypt
    path_encrypted_file = str(file)
    
    # Extract the file name
    parts = path_encrypted_file.split('\\')
    str_file_name = parts[len(parts)-1]
    str_clean_file_name = str_file_name[:-4]
    
    # Extract the file exension
    str_extension = str_clean_file_name.split('.')
    str_extension = str_extension[len(str_extension) - 1]
    
    # Create the path to the new decryped file, dropping the ".pgp" extension
    path_decrypted_file = path_decrypted_files + '\\' + str_clean_file_name
    
    # Create the path to the place we'll store the encryped file
    path_archived_encrypted_file = path_encrypted_files + '\\' + str_file_name
    
    # Decrypt the file
    try:
        file_decrypt(path_encrypted_file, path_decrypted_file, key_private)
        
        # Move the encryped file to its new location
        shutil.move(path_encrypted_file, path_archived_encrypted_file)
    except:
        print('DECRYPTION ERROR!')
        print(f'Unable to decrypt {path_encrypted_file}')
    
# Just for reference, here's how you would call the function to encrypt a file:
# file_encrypt(path_original_file, path_encrypted_file, key_public)
Overburden answered 29/11, 2022 at 22:8 Comment(0)
W
1

To sign with only the exported public key file without a keyring.

With PGPy 0.5.2 (pure Python GPG RFC implementation):

key_fpath = './recipient-PUB.gpg'
     
rsa_pub, _ = pgpy.PGPKey.from_file(rkey_fpath)
rkey = rsa_pub.subkeys.values()[0]                                                                                                     
     
text_message = pgpy.PGPMessage.new('my msg')
encrypted_message = rkey.encrypt(text_message)
print encrypted_message.__bytes__()

With gpg 1.10.0 (gpgme Python bindings - former PyME):

rkey_fpath = './recipient-PUB.gpg'
cg = gpg.Context()
rkey = list(cg.keylist(source = rkey_fpath))                                                                                                                
 
ciphertext, result, sign_result = cg.encrypt('my msg', recipients=rkey, sign=False, always_trust=True)
print ciphertext

A simple benchmark in a for loop shows me that for this simple operation on my system PGPy is ~3x time faster than gpgme Python bindings (please do not take this statement as X is faster than Y: I will invite you to test in your environment).

Woodworm answered 21/6, 2020 at 20:51 Comment(2)
Using PGP, Whats the Python function to generate public /private key --> rkey_fpathCoreencorel
I tried your logic but got an error TypeError: 'odict_values' object is not subscriptable . I have exported mypublic key to my-pubkey.ascCoreencorel
W
0

I will just append to @Roee Anuar and his idea with pgpy

# pip install pgpy
from pgpy import PGPKey, PGPMessage
from pgpy.packet.packets import LiteralData
from pgpy.constants import CompressionAlgorithm
from datetime import datetime, timezone
import json

pass_phrase = "some_password_anyway"

# simple string
message = PGPMessage.new("42 is quite a pleasant number")
enc_message = message.encrypt(pass_phrase)
print(json.dumps(str(enc_message)))

# file
PGPMessage.filename = "filename.txt"
file_message = PGPMessage.new("/tmp/123", file=True)
enc_message = file_message.encrypt(pass_phrase)
print(json.dumps(str(enc_message)))

This is how you can encrypt strings and files. Also I've implemented a way of encrypting data as a file:

# file from byte array and with custom name
msg = PGPMessage()
lit = LiteralData()
lit._contents = bytearray(msg.text_to_bytes("Some stuff in file"))
lit.filename = "any file name here even long ones are ok but do not exceed 192 bytes.txt"
lit.mtime = datetime.now(timezone.utc)
lit.format = 'b'
lit.update_hlen()

msg |= lit
msg._compression = CompressionAlgorithm.ZIP

enc_message = msg.encrypt(pass_phrase)
print(json.dumps(str(enc_message)))

Winola answered 5/6, 2023 at 22:45 Comment(0)
J
-2

I think calling gpg directly will work better for you. regarding your stated goals:
"generate public and private PGP keys"

  1. this creates the full keypair: gpg --full-generate-key

  2. this lists the keys in your keyring once created:
    gpg --list-keys

  3. this exports the public key from that keypair:
    gpg --output --armor -export

...where pubkeyfile is the filename of your choice which you will share with counterparties, keyid is obtained from command #2

regarding your needs: "decrypt files encrypted with the public key"

  1. this decrypts your encrypted files: gpg --decrypt --output </path/to/decrypted filename> </path/to/encrypted filename>

4a. if you want to include the passphrase entry used for the private key in the command: gpg --pinentry-mode=loopback --passphrase "PASSPHRASE" --decrypt --output "PATH\TO\OUTPUT" "PATH\TO\FILE.gpg"

note that -d and -o can be interchanged for --decrypt and --output

  1. Regarding your observations regarding Gpg4Win: "Windows does stuff to the registry and throws dll's everywhere, and then I have to worry about whether the user already has this installed"

I would not worry about this. Installing gpg4win once installs it for everyone. Each user, however, will use their own keyring. This is standard security (and recommended best) practice. If you are trying to manage multiple users, you can take one of the following strategies.. 5a - let each user have their own private keyring, they can import and then trust a single keypair, possibly the one you created from above. You perform these steps as follows:

5a.1 - export your secret key, created above: gpg --output --armor --export-secret-key , then share this file with your users
note: you will need to input the passphrase used when you generated the keypair and then share this with the users

5a.2 - each user will need to create their own keyring once: gpg --list-keys this will generate the keyring and report back no keys, next that user will need to import your keypair:

gpg --import

once done each user can use the commands provided above to decrypt the files on their own as the private key is now in their own keyring

5b - perform decryption upstream of user consumption, via automation, depositing decrypted files into a folder for user consumption. This works best when dealing with users unwilling to navigate learn encryption specifics themselves. I advocate this solution as it removes the hassles of key management from less-technical users.

5c - call gpg but specify a shared keyring. I do not personally advocate doing this for my needs, and it violates standard security tenets, but everyone's needs are different. You can find more information on how to do this here:

gpg2: How to use another secret and public keyring?

When you try to orchestrate all this via python using python libraries, you add a layer of abstraction which is more trouble than its worth in my opinion. Versioning issues with python can arise over time. If you invoke the gpg commands above within your python code instead it is a more reliable solution.

Best of Luck!

Judiejudith answered 30/6, 2024 at 11:56 Comment(1)
Looks AI generated and does not answer the question which mentioned using python.Ebonyeboracum

© 2022 - 2025 — McMap. All rights reserved.