Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
vzuevsky committed Nov 11, 2022
1 parent 164d89e commit 360f613
Show file tree
Hide file tree
Showing 14 changed files with 201 additions and 6 deletions.
6 changes: 3 additions & 3 deletions CSCA/CNlist
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
dn: cn=CN\=United Nations CSCA\,OU\=Certification Authorities\,O\=United Nat
CMS extraction: 536150 bytes in - 532482 bytes out
CMS Verification failure
802BE9F64F7F0000:error:02000068:rsa routines:ossl_rsa_verify:bad signature:../crypto/rsa/rsa_sign.c:430:
802BE9F64F7F0000:error:1C880004:Provider routines:rsa_verify:RSA lib:../providers/implementations/signature/rsa_sig.c:774:
802BE9F64F7F0000:error:1700009E:CMS routines:CMS_SignerInfo_verify:verification failure:../crypto/cms/cms_sd.c:899:
80DB01C6DF7F0000:error:02000068:rsa routines:ossl_rsa_verify:bad signature:../crypto/rsa/rsa_sign.c:430:
80DB01C6DF7F0000:error:1C880004:Provider routines:rsa_verify:RSA lib:../providers/implementations/signature/rsa_sig.c:774:
80DB01C6DF7F0000:error:1700009E:CMS routines:CMS_SignerInfo_verify:verification failure:../crypto/cms/cms_sd.c:899:
355 certificates are on the list...

10077
Expand Down
137 changes: 134 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,138 @@ The meaning of the following line options can be deduced from respective man pag
# verifying the signature of the body with the public key :
openssl dgst -sha256 -verify cs.pkey -signature ds.sig ds.body
Verified OK
#### TODO
- Read NFC to extend the trust chain onto document's data e.g., DG1 (hashed MRZ)
#### Understanding MRTD Secure Object (SO<sub>D</sub>) Structure
At a time of the writing [D-Logic Reader](https://www.d-logic.com/nfc-rfid-reader-sdk/software/epassport-reading-machine-readable-travel-documents-mrtd/) can read SOD from LDS v1.7 (see [Appendix D here](https://www.icao.int/publications/Documents/9303_p10_cons_en.pdf)) but not from contemporary LDS v1.8 ([para 4.6.2](https://www.icao.int/publications/Documents/9303_p10_cons_en.pdf)). Hence, an example in `sod-example` folder concerns the older LDS v1.7.

Proud users of [D-Logic Readers](https://www.d-logic.com/nfc-rfid-reader-sdk/software/epassport-reading-machine-readable-travel-documents-mrtd/) or equivalent are sought - your help would be appreciated!
NFC read SOD object is present as binary file `sod`. We first strip SOD header with tag byte 0x77 to get more convenient PKCS7/CMS format:

# strip SOD header :
openssl asn1parse -inform der -in sod -strparse 4 -noout -out pkcs7
This format represents cryptographic message syntax (CMS), where the message..

openssl cms -inform der -noverify -verify -in pkcs7 -out message
openssl asn1parse -inform der -in message # datagroup hashes :
is a signed list of sha1 hashes for all data groups (DG) the document contains. The first command extracting the `message` binary file emits `CMS Verification successful`, confirming that the message is signed by the document signer (DS) certificate. We extract DS certificate and its parametrized public key like so:

# extract document signer (ds), assuming no country signer (cs) in SOD :
openssl pkcs7 -inform der -print_certs -in pkcs7 |grep -A99 CERT >ds.pem
openssl x509 -in ds.pem -pubkey -noout >ds.pkey
Note, that a digest being signed is calculated over a structure called `SignedAttrs` from [CMS RFC](https://www.rfc-editor.org/rfc/rfc5652#section-5.4). Then, a signature of that structure is appended to the very end of `pkcs7` file, provided that `unsignedAttrs` optional field is missing as per Table 37 of [ICAO framework](https://www.icao.int/publications/Documents/9303_p10_cons_en.pdf). Let's examine layout in question:

openssl cms -cmsout -print -inform der -in pkcs7 |tail -28
-- out :

digestAlgorithm:
algorithm: sha1 (1.3.14.3.2.26)
parameter: <ABSENT>
signedAttrs:
object: contentType (1.2.840.113549.1.9.3)
set:
OBJECT:undefined (2.23.136.1.1.1)

object: signingTime (1.2.840.113549.1.9.5)
set:
UTCTIME:May 21 03:08:11 2015 GMT

object: messageDigest (1.2.840.113549.1.9.4)
set:
OCTET STRING:
0000 - fa f7 c7 ec 04 f8 f8 44-7b 5b 82 a5 ab .......D{[...
000d - de 6c c7 92 91 1b a9 .l.....
signatureAlgorithm:
algorithm: ecdsa-with-SHA1 (1.2.840.10045.4.1)
parameter: <ABSENT>
signature:
0000 - 30 44 02 20 4d b0 0b 91-68 57 93 51 0f 96 f6 0D. M...hW.Q...
000f - a5 62 07 b7 00 c1 bc 30-27 d6 88 05 76 18 1c .b.....0'...v..
001e - e7 5d 6f 28 14 92 02 20-10 e4 1f 3d 02 e8 ed .]o(... ...=...
002d - 41 60 be 5a 57 6f 9f da-de bd 2e 93 5f 2d fe A`.ZWo......_-.
003c - 8a e6 9b af a2 02 10 58-7b 14 .......X{.
unsignedAttrs:
<ABSENT>
Signed bytes here: OID `2.23.136.1.1.1`, which is undefined in CMS but defined as [LdsSecurityObject](https://oidref.com/2.23.136.1.1.1) from ICAO; time stamp when signing took place - here it predates passport issuance; message digest, algorithm of which is given right at the beginning of the snippet (sha1). And since we already have the "message" extracted, let's verify:

sha1sum message
faf7c7ec04f8f8447b5b82a5abde6cc792911ba9 message

Magic. Note, that `signatureAlgorithm` employs sha1 as well. Generally, hashing `message` and hashing `signedAttrs` could use different algorithms. Now, let's extract `signedAttrs` and `signature`. We do so by means of ASN1 parser. Although it is terser than the CMS parsing above, it provides byte offsets we need for extraction:

openssl asn1parse -i -inform der -in pkcs7 |tail -18
1137:d=5 hl=2 l= 7 cons: SEQUENCE
1139:d=6 hl=2 l= 5 prim: OBJECT :sha1
1146:d=5 hl=2 l= 90 cons: cont [ 0 ]
1148:d=6 hl=2 l= 21 cons: SEQUENCE
1150:d=7 hl=2 l= 9 prim: OBJECT :contentType
1161:d=7 hl=2 l= 8 cons: SET
1163:d=8 hl=2 l= 6 prim: OBJECT :2.23.136.1.1.1
1171:d=6 hl=2 l= 28 cons: SEQUENCE
1173:d=7 hl=2 l= 9 prim: OBJECT :signingTime
1184:d=7 hl=2 l= 15 cons: SET
1186:d=8 hl=2 l= 13 prim: UTCTIME :150521030811Z
1201:d=6 hl=2 l= 35 cons: SEQUENCE
1203:d=7 hl=2 l= 9 prim: OBJECT :messageDigest
1214:d=7 hl=2 l= 22 cons: SET
1216:d=8 hl=2 l= 20 prim: OCTET STRING [HEX DUMP]:FAF7C7EC04F8F8447B5B82A5ABDE6CC792911BA9
1238:d=5 hl=2 l= 9 cons: SEQUENCE
1240:d=6 hl=2 l= 7 prim: OBJECT :ecdsa-with-SHA1
1249:d=5 hl=2 l= 70 prim: OCTET STRING [HEX DUMP]:304402204DB00B91685793510F96F6A56207B700C1BC3027D6880576181CE75D6F281492022010E41F3D02E8ED4160BE5A576F9FDADEBD2E935F2DFE8AE69BAFA20210587B14

Note a block at offset 1146 and 90 bytes in length (`l= 90`). Parameter `d=` for depth shows level of indentation in pkcs7. Knowing these couple of things, we can be sure that the block is actually `signedAttrs`. Similarly, the last one is the sought signature. Extracting both:

openssl asn1parse -inform der -in pkcs7 -strparse 1146 -out attrs
openssl asn1parse -inform der -in pkcs7 -strparse$(openssl asn1parse -inform der -in pkcs7 |awk -F: '{x=$1}END{print x}') -out sod.sig

Changing the first byte of `attrs` extracted from 0xA0 to 0x31. Some [details on the trick](https://stackoverflow.com/a/24581628/2550808).

# what we had :
xxd attrs |head -1
00000000: a05a 3015 0609 2a86 4886 f70d 0109 0331 .Z0...*.H......1

xxd attrs >temp
vi temp # first byte a0 -> 31
cat temp |xxd -r >attrsExplicit

# what we use :
xxd attrsExplicit |head -1
00000000: 315a 3015 0609 2a86 4886 f70d 0109 0331 1Z0...*.H......1

We can now verify the signature like so..

openssl dgst -sha1 -verify ds.pkey -signature sod.sig attrsExplicit
Verified OK
However, we'd better compress it all down to a hash being signed, that is

sha1sum attrsExplicit |awk '{print$1}' |xxd -r -ps >sod.hash
Time to recap. Passport's DG1 (ordinary passport data) and DG2 (face-photo file) are both hashed, and the hashes are injected in a `message` (hash algorithm is there too). The `message` is hashed, and the hash is injected into a `signedAttrs` (the algo is in pkcs7). The `signedAttrs` is hashed (the algo is in pkcs7) and we have it in `sod.hash` file (20 bytes' token in case of sha1).

The token is uniquely derived from some personal data. As such, it can serve as a personal identifier, albeit with multiple levels of indirection. The token is non-fudgeable (aka NFT) in a sense that it is signed by a State (as opposed to recording on a decentralized blockchain), so it cannot be altered if accompanied by the signature (70 bytes in `sod.sig` file) and the final ingredient - reference to the public key - another 20 bytes of `Subject Key Identifier` from the signing certificate:

openssl x509 -in ds.pem -noout -text |grep -A1 X509

X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature
X509v3 Subject Key Identifier:
07:10:06:8A:48:58:FA:04:58:08:8C:47:67:99:BA:1D:5F:EB:2C:3F
X509v3 Authority Key Identifier:
56:59:99:89:A1:CC:1C:13:D3:9F:BC:B0:C8:77:00:38:50:33:A5:33

As all certificates are supposed to be publicly available at ICAO PKI, anyone could download this certificate, extract public key, and verify the "NFT" like so:

openssl pkeyutl -verify -sigfile sod.sig -pubin -inkey ds.pkey -in sod.hash
Signature Verified Successfully

The problem is that this particular document signer isn't on ICAO PKI:

python3 icao-dsprobe.py icaopkd-001-dsccrl-005973.ldif 07:10:06:8A:48:58:FA:04:58:08:8C:47:67:99:BA:1D:5F:EB:2C:3F

17763 inspected, 0 certificate(s) dumped in DSCA/0710068A4858FA0458088C476799BA1D5FEB2C3F folder

Authority certificate, on the other hand, is on ICAO Master list. So, our "NFT" would have to comprise 20 bytes token + 70 bytes signature + 844 byes document signer (whole certificate):

openssl x509 -in ds.pem -outform der -out ds.der

Not very elegant.
#### Future?
It is interesting to notice that conventional identification relies on subjective (latterly AI-based) matching between a state issued document and a personal look (generally - biometric scans). That would be comparable if not inferior to a cryptographic ["limited knowledge" proof](https://en.wikipedia.org/wiki/Zero-knowledge_proof) of possession of a signed message (e.g., State-signed identifier). The latter would not require biometric scans, however, which makes it suitable for paperless remote identification. An abstract problem statement - [here](https://crypto.stackexchange.com/q/102705/104362).
1 change: 1 addition & 0 deletions sod-example/attrs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
�Z0 *�H�� 1g�0 *�H�� 1150521030811Z0# *�H�� 1������D{[����lǒ��
Expand Down
1 change: 1 addition & 0 deletions sod-example/attrsExplicit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1Z0 *�H�� 1g�0 *�H�� 1150521030811Z0# *�H�� 1������D{[����lǒ��
Expand Down
25 changes: 25 additions & 0 deletions sod-example/cs.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
-----BEGIN CERTIFICATE-----
MIIEKDCCA8+gAwIBAgIJANwdrlnS2BZbMAkGByqGSM49BAEwgZQxCzAJBgNVBAYT
AlJVMRswGQYDVQQIExJSdXNzaWFuIEZlZGVyYXRpb24xDzANBgNVBAcTBk1vc2Nv
dzESMBAGA1UEChMJU1RDIEF0bGFzMQwwCgYDVQQLEwNTWkQxFDASBgNVBAMTC0NT
Q0EtUnVzc2lhMR8wHQYJKoZIhvcNAQkBFhBjYW1haWxAc3RjbmV0LnJ1MB4XDTEw
MDIwNTA4MzE0NVoXDTMyMDEzMTA4MzE0NVowgZQxCzAJBgNVBAYTAlJVMRswGQYD
VQQIExJSdXNzaWFuIEZlZGVyYXRpb24xDzANBgNVBAcTBk1vc2NvdzESMBAGA1UE
ChMJU1RDIEF0bGFzMQwwCgYDVQQLEwNTWkQxFDASBgNVBAMTC0NTQ0EtUnVzc2lh
MR8wHQYJKoZIhvcNAQkBFhBjYW1haWxAc3RjbmV0LnJ1MIIBSzCCAQMGByqGSM49
AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP////8AAAABAAAAAAAAAAAAAAAA////////
////////MFsEIP////8AAAABAAAAAAAAAAAAAAAA///////////////8BCBaxjXY
qjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMVBMSdNgiG5wSTamZ44ROdJreB
n36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5RdiYwpZP40Li/hp/m47n
60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA//////////+85vqtpxee
hPO5ysL8YyVRAgEBA0IABFgXbfjKUQhG14XIHLlpseIqYugSweVrgQWnbbfvlGX6
pcBrLM/JoDcAOi4WlkILJGGU49ybVJ+83B/vr4TSAnejggETMIIBDzAdBgNVHQ4E
FgQUVlmZiaHMHBPTn7ywyHcAOFAzpTMwgckGA1UdIwSBwTCBvoAUVlmZiaHMHBPT
n7ywyHcAOFAzpTOhgZqkgZcwgZQxCzAJBgNVBAYTAlJVMRswGQYDVQQIExJSdXNz
aWFuIEZlZGVyYXRpb24xDzANBgNVBAcTBk1vc2NvdzESMBAGA1UEChMJU1RDIEF0
bGFzMQwwCgYDVQQLEwNTWkQxFDASBgNVBAMTC0NTQ0EtUnVzc2lhMR8wHQYJKoZI
hvcNAQkBFhBjYW1haWxAc3RjbmV0LnJ1ggkA3B2uWdLYFlswEgYDVR0TAQH/BAgw
BgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwCQYHKoZIzj0EAQNIADBFAiAEo0jligNV
t8laftPk8x/toeyQyaGBfJHBxXOFNl/UEAIhAPsznr12itghRhgyEE8AROl+WsIT
eOG4EX0HFk0NZXfT
-----END CERTIFICATE-----
Binary file added sod-example/ds.der
Binary file not shown.
21 changes: 21 additions & 0 deletions sod-example/ds.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDSDCCAvCgAwIBAgIBTTAJBgcqhkjOPQQBMIGUMQswCQYDVQQGEwJSVTEbMBkG
A1UECBMSUnVzc2lhbiBGZWRlcmF0aW9uMQ8wDQYDVQQHEwZNb3Njb3cxEjAQBgNV
BAoTCVNUQyBBdGxhczEMMAoGA1UECxMDU1pEMRQwEgYDVQQDEwtDU0NBLVJ1c3Np
YTEfMB0GCSqGSIb3DQEJARYQY2FtYWlsQHN0Y25ldC5ydTAeFw0xNTAyMDMxMTA2
MTJaFw0yNzAxMzExMTA2MTJaMIGAMQswCQYDVQQGEwJSVTEPMA0GA1UEBwwGTW9z
Y293MRIwEAYDVQQKDAlTVEMgQXRsYXMxDTALBgNVBAsMBFVaSVMxHDAaBgNVBAMM
E0RvY3VtZW50IFNpZ25lciAzLjIxHzAdBgkqhkiG9w0BCQEWEGNhbWFpbEBzdGNu
ZXQucnUwggFLMIIBAwYHKoZIzj0CATCB9wIBATAsBgcqhkjOPQEBAiEA/////wAA
AAEAAAAAAAAAAAAAAAD///////////////8wWwQg/////wAAAAEAAAAAAAAAAAAA
AAD///////////////wEIFrGNdiqOpPns+u9VXaYhrxlHQawzFOw9jvOPD4n0mBL
AxUExJ02CIbnBJNqZnjhE50mt4GffpAEQQRrF9Hy4SxCR/i85uVjpEDydwN9gS3r
M6D0oTlF2JjClk/jQuL+Gn+bjufrSnwPnhYrzjNXazFezsu2QGg3v1H1AiEA////
/wAAAAD//////////7zm+q2nF56E87nKwvxjJVECAQEDQgAERB1rAeLm0VFpXKjU
5kDqddxpHnFLt6tbh3xJrIT7nE9N+ygZy3gQkp1uPSSvE3t55i5xfx8t3nP/aXf9
bpnky6NSMFAwDgYDVR0PAQH/BAQDAgeAMB0GA1UdDgQWBBQHEAaKSFj6BFgIjEdn
mbodX+ssPzAfBgNVHSMEGDAWgBRWWZmJocwcE9OfvLDIdwA4UDOlMzAJBgcqhkjO
PQQBA0cAMEQCIHUaHEmkfqCrtaoVVnfLl81M4M6Dc/+ArIwbZxrn48EWAiAUp7NM
lGLzPN4E1YFZ5MEFFX6bkCr/fVl/uUvs3FU9yA==
-----END CERTIFICATE-----

9 changes: 9 additions & 0 deletions sod-example/ds.pkey
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBSzCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP////8AAAABAAAA
AAAAAAAAAAAA////////////////MFsEIP////8AAAABAAAAAAAAAAAAAAAA////
///////////8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMVAMSd
NgiG5wSTamZ44ROdJreBn36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5
RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA
//////////+85vqtpxeehPO5ysL8YyVRAgEBA0IABEQdawHi5tFRaVyo1OZA6nXc
aR5xS7erW4d8SayE+5xPTfsoGct4EJKdbj0krxN7eeYucX8fLd5z/2l3/W6Z5Ms=
-----END PUBLIC KEY-----
Binary file added sod-example/message
Binary file not shown.
Binary file added sod-example/pkcs7
Binary file not shown.
Binary file added sod-example/sod
Binary file not shown.
1 change: 1 addition & 0 deletions sod-example/sod.hash
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
���63�8[�=_�����-k�c
Binary file added sod-example/sod.sig
Binary file not shown.
6 changes: 6 additions & 0 deletions sod-example/temp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
00000000: 315a 3015 0609 2a86 4886 f70d 0109 0331 .Z0...*.H......1
00000010: 0806 0667 8108 0101 0130 1c06 092a 8648 ...g.....0...*.H
00000020: 86f7 0d01 0905 310f 170d 3135 3035 3231 ......1...150521
00000030: 3033 3038 3131 5a30 2306 092a 8648 86f7 030811Z0#..*.H..
00000040: 0d01 0904 3116 0414 faf7 c7ec 04f8 f844 ....1..........D
00000050: 7b5b 82a5 abde 6cc7 9291 1ba9 {[....l.....

0 comments on commit 360f613

Please sign in to comment.