Stream: smart/health-cards
Topic: generating QR code (compression)
Brian Agnes (Apr 15 2021 at 20:03):
I am following the instructions in "Creating a QR code (or a set of QR codes) from a Health Card JWS" to encode characters into bytes to generate a string that looks like "shc:/5676295953265460346029254077280433602870286567675422280928623725376028702864716745222..."
My problem is the new QR code is larger than the original. How should I pass the new string to the QR code generator so that it treats it as numeric instead of alpha-numeric? I am happy to use a different C# QR generator if needed.
QR generator = https://github.com/codebude/QRCoder/
Implementation ref = https://github.com/smart-on-fhir/health-cards/blob/main/docs/index.md#creating-a-qr-code-or-a-set-of-qr-codes-from-a-health-card-jws
Michael O'Keefe (Apr 15 2021 at 20:16):
reading through the source in that QR Code Generation library, it looks like it should set the encoding to numeric
if you pass it a purely numeric (aka only characters 0-9
) and you don't force UTF-8: https://github.com/codebude/QRCoder/blob/37ec9a44724c5b3a5ad53108d374dd5b665d0e53/QRCoder/QRCodeGenerator.cs#L881
Michael O'Keefe (Apr 15 2021 at 20:17):
So my guess is that the shc:/
at the beginning is forcing it into alphanumeric
Michael O'Keefe (Apr 15 2021 at 20:20):
Ah, it looks like the way it should work is that you do more than 1 segment to the QR code. One segment is just shc:/
plus any chunk metadata (aka 1/2/
) if this is chunk 1 of 2
Michael O'Keefe (Apr 15 2021 at 20:20):
That segment is byte-encoded. Then the second segment, with the JWS data, is numeric-encoded
Michael O'Keefe (Apr 15 2021 at 20:24):
You'd have to figure out how to encode a QR code with multiple data segments in that C# library. A cursory glance doesn't show any way to do so with that particular library, but I may have missed something
Reece Adamson (Apr 15 2021 at 20:31):
This is an example of a Javascript library that supports segments with different modes: https://www.npmjs.com/package/qrcode#manual-mode
Brian Agnes (Apr 15 2021 at 20:42):
@_Michael O'Keefe|191647 said:
You'd have to figure out how to encode a QR code with multiple data segments in that C# library. A cursory glance doesn't show any way to do so with that particular library, but I may have missed something
is there a library in c# that you prefer?
sorry just saw reply from Reece...
Notification Bot (Apr 15 2021 at 20:43):
This topic was moved here from #implementers > generating QR code (compression) by Josh Mandel
Michael O'Keefe (Apr 15 2021 at 20:59):
Unfortunately I don't have much experience with C#, so I'm not sure really
Michael O'Keefe (Apr 15 2021 at 21:02):
There might be a way to make that QR code generator use multiple segments, if you can pre-generate the final bitstring and pass it to the low-level generateQRCode method: https://github.com/codebude/QRCoder/blob/49d5b35e186437c086de152f50a0c7348f7c84cc/QRCoder/QRCodeGenerator.cs#L184
Josh Mandel (Apr 15 2021 at 21:10):
https://github.com/manuelbl/QrCodeGenerator looks like a library that has multi-segment support
Josh Mandel (Apr 15 2021 at 21:12):
the MakeSegmentsOptimally
fn may work out of the box, or else you can manually pass in an array of segments, which is probably more reliable
Brian Agnes (Apr 15 2021 at 23:13):
Thanks for the help everyone! using https://github.com/manuelbl/QrCodeGenerator worked great. The test app seems happy with the results:
~/projects/smarthealthcard/health-cards-validation-SDK-0.4.4-1 :check: node . --path devmale.png --type qr
SMART Health Card Validation SDK v0.4.4-1
(node:9882) ExperimentalWarning: The dns.promises API is experimental
(node:9882) ExperimentalWarning: The fs.promises API is experimental
(node:9882) ExperimentalWarning: Readable[Symbol.asyncIterator] is an experimental feature. This feature could change at any time
QR image
|
QR numeric
|
JWS-compact
|
JWS.payload
|
FhirBundle
NOTE: the SDK v0.4.4-1 is not validating the latest version of the spec: v0.4.5
Validation completed
Brian Agnes (Apr 15 2021 at 23:16):
my pixel 4xl phone can't scan QR anymore... is this normal? (probably because of segments & numeric)
Josh Mandel (Apr 15 2021 at 23:35):
Brian Agnes: my pixel 4xl phone can't scan QR anymore... is this normal? (probably because of segments & numeric)
That doesn't sound normal!
Josh Mandel (Apr 15 2021 at 23:38):
I can scan this from my android phone's built-in camera app
Josh Mandel (Apr 15 2021 at 23:39):
(though I can't validate the Health Card because there's no https://mychartpoc.uchealth.org/.well-known/jwks.json)
Josh Mandel (Apr 15 2021 at 23:40):
Also note that you have extra data beyond the "DM" profile in there (the recommendation is to remove Location and populate Immunization.performer.actor.display)
Brian Agnes (Apr 16 2021 at 17:26):
yes, that is an internal server for us. It will eventually move to https://mychart.uchealth.org/.well-known/jwks.json
Brian Agnes (Apr 16 2021 at 18:45):
Does this look like it follows all of the DM (whitespace added for readability (and removed by chat))
{"iss":"https://mychartpoc.uchealth.org","nbf":1618597458,"vc":{
"@context":["https://www.w3.org/2018/credentials/v1"],
"type":["VerifiableCredential","https://smarthealth.cards#covid19","https://smarthealth.cards#health-card","https://smarthealth.cards#immunization"],
"credentialSubject":{"fhirVersion":"4.0.1","fhirBundle":{
"resourceType":"Bundle",
"type":"collection",
"entry":[
{"fullUrl":"resource:0","resource":{
"resourceType":"Patient",
"name":[{"family":"Dev","given":["Male"]}],
"birthDate":"1945-02-01"
}},
{"fullUrl":"resource:1","resource":{
"resourceType":"Immunization",
"status":"completed",
"vaccineCode":{"coding":[{"system":"http://hl7.org/fhir/sid/cvx","code":"207"}]},
"patient":{"reference":"resource:0"},
"occurrenceDateTime":"2021-01-13",
"performer":{"actor":{"display":"University of Colorado Hospital - Aurora"}},
"lotNumber":"13355"
}},
{"fullUrl":"resource:2","resource":{
"resourceType":"Immunization",
"status":"completed",
"vaccineCode":{"coding":[{"system":"http://hl7.org/fhir/sid/cvx","code":"207"}]},
"patient":{"reference":"resource:0"},
"occurrenceDateTime":"2021-03-17",
"performer":{"actor":{"display":"University of Colorado Hospital - Aurora"}},
"lotNumber":"EH5678"
}}
]
}}
}}
Josh Mandel (Apr 16 2021 at 18:48):
It gets full marks from the Josh-visual-inspection test suite!
Josh Mandel (Apr 16 2021 at 18:49):
(I should add some sort of caveat about being sleep deprived ;-))
Christian Paquin (Apr 19 2021 at 14:49):
Brian Agnes said:
Does this look like it follows all of the DM (whitespace added for readability (and removed by chat))
Passing this through the validation SDK, I get this warning:
JWS.payload.vc shouldn't have a @context property
(new change in v0.4.5), and this error:
Schema: {"instancePath":"/performer","schemaPath":"#/properties/performer/type","keyword":"type","params":{"type":"array"},"message":"must be array"}
so I think the "performer"
value should be wrapped in an array: "performer":[{"actor":{"display":"University of Colorado Hospital - Aurora"}}],
Josh Mandel (Apr 19 2021 at 15:46):
Yep! (This is why visual inspection isn't our primary methodology ;-))
Abbie Watson (Apr 20 2021 at 00:53):
Reece Adamson said:
This is an example of a Javascript library that supports segments with different modes: https://www.npmjs.com/package/qrcode#manual-mode
Great find!!
Brian Agnes (Apr 21 2021 at 19:31):
thanks for all your help! I corrected the errors you found.
{"iss":"https://mychartpoc.uchealth.org","nbf":1619033340,"vc":{"type":["VerifiableCredential","https://smarthealth.cards#covid19","https://smarthealth.cards#health-card","https://smarthealth.cards#immunization"],"credentialSubject":{"fhirVersion":"4.0.1","fhirBundle":
{"resourceType":"Bundle","type":"collection","entry":[
{"fullUrl":"resource:0","resource":{"resourceType":"Patient","name":[{"family":"Dev","given":["Male"]}],"birthDate":"1945-02-01"}},
{"fullUrl":"resource:1","resource":{"resourceType":"Immunization","status":"completed","vaccineCode":{"coding":[{"system":"http://hl7.org/fhir/sid/cvx","code":"207"}]},"patient":{"reference":"resource:0"},"occurrenceDateTime":"2021-01-13","performer":[{"actor":{"display":"University of Colorado Hospital - Aurora"}}],"lotNumber":"13355"}},
{"fullUrl":"resource:2","resource":{"resourceType":"Immunization","status":"completed","vaccineCode":{"coding":[{"system":"http://hl7.org/fhir/sid/cvx","code":"207"}]},"patient":{"reference":"resource:0"},"occurrenceDateTime":"2021-03-17","performer":[{"actor":{"display":"University of Colorado Hospital - Aurora"}}],"lotNumber":"EH5678"}}]}}}}
Josh Mandel (Apr 21 2021 at 19:38):
Nice!
Alan Viars (Apr 23 2021 at 22:27):
Ive been working on improving my SHC implementation. Here is a link that contains my SHC. https://id.verifymyidentity.com/smart-health-cards/psi/197330163473583 What is the best way to verify it. I guess now that I have all the pieces in place it can be verified with the node.js tool?
Josh Mandel (Apr 23 2021 at 22:43):
That'd be a great step. You can also run the FHIR validator per https://smarthealth.cards/#what-testing-tools-are-available-to-validate-smart-health-cards-implementations
Alan Viars (Apr 23 2021 at 22:47):
I'm just getting tripped up on the SDK tool. Im not sure what im doing is right or not, but I'm getting errors. Seems to be finding this now: https://id.verifymyidentity.com/.well-known/jwks.json Here is what I'm getting.
Screen-Shot-2021-04-23-at-6.46.59-PM.png
Alan Viars (Apr 23 2021 at 22:50):
Im using @James Kizer code to generate the JWKS and to do the encoding/signing. I'm attempting to use the Node.js by @Christian Paquin to decode/validate. There is a high probability these both work just fine and I'm doing something wrong. Any help is greatly appreciated.
Christian Paquin (Apr 23 2021 at 22:58):
Alan Viars said:
Any help is greatly appreciated.
Can you share an updated QR image?
Josh Mandel (Apr 23 2021 at 23:06):
https://id.verifymyidentity.com/smart-health-cards/psi/197330163473583 has one
Christian Paquin (Apr 24 2021 at 21:37):
Alan Viars said:
Any help is greatly appreciated.
Ok, ran the SDK on the QR, I get the same output as you. The first set of warnings/errors related to the key identifiers (kid
) of the issuer keys; the spec mandates that they are the hash of their crypto values, rather than an application-specific value (like your "id.verifymyidentity.com"); see this section of the spec. You can ignore the warnings about the wrong algorithm and key type; these relate to the encryption key in the key set; it's ok to be present in the set (although not used by SMART health cards), but the SDK warns about them for completeness.
One warning is about the extra @context
in the JWS.vc; this has been removed in v0.4.5 of the spec.
The schema error in the fhir bundle relates to the occurrence date for resource:1
; it should be YYYY-MM-DD, so you either flipped the MM and DD in "2021-22-01", or it's a typo (probably the latter, because the 2nd dose's date is ok).
Christian Paquin (Apr 24 2021 at 21:42):
Christian Paquin said:
The first set of warnings/errors related to the key identifiers (
kid
) of the issuer keys; the spec mandates that they are the hash of their crypto values, rather than an application-specific value (like your "id.verifymyidentity.com"); see this section of the spec.
FYI @James Kizer, since Alan said he used your code to generate the JWKS; just wanted point to the kid
issue he faced.
Alan Viars (Apr 27 2021 at 20:39):
I modified those kid
values, so @James Kizer code may be just fine. Let me have another go at it @Christian Paquin
Christian Paquin (Apr 27 2021 at 20:48):
Alan Viars said:
I modified those
kid
values, so James Kizer code may be just fine. Let me have another go at it Christian Paquin
Having the kid
values being the hash digest of the key values provide a secure fingerprint which prevents an attacker from swapping keys or pretending to be the issuer.
Alan Viars (Apr 28 2021 at 12:39):
@Christian Paquin Is this looking better ? https://id.verifymyidentity.com/smart-health-cards/psi/197330163473583
Here is what I'm getting. It looks better but still saying JWS Validation failed. Screen-Shot-2021-04-28-at-8.43.37-AM.png
Christian Paquin (Apr 28 2021 at 13:33):
Alan Viars said:
Christian Paquin Is this looking better ? https://id.verifymyidentity.com/smart-health-cards/psi/197330163473583
I get the same. I'll trace into the validation tool to see if I can more info...
Alan Viars (Apr 28 2021 at 14:47):
Thanks @Christian Paquin Here is my JWKS https://id.verifymyidentity.com/.well-known/jwks.json i think its still the kid.
Christian Paquin (Apr 28 2021 at 14:55):
Alan Viars said:
Thanks Christian Paquin Here is my JWKS https://id.verifymyidentity.com/.well-known/jwks.json i think its still the kid.
I think the key is ok; validation code can find and use it. I just tried validating the JWS with a different module (jose
) than the one used in the SDK (node-jose
), to see if I'd get a clearer error message: no luck, same invalid signature. Crypto errors are hard to debug, any modification to headers or payload after signing will result in an invalid signature. Was that the case? I noticed the "typ":"JWT"
header in the JWS, not specified in the spec. Was that added post-signing by some encoding code? Can you share the code snippet used to generate the JWS, it'd be helpful to pinpoint the issue.
Christian Paquin (Apr 28 2021 at 14:59):
Alan Viars said:
Thanks Christian Paquin Here is my JWKS https://id.verifymyidentity.com/.well-known/jwks.json i think its still the kid.
And of course, as I mentioned before, the key warning is about the encryption key in the JWKS. This is ok for the spec, but I recommend removing it from the file as 1) it's not needed for SMART health card processing, and 2) it might confuse fragile verifier implementations.
Alan Viars (Apr 28 2021 at 15:00):
@Christian Paquin yes...just a minute.. Maybe i've fixed it. Need to merge PR and deploy updates. I
Alan Viars (Apr 28 2021 at 15:08):
@Christian Paquin I'm pretty sure i fixed it. I should remove those use=enc from both pub/private right? It was the code where i signed.
https://id.verifymyidentity.com/smart-health-cards/psi/197330163473583 Is this looking right to you now?
Christian Paquin (Apr 28 2021 at 15:55):
Alan Viars said:
Christian Paquin I'm pretty sure i fixed it. I should remove those use=enc from both pub/private right? It was the code where i signed.
https://id.verifymyidentity.com/smart-health-cards/psi/197330163473583 Is this looking right to you now?
Yes, new QR works! And yes, you can just delete the JWK with use=enc
from your private and public sets.
Alan Viars (Apr 28 2021 at 18:27):
Working now with no warnings or errors. @Christian Paquin Screen-Shot-2021-04-28-at-2.23.40-PM.png I'm still using @James Kizer 's utilities to generate the keyset, but stripping out anything that is not a use=sig
. Thanks so much for your help!
Alan Viars (Apr 28 2021 at 18:27):
@James Kizer maybe you saw my PR's that make your tools pip installable.
Last updated: Apr 12 2022 at 19:14 UTC