piknik

Unnamed repository; edit this file 'description' to name the repository.
Info | Log | Files | Refs | README | LICENSE

commit 6c27c2206c000db151acde595657ecde809cb652
parent 52a296abfb5ae51894631b07f7f9f75639175f27
Author: lash <dev@holbrook.no>
Date:   Wed,  9 Nov 2022 13:11:31 +0000

Add pgp signature, with tests direct and via basket

Diffstat:
Mpiknik/crypto.py | 26++++++++++++++++++++++----
Mpiknik/msg.py | 2+-
Mrequirements.txt | 2+-
Atests/test_crypto.py | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 85 insertions(+), 6 deletions(-)

diff --git a/piknik/crypto.py b/piknik/crypto.py @@ -1,13 +1,31 @@ +# standard imports +from email.message import Message + # external imports import gnupg -class Signer: +class PGPSigner: - def __init__(self, home_dir=None, default_key=None): + def __init__(self, home_dir=None, default_key=None, passphrase=None): self.gpg = gnupg.GPG(gnupghome=home_dir) self.default_key = default_key + self.passphrase = passphrase + + + def sign(self, msg, passphrase=None): # msg = IssueMessage object + m = Message() + v = msg.as_string() + m.set_type('multipart/relative') + ms = Message() + ms.set_type('application/pgp-signature') + fn = '{}.asc'.format(msg.get('X-Piknik-Msg-Id')) + ms.add_header('Content-Disposition', 'attachment', filename=fn) + sig = self.gpg.sign(v, keyid=self.default_key, detach=True, passphrase=self.passphrase) + ms.set_payload(str(sig)) + + m.attach(msg) + m.attach(ms) - def sign(self, issue_msg): - pass + return m diff --git a/piknik/msg.py b/piknik/msg.py @@ -24,7 +24,7 @@ class IssueMessage: self.__m.add_header('X-Piknik-Id', issue.id) self.__m.add_header('Date', formatdate(time.time())) self.__m.set_payload(None) - self.__m.set_type('multipart/mixed') + self.__m.set_type('multipart/relative') self.__m.set_boundary(str(uuid.uuid4())) diff --git a/requirements.txt b/requirements.txt @@ -1,3 +1,3 @@ -shep~=0.2.11 +shep~=0.3.0 leveldir~=0.3.1 python-gnupg~=0.5.0 diff --git a/tests/test_crypto.py b/tests/test_crypto.py @@ -0,0 +1,61 @@ +# standard imports +import os +import unittest +import logging +import json +import tempfile +import shutil +from email.message import Message + +# external imports +import gnupg + +# local imports +from piknik import Basket +from piknik import Issue +from piknik.crypto import PGPSigner + +# test imports +from tests.common import TestStates +from tests.common import TestMsgStore + +logging.basicConfig(level=logging.DEBUG) +logg = logging.getLogger() + +test_dir = os.path.realpath(os.path.dirname(__file__)) + + +class TestMsg(unittest.TestCase): + + def setUp(self): + self.store = TestStates() + self.gpg_dir = tempfile.mkdtemp() + gpg = gnupg.GPG(gnupghome=self.gpg_dir) + gpg_input = gpg.gen_key_input(key_type='RSA', key_length=1024, passphrase='foo') + gpg_key = gpg.gen_key(gpg_input) + self.crypto = PGPSigner(self.gpg_dir, default_key=gpg_key.fingerprint, passphrase='foo') + self.b = Basket(self.store, message_wrapper=self.crypto.sign) + + + def tearDown(self): + shutil.rmtree(self.gpg_dir) + + def test_wrap_sig(self): + m = Message() + m.set_charset('utf-8') + m.set_payload('foo') + r = self.crypto.sign(m, passphrase='foo') + print(str(r)) + + + def test_wrap_basket_sig(self): + o = Issue('foo') + v = self.b.add(o) + r = self.b.msg(v, 's:foo', 's:bar') + print(r) + + + + +if __name__ == '__main__': + unittest.main()