Closed hejsan closed 4 years ago
I would need an example of the raw data you are passing into tsp.TimeStampResp.load
.
Thank you for the quick response Here's what the timestamp looks like:
b'0\x82\t\x8c\x06\t*\x86H\x86\xf7\r\x01\x07\x02\xa0\x82\t}0\x82\ty\x02\x01\x031\x0f0\r\x06\t`\x86H\x01e\x03\x04\x02\x01\x05\x000\x81\xe6\x06\x0b*\x86H\x86\xf7\r\x01\t\x10\x01\x04\xa0\x81\xd6\x04\x81\xd30\x81\xd0\x02\x01\x01\x06\t+\x06\x01\x04\x01\xa02\x01\x1f010\r\x06\t`\x86H\x01e\x03\x04\x02\x01\x05\x00\x04 \x04|\x11\xd9\xcf\xf9\xb53\x91C\x9f\x01mi\x0e\xd3]4\xc7\xa4\x1f\x146#\xa6\xa8Ve(\xaf\xe1s\x02\x10\tlN|\x11#\x8aFWm\x01O\xfe\xc1\xdft\x18\x0f20200403111050Z0\x03\x02\x01\x01\xa0e\xa4c0a1503\x06\x03U\x04\x03\x0c,Globalsign TSA for AATL on DSS - SHA384 - G51\x1b0\x19\x06\x03U\x04\n\x0c\x12GMO GlobalSign Ltd1\x0b0\t\x06\x03U\x04\x06\x13\x02GB\xa0\x82\x05\xd40\x82\x05\xd00\x82\x03\xb8\xa0\x03\x02\x01\x02\x02\x0c\x167\xae\x1d\xe7\xf0\xf1T\xc7\x90\xde\xa00\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0c\x05\x000W1\x0b0\t\x06\x03U\x04\x06\x13\x02BE1\x190\x17\x06\x03U\x04\n\x13\x10GlobalSign nv-sa1-0+\x06\x03U\x04\x03\x13$GlobalSign CA for AATL - SHA384 - G40\x1e\x17\r191024000000Z\x17\r310121000000Z0a1503\x06\x03U\x04\x03\x0c,Globalsign TSA for AATL on DSS - SHA384 - G51\x1b0\x19\x06\x03U\x04\n\x0c\x12GMO GlobalSign Ltd1\x0b0\t\x06\x03U\x04\x06\x13\x02GB0\x82\x01"0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x000\x82\x01\n\x02\x82\x01\x01\x00\x88e9&Bd\xfcVa\x92\x14E0no\xdfu\xbdg\xc9\xa2&\x15\x1b\x86\xc4\xff\x12\x88n1\xd2M\x8f(\x9b\xf30\x08pi\xba\x08\x8b\xe3\xce\xcc\x91\x81\x1a\x95\x90\x1b\x15\xd3d\x9ew"\xb1\x8b\x0f.\x805h:\x1dG,\xe5\x10\xb6>\xd4\xd5\xe3\x01*I;\x00\xdc\xe0\x17\xa9\x01\xfe9\xefGt\xd0P$<\x8a=\xe9\xcd\x16.L^\x11\xda\x02k\x1a\xe1\xb0:\xba\xa1\x80W\x9eu\xf0\x82\xb6\xf2\xc9\xe3\x95F\xb2W\xe4\xdd\xab<\r2\xab\x1c\x0c\x1bie\xfc\xca\x90:\xb5\xb6! w\xc4ne\xe8;\xeb$92I!\xb2\xc7\x15\xc0\x05\xdb\xde+\x86\xc8\x92\xb4x\x84\xe5\xc6!\xc0l\xaf\xf4\x02A\xcb^\x16~\x97\x95\xc4o\xff\x8a\xdc\xe6\x9bU!<\x90\xc7;\xf9\x90\xc7\x85\xe3\x1d\x84!\x8c\x9c\xeb\xb0!\xe3\xf1\xab\x8f\x95\x976\xc5\xa1\xfa\x9f)3\xc5\xc4\xa3?\xd0\xa5\xcb\xc5i\x8b\x80;\x9a\xa8\xf83\x00\xe0\x8d\xd9\\\x1b\x1e\x9a\x1f>\xcf\x99\x02\x03\x01\x00\x01\xa3\x82\x01\x900\x82\x01\x8c0\x0e\x06\x03U\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x07\x800L\x06\x03U\x1d \x04E0C0A\x06\t+\x06\x01\x04\x01\xa02\x01\x1f0402\x06\x08+\x06\x01\x05\x05\x07\x02\x01\x16&https://www.globalsign.com/repository/0\t\x06\x03U\x1d\x13\x04\x020\x000\x16\x06\x03U\x1d%\x01\x01\xff\x04\x0c0\n\x06\x08+\x06\x01\x05\x05\x07\x03\x080>\x06\x03U\x1d\x1f\x0470503\xa01\xa0/\x86-http://crl.globalsign.com/ca/gsaatlsha2g4.crl0\x81\x88\x06\x08+\x06\x01\x05\x05\x07\x01\x01\x04|0z0@\x06\x08+\x06\x01\x05\x05\x070\x02\x864http://secure.globalsign.com/cacert/gsaatlsha2g4.crt06\x06\x08+\x06\x01\x05\x05\x070\x01\x86*http://ocsp.globalsign.com/ca/gsaatlsha2g40\x1f\x06\x03U\x1d#\x04\x180\x16\x80\x14\x89\xefuqz_G\x1b\x97#\xdc\x90J\xcb\xff\xc0&6\x08\xd50\x1d\x06\x03U\x1d\x0e\x04\x16\x04\x14MG{=\x16q\x8a\x99\xe3\x12\xef\x8b\x06\xbe9\xb6\xbd\xd8N\xca0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0c\x05\x00\x03\x82\x02\x01\x006r\xac\x11\x160\x8fX|b!\xf7\x88\x82Wj9{o\xf84N-\xca\x87\xc8A\xdd\xac_\xc1\x94\xb8r\x82\xca\xf0\x16\nx\xe2\x9ch\xf4\x9d\xde\x9c\x04\x16\x01\xa8\xe8\xed{\x0b\x8c\xd2d\xcc\xa7\x98\\\xdaZ#\x83\x0b\xc0\x17i\x9b\x14\xaa\xd9\xd5@\x11y\x9fW\xf0\x1df\x01\xab_\x07q+\x8bx7\x1fS\xf9\xfd\xb2\x89\x83\xdf\xaeS\x8d\xde\x80\x93%\xc1tt\xbe\xd7`\xae`G\\1\xe3\xeeo\x9e\xff\xf0\x8e\xe2\xbaEn\xb3\xba\x8dw6H,\xea\x9a!\x15\x82\xc8.\x8e\xd4\xfc\xfb\xb6\xc4t\xa3\x87\xcd\x80\x85\xc1\xe3E\xf3\xddp)\x99\xd0\x99*.\x8fh]\x92:u\x14]0v\xa7\x98Z\xb1LD\x1d*^\xb0A\xb2\n\xfd\x96\xc0\xe4\xf4\xcdp\x81\x133*\x17\n\x92\xcf\x93f\x0e\xec\x86\xa5\xd8\x1c\x07`c\xa5\xa1\xa2\xee\xb4ge\x01\x86\xe8\x0e\xbd\x88d\x98w\x99\r\xe5u\xc2\x94<cC\x19\x14\xdaY\x8a\\g\xb75m\xb7\xe9\x8f\xfdh\x94\xf6\x82\x10p\xb6\xdc\x00o\x85)K\x0f\xc1XG\x02\xceY\x1dh4\x17\xeb\xecpd\xecV\xb7\xf0\xdb\xcc\xe1\x84AP\x1d\n\xf0\xcf{p\x82\x86\xd4\xc7\xec\xc6D\x17\\\xc6\x95\xa7\xbd}\xb2\x81\xc2\x9c(\xd3:u\xd8\xceY\xfd\xdc\xc9`\x7f\x15\xf2=\x93-)h\xc0\x90\xd3\xf9\x15~\xe4\xaaO\\\xe8\xc2R\xec3\x12\xd8\xca\xb7\x13\xc0\x14P\x14\xeby\x04\xb7\xe8\x06\xf7t"yB\x16{\xe3VL\xd4\x1fS\xbaTe)\xca\xf7\xbf\x08\n\x9e\x04g\xa8lJ\x02Y\x95L\xb8\x0b\x01\x83\x85v\xfc$N|~\x85hg$\x8d\xf5\xa9[<\xb9#\x8ex\xd9\xdc\xf5\xc7\xc9\xe6\xd4(\xd21\xf2\xae\x9f\xa1\x1c\x94\x96\xe7\x00\x04\x946\'\xa4\xea6\xd7\xd9[@\xe6#\xc1\xb2\x10]\xcd\t\xd6\xf5q\xd2\x9b\xffdJ\x13\x8d\xe0\xf8%\xfc \x9e\xa7dA-\xd0\xa0\x0bsU\x9c\xd7\x8bf\x03E\x05K\x848\xa6\xaa\xf4\xf0\x87t\x9dLV\xa3\xd9C-\xbe\x03\xcf61\x82\x02\xa00\x82\x02\x9c\x02\x01\x010g0W1\x0b0\t\x06\x03U\x04\x06\x13\x02BE1\x190\x17\x06\x03U\x04\n\x13\x10GlobalSign nv-sa1-0+\x06\x03U\x04\x03\x13$GlobalSign CA for AATL - SHA384 - G4\x02\x0c\x167\xae\x1d\xe7\xf0\xf1T\xc7\x90\xde\xa00\r\x06\t`\x86H\x01e\x03\x04\x02\x01\x05\x00\xa0\x82\x01\n0\x1c\x06\t*\x86H\x86\xf7\r\x01\t\x051\x0f\x17\r200403111050Z0\x1a\x06\t*\x86H\x86\xf7\r\x01\t\x031\r\x06\x0b*\x86H\x86\xf7\r\x01\t\x10\x01\x040\x81\x9c\x06\x0b*\x86H\x86\xf7\r\x01\t\x10\x02\x0c1\x81\x8c0\x81\x890\x81\x860\x81\x83\x04\x14\x17\xf84`\\=\xd4|\xbc\x83\x8b\x8a\xb3>\x84\xda\xf1\xf1\xc1\xb50k0[\xa4Y0W1\x0b0\t\x06\x03U\x04\x06\x13\x02BE1\x190\x17\x06\x03U\x04\n\x13\x10GlobalSign nv-sa1-0+\x06\x03U\x04\x03\x13$GlobalSign CA for AATL - SHA384 - G4\x02\x0c\x167\xae\x1d\xe7\xf0\xf1T\xc7\x90\xde\xa00/\x06\t*\x86H\x86\xf7\r\x01\t\x041"\x04 \x94\x97\x84`\x9c)p\x1f\x9b\xf0\x9c\xc6\xd6\xcf\xca\x9d\tBX\x8e.b\x8b\xee\x05\xeb\x8b\xcd\xb2\xf7\xf0?0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0b\x05\x00\x04\x82\x01\x00\x120-\xf2\x07U\x8e+\x94\xa4\x02\xec4\x06d\xc5\xd6\xc8tP\xe4\xa6\xdd<\xb8m}h\xd4\x15\xa2\xf1\xe5\x86o-\xdf]:\xdf27\xeb\xff\xd9\x9c\xa2\n\xe4+m\xa6\x85\xb7a~\xdf\xa9\xb3\x1fHs\xa8\x8c\x98\xad\xc1!\x920\nVnK\xbf?m4\x18\xff\x10$\x8a\x14H\t\x85\xb2\x08\xa0Y\xa6\xc3\xe3\xcf6\xf6\xf8\x96\x19T\xa1\xc5\xe53\xb8E\x88\x14\xb9?\xddJRz\xee\xed\xf2\xf9\xb3\xa3`H\xc3\xd9b\xe8\x05\xef\x05\xdc\xa4\x17h\x03\xb5\x95\xa6\xd3\x81\x9d=\xc6\xe66\xbd\x89M\xb49\xb0L\xb8\xbaZPZ\x90\x9e\xeb\nmk\xef\x0b\x8f\x90\xa4\xb5\xee4\nq_\xe8\xfb\xe4\xfe\xc6\xe6;\xf7eJ*\x04\x8f\xd2\x8f\xf1\xda\x96V\xd1\x9d#\xa3\xb3\xaa0\xe6\xe1]m:(\xe3\xc4\xbf\xf1\xd5\xe4\xad\x98\x88\x81*1mTo,S\xc8,Lu+\xce+p\xc8d\xf6\xf3\xa9\xc5\x17\xaf\xf4E\xdb\xe7G#iX\x02IpHA%\xb6\x13{'
Does pdf.AdobeTimestamp have a solution maybe?
Looks like a signedData object inside of a CMS ContentInfo.
Try:
from asn1crypto import cms, tsp # importing tsp adds relevant structures to cms
timestamp_token = base64.b64decode(timestamp_token)
resp = cms.ContentInfo.load(timestamp_token)
resp.native
OrderedDict([('content_type', 'signed_data'), ('content', OrderedDict([('version', 'v3'), ('digest_algorithms', [OrderedDict([('algorithm', 'sha256'), ('parameters', None)])]), ('encap_content_info', Orde
redDict([('content_type', 'tst_info'), ('content', OrderedDict([('version', 'v1'), ('policy', '1.3.6.1.4.1.4146.1.31'), ('message_imprint', OrderedDict([('hash_algorithm', OrderedDict([('algorithm', 'sha2
56'), ('parameters', None)])), ('hashed_message', b'\xa3\xd1\xcb\xd2|\xf8\x1c1#\xd4\xc7\x1c\x8e51\x1f\xb2\x14b\xee\xfct\xd7\x9c\x18&\xae\xb2\xabB\xdb?')])), ('serial_number', 13135542045286184509407547912
963992356), ('gen_time', datetime.datetime(2020, 4, 3, 12, 14, 49, tzinfo=datetime.timezone.utc)), ('accuracy', OrderedDict([('seconds', 1), ('millis', None), ('micros', None)])), ('ordering', False), ('n
once', None), ('tsa', OrderedDict([('common_name', 'Globalsign TSA for AATL on DSS - SHA384 - G5'), ('organization_name', 'GMO GlobalSign Ltd'), ('country_name', 'GB')])), ('extensions', None)]))])), ('ce
rtificates', [OrderedDict([('tbs_certificate', OrderedDict([('version', 'v3'), ('serial_number', 6875983379585117135997820576), ('signature', OrderedDict([('algorithm', 'sha384_rsa'), ('parameters', None)
])), ('issuer', OrderedDict([('country_name', 'BE'), ('organization_name', 'GlobalSign nv-sa'), ('common_name', 'GlobalSign CA for AATL - SHA384 - G4')])), ('validity', OrderedDict([('not_before', datetim
e.datetime(2019, 10, 24, 0, 0, tzinfo=datetime.timezone.utc)), ('not_after', datetime.datetime(2031, 1, 21, 0, 0, tzinfo=datetime.timezone.utc))])), ('subject', OrderedDict([('common_name', 'Globalsign TS
A for AATL on DSS - SHA384 - G5'), ('organization_name', 'GMO GlobalSign Ltd'), ('country_name', 'GB')])), ('subject_public_key_info', OrderedDict([('algorithm', OrderedDict([('algorithm', 'rsa'), ('param
eters', None)])), ('public_key', OrderedDict([('modulus', 17218324515407407201512494811033403035174248665311860625630767085416783692205788940816841717160724751799774887271888023108501034377480777433522311
313480786937929209658484945118164275404578533799811011889484301698696835440768293580350136804239827328879470313280883965964761270681460864365662521470536858120087964617431771037668806621095274858526361985
131509386926435488782290975260939109078008906500882807290091233923844415234807503451004544330605516006833929612467093007931099210641299368465542631478927741090099679243706474326475341655174582218791675094
326683591373586355394603205420196435402750626273067984270315417), ('public_exponent', 65537)]))])), ('issuer_unique_id', None), ('subject_unique_id', None), ('extensions', [OrderedDict([('extn_id', 'key_u
sage'), ('critical', True), ('extn_value', {'digital_signature'})]), OrderedDict([('extn_id', 'certificate_policies'), ('critical', False), ('extn_value', [OrderedDict([('policy_identifier', '1.3.6.1.4.1.
4146.1.31'), ('policy_qualifiers', [OrderedDict([('policy_qualifier_id', 'certification_practice_statement'), ('qualifier', 'https://www.globalsign.com/repository/')])])])])]), OrderedDict([('extn_id', 'basic_constraints'), ('critical', False), ('extn_value', OrderedDict([('ca', False), ('path_len_constraint', None)]))]), OrderedDict([('extn_id', 'extended_key_usage'), ('critical', True), ('extn_value', ['time_stamping'])]), OrderedDict([('extn_id', 'crl_distribution_points'), ('critical', False), ('extn_value', [OrderedDict([('distribution_point', ['http://crl.globalsign.com/ca/gsaatlsha2g4.crl']), ('reasons', None), ('crl_issuer', None)])])]), OrderedDict([('extn_id', 'authority_information_access'), ('critical', False), ('extn_value', [OrderedDict([('access_method', 'ca_issuers'), ('access_location', 'http://secure.globalsign.com/cacert/gsaatlsha2g4.crt')]), OrderedDict([('access_method', 'ocsp'), ('access_location', 'http://ocsp.globalsign.com/ca/gsaatlsha2g4')])])]), OrderedDict([('extn_id', 'authority_key_identifier'), ('critical', False), ('extn_value', OrderedDict([('key_identifier', b'\x89\xefuqz_G\x1b\x97#\xdc\x90J\xcb\xff\xc0&6\x08\xd5'), ('authority_cert_issuer', None), ('authority_cert_serial_number', None)]))]), OrderedDict([('extn_id', 'key_identifier'), ('critical', False), ('extn_value', b'MG{=\x16q\x8a\x99\xe3\x12\xef\x8b\x06\xbe9\xb6\xbd\xd8N\xca')])])])), ('signature_algorithm', OrderedDict([('algorithm', 'sha384_rsa'), ('parameters', None)])), ('signature_value', b'6r\xac\x11\x160\x8fX|b!\xf7\x88\x82Wj9{o\xf84N-\xca\x87\xc8A\xdd\xac_\xc1\x94\xb8r\x82\xca\xf0\x16\nx\xe2\x9ch\xf4\x9d\xde\x9c\x04\x16\x01\xa8\xe8\xed{\x0b\x8c\xd2d\xcc\xa7\x98\\\xdaZ#\x83\x0b\xc0\x17i\x9b\x14\xaa\xd9\xd5@\x11y\x9fW\xf0\x1df\x01\xab_\x07q+\x8bx7\x1fS\xf9\xfd\xb2\x89\x83\xdf\xaeS\x8d\xde\x80\x93%\xc1tt\xbe\xd7`\xae`G\\1\xe3\xeeo\x9e\xff\xf0\x8e\xe2\xbaEn\xb3\xba\x8dw6H,\xea\x9a!\x15\x82\xc8.\x8e\xd4\xfc\xfb\xb6\xc4t\xa3\x87\xcd\x80\x85\xc1\xe3E\xf3\xddp)\x99\xd0\x99*.\x8fh]\x92:u\x14]0v\xa7\x98Z\xb1LD\x1d*^\xb0A\xb2\n\xfd\x96\xc0\xe4\xf4\xcdp\x81\x133*\x17\n\x92\xcf\x93f\x0e\xec\x86\xa5\xd8\x1c\x07`c\xa5\xa1\xa2\xee\xb4ge\x01\x86\xe8\x0e\xbd\x88d\x98w\x99\r\xe5u\xc2\x94<cC\x19\x14\xdaY\x8a\\g\xb75m\xb7\xe9\x8f\xfdh\x94\xf6\x82\x10p\xb6\xdc\x00o\x85)K\x0f\xc1XG\x02\xceY\x1dh4\x17\xeb\xecpd\xecV\xb7\xf0\xdb\xcc\xe1\x84AP\x1d\n\xf0\xcf{p\x82\x86\xd4\xc7\xec\xc6D\x17\\\xc6\x95\xa7\xbd}\xb2\x81\xc2\x9c(\xd3:u\xd8\xceY\xfd\xdc\xc9`\x7f\x15\xf2=\x93-)h\xc0\x90\xd3\xf9\x15~\xe4\xaaO\\\xe8\xc2R\xec3\x12\xd8\xca\xb7\x13\xc0\x14P\x14\xeby\x04\xb7\xe8\x06\xf7t"yB\x16{\xe3VL\xd4\x1fS\xbaTe)\xca\xf7\xbf\x08\n\x9e\x04g\xa8lJ\x02Y\x95L\xb8\x0b\x01\x83\x85v\xfc$N|~\x85hg$\x8d\xf5\xa9[<\xb9#\x8ex\xd9\xdc\xf5\xc7\xc9\xe6\xd4(\xd21\xf2\xae\x9f\xa1\x1c\x94\x96\xe7\x00\x04\x946\'\xa4\xea6\xd7\xd9[@\xe6#\xc1\xb2\x10]\xcd\t\xd6\xf5q\xd2\x9b\xffdJ\x13\x8d\xe0\xf8%\xfc \x9e\xa7dA-\xd0\xa0\x0bsU\x9c\xd7\x8bf\x03E\x05K\x848\xa6\xaa\xf4\xf0\x87t\x9dLV\xa3\xd9C-\xbe\x03\xcf6')])]), ('crls', None), ('signer_infos', [OrderedDict([('version', 'v1'), ('sid', OrderedDict([('issuer', OrderedDict([('country_name', 'BE'), ('organization_name', 'GlobalSign nv-sa'), ('common_name', 'GlobalSign CA for AATL - SHA384 - G4')])), ('serial_number', 6875983379585117135997820576)])), ('digest_algorithm', OrderedDict([('algorithm', 'sha256'), ('parameters', None)])), ('signed_attrs', [OrderedDict([('type', 'signing_time'), ('values', [datetime.datetime(2020, 4, 3, 12, 14, 49, tzinfo=datetime.timezone.utc)])]), OrderedDict([('type', 'content_type'), ('values', ['tst_info'])]), OrderedDict([('type', 'signing_certificate'), ('values', [OrderedDict([('certs', [OrderedDict([('cert_hash', b'\x17\xf84`\\=\xd4|\xbc\x83\x8b\x8a\xb3>\x84\xda\xf1\xf1\xc1\xb5'), ('issuer_serial', OrderedDict([('issuer', [OrderedDict([('country_name', 'BE'), ('organization_name', 'GlobalSign nv-sa'), ('common_name', 'GlobalSign CA for AATL - SHA384 - G4')])]), ('serial_number', 6875983379585117135997820576)]))])]), ('policies', None)])])]), OrderedDict([('type', 'message_digest'), ('va
lues', [b'\x16\xdfH\xca\x1aS\nh:\x8f\x84\x8c\xe9\x87\xd72\x13\xd5rx\x1e\xde\x90{\xb20r\xb6G\x18\x0eC'])])]), ('signature_algorithm', OrderedDict([('algorithm', 'sha256_rsa'), ('parameters', None)])), ('si
gnature', b")9\x04\xb0\xee\x00tc<\x01^\x8fj\xb1(\xd9\x11\xf3\x9e\xdb\xecJ\xef\x186\x895\xcfJ\xdbO|\xc8\x14ncR\x1b\xee^\x84\xa5\xa7\xc0\xf0G_\xe5 \xbe\x03\x009W\xc54e\x92>\x1c\xc9\x80\x17\x8a\x02,\x1f\xf1\
x8a\xe1\x0em]\xd8\x83\r\xd4\xbc\x99ik\x90\xbeP\xd8k\xd7\x10\x80\x8b\n.\xfe\x93g\rPjZ$\xfc>\xb2\x9b\xfcr\r\xb1+FXj: \x87\xdc\xfc\xac\x02\xe6m\xdbj)\xe2\xb0G\xac\xa0\xfb8\xbf\xe9/\x19\x00\xe2c\xc7!\xdb\xa6b
\xd5%\xb6f}\xdc|\xe1\xb7\x0ew~gg<\x96S\xb6\xfa]\x01\xed5F\xf4A,\xc1\xcf9\xea\x02\x05\x1d\xcc\xbc\xcf\xcfWA\x146\xb6\r$\xabL\\m\x80\xb1\x7f7\xdc\xa8\xae\x07\xcc\x14'Y\x9f\xdc\x06\x01\xa7\x0f\xbaDp\xe5a\xcb
\xd4r\xb3\x1fS\xc4\xe1{\xdc!9\xa6\\a4\x10\x8f\xd0<\xaa\xba\x87\x85\x06:\xac\xaf\x07l\x8c\xf2\x98[\x87\xde\xe2\xfd%\xe1\xe1"), ('unsigned_attrs', None)])])]))])
That looks like it!
Ok, great that's awesome, thanks so much for taking the time, I was at my wits end :) I actually got the massive project of enabling all my Universities documents to be served digitally signed asap due to the coronavirus, to facilitate working from home. I've never had to learn such a massive amount of complex stuff in such a short time, just to let you know how appreciated your help is ๐ I'm going to ask to make my project open sourced also asap. Only thing I haven't figured out is how to enable LTV - Long Term Validation.
For possible future readers I added the timestamp to my datas dictionary like this:
tsp_attrs = [
cms.CMSAttribute({
'type': cms.CMSAttributeType('signature_time_stamp_token'),
'values': cms.SetOfContentInfo([
cms.ContentInfo({
'content_type': cms.ContentType('signed_data'),
'content': tsp_dict['content'],
})
])
})
]
datas['content']['signer_infos'][0]['unsigned_attrs'] = tsp_attrs
LTV is much more complex. You'll have to look into the PDF spec for that. I started the process of writing asn1crypto originally to solve LTV certificate signing. I've never had the time to finish that project.
It involves storing full certificate chains for the signature, along with cached revocation info. certvalidator includes some features like fetching OCSP and CRL info, which I believe will have to be cached and timestamped and then added to the PDF.
Yes I've seen a lot of questions but few answers. Fortunately Globalsigns API recently made it a bit easier because you can request the full trust chain and their respective ocsp responses as well as the ocsp response for the autogenerated signing certificate.
I just can't quite grasp yet how and where I make the dss section. Just fyi this is how I'm adding the ocsp stuff to the datas dict:
for rev in self._revocation_info:
rev = base64.b64decode(rev)
rev = ocsp.OCSPResponse.load(rev)
ocsp_revocation.append(
cms.RevocationInfoChoice({
'other': cms.OtherRevocationInfoFormat({
'other_rev_info_format': cms.OtherRevInfoFormatId('ocsp_response'),
'other_rev_info': rev
})
})
)
config = {
'version': 'v1',
'digest_algorithms': cms.DigestAlgorithms((
algos.DigestAlgorithm({'algorithm': hashalgo}),
)),
'encap_content_info': {
'content_type': 'data',
},
'certificates': certificates,
'crls': ocsp_revocation,
'signer_infos': [
signer,
],
}
datas = cms.ContentInfo({
'content_type': cms.ContentType('signed_data'),
'content': cms.SignedData(config),
})
But then if I read the spec correctly I have to also add some new dictionaries to the PDF to actually enable the LTV - which I thought would mess up the digest ๐
The digest is only supposed to be on part of the PDF - you have to provide a range of bytes that includes everything but the signature and the trailer, if I recall correctly.
You are correct that there are lots of questions and not answers. I got to around 95% of the way there, but putting the final bits together I've just never had time to fully work out. Looking at some existing LTV PDFs may be helpful, assuming you have a parser that can break down the portions of the PDF for you so you can understand the structure.
Unfortunately I don't have time to work on this any time soon (such is life), and the work I've done so far is commercial in nature, not open source.
Good luck!
Thanks! Do you have any recommendations for a nice pdf parser?
Unfortunately, no. ๐ I ended writing my own because I couldn't find one - kind of like asn1crypto.
ok, I see, so the one you wrote is not available?
Correct. It is part of the commercial project I am working on related to PDF signatures.
Hi again, I thought you might appreciate knowing that I figured out the LTV part and am now able to properly Digitally sign pdf's. My first very rough edition is here: https://github.com/hejsan/WeasySign
I dug up this here treasure of a document that actually explains DSS, Timestamps and LTV in quite a concise read. https://www.etsi.org/deliver/etsi_ts/102700_102799/10277804/01.01.02_60/ts_10277804v010102p.pdf
Oh, and I found this utility collection that helped me debug PDF syntax errors: https://pdfbox.apache.org/ - It kinda sucks - but it worked and saved my sanity.
Hi, thanks for a great library. I am writing a small library intended to be a high level (as in simple to use) library for digitally signing pdf's generated with the WeasyPrint library (https://github.com/Kozea/WeasyPrint).
I have already got it working for self-signed certificates and now I'm working on an adapter for digital signatures from the Globalsign DSS API (https://www.globalsign.com/en/resources/apis/api-documentation/digital-signing-service-api-documentation.html)
This is a direct link to the API Doc for the API call for a timestamp: https://www.globalsign.com/en/resources/apis/api-documentation/digital-signing-service-api-documentation.html#timestamp__digest__get
I get an error when I try to load the timestamp token:
Do you have an idea of what is wrong? Is globalsign using it a different format for the timestamp token? Thanks Bjarni