# Do Your Own Encryption: A Simple Guide

Encrypting your own data is easier than you might think. This guide will show you how encryption works and how you can use it to protect your communications. No need to trust a third party like Google, Facebook, Microsoft or Signal.

## Why You Need Encryption

Your communication provider can easily monitor your activities. A small number of global infrastructure providers can monitor and read all internet traffic. The post office can read your snail mail, telecom companies can listen to your calls, and your WhatsApp messages may be revealed by Facebook to comply with government requests. However, by creating your own encryption, you can ensure that your messages remain private. Here's how you can do it.

## Bob and Alice: An Introduction to Asymmetric Encryption

Asymmetric encryption involves each user having two keys: a private key and a public key. The private key must remain secret, while the public key can be shared openly.

Creating your own encryption requires writing some lines of code. Don’t worry, it’s simple. You’ll need to install Python on your computer. Search for "install Python on Windows/Mac/Linux" for instructions.

### Step 1: Create RSA Keys

Start by generating a pair of RSA keys in Python:

```
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes, serialization
bob_private_key = rsa.generate_private_key(key_size=4096, public_exponent=65537)
bob_public_key = bob_private_key.public_key()
```

If you encounter an error with `from cryptography.hazmat...`, you may need to install the package with `pip install cryptography`. A key size of 4096 bits is currently (2024) considered secure. The `public_exponent` is kind of a standard constant.

Next, generate keys for Alice also:

```
alice_private_key = rsa.generate_private_key(key_size=4096, public_exponent=65537)
alice_public_key = alice_private_key.public_key()
```

### Step 2: Encrypt the Message

Now you can use these secret keys to establish an encrypted conversation. Let’s say Bob wants to schedule a secret meeting with Alice:

```
secret_appointment = 'Let’s meet at the theater at 8 p.m. next Saturday'
```

Bob will encrypt this message using Alice’s public key, remember that public keys are openly shared:

```
encrypted_msg = alice_public_key.encrypt(
secret_appointment.encode(),
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
```

The encrypted message will look unreadable, something like this:

```
print(encrypted_msg)
# Output: b"w\x0f\x07\xa4\xe0>g[4Q\xb3\xa16\xeb3\xd5)..."
```

### Step 3: Decrypt the Message

Bob sends this encrypted message to Alice. Alice can decrypt it because she owns her secret private key:

```
decrypted_secret_message = alice_private_key.decrypt(
encrypted_msg,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
print(decrypted_secret_message)
# Output: b'Let\xe2\x80\x99s meet at the theater at 8 p.m. next Saturday'
```

That was easy, right? If you have a reliable communication channel, you're all set. Unfortunately, most of the time, such highly secure channels aren't available.

### Improvement: Sign the Message

So far, we've covered encryption and decryption. But how can Alice be sure that the message was sent by Bob? Just like with snail mail and email, you can’t always trust the sender’s identity. Fortunately, RSA provides a solution. Bob can add a digital signature to the secret_appointment using his bob_private_key:

```
bob_signature = bob_private_key.sign(
encrypted_msg,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
secret_appointment_signed = bob_signature + b"|||" + encrypted_msg
```

Bob now sends the secret_appointment_signed to Alice.

### Alice to verify the Signature

Alice splits the message and verifies Bob's signature with Bob's public key:

```
bob_signature, encrypted_secret_message = secret_appointment_signed.split(b'|||')
bob_public_key = bob_private_key.public_key()
try:
bob_public_key.verify(
bob_signature,
encrypted_secret_message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
print("Signature is valid.")
except:
print("Signature is invalid.")
```

When the signature is valid, Alice can be sure that Bob is the sender and now can decrypt the secret with her private key:

```
decrypted_secret_message = alice_private_key.decrypt(
encrypted_secret_message,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
print(decrypted_secret_message)
# Output: b'Let\xe2\x80\x99s meet at the theater at 8 p.m. next Saturday'
```

This process ensures Alice that the message is indeed from Bob and that only she can read it.

Just a few lines of code are needed. Bob can send the encrypted message via email, phone, QR codes, images, CB radio or any other medium.

## Final thoughts

- Public keys must be exchanged securely, such as through an in-person meeting.
- Parties must agree on some conditions like the padding, algorithm, split-sequence beforehand.
- With the advancement of quantum computing, RSA-4096 could become vulnerable to hacking within the next three years.
- Every encrypted communication on the internet leaves traces of metadata, use VPNs or public spots.

If you have any comments or questions, please reach out by nostr DM or via this Nostr note: nostr:note1vy5kf4em5670a79gxk5z5wsxle6wm4359d4kcauchqf83hqt2hhq7n54hg

If you found this guide useful, consider sending some sats to lud16 - cygus44@hubstr.org - or zap my profile nostr:npub1cygus44llmuj4m7w5yfpgqk83x9lvrtr2qavn26ugsyduzv7jc0qnjw7h8

Thanks, stay brave and private 🧡