Skip to content

Commit 085f8c3

Browse files
authored
Merge pull request IdentityPython#9 from IdentityPython/fix/eu_integration
EU fork integration
2 parents 9fbf822 + 8d3d2be commit 085f8c3

22 files changed

+748
-418
lines changed

.github/workflows/python-app.yml

+4-3
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,15 @@ on:
1212
jobs:
1313
build:
1414

15-
runs-on: ubuntu-latest
15+
runs-on: ubuntu-22.04
1616

1717
strategy:
1818
fail-fast: false
1919
matrix:
2020
python-version:
2121
- '3.10'
22-
- '3.11'
22+
- "3.11"
23+
- "3.12"
2324

2425
steps:
2526
- uses: actions/checkout@v2
@@ -30,7 +31,7 @@ jobs:
3031
- name: Install system package
3132
run: |
3233
sudo apt update
33-
sudo apt install python3-dev libssl-dev make automake gcc g++
34+
sudo apt install python3-dev libssl-dev libffi-dev make automake gcc g++
3435
- name: Install dependencies
3536
run: |
3637
python -m pip install --upgrade pip

README.md

+71-37
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,20 @@ Python parser and writer for EUDI Wallet MDOC CBOR for credential Type 1 and als
99
- [ISO 18013-5 - ISO-compliant driving licence — Mobile driving licence (mDL) application](https://www.iso.org/standard/69084.html)
1010
- [RFC 8949 - Concise Binary Object Representation (CBOR)](https://datatracker.ietf.org/doc/html/rfc8949)
1111
- [RFC 9052 - CBOR Object Signing and Encryption (COSE): Structures and Process](https://www.rfc-editor.org/rfc/rfc9052.html)
12-
- deprecates [RFC 8152 - CBOR Object Signing and Encryption (COSE)](https://datatracker.ietf.org/doc/html/rfc8152)
12+
- deprecates [RFC 8152 - CBOR Object Signing and Encryption (COSE)](https://datatracker.ietf.org/doc/html/rfc8152)
1313
- [IANA Registry - Concise Binary Object Representation (CBOR) Tags](https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml)
1414

1515
COSE label 33 (x5chain) in MSO:
1616

1717
- [RFC 9360 CBOR Object Signing and Encryption (COSE) - Header Parameters for Carrying and Referencing X.509 Certificates](https://www.rfc-editor.org/rfc/rfc9360.html)
1818

19-
## Scope
19+
## Scope
2020

21-
pyMDOC-CBOR is a
22-
[cbor2](https://github.com/agronholm/cbor2)
23-
and
24-
[pycose](https://github.com/TimothyClaeys/pycose)
25-
wrapper that parses, creates and validates MDOC CBOR encoded binaries
21+
pyMDOC-CBOR is a
22+
[cbor2](https://github.com/agronholm/cbor2)
23+
and
24+
[pycose](https://github.com/TimothyClaeys/pycose)
25+
wrapper that parses, creates and validates MDOC CBOR encoded binaries
2626
according to ISO 18013-5.
2727

2828
## Setup
@@ -39,14 +39,41 @@ pip install git+https://github.com/peppelinux/pyMDOC-CBOR.git
3939

4040
## Usage
4141

42+
### Issue an MDOC CBOR signed with HSM key
43+
44+
````
45+
PID_DATA = {
46+
"eu.europa.ec.eudiw.pid.1": {
47+
"family_name": "Raffaello",
48+
"given_name": "Mascetti",
49+
"birth_date": "1922-03-13"
50+
}
51+
}
52+
53+
mdoci = MdocCborIssuer(
54+
alg = 'ES256',
55+
kid = "demo-kid",
56+
hsm=True,
57+
key_label="p256-1",
58+
user_pin="1234",
59+
lib_path="/etc/utimaco/libcs2_pkcs11.so",
60+
slot_id=3
61+
)
62+
63+
mdoc = mdoci.new(
64+
doctype="eu.europa.ec.eudiw.pid.1",
65+
data=PID_DATA,
66+
# cert_path="app/keys/IACAmDLRoot01.der" # DS certificate
67+
)
68+
69+
````
70+
4271
### Issue an MDOC CBOR
4372

4473
`MdocCborIssuer` must be initialized with a private key.
4574
The method `.new()` gets the user attributes, devicekeyinfo and doctype.
4675

4776
````
48-
import os
49-
5077
from pymdoccbor.mdoc.issuer import MdocCborIssuer
5178
5279
PKEY = {
@@ -58,17 +85,14 @@ PKEY = {
5885
}
5986
6087
PID_DATA = {
61-
"eu.europa.ec.eudiw.pid.1": {
62-
"family_name": "Raffaello",
63-
"given_name": "Mascetti",
64-
"birth_date": "1922-03-13",
65-
"birth_place": "Rome",
66-
"birth_country": "IT"
67-
},
68-
"eu.europa.ec.eudiw.pid.it.1": {
69-
"tax_id_code": "TINIT-XXXXXXXXXXXXXXX"
88+
"eu.europa.ec.eudiw.pid.1": {
89+
"family_name": "Raffaello",
90+
"given_name": "Mascetti",
91+
"birth_date": "1922-03-13",
92+
"birth_place": "Rome",
93+
"birth_country": "IT"
94+
}
7095
}
71-
}
7296
7397
mdoci = MdocCborIssuer(
7498
private_key=PKEY
@@ -78,16 +102,20 @@ mdoc = mdoci.new(
78102
doctype="eu.europa.ec.eudiw.pid.1",
79103
data=PID_DATA,
80104
devicekeyinfo=PKEY # TODO
105+
# cert_path="/path/"
81106
)
82107
83108
mdoc
84109
>> returns a python dictionay
85110
111+
mdoc.dump()
112+
>> returns mdoc MSO bytes
113+
86114
mdoci.dump()
87115
>> returns mdoc bytes
88116
89117
mdoci.dumps()
90-
>> returns AF Binary string representation
118+
>> returns AF Binary mdoc string representation
91119
````
92120

93121
### Issue an MSO alone
@@ -96,7 +124,7 @@ MsoIssuer is a class that handles private keys, data processing, digests and sig
96124

97125
The `disclosure_map` is used in the Mdoc `nameSpaces` object for issuance and presentations,
98126
it's carried in the mdoc but outside of the MSO, even if it is produced by `MsoIssuer`.
99-
that's why `MsoIssuer.sign()` returns a pure MSO, while `disclosure_map`
127+
that's why `MsoIssuer.sign()` returns a pure MSO, while `disclosure_map`
100128
is an attribute of the `MsoIssuer` instance.
101129

102130
````
@@ -124,15 +152,16 @@ mso = msoi.sign()
124152
````
125153

126154
API usage:
127-
- `msoi.data`, user attributes to be encoded
128-
- `msoi.private_key`, COSEKey
129-
- `msoi.public_key`, COSEKey without `d` (for EC2Key)
130-
- `msoi.selfsigned_x509cert`, using the private and the public keys returns a self-signed x509 certificate
131-
- `msoi.hash_map`, digests that will be signed in the MSO
132-
- `msoi.disclosure_map`, disclosure objects grouped by namespaces
133-
- `msoi.sign`, signs the MSO and returns it
134155

135-
### Parse a binary Mdoc
156+
- `msoi.data`, user attributes to be encoded
157+
- `msoi.private_key`, COSEKey
158+
- `msoi.public_key`, COSEKey without `d` (for EC2Key)
159+
- `msoi.selfsigned_x509cert`, using the private and the public keys returns a self-signed x509 certificate
160+
- `msoi.hash_map`, digests that will be signed in the MSO
161+
- `msoi.disclosure_map`, disclosure objects grouped by namespaces
162+
- `msoi.sign`, signs the MSO and returns it
163+
164+
### Parse a binary Mdoc
136165

137166
````
138167
from pymdoccbor.mdoc.verifier import MdocCbor
@@ -166,13 +195,14 @@ msop.verify_signature()
166195
````
167196

168197
API usage:
169-
- `msop.payload_as_dict`: returns the MSO as Python dictionary.
170-
- `msop.payload_as_raw`: returns the MSO as bytes in its original format.
171-
- `msop.payload_as_cbor`: returns the MSO as CBOR encoded object.
172-
- `msop.object`: returns a pycose COSE_Sign1 object.
173-
- `msop.raw_public_keys`: returns the list of the public keys from the unprotected COSE header
174-
- `msop.public_key`: returns `cryptography.hazmat` key.
175-
- `msop.x509_certificates`: returns a list of `cryptography.x509` certificate objects
198+
199+
- `msop.payload_as_dict`: returns the MSO as Python dictionary.
200+
- `msop.payload_as_raw`: returns the MSO as bytes in its original format.
201+
- `msop.payload_as_cbor`: returns the MSO as CBOR encoded object.
202+
- `msop.object`: returns a pycose COSE_Sign1 object.
203+
- `msop.raw_public_keys`: returns the list of the public keys from the unprotected COSE header
204+
- `msop.public_key`: returns `cryptography.hazmat` key.
205+
- `msop.x509_certificates`: returns a list of `cryptography.x509` certificate objects
176206

177207
## Tests
178208

@@ -184,6 +214,7 @@ pytest --cov-report term-missing --cov-report term:skip-covered --cov
184214
## Other examples
185215

186216
Quick preview in bash using AF binary
217+
187218
````
188219
# D.4.1.2 mdoc response
189220
export ISSUED_MDOC="a36776657273696f6e63312e3069646f63756d656e747381a367646f6354797065756f72672e69736f2e31383031332e352e312e6d444c6c6973737565725369676e6564a26a6e616d65537061636573a1716f72672e69736f2e31383031332e352e3186d8185863a4686469676573744944006672616e646f6d58208798645b20ea200e19ffabac92624bee6aec63aceedecfb1b80077d22bfc20e971656c656d656e744964656e7469666965726b66616d696c795f6e616d656c656c656d656e7456616c756563446f65d818586ca4686469676573744944036672616e646f6d5820b23f627e8999c706df0c0a4ed98ad74af988af619b4bb078b89058553f44615d71656c656d656e744964656e7469666965726a69737375655f646174656c656c656d656e7456616c7565d903ec6a323031392d31302d3230d818586da4686469676573744944046672616e646f6d5820c7ffa307e5de921e67ba5878094787e8807ac8e7b5b3932d2ce80f00f3e9abaf71656c656d656e744964656e7469666965726b6578706972795f646174656c656c656d656e7456616c7565d903ec6a323032342d31302d3230d818586da4686469676573744944076672616e646f6d582026052a42e5880557a806c1459af3fb7eb505d3781566329d0b604b845b5f9e6871656c656d656e744964656e7469666965726f646f63756d656e745f6e756d6265726c656c656d656e7456616c756569313233343536373839d818590471a4686469676573744944086672616e646f6d5820d094dad764a2eb9deb5210e9d899643efbd1d069cc311d3295516ca0b024412d71656c656d656e744964656e74696669657268706f7274726169746c656c656d656e7456616c7565590412ffd8ffe000104a46494600010101009000900000ffdb004300130d0e110e0c13110f11151413171d301f1d1a1a1d3a2a2c2330453d4947443d43414c566d5d4c51685241435f82606871757b7c7b4a5c869085778f6d787b76ffdb0043011415151d191d381f1f38764f434f7676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676ffc00011080018006403012200021101031101ffc4001b00000301000301000000000000000000000005060401020307ffc400321000010303030205020309000000000000010203040005110612211331141551617122410781a1163542527391b2c1f1ffc4001501010100000000000000000000000000000001ffc4001a110101010003010000000000000000000000014111213161ffda000c03010002110311003f00a5bbde22da2329c7d692bc7d0d03f52cfb0ff75e7a7ef3e7709723a1d0dae146ddfbb3c039ce07ad2bd47a7e32dbb8dd1d52d6ef4b284f64a480067dfb51f87ffb95ff00eb9ff14d215de66af089ce44b7dbde9cb6890a2838eddf18078f7add62d411ef4db9b10a65d6b95a147381ea0d495b933275fe6bba75c114104a8ba410413e983dff004f5af5d34b4b4cde632d0bf1fd1592bdd91c6411f3934c2fa6af6b54975d106dcf4a65ae56e856001ebc03c7ce29dd9eef1ef10fc447dc9da76ad2aee93537a1ba7e4f70dd8eff0057c6dffb5e1a19854a83758e54528750946ec6704850cd037bceb08b6d7d2cc76d3317fc7b5cc04fb6707269c5c6e0c5b60ae549242123b0e493f602a075559e359970d98db89525456b51c951c8afa13ea8e98e3c596836783d5c63f5a61a99fdb7290875db4be88ab384bbbbbfc7183fdeaa633e8951db7da396dc48524fb1a8bd611a5aa2a2432f30ab420a7a6d3240c718cf031fa9ef4c9ad550205aa02951df4a1d6c8421b015b769db8c9229837ea2be8b1b0d39d0eba9c51484efdb8c0efd8d258daf3c449699f2edbd4584e7af9c64e3f96b9beb28d4ac40931e6478c8e76a24a825449501d867d2b1dcdebae99b9c752ae4ecd6dde4a179c1c1e460938f9149ef655e515c03919a289cb3dca278fb7bf177f4faa829dd8ce3f2ac9a7ecde490971fafd7dce15eed9b71c018c64fa514514b24e8e4f8c5c9b75c1e82579dc1233dfec08238f6add62d391acc1c5256a79e706d52d431c7a0145140b9fd149eb3a60dc5e88cbbc2da092411e9dc71f39a7766b447b344e847dcac9dcb5abba8d145061d43a6fcf1e65cf15d0e90231d3dd9cfe62995c6dcc5ca12a2c904a15f71dd27d451453e09d1a21450961cbb3ea8a956433b781f1ce33dfed54f0e2b50a2b71d84ed6db18028a28175f74fc6bda105c529a791c25c4f3c7a11f71586268f4a66b726e33de9ea6f1b52b181c760724e47b514520a5a28a283ffd9d81858ffa4686469676573744944096672616e646f6d58204599f81beaa2b20bd0ffcc9aa03a6f985befab3f6beaffa41e6354cdb2ab2ce471656c656d656e744964656e7469666965727264726976696e675f70726976696c656765736c656c656d656e7456616c756582a37576656869636c655f63617465676f72795f636f646561416a69737375655f64617465d903ec6a323031382d30382d30396b6578706972795f64617465d903ec6a323032342d31302d3230a37576656869636c655f63617465676f72795f636f646561426a69737375655f64617465d903ec6a323031372d30322d32336b6578706972795f64617465d903ec6a323032342d31302d32306a697373756572417574688443a10126a118215901d2308201ce30820174a003020102021401ec51916031e6898e8fc7864af5e6d5f86602b6300a06082a8648ce3d04030230233114301206035504030c0b75746f7069612069616361310b3009060355040613025553301e170d3230313030313030303030305a170d3231313030313030303030305a30213112301006035504030c0975746f706961206473310b30090603550406130255533059301306072a8648ce3d020106082a8648ce3d03010703420004ace7ab7340e5d9648c5a72a9a6f56745c7aad436a03a43efea77b5fa7b88f0197d57d8983e1b37d3a539f4d588365e38cbbf5b94d68c547b5bc8731dcd2f146ba38187308184301e0603551d120417301581136578616d706c65406578616d706c652e636f6d301c0603551d1f041530133011a00fa00d820b6578616d706c652e636f6d301d0603551d0e0416041414e29017a6c35621ffc7a686b7b72db06cd12351300e0603551d0f0101ff04040302078030150603551d250101ff040b3009060728818c5d050102300a06082a8648ce3d0403020348003045022100bac6f93a8bacf0fc9aeac1c89a5c9293af2076942e9e972882a113640330702702207b7b73c0444371a4c94c9c888ddfe553ffde84ca492fd64dfbf02ad46a31cbc85903a2d81859039da66776657273696f6e63312e306f646967657374416c676f726974686d675348412d3235366c76616c756544696765737473a2716f72672e69736f2e31383031332e352e31ad00582075167333b47b6c2bfb86eccc1f438cf57af055371ac55e1e359e20f254adcebf01582067e539d6139ebd131aef441b445645dd831b2b375b390ca5ef6279b205ed45710258203394372ddb78053f36d5d869780e61eda313d44a392092ad8e0527a2fbfe55ae0358202e35ad3c4e514bb67b1a9db51ce74e4cb9b7146e41ac52dac9ce86b8613db555045820ea5c3304bb7c4a8dcb51c4c13b65264f845541341342093cca786e058fac2d59055820fae487f68b7a0e87a749774e56e9e1dc3a8ec7b77e490d21f0e1d3475661aa1d0658207d83e507ae77db815de4d803b88555d0511d894c897439f5774056416a1c7533075820f0549a145f1cf75cbeeffa881d4857dd438d627cf32174b1731c4c38e12ca936085820b68c8afcb2aaf7c581411d2877def155be2eb121a42bc9ba5b7312377e068f660958200b3587d1dd0c2a07a35bfb120d99a0abfb5df56865bb7fa15cc8b56a66df6e0c0a5820c98a170cf36e11abb724e98a75a5343dfa2b6ed3df2ecfbb8ef2ee55dd41c8810b5820b57dd036782f7b14c6a30faaaae6ccd5054ce88bdfa51a016ba75eda1edea9480c5820651f8736b18480fe252a03224ea087b5d10ca5485146c67c74ac4ec3112d4c3a746f72672e69736f2e31383031332e352e312e5553a4005820d80b83d25173c484c5640610ff1a31c949c1d934bf4cf7f18d5223b15dd4f21c0158204d80e1e2e4fb246d97895427ce7000bb59bb24c8cd003ecf94bf35bbd2917e340258208b331f3b685bca372e85351a25c9484ab7afcdf0d2233105511f778d98c2f544035820c343af1bd1690715439161aba73702c474abf992b20c9fb55c36a336ebe01a876d6465766963654b6579496e666fa1696465766963654b6579a40102200121582096313d6c63e24e3372742bfdb1a33ba2c897dcd68ab8c753e4fbd48dca6b7f9a2258201fb3269edd418857de1b39a4e4a44b92fa484caa722c228288f01d0c03a2c3d667646f6354797065756f72672e69736f2e31383031332e352e312e6d444c6c76616c6964697479496e666fa3667369676e6564c074323032302d31302d30315431333a33303a30325a6976616c696446726f6dc074323032302d31302d30315431333a33303a30325a6a76616c6964556e74696cc074323032312d31302d30315431333a33303a30325a5840cff12c17d4739aba806035a9cb2b34ae8a830cef4f329289f9a3ebd302dd6b99c584068257569397b92ba9aa5128554eb05d1273dafea313da4aff6b01a5fb3f6c6465766963655369676e6564a26a6e616d65537061636573d81841a06a64657669636541757468a1696465766963654d61638443a10105a0f65820200d73ded787c64652dc8ee743ea83a5260d5a3283fddc919b7b9cfb486addb26673746174757300"
@@ -194,11 +225,13 @@ echo $ISSUED_MDOC | xxd -r -ps | python3 -m cbor2.tool --pretty
194225
### using cbor-diag
195226

196227
Install cbor-diag
228+
197229
````
198230
pip install cbor-diag
199231
````
200232

201233
Print a cbor diagnostic representation
234+
202235
````
203236
from cbor_diag import *
204237
@@ -222,4 +255,5 @@ Other examples at [cbor official documentation](https://github.com/agronholm/cbo
222255

223256
## Authors and contributors
224257

225-
- Giuseppe De Marco
258+
- Giuseppe De Marco
259+
- Pasquale De Rose

examples/it_data_model.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,19 @@
5353
}
5454

5555
mdoci = MdocCborIssuer(
56-
private_key=PKEY
56+
private_key=PKEY,
57+
alg="ES256",
5758
)
5859

5960
mdoc = mdoci.new(
6061
doctype="org.iso.18013.5.1.mDL",
6162
data=PID_DATA,
62-
devicekeyinfo=PKEY # TODO
63+
validity={
64+
"issuance_date": "2024-12-31",
65+
"expiry_date": "2050-12-31"
66+
},
6367
)
6468

6569
mdoc
6670
mdoci.dump()
67-
mdoci.dumps()
71+
mdoci.dumps()

pymdoccbor/mdoc/exceptions.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ class NoSignedDocumentProvided(Exception):
88
pass
99

1010
class MissingIssuerAuth(Exception):
11-
pass
11+
pass

0 commit comments

Comments
 (0)