- add pgpy to poetry
- add test PGP keys to local_data
- add encrypt_file_with_pgpy()
- use randomly pgpy
This commit is contained in:
Son NK 2020-10-28 11:50:14 +01:00
parent 71be3b27f7
commit 9210459a72
8 changed files with 183 additions and 104 deletions

View File

@ -1278,7 +1278,7 @@ class EmailLog(db.Model, ModelMixin):
# for ex if alias is disabled, this forwarding is blocked
blocked = db.Column(db.Boolean, nullable=False, default=False)
# can happen when user email service refuses the forwarded email
# can happen when user mailbox refuses the forwarded email
# usually because the forwarded email is too spammy
bounced = db.Column(db.Boolean, nullable=False, default=False, server_default="0")

View File

@ -3,11 +3,13 @@ from io import BytesIO
import gnupg
from memory_profiler import memory_usage
from pgpy import PGPMessage
from app.config import GNUPGHOME
from app.log import LOG
from app.models import Mailbox, Contact
from app.utils import random_string
import pgpy
gpg = gnupg.GPG(gnupghome=GNUPGHOME)
gpg.encoding = "utf-8"
@ -92,3 +94,12 @@ def encrypt_file(data: BytesIO, fingerprint: str) -> str:
raise PGPException(f"Cannot encrypt, status: {r.status}")
return str(r)
def encrypt_file_with_pgpy(data: bytes, public_key: str) -> PGPMessage:
key = pgpy.PGPKey()
key.parse(public_key)
msg = pgpy.PGPMessage.new(data, encoding="utf-8")
r = key.encrypt(msg)
return r

View File

@ -34,6 +34,7 @@ import argparse
import asyncio
import email
import os
import random
import time
import uuid
from email import encoders
@ -392,7 +393,7 @@ _MIME_HEADERS = [
_MIME_HEADERS = [h.lower() for h in _MIME_HEADERS]
def prepare_pgp_message(orig_msg: Message, pgp_fingerprint: str):
def prepare_pgp_message(orig_msg: Message, pgp_fingerprint: str, public_key: str):
msg = MIMEMultipart("encrypted", protocol="application/pgp-encrypted")
# copy all headers from original message except all standard MIME headers
@ -417,11 +418,23 @@ def prepare_pgp_message(orig_msg: Message, pgp_fingerprint: str):
"octet-stream", _encoder=encoders.encode_7or8bit, name="encrypted.asc"
)
second.add_header("Content-Disposition", 'inline; filename="encrypted.asc"')
# encrypt original message
encrypted_data = pgp_utils.encrypt_file(
BytesIO(orig_msg.as_bytes()), pgp_fingerprint
)
second.set_payload(encrypted_data)
# ABTest between pgpy and python-gnupg
x = random.randint(0, 9)
if x >= 5:
LOG.d("encrypt using python-gnupg")
encrypted_data = pgp_utils.encrypt_file(
BytesIO(orig_msg.as_bytes()), pgp_fingerprint
)
second.set_payload(encrypted_data)
else:
LOG.d("encrypt using pgpy")
encrypted_data = pgp_utils.encrypt_file_with_pgpy(
orig_msg.as_bytes(), public_key
)
second.set_payload(str(encrypted_data))
msg.attach(second)
return msg
@ -632,7 +645,9 @@ def forward_email_to_mailbox(
if mailbox.pgp_finger_print and user.is_premium() and not alias.disable_pgp:
LOG.d("Encrypt message using mailbox %s", mailbox)
try:
msg = prepare_pgp_message(msg, mailbox.pgp_finger_print)
msg = prepare_pgp_message(
msg, mailbox.pgp_finger_print, mailbox.pgp_public_key
)
except PGPException:
LOG.exception(
"Cannot encrypt message %s -> %s. %s %s", contact, alias, mailbox, user
@ -901,7 +916,9 @@ def handle_reply(envelope, msg: Message, rcpt_to: str) -> (bool, str):
if contact.pgp_finger_print and user.is_premium():
LOG.d("Encrypt message for contact %s", contact)
try:
msg = prepare_pgp_message(msg, contact.pgp_finger_print)
msg = prepare_pgp_message(
msg, contact.pgp_finger_print, contact.pgp_public_key
)
except PGPException:
LOG.exception(
"Cannot encrypt message %s -> %s. %s %s", alias, contact, mailbox, user

View File

@ -0,0 +1,57 @@
-----BEGIN PGP PRIVATE KEY BLOCK-----
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
0GzRi859Yrp2jhdAzkXArMVq6CS8G+8H5w==
=1B0F
-----END PGP PRIVATE KEY BLOCK-----

30
local_data/public-pgp.asc Normal file
View File

@ -0,0 +1,30 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQENBF+YdvUBCAC6ztR1r2A5Sl8MuHrNavIHPI2/GKYe61GnR8h8HVocJ8Q7j6dd
XeeaMkfiZWwvP1ya3b4F+irQXNXtsWqV3F3QLBF7NYtqW96JJsKZIuvehI8UXPIL
4ibA/ptGd8Cd6713PhByZGUPAQsdFKjsVRgdIm6aJpvFZpGktn2T3Yx6sJZ0CXQS
WEbRv+ld9sE9Pe0CRwJ/R29ktFSZ8A7hHABXXoLtawgtsa6EIvbn+XbsQxs5WpyK
Zr7XNrPCflkSOHihjOnbFsmEsGIyMFZvwrsc5akqF9dPIJNWp/j+SXuRuMFj+7jd
LQHitppBuloPMtCja41xEAyan4mbF795FK4VABEBAAG0F1Rlc3QgPHRlc3RAZXhh
bXBsZS5vcmc+iQFOBBMBCAA4FiEE3tfq+zchw8t7RxNrI+oMxASbosIFAl+YdvUC
GwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQI+oMxASbosKdcwgAjwnmkHPG
nS1tuTJrlZjqtH7Apvwv0HBUe4HEVJv1TivmTvDwQ0fsSc/57tdUqgd2Vcq00qSP
Gq1Un/7e7WMIlZP7vtj2FWkowxcAFI1Nf5CgKiADlay0p4KSmTpZoPTLgfraRPlj
O7xjjiXjEmYrk1GugUN8LbeTP2evYx3RbsEibDT0kWY5kaqcG2OY4sKWEPHdKXEe
DzDU5f6DBequ/rhpmBQj5Y5qbRR8TCCgAlLhPo5favos09HyPKGBGz4PLxBP9UbV
Qs2yjxJH9M2KC4omkNJQjVbocGjUVnsYk70JYjymB0DHvqUPW2c0WpEQDBIFadaa
tkdDQBiCZ7KcrLkBDQRfmHb1AQgAtInXbwTh0QwZC3yXv55dN5We1tCgLQXDaJlV
r7k4eJ54lYBn0+8xYvWJD6JZ3TPVsmf/vFVQLjMI1X5CLGS1BiWNtfQxGZ42gyXK
MGg7WoTJ4iHlbmIsAPL60/lt3j8aS6x+sBJlXVV0pklBMasMUXn+AvPDz4EbhMc4
oLp9L4lqRb5759aMUoAYOp06HxfxbhM5EqE60DzPAKEP+WZ7fJea/o9fJCHeBuA7
2AuJHOBcFPQPeqhFY1Bht3WMd5L5OhGbmR1mCsR7up9yVvdqaPTzE6aCDXEvbeZ9
y/QSwpCAGFECUNIZbmiJrKL6HVVto6VozomkYISNVwSJ0SoI2QARAQABiQE2BBgB
CAAgFiEE3tfq+zchw8t7RxNrI+oMxASbosIFAl+YdvUCGwwACgkQI+oMxASbosJh
FQgAs/g+srMLJO4PZYx2vCrZXvi5M2YeIr4LZyyo8wu1vLRIyZixhQgEaDAz8Af/
jnhhJaXb/xIvokspRHbV8+WckL+RDChibngqo5NMzsnjGThLWnmQ/Ys8q0ZF5kPD
QjR+CvR5seTF5a232YzgX2AoRONqle7SzxbkyzM0iTaT4cabzSvBd5CK7jRurAmK
C6+WlunG2mkfJ6t01Rx/aKoWJpSc2Frw7SCTBYhRq0qDdiRsDGHGlb5UdqEfR1b1
DlR05txblUYSFun369BjpuPA5MWAEaAH7SI9ThCbfQ1vjUH1iIBxT4kX0GzRi859
Yrp2jhdAzkXArMVq6CS8G+8H5w==
=/FAe
-----END PGP PUBLIC KEY BLOCK-----

19
poetry.lock generated
View File

@ -983,6 +983,19 @@ version = "4.8.0"
[package.dependencies]
ptyprocess = ">=0.5"
[[package]]
category = "main"
description = "Pretty Good Privacy for Python"
name = "pgpy"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7"
version = "0.5.3"
[package.dependencies]
cryptography = ">=2.6"
pyasn1 = "*"
six = ">=1.9.0"
[[package]]
category = "main"
description = "a port of the serialize and unserialize functions of php to python."
@ -1688,7 +1701,7 @@ test = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]
testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]
[metadata]
content-hash = "0e3ade53af79b805e718ebf5e7a047ff0d067ec4ed32154d77255579b1940e83"
content-hash = "16dc20a48cada11374ca312b3cbcccfe3b4b93380c6d8b3964eb6a64d37c1fe5"
lock-version = "1.0"
python-versions = "^3.7"
@ -2161,6 +2174,10 @@ pexpect = [
{file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"},
{file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"},
]
pgpy = [
{file = "PGPy-0.5.3-py2.py3-none-any.whl", hash = "sha256:cba6fbbb44a896a8a4f5807b3d8d4943a8f7a6607be11587f4a27734c711c1dd"},
{file = "PGPy-0.5.3.tar.gz", hash = "sha256:a49c269cedcaf82ac6999bcae5fd3f543ecb1c759f9d48a15ad8d8fa4ac03987"},
]
phpserialize = [
{file = "phpserialize-1.3.tar.gz", hash = "sha256:bf672d312d203d09a84c26366fab8f438a3ffb355c407e69974b7ef2d39a0fa7"},
]

View File

@ -73,6 +73,7 @@ memory_profiler = "^0.57.0"
gevent = "^20.9.0"
aiospamc = "^0.6.1"
email_validator = "^1.1.1"
PGPy = "^0.5.3"
[tool.poetry.dev-dependencies]
pytest = "^6.1.0"

View File

@ -1,107 +1,53 @@
import os
from io import BytesIO
from app.pgp_utils import load_public_key, gpg, encrypt_file
import pgpy
from pgpy import PGPMessage
pubkey = """-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: Keybase OpenPGP v1.0.0
Comment: https://keybase.io/crypto
xo0EXlqP9wEEALoJsLHZA5W4yGQf+TIlIuYjj72SGEXbZyvMJxDk89YE8SWHAP+L
+GkyNBfiPidJ1putLBOTDuxjDroDa6zMmjxCORUYdtq35RIDo/raamAaYg32X/TI
3WyL3lgVf7K+VhXntG2V3OfM1r5nt3C1sy8Rsvzbih3p+eHpE3xCImg7ABEBAAHN
FFRlc3QgPHRlc3RAc2wubG9jYWw+wq0EEwEKABcFAl5aj/cCGy8DCwkHAxUKCAIe
AQIXgAAKCRCtrxG3FC3nSGhDA/wMT4PM8pWCsbsGA32SMN0j0MRsmc6KT4BGX8qd
CwTv7s5DvZlkFL9uJQxcKFe+yYpjnrPvW0p81ispj7pVJqUTyx4brZHiWFi/vODz
YyzTXNJvWJOp27G4YzWPeEeSKuGjF1CQScmZJA5luay7mkI5gttw4q3iqJlcDDFq
1sz2486NBF5aj/cBBADA7KbOa8klxOC8Oact0zzc30SCGxtCLuFQCBI/dIrnv2KC
lIbUd+CDlmD+cKCIu7MlrYPhCLF24MYnUXVFDbT3fP8YVy2HZTfk4Q64tj0S17ve
E9H1G1W6FqdDUhMCU1EmJgd8sKOrNOFtz4+b3IHJhtJIoUILDkiMjfUCHmQaqQAR
AQABwsCDBBgBCgAPBQJeWo/3BQkPCZwAAhsuAKgJEK2vEbcULedInSAEGQEKAAYF
Al5aj/cACgkQDjygQt7BuGFtPQQAmzUJqXB4UWo9HPZfutqSU6GElSMwZq1Dlf8S
Stjq7cYK+HSfcyw4wSBMRxMtG2zmbyhWlYTqx3fAAjgE32dBI/Rq8ku60u6SGEiE
egKCcm0lyR1TVUTYEsfjiYD5AmGWng8tTavz1ANdEoE66wGApkETfmTM7hOuQrKm
BjXpmembUQP5AXln8rWuDkeXVXhBa5RR3NgoD/fos2QJ5NxkZdfPmM57EwQkEXKv
S3c5rlvvhIupElSyJkxOzfykNlJewVrLxCicj+JPSt7ly6YlkMQglyevntI46y1l
2Msf0oeQZ3uedURGQiGQalC7nzPFnOARbNffFEJI3cJhcLkr2UFdL0rOjQReWo/3
AQQA+MJeovqVVVrE1Vsc3M/BuG5ao7xyP1y7YhgmJg3gi8HR7b4/ySJtKnCYAmLg
wwjfCUWed/GZ+3bGw48x8Fmn+6QTPG04j8RUOMUgVt9jc+TxC8VWSvqH1Taho3MK
6ZQpCwXPO0FmWc5ybp0AJzqy2YS4eZwue1WH3zFzjXrOBd0AEQEAAcLAgwQYAQoA
DwUCXlqP9wUJDwmcAAIbLgCoCRCtrxG3FC3nSJ0gBBkBCgAGBQJeWo/3AAoJEFJq
ki+hZCNMgH4EAPiamTuezRtMIEWpjEjYGjpRF+2uj5VmU6N2E6+5Nh73HUKNCVRj
AWeRarplye/CqZyhzPgotDNzAPzE4smo0N0vvc4zi6toqMiO4ODjR313d0y0v4iP
+n576QwpfGw/ddlTEL7Iv28dzdKJArjNc2/jRxefHrAYSzjEunl/GUq+ToQD/izQ
mPo6SWhlODsIy4eR/u3NpKtQQcs40XWLVci6M66ntyl5XmBGgFFu0WHIYeDOnTRc
qL1W5yEYaaJhaEbmNGk3tf26Ns9cTl91S2eylO9nWGOnqFg58jP63TZVR7q3jIq1
e5DKgszG2Vvye+bbK6qMKmaIXEMhnjw9eZuW6MGf
=yDVI
-----END PGP PUBLIC KEY BLOCK-----
"""
private_key = """-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: Keybase OpenPGP v1.0.0
Comment: https://keybase.io/crypto
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
U9jtqNTsHrr0XFzA2zno+zcopiZZOoPXcwxLf+pCetjN5EOkpMgqZTtV2nCppQRB
d3ZpsguOO4OVexEW6gWGOuas5+/qa846it9VMo+nlqtLyIAFbj2P02Zk/QrUnPF3
PEjKDJssrOEnZWlpAdEDfFhC1OrBVlG0lkD1qHDCNO9MTeT2dRMghbFGxlno9z2K
wnnB+Ep4UULuvbh08GsVflQPaA0a59IFDbOzYc7puS5kpJ5fQWwdXZvjNc/jOeQX
BHaLfQKmWYW3pCxs0BqKRhAnZ9E+kkIL6xU6MlJPs/NGO7aAykrFv8BdmBJQ8s00
9LGlgSUhdEdIsn5h3Kdn0f/7FXXWwsCDBBgBCgAPBQJeWo/3BQkPCZwAAhsuAKgJ
EK2vEbcULedInSAEGQEKAAYFAl5aj/cACgkQUmqSL6FkI0yAfgQA+JqZO57NG0wg
RamMSNgaOlEX7a6PlWZTo3YTr7k2HvcdQo0JVGMBZ5FqumXJ78KpnKHM+Ci0M3MA
/MTiyajQ3S+9zjOLq2ioyI7g4ONHfXd3TLS/iI/6fnvpDCl8bD912VMQvsi/bx3N
0okCuM1zb+NHF58esBhLOMS6eX8ZSr5OhAP+LNCY+jpJaGU4OwjLh5H+7c2kq1BB
yzjRdYtVyLozrqe3KXleYEaAUW7RYchh4M6dNFyovVbnIRhpomFoRuY0aTe1/bo2
z1xOX3VLZ7KU72dYY6eoWDnyM/rdNlVHureMirV7kMqCzMbZW/J75tsrqowqZohc
QyGePD15m5bowZ8=
=4OSo
-----END PGP PRIVATE KEY BLOCK-----"""
from app.config import ROOT_DIR
from app.pgp_utils import (
load_public_key,
gpg,
encrypt_file,
encrypt_file_with_pgpy,
)
def test_load_public_key():
load_public_key(pubkey)
public_key_path = os.path.join(ROOT_DIR, "local_data/public-pgp.asc")
public_key = open(public_key_path).read()
load_public_key(public_key)
assert len(gpg.list_keys()) == 1
def test_encrypt():
fingerprint = load_public_key(pubkey)
public_key_path = os.path.join(ROOT_DIR, "local_data/public-pgp.asc")
public_key = open(public_key_path).read()
fingerprint = load_public_key(public_key)
secret = encrypt_file(BytesIO(b"abcd"), fingerprint)
assert secret != ""
def test_encrypt_file_with_pgpy():
encrypt_decrypt_text("heyhey")
encrypt_decrypt_text("👍💪")
encrypt_decrypt_text("éèù")
encrypt_decrypt_text("片仮名")
def encrypt_decrypt_text(text: str):
public_key_path = os.path.join(ROOT_DIR, "local_data/public-pgp.asc")
public_key = open(public_key_path).read()
encrypted: PGPMessage = encrypt_file_with_pgpy(text.encode(), public_key)
# decrypt
private_key_path = os.path.join(ROOT_DIR, "local_data/private-pgp.asc")
private_key = open(private_key_path).read()
priv = pgpy.PGPKey()
priv.parse(private_key)
decrypted = priv.decrypt(encrypted).message
if type(decrypted) == str:
assert decrypted == text
elif type(decrypted) == bytearray:
assert decrypted.decode() == text