Last active
March 31, 2018 08:39
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
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