Code Monkey home page Code Monkey logo

smarthealthcard's People

Contributors

angusmillar avatar snowke avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

smarthealthcard's Issues

SmartHealthCardJwsDecoder.DecodePayloadAsync(..., Verify: false) does not disable required SmartHealthCardModel json property checks

Motivation

Quebec, Canada, uses QR-code-based vaccine passports. These generally follow the SMART Health Card Framework, but are non-compliant in that they lack the "nbf" property. I would still like to use the library, but despite requesting no verification, it still throws an error.

Code flow

Here in the SmartHealthCardJwsDecoder the payload is unzipped and parsed. However, the code does not pass on the Verify flag, and the Newtonsoft.Json.JsonSerializer within SmartHealthCard.Token.Serializers.Json.JsonSerializer remains strict and throws when the nbf property defined in SmartHealthCardModel is missing.

Work-around

I set JsonProperty nfb to .Default.

Avenues for a fix

Consider propagating Verify down to the serializer constructor/configuration of your JsonSerializer. For example, the implementation of a handler for Serializer_Error allows the implementer to set Newtonsoft.Json.Serialization.ErrorEventArgs.ErrorContext.Handled = true when Verify is false.

Alternatively, use .Default for all models and explicitly verify as needed, when the flag is set.

Nit: Verify is written as Verity in a few places in the code.

Thanks for the lib, great work!

Need Support For Processing EU Digital Vaccine Card

Hi @angusmillar

The library has been a big help for us to process SmartHealthCard and we wanted to see if we can use it for EU Vaccine Card.

While accessing the QR code for EU vaccine card we are getting HC1 details instead of SHC details

We are able to use your library to retrieve Immunization Info from SHC1 where QR payload is of form:
SHC:/56762909524320603460292437404460

We are trying to evaluate how we can use your library for HC1:
HC1:6BFW70F90T9WJWG.FKY4GO0RKPNHILCJ$VBFBB4W0

We found below links while researching for implementation of EU Digital Vaccine Card

  1. QR Code (Extract to get HC1 details)
  2. Extracted HC1 Data From QR Code (.txt File)
  3. https://dencode.com/en/string/base45 (To get vaccine info from HC1)
  4. https://www.nuget.org/packages/DigitalCovidCertificate (Existing library to extract vaccine information from HC1)

QRCode-1
HC1 Sample Data.txt
QRCode-2

500 Error on JWKS.Endpoint.

Not sure why this is giving an error.
Created keys with OpenSSL, exported as .pfx and imported.
Additionally had to import the pfx to "Trusted Root" (This is not specified in the SSL instructions provided).

Able to get the Certificate by Thumbprint.
But once it start reading certificate i get this.

Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Keyset does not exist at System.Security.Cryptography.CngKey.Open(String keyName, CngProvider provider, CngKeyOpenOptions openOptions) at System.Security.Cryptography.CngKey.Open(String keyName, CngProvider provider) at Internal.Cryptography.Pal.CertificatePal.GetPrivateKey[T](Func2 createCsp, Func2 createCng) at Internal.Cryptography.Pal.CertificatePal.GetECDsaPrivateKey() at Internal.Cryptography.Pal.CertificateExtensionsCommon.GetPrivateKey[T](X509Certificate2 certificate, Predicate1 matchesConstraints)
at System.Security.Cryptography.X509Certificates.ECDsaCertificateExtensions.GetECDsaPrivateKey(X509Certificate2 certificate)
at SmartHealthCard.Token.Algorithms.ES256Algorithm.GetPrivateKey(X509Certificate2 cert) in E:\SmartHealthCard-1.0.1\SmartHealthCard.Token\Algorithms\ES256Algorithm.cs:line 102
at SmartHealthCard.Token.Algorithms.ES256Algorithm..ctor(X509Certificate2 Certificate, IJsonSerializer JsonSerializer) in E:\SmartHealthCard-1.0.1\SmartHealthCard.Token\Algorithms\ES256Algorithm.cs:line 24
at SmartHealthCard.Token.SmartHealthCardJwks.GetJsonWebKeySet(IEnumerable1 CertificateList) in E:\SmartHealthCard-1.0.1\SmartHealthCard.Token\SmartHealthCardJWKS.cs:line 48 at SmartHealthCard.Token.SmartHealthCardJwks.Get(IEnumerable1 CertificateList, Boolean Minified) in E:\SmartHealthCard-1.0.1\SmartHealthCard.Token\SmartHealthCardJWKS.cs:line 78
at SmartHealthCard.JwksEndpoint.JwksSupport.JwksJsonProvider.GetJwksJson() in E:\SmartHealthCard-1.0.1\SmartHealthCard.JwksEndpoint\JwksSupport\JwksJsonProvider.cs:line 44
at SmartHealthCard.JwksEndpoint.Controllers.JwksController.Get() in E:\SmartHealthCard-1.0.1\SmartHealthCard.JwksEndpoint\Controllers\JwksController.cs:line 26
at lambda_method3(Closure , Object , Object[] )
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
'iisexpress.exe' (CoreCLR: clrhost): Loaded 'C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App\5.0.9\Microsoft.AspNetCore.Http.Extensions.dll'. Symbols loaded.`

ES256Algorithm Returns Result<bool>.Ok() Even If this.PublicKey.VerifyData() Returns False

Hi @angusmillar,

I noticed an issue in the ES256Algorithm. It looks to return Result.OK(...) regardless of the outcome of the verification of the payload/signature.

public Result<bool> Verify(byte[] bytesToSign, byte[] signature)
{
if (this.PublicKey is null)
return Result<bool>.Fail("Unable to verify signature as no public key has been provided.");
return Result<bool>.Ok(this.PublicKey.VerifyData(bytesToSign, signature, this.HashAlgorithmName));
}

I don't see anything in the JwsSignatureValidator that reacts to that boolean passed back either.

public Result Validate(IAlgorithm Algorithm, string Token)
{
if (string.IsNullOrEmpty(Token))
return Result.Fail("The provided Token was found to be null or empty.");
Result<JwsParts> JwtPartsParseResult = JwsParts.ParseToken(Token);
if (JwtPartsParseResult.Failure)
return Result.Fail(JwtPartsParseResult.ErrorMessage);
byte[] BytesToSign = Utf8EncodingSupport.GetBytes(JwtPartsParseResult.Value.Header, (byte)'.', JwtPartsParseResult.Value.Payload);
byte[] Signature = Base64UrlEncoder.Decode(JwtPartsParseResult.Value.Signature);
Result<bool> VerifyResult = Algorithm.Verify(BytesToSign, Signature);
if (VerifyResult.Failure)
{
return Result.Fail($"The JWS signing signature is invalid. {VerifyResult.ErrorMessage}");
}
return Result.Ok();
}

Unless I'm missing something else, it looks like it's always returning that the SmartHealthCard is valid even if the payload/signature doesn't validate correctly. Let me know if I'm mistaken.

Again, thanks for your hard work. Your code has been really easy to work with.

How to test Layer 1 - Keyset

Hello,
Well, I have created keys with OpenSSL, exported as .pfx and also able to generate JWKS json file. Here is that -

{
  "keys": [
    {
      "kty": "EC",
      "kid": "5R3coMqhfi9TyIKJf4HZlEDtsSCrcS59odiCQzJy_OM",
      "use": "sig",
      "alg": "ES256",
      "crv": "P-256",
      "x": "OQltcX7Gj9zsWIbLL9hr7kS1odNslldRhfXidiIcXgE",
      "y": "gx-dtHFnW0cU1gSEBUlgJ4f6uezelXGUVsPUw0L7e6M"
    }
  ]
}

But now I am not sure is this correct one. Could you please guide me how to validate this json in SHC Verifier Portal. Not sure how to use this verifier portal.

other thing is on this url - https://smarthealth.cards/examples/issuer/.well-known/jwks.json , I can see there is "x5c": element in the json. How to generate that element? What am I missing?

Result for Static Method Result<T>.Retry(...) Does Not Set Retryable to True

Hi @angusmillar,

Thanks for all your hard work on this. Your project is really helping my team ramp up quickly with our application.

I noticed that in your Result support class that Retryable does get set correctly for the constructor. See line 139:

protected internal Result(bool Success, bool Retryable, string ErrorMessage)
: base(Success: Success, Retryable: false, ErrorMessage: ErrorMessage)
{
this.ResultValue = default;
}

Retryable is set False, when it should really be set to the incoming parameter.

Thanks!

COVID 19 Vaccination Apple Wallet

Hi

I want to create an Apple wallet for COVID 19 Vaccination Pass (https://support.apple.com/en-us/HT212752). As of now, I have generated the QR Code with the help of this NuGet package but after I scanned that QR code on my iPhone it's open the Health App with the COVID-related Data. But, I want to add the Same data to both Health App and Apple Wallet like the above-mentioned URL.

FhirBundleJson
{"resourceType":"Bundle","type":"collection","entry":[{"fullUrl":"resource:0","resource":{"resourceType":"Patient","name":[{"family":"Anyperson","given":["John","B."]}],"birthDate":"1951-01-20"}},{"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-01","performer":[{"actor":{"display":"ABCGeneralHospital"}}],"lotNumber":"0000001"}},{"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-01-29","performer":[{"actor":{"display":"ABCGeneralHospital"}}],"lotNumber":"0000007"}}]}

So, Can you please help guide me to resolve these issues?

Incomplete merge in README.md

When you look at the bottom of README.md on the repository web site, you see marks of file merge conflicts. This is a minor issue, but hurts understatnding.

VerifiableCredentialTypes (vc.type) Was Not An Allowed Value

We are getting below mention issue in one scenario.

One of the VerifiableCredentialTypes (vc.type) was not an allowed value, type found was: VerifiableCredential.The supported types are:
https://smarthealth.cards#covid19,
https://smarthealth.cards#health-card,
https://smarthealth.cards#immunization,
https://smarthealth.cards#laboratory

Decoded Token has a non standard string highlighted below. Going by the specifications (https://spec.smarthealth.cards/vocabulary/) , this is not a valid type, so validation error thrown is correct. And we didn’t see such issue for any other Issuer.

type: [
"VerifiableCredential",
"https://smarthealth.cards#health-card",
"https://smarthealth.cards#immunization",
"https://smarthealth.cards#covid19"
]

Below is the reason we got from Channel which passes us the Smart Health Card JWS
some providers use:
the root top level type “VerifiableCredential” for their cards, which is a default for verifiable credentials but is not used by SMART Health Cards anymore"

Can we please ignore additional types, the library is working very well for us for all scenarios except this one?

How do I decode a shc:/... string?

I would like to try out decoding, but I don't understandand where should I put the string starting with "shc:/" I get after reading the QR code. Can you explain me please?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.