Skip to content

Commit

Permalink
Helper function to extract payload from PGP clearsigned message files.
Browse files Browse the repository at this point in the history
  • Loading branch information
kashifpk committed Feb 11, 2022
1 parent 2e33799 commit 937838f
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 1 deletion.
55 changes: 55 additions & 0 deletions hm_pyhelper/tests/test_util_pgp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"Test cases for util.gpg module."

import unittest
import json

from hm_pyhelper.util.pgp import get_payload_from_clearsigned_message


SAMPLE_CLEARSIGNED_MESSAGE = """
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
{
"key1": "value1",
"key2": [1, 2, 3, 4]
}
-----BEGIN PGP SIGNATURE-----
iQGzBAEBCgAdFiEEfSH7Wj/J4hZxOpWqMy5fwG12lo0FAmIDUGEACgkQMy5fwG12
lo0WDwv+Nn8ffqY3oKOQv11eRkn+w4NcAp5XFqwYz0e5e+DEfjoYYTVAEgUdK1gF
W2u8Jed9rW710A6yYXHlIZWKSHsQ1sob5lK3R/r+/lFrXLYYwgFGBWJmph/wuiQW
OuZPpenOPNNjh37xxxxwxMj2kqUHKfJ489H2xOpPqpA4tWRKAspQCkv/AFVctcr5
1gWhJ5M5Mw/W6mgLswzonpsRy9M+vknuiDJ9F/Qe2hWUBJ0p7Si7YJkrynF3Oiqz
3D3JCiZAmoHq31hxO3bU7Sltf0lp1E7rG7mx7l0Pxq3fzNgaA9IW30NuF9J3YohK
Cv4pl11BYuUsBiQZktKcUwAsNj+UmZTnFBWACn4444+tFvs/tgG3wFZA33y3HAkl
6X9WGEa4d+DXeMgk2hr5oMRI9tZWqhNFqpu96CzrjJDxchgpeYjSCFiiX3po6Gyd
vH8uvB5hNKzj1vwqEtyyyyikUrPBe+273VeXNB+npF4LRok1MBjHZ49oZd2GZKBl
vo5u8szs
=i6qt
-----END PGP SIGNATURE-----
"""


class TestUtilPGP(unittest.TestCase):

def test_empty_file(self):
with self.assertRaises(RuntimeError) as exp:
get_payload_from_clearsigned_message("")

assert str(exp.exception) == \
'Invalid message format, no --BEGIN PGP SIGNED MESSAGE-- header'

def test_invalid_clearsigned_payload(self):
with self.assertRaises(RuntimeError) as exp:
get_payload_from_clearsigned_message("Just\nSome\nMessage\na\nb\nc")

assert str(exp.exception) == \
'Invalid message format, no --BEGIN PGP SIGNED MESSAGE-- header'

def test_payload_extraction(self):
payload = get_payload_from_clearsigned_message(SAMPLE_CLEARSIGNED_MESSAGE)
d = json.loads(payload)
assert d['key1'] == 'value1'
assert d['key2'] == [1, 2, 3, 4]
Empty file added hm_pyhelper/util/__init__.py
Empty file.
35 changes: 35 additions & 0 deletions hm_pyhelper/util/pgp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""Utility code to work with GPG signed messages."""


def get_payload_from_clearsigned_message(message: str) -> str:
"""
Given a message in clearsign format removes signature and marker strings like
-----BEGIN PGP SIGNATURE-----, -----BEGIN PGP SIGNED MESSAGE----- to extract
the original payload.
:param message: The message containing the signature and the payload.
:return: Extracted payload as string. Calling code is responsible for
converting it to proper data type.
"""
lines = message.strip().split('\n')

if len(lines) < 5 \
or lines[0] != '-----BEGIN PGP SIGNED MESSAGE-----' \
or lines[1].startswith('Hash:') is False:
raise RuntimeError("Invalid message format, no --BEGIN PGP SIGNED MESSAGE-- header")

start_idx = 3 # Payload starts from 3rd line in clearsigned messages
end_idx = None
prev_line = ""

for idx, line in enumerate(lines[3:]):
if line.strip() == '-----BEGIN PGP SIGNATURE-----' and prev_line.strip() == "":
end_idx = idx + start_idx
break

prev_line = line

if end_idx is None:
raise RuntimeError("Invalid message format, no --BEGIN PGP SIGNATURE-- section")

return "\n".join(lines[start_idx: end_idx-1])
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

setup(
name='hm_pyhelper',
version='0.13.10',
version='0.13.11',
author="Nebra Ltd",
author_email="[email protected]",
description="Helium Python Helper",
Expand Down

0 comments on commit 937838f

Please sign in to comment.