stapelberg / coronaqr

Go decoder and verifier for EU Digital COVID Certificate (EUDCC) QR code data
Apache License 2.0
169 stars 15 forks source link

Expiration date for recovery #11

Closed WindowsNT closed 3 years ago

WindowsNT commented 3 years ago

In my certificate prints this:

Cryptographic signature successfully verified from: CN=grnet.gr,C=GR

COVID certificate: Issued: 2021-06-01 05:13:41 -0400 EDT Expiration: 2023-05-24 11:35:24 -0400 EDT Contents: (coronaqr.CovidCert) { Version: (string) (len=5) "1.0.0", PersonalName: (coronaqr.Name) { FamilyName: (string) (len=18) "...", FamilyNameStd: (string) (len=10) "...", GivenName: (string) (len=12) "...", GivenNameStd: (string) (len=7) "..." }, DateOfBirth: (string) (len=10) "...", VaccineRecords: ([]coronaqr.VaccineRecord) , TestRecords: ([]coronaqr.TestRecord) , RecoveryRecords: ([]coronaqr.RecoveryRecord) (len=1 cap=1) { (coronaqr.RecoveryRecord) { Target: (string) (len=9) "840539006", Country: (string) (len=2) "GR", Issuer: (string) (len=43) "Ministries of Health and Digital Governance", CertificateID: (string) (len=43) "URN:UVCI:01:GR:HFR6ZMD6GJDON7UQZI4FTKNDHY#M" } } }

However there must be an expiration of the RecoveryRecord. The "Expiration" is the certificate's expiration, not the recovery record expiration.

Also, what's the "target" string?

I 'd be grateful if you can take a look.

stapelberg commented 3 years ago

However there must be an expiration of the RecoveryRecord. The "Expiration" is the certificate's expiration, not the recovery record expiration.

I don’t think there is an expiration time for recovery records in the certificate itself.

But: Countries impose additional rules via so-called Business Rules. Those are not implemented yet (I have a pending commit for the logic, but the rules are unfortunately not yet public), see https://github.com/stapelberg/coronaqr/issues/10 for details.

Also, what's the "target" string?

It’s a way of saying covid-19. See https://github.com/stapelberg/coronaqr/issues/8

WindowsNT commented 3 years ago

The actual PDF has an expiration time inside. Do you mean that it's hard coded in the PDF but not included in the QR/certificate code? (certificate link removed to prevent abuse)

Certificate valid until (not more than 180 days after the date of first positive test result) 03/11/2021

stapelberg commented 3 years ago

Do you mean that it's hard coded in the PDF but not included in the QR/certificate code?

Yep. The 180 day validity is most likely expressed only as a Business Rule.

Here’s the example for France: https://github.com/eu-digital-green-certificates/dgc-business-rules-testdata/blob/main/FR/RR-FR-0001/rule.json

Unfortunately, I don’t see any Business Rules from Greece in this testdata repository.

PS: I removed your certificate link so that nobody can abuse your personal data.

WindowsNT commented 3 years ago

Okay there's the 180 day business rule (which I can hardcode), but I guess that the first test date is also hardcoded (from which the expiration date +180 is calculated), so we can't use the certificate for validation :(

Thanks for your support anyway.

stapelberg commented 3 years ago

but I guess that the first test date is also hardcoded

No that’s actually part of the certificate, but not currently exposed (I didn’t have any recovery certificates to test with): https://github.com/stapelberg/coronaqr/blob/39dcf25a0c4b85bd0a4734798da6d48b176873f4/coronaqr.go#L91

I’ll see if I can make that work.

stapelberg commented 3 years ago

Okay, update to the latest version and give it a shot again!

Sorry about the confusion — I had incorrectly thought we had already added all fields, but we only added all fields for test certificates, not for recovery certificates. There is indeed the date of the first test, and even a valid from/valid until field. That should contain all you need.

WindowsNT commented 3 years ago

Ah. Excellent.

Cryptographic signature successfully verified from:
  CN=grnet.gr,C=GR

COVID certificate:
Issued:     2021-06-01 05:13:41 -0400 EDT
Expiration: 2023-05-24 11:35:24 -0400 EDT
Contents:   (coronaqr.CovidCert) {
 Version: (string) (len=5) "1.0.0",
 PersonalName: (coronaqr.Name) {
  FamilyName: (string) (len=18) "",
  FamilyNameStd: (string) (len=10) "",
  GivenName: (string) (len=12) "",
  GivenNameStd: (string) (len=7) ""
 },
 DateOfBirth: (string) (len=10) "",
 VaccineRecords: ([]coronaqr.VaccineRecord) <nil>,
 TestRecords: ([]coronaqr.TestRecord) <nil>,
 RecoveryRecords: ([]coronaqr.RecoveryRecord) (len=1 cap=1) {
  (coronaqr.RecoveryRecord) {
   Target: (string) (len=9) "840539006",
   Country: (string) (len=2) "GR",
   Issuer: (string) (len=43) "Ministries of Health and Digital Governance",
   FirstPositiveTest: (string) (len=10) "2021-05-07",
   ValidFrom: (string) (len=10) "2021-06-01",
   ValidUntil: (string) (len=10) "2021-11-03",
   CertificateID: (string) (len=43) "URN:UVCI:01:GR:HFR6ZMD6GJDON7UQZI4FTKNDHY#M"
  }
 }

Thanks a lot!