Skip to content

Instantly share code, notes, and snippets.

@bzamecnik
Last active March 31, 2018 08:39
Show Gist options
  • Save bzamecnik/4e78117dcbcb6226960489aceefffdc8 to your computer and use it in GitHub Desktop.
Save bzamecnik/4e78117dcbcb6226960489aceefffdc8 to your computer and use it in GitHub Desktop.
Extracts original submission XML of CZ tax statement from digitally signed confirmation P7S
"""
Extracts original submission XML from digitally signed confirmation P7S
(Potvrzení o podání písemnosti) of the Czech tax return statement
(Daň z příjmů fyzických osob).
The confirmation is a sigitally signed XML file (P7S extension) and can be
opened using openssl (kudos to
[moldovan.IT blog](http://moldovan.it/blog/open-and-read-p7s-files-in-ubuntu-linux/)):
```
openssl smime -inform DER -verify -noverify -in input.p7s -out output.xml
```
Then the confirmation is just a wrapper over the original submission XML,
In the `<Pisemnost><Data>` element it just contains the hex-encoded binary data.
Usage:
```
pip install xmltodict
```
```
python extract_tax_confirmation.py DPFDP5-0000000000-20180331-094412-000000000-potvrzeni.p7s
```
And it extracts the submission XML to:
`DPFDP5-0000000000-20180331-094412-000000000-potvrzeni_submission.xml`.
See: https://adisepo.mfcr.cz/adistc/adis/idpr_epo/epo2/spol/odeslani.faces
"""
import argparse
import binascii
import os
import subprocess
import xmltodict
def extract_signed_xml(p7s_path):
print('Extracting signed confirmation XML from P7S:', p7s_path)
xml_path = os.path.splitext(p7s_path)[0] + '.xml'
err_code = subprocess.call([
'openssl', 'smime', '-inform', 'DER', '-verify', '-noverify',
'-in', p7s_path,
'-out', xml_path
])
if err_code > 0:
raise ValueError('Could not extract signed XML file from %s' % p7s_path)
return xml_path
def extract_submission_from_confirmation(confirmation_xml_path, submission_xml_path):
print('Reading confirmation XML:', confirmation_xml_path)
with open(confirmation_xml_path, 'rb') as f:
doc = xmltodict.parse(f)
# b'<?xml version="1.0" encoding="UTF-8"?><Pisemnost><Data>3c3f786d6c2076657273696f6e3d22312e302220656e6'
data_hex = doc['Pisemnost']['Data']
data_bin = binascii.a2b_hex(data_hex)
# b'<?xml version="1.0" encoding="UTF-8"?>\n<Pisemnost nazevSW="EPO MF \xc4\x8cR" verzeSW="40.7.3">\n<DPFDP5 ver'
with open(submission_xml_path, 'wb') as f:
f.write(data_bin)
print('Original submission XML written to:', submission_xml_path)
def extract_submission_from_signed_confirmation(confirmation_p7s_path, submission_xml_path):
confirmation_xml_path = extract_signed_xml(confirmation_p7s_path)
extract_submission_from_confirmation(confirmation_xml_path, submission_xml_path)
def make_submission_path(confirmation_xml_path):
name = os.path.splitext(confirmation_xml_path)[0]
return '%s_submission.xml' % name
def parse_args():
parser = argparse.ArgumentParser(description=
'Extracts tax statement submission from signed confirmation.')
parser.add_argument('p7s_path', metavar='P7S_PATH',
help='Signed confirmation file (P7S)')
return parser.parse_args()
if __name__ == '__main__':
args = parse_args()
confirmation_p7s_path = args.p7s_path
submission_xml_path = make_submission_path(confirmation_p7s_path)
extract_submission_from_signed_confirmation(confirmation_p7s_path,
submission_xml_path)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment