PGP Encryption: Securely Sharing Sensitive Company Data
Have you ever been in a situation where you needed to share an API client secret, a database password, or another critical environment variable with a coworker? And did you, perhaps, instinctively copy-paste it into a chat message, a shared document, or even an email? If so, you’re not alone — it’s a common practice in many development teams. But here’s the uncomfortable truth: that’s not secure at all. These seemingly convenient methods expose your most sensitive data to unnecessary risks, making it vulnerable to interception, unauthorized access, or accidental logging.
But don’t worry, we bring you a solution! This article will introduce you to OpenPGP, often simply known as PGP (Pretty Good Privacy), a robust and widely trusted standard for data encryption and digital signatures. We’ll explore how this powerful tool can become your go-to solution for securely exchanging environment variables and other confidential work-related data, significantly improving your team’s security posture.
We’ll be using my terminal and also a docker container to simulate a coworker’s environment. We’ll exchange keys, sign them and then start sharing files. Hopefully, you’ll start doing the same after this tutorial.
Jorge Trinomio will be our helper today, so let’s start with a docker image for him in order to simulate a coworker’s environment:
docker run --rm -it alpine:latest sh
> mkdir app
> cd app
> apk add --no-cache gnupgNow Jorge has gpg installed in his machine. Let’s generate a personal key for work:
> gpg --full-generate-key Jorge will pick the following option RSA and RSA and no expiration:
Real name: Jorge Trinomio
Email address: jorge.trinomio@trinom.io
Comment: Clave para sharear envs en el trabajo
You selected this USER-ID:
"Jorge Trinomio (Clave para sharear envs en el trabajo) <jorge.trinomio@trinom.io>"And of course, set up his passphrase but we won’t share it here.
Now it’s time to share keys, so ill be providing Jorge my personal work public key.
gpg --armor --export federico.mieres@trinom.ioSince the export returns bytes , the armor option transforms it in a easier to share format such as:
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQGNBGhbMZUBDADNIYLxDP0zzJqMvdXfmfCcSnF0SE5J+2A/TYxCfORW0gFNS9zi
baprKB7khmt7618b/dWq2YYO4NGu4Ztn1v959l7AB8GiSMhMRIWiV8SueoaSh3gR
xt+sseM9Tkt4CqSrSZtr8tyGiGIf6Vp80K+n+0U66s7JPxbjSNIXVy+h38+jeqk3
jSBh6Ay764v8c1g4WhapHm2lrUkKZhXjYMItXCmNePmRc4IZDAy2voBszzasm58F
iHSPnFhZFSVtSg==...........................................=9vW7
-----END PGP PUBLIC KEY BLOCK-----So, ill share this content with Jorge via company’s chat. Him or anyone who wants to share anything encrypted with me will use it so this doesn’t need to be a hidden message.
Get Federico Mieres’s stories in your inbox
Join Medium for free to get updates from this writer.
Jorge will paste it in a file called fede.gpg.key and then will use add it to his keyring.
A keyring is your personal, secure database where GnuPG stores all the PGP keys (both public and private) you use for encrypting and decrypting data.
> gpg --import fede.gpg.key
gpg: key 975CE42E4E1B1877: public key "Federico Mieres (my key to share stuff at work) <federico.mieres@trinom.io>" imported
gpg: Total number processed: 1
gpg: imported: 1That should be enough but… what if a man in the middle replace my public key with theirs ? That’s why we check fingerprints as a second validation. This only needs to be done once and we should do it verbally or in a quick call?
> gpg --fingerprint federico.mieres@trinom.io
gpg: checking the trustdb
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
pub rsa3072 2025-06-24 [SC]
D7C8 F1E0 B6A3 9C2D E5F4 0B1A C9D2 3F4E 5A6B 7C8D
uid [ unknown] Federico Mieres (my key to share stuff at work) <federico.mieres@trinom.io>
sub rsa3072 2025-06-24 [E]My fingerprint
D7C8 F1E0 B6A3 9C2D E5F4 0B1A C9D2 3F4E 5A6B 7C8Dand pay attention to the unknown tag at my key in Jorge’s keyring.
This[ unknown]tag simply means Jorge's GnuPG doesn't yet have an established trust relationship with my key, which is what verifying the fingerprint and then signing will address.
Jorge: hey fede, is your fingerprint ……
Fede: yes! exactly!
So as an additional, optional and recommended step, Jorge now can sign my key in order to set it as trustworthy.
> gpg --sign-key federico.mieres@trinom.io
pub rsa3072/975CE42E4E1B1877
created: 2025-06-24 expires: never usage: SC
trust: unknown validity: unknown
sub rsa3072/9B9D43B7402FC32B
created: 2025-06-24 expires: never usage: E
[ unknown] (1). Federico Mieres (my key to share stuff at work) <federico.mieres@trinom.io>
pub rsa3072/975CE42E4E1B1877
created: 2025-06-24 expires: never usage: SC
trust: unknown validity: unknown
Primary key fingerprint: D7C8 F1E0 B6A3 9C2D E5F4 0B1A C9D2 3F4E 5A6B 7C8D
Federico Mieres (my key to share stuff at work) <federico.mieres@trinom.io>
Are you sure that you want to sign this key with your
key "Jorge Trinomio (Clave para sharear envs en el trabajo) <jorge.trinomio@trinom.io>" (39BDF440C7EAC437)
Really sign? (y/N) y
> gpg --fingerprint federico.mieres@trinom.io
gpg: checking the trustdb
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
gpg: depth: 0 valid: 1 signed: 1 trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: depth: 1 valid: 1 signed: 0 trust: 1-, 0q, 0n, 0m, 0f, 0u
pub rsa3072 2025-06-24 [SC]
D7C8 F1E0 B6A3 9C2D E5F4 0B1A C9D2 3F4E 5A6B 7C8D
uid [ full ] Federico Mieres (my key to share stuff at work) <federico.mieres@trinom.io>
sub rsa3072 2025-06-24 [E]So, done with the set up. This is something you do only once per new key and now Jorge is ready to securely share the envars of the project I’m being onboarded today.
Let’s say we have:
> cat .env.toml
# Application Settings
APP_NAME="MyTrinoApp"
APP_ENV="development"
APP_DEBUG=true
APP_URL="http://localhost:8000"
# Database Configuration
DB_CONNECTION="mysql"
DB_HOST="127.0.0.1"
DB_PORT="3306"
DB_DATABASE="my_app_db"
DB_USERNAME="app_user"
DB_PASSWORD="rAnd0M_DbP@ssw0rd_hjkL5tY"
# API Keys and Credentials
API_KEY_STRIPE="sk_test_aBcD1eFgH2iJ3kL4mN5oPqR6sT7uV8wXyZ"
THIRD_PARTY_SERVICE_TOKEN="token_xyz123abc456def789ghi0jklmnop"
# AWS Credentials
AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
AWS_REGION="us-east-1"
# JWT Secret
JWT_SECRET="super-secret-jwt-key-256bit-randomstring-QvR6sT7uV8wXyZ"
# Cache and Queue
CACHE_DRIVER="redis"
REDIS_HOST="127.0.0.1"
REDIS_PORT="6379"
QUEUE_CONNECTION="sync"
# Other
FEATURE_FLAG_ALPHA=false
ANALYTICS_ID="UA-XXXXXXXXX-Y"Jorge will encrypt it using my public key:
> gpg --output .env.toml.gpg --encrypt -r federico.mieres@trinom.io .env.tomlThis will generate a file .env.toml.gpg which only I will be able to decrypt.
After Jorge shares the file with me via company’s email, I’ll decrypt it with:
> gpg --output .env.toml -d env.toml.gpg
gpg: encrypted with rsa3072 key, ID 9B9D43B7402FC32B, created 2025-06-24
"Federico Mieres (my key to share stuff at work) <federico.mieres@trinom.io>"GnuPG will then prompt me for my private key’s passphrase to decrypt the file.
And voila! Now we know how to share secrets securely and no one will be able to maliciously get them unless i share my secret key (which i won’t, hopefully)
I hope this helps you and see you next time!







