Coder Social home page Coder Social logo

devtrevi / dgcreader Goto Github PK

View Code? Open in Web Editor NEW
13.0 4.0 5.0 1.09 MB

Extensible .NET library for decoding and validating European Digital Green Certificates

License: Apache License 2.0

C# 100.00%
digital-green-certificate dcc dgc greenpass eu-digital-covid-19-certificate

dgcreader's Introduction

DgcReader

Extensible .NET library for decoding and validating European Digital Green Certificates

NuGet version (DgcReader) Nuget CodeQL

Summary

The library allows to decode and validate any EU Digital Green Certificate, providing some abstractions to easily implement specific providers for every country backend.

It supports any kind of project compatible with .NET Standard 2.0 and also legacy applications from .NET Framework 4.5.2 onwards.

Starting from version 1.3.0, the library has been included in the list of verified SDKs by Italian authorities (Ministero della salute).
The approval only refers to the main module DgcReader in combination with the Italian providers included in the project (DgcReader.RuleValidators.Italy, DgcReader.BlacklistProviders.Italy and DgcReader.TrustListProviders.Italy )
Please refer to this guide in order to correctly configure the required services.

For usage in different countries, please refer to the disclaimer and to the specific documentation of each project.

Usage

The main entry point of the library is the DgcReaderService class.

You can simply register it as a service:

public void ConfigureServices(IServiceCollection services)
{
   ...
   services.AddDgcReader()                     // Add the DgcReaderService as singleton
       .AddItalianTrustListProvider(o =>       // Register at least one trust list provider
       {
           // Optionally, configure the provider with custom options
           o.RefreshInterval = TimeSpan.FromHours(24);
           o.MinRefreshInterval = TimeSpan.FromHours(1);
           o.SaveCertificate = true;
           ...
       })
       .AddItalianDrlBlacklistProvider()      // The blacklist provider(s)
       .AddItalianRulesValidator()         // Finally, the rule validator(s)
       .AddGermanRulesValidator();         // Each rule validator will enable more acceptance countries to be supported
}

then getting it from the DI ServiceCollection:

...
// Getting an instance by dependency injection (from .NET standard 2.0 onward)
var dgcReader = ServiceCollection.GetService<DgcReaderService>();

If you don't use the dependency injection, you can instantiate it directly:

a) Use factory methods:

// Create an instance of the TrustListProvider (eg. ItalianTrustListProvider) and the other required services
var httpClient = new HttpClient();
var trustListProvider = new ItalianTrustListProvider(httpClient);
var drlBlacklistProvider = new ItalianDrlBlacklistProvider(httpClient);
var rulesValidator = new DgcItalianRulesValidator(httpClient);

// Create an instance of the DgcReaderService
var dgcReader = DgcReaderService.Create(
        trustListProviders: new[] { trustListProvider },
        blackListProviders: new IBlacklistProvider[] { rulesValidator, drlBlacklistProvider },
        rulesValidators: new[] { rulesValidator });

Once instantiated and configured with at least the ITrustListProvider service, you can simply call one of the methods shown in c)

b) Use the DgcReaderService for decoding only (no validation):

This lets you decode all the QR code data without verification, but still gives you a quick idea about how the library works. You can use the open source EU Digital Green Test Certificates or your personal certificate.

// Create the default instance of the `DgcReaderService` with an empty constructor
var dgcReader = new DgcReaderService();
var decoded = await dgcReader.Decode("HC1:01234...");

c) Run the validation

...
string qrCodeData = "Raw qr code data staring with HC1:";
string acceptanceCountry = "IT";    // Specify the 2-letter ISO code of the acceptance country

// Decode and validate the qr code data.
// The result will contain all the details of the validated object
var result = await dgcReader.GetValidationResult(qrCodeData, acceptanceCountry);

var status = result.Status;
// Note: all the validation details are available in the result
...

or

...
string qrCodeData = "Raw qr code data staring with HC1:";
string acceptanceCountry = "IT";    // Specify the 2-letter ISO code of the acceptance country
try
{
    // Decode and validate the signature.
    // If anything fails, an exception is thrown containing the error details
    var result = await dgcReader.Verify(qrCodeData, acceptanceCountry);
}
catch(Exception e)
{
    Console.WriteLine($"Error verifying DGC: {e.Message}");
}

Information about how to interprete the decoded values can be found in the Value Sets for Digital Green Certificates and the COVID-19 Data Reporting for Non-Lab-Based Testing.

What's new in 2.0

The new version of the service supports validation for multiple acceptance countries by registering multiple validator services.
It support also registration of multiple TrustList providers and BlackList providers.

In order to support these new features, there are some breaking changes that must be taken into account when upgrading from version 1.x:

  • The DgcReaderService constructor now accepts multiple instances for each kind of service.
    If you don't need to add multiple providers per kind and you don't use dependency injection, you can simply use the Create factory method.
  • Methods Verify and GetValidationResult now requires to specify the acceptance country
  • Files stored by the providers are now organized in subfolders relative to the BasePath option
  • The DgcValidationResult and the exceptions has been reorganized in a cleaner way, and the DgcResultStatus values are less bound to countries specific rules.
    If you need, you can still access specific informations or customized status for a specific implementation of a RuleValidator service by accessing the RulesValidation property of the result.
    By checking the actual implementation, you will get all the details returned by the RuleProvider used for the validation:
...
if (result.RulesValidation is ItalianRulesValidationResult italianResult)
{
    var italianStatus = italianResult.ItalianStatus;    // Access specific status, according to the official Italian SDK
}
else if (result.RulesValidation is GermanRulesValidationResult germanResult)
{
    // do something else...
}

In order to simplify this operation, each RuleValidator may expose some extension methods:

...

var result = await dgcReader.Verify(data, "AT"); // Get validation result for country "AT"

var germanRulesResult = result.GetGermanValidationResult();          // This should return the RulesValidation property as GermanRulesValidationResult, because the german validator supports Austria as an acceptance country
var italianRulesResult = result.GetItalianValidationResult();   // This will return null

Please refer to each RuleValidator readme for more details.

Understanding validation workflow with multiple providers

There are some differences about how each service type is managed by the validation workflow.
When registering multiple services, the following logic is applied:

  • Multiple 'IRulesValidator': having multiple rule validators increases the capability of the service, by expanding the list of supported acceptance countries. When validating a certificate, a validator supporting the required country will be searched.

    • If no validators are found, the validation fails with status NeedRulesVerification
    • If the validator could not return a final verdict (NeedRulesVerification or OpenResult), the service will try to validate the certificate with the next available validator for the acceptance country, if any.
    • When a validator can obtain a final result, either positive or negative, the result is returned.
    • Otherwise, if a final result is not available, the result obtained from the last validator is returned.
  • Multiple 'IBlackListProvider': the certificate identifier will be searched in every registered provider, unless a match is found. The first match will cause the Blacklist check to fail. Using multiple blacklist providers increases the propability of a match for a banned certificate.

  • Multiple ITrustListProvider: when checking for signature validity, the public key of the certificate is searched using each provider, until a match is found. The first match found will be used for validating the signature, without searching it in the remaining TrustList providers. Registering multiple trustlist providers can improve resiliency to national service backend temporary issues, or delays in propagation of the trusted certificates.

Supported frameworks differences

The library supports a wide range of .NET and .NET Framework versions, trying to keep the dependencies to third party libraries at minimum. For this reason, the implementation of the cryptographic functionalities for signature validations and certificates parsing are implemented with the apis of the System.Security.Cryptography namespace.
These APIs were not fully implemented in previous versions of the framework, so the version compiled for .NET Framework 4.5.2 uses the BouncyCastle library instead.

Packages

Description Version
Main package, containing the DgcReaderService NuGet version (DgcReader) Nuget
TrustList implementation for the Italian backend NuGet version (DgcReader.TrustListProviders.Italy) Nuget
TrustList implementation for the Swedish backend NuGet version (DgcReader.TrustListProviders.Sweden) Nuget
TrustList implementation for the German backend NuGet version (DgcReader.TrustListProviders.Germany) Nuget
Implementation of the Italian Blacklist provider NuGet version (DgcReader.BlacklistProviders.Italy) Nuget
Implementation of the Italian validation rules NuGet version (DgcReader.RuleValidators.Italy) Nuget
Implementation of the German rules validation engine NuGet version (DgcReader.RuleValidators.Germany) Nuget
Abstractions for building providers and rules validators NuGet version (DgcReader.Providers.Abstractions) Nuget
Abstractions for building TrustList providers NuGet version (DgcReader.TrustListProviders.Abstractions) Nuget

Extending the library

All you have to do in order to extend the library is to implement the interfaces exposed under the DgcReader.Interfaces.* namespace. You can use the implementations in the repository as an example, or you can code them from scratch.
If you are implementing a TrustList provider, the DgcReader.TrustListProviders.Abstractions package can results useful to simply implement a service optimized for multiple concurrent requests like a web application.
Any suggestion will be appreciated!

Requirements

In order to compile and run the solution, you will need the following tools:

  • Microsoft Visual Studio 2019 with the latest updates installed (16.11.7 at the moment of writing), or Microsoft Visual Studio 2022
  • Because some projects supports multiple version of the .NET framework, you should have installed the related targeting packs. At the moment, .NET Framework 4.5.2, .NET Framework 4.7 and .NET Standard 2.0 are supported

Some implementations in this repository may not have been approved by official authorities, or may be approved only by some countries.
Unless otherwise indicated, such implementations must be considered unofficial, and it is not assured in any way that they fully comply with dispositions of the reference countries.

The author assumes no responsibility for any unauthorized use of the library and no warranties about the correctness of the implementation, as better stated in the License.

Some code of the library is based on the DCCValidator App.
Many thanks to their authors for sharing their code!


Copyright © 2021 Davide Trevisan
Licensed under the Apache License, Version 2.0

dgcreader's People

Contributors

axunonb avatar devtrevi avatar mrizzi-96 avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar

dgcreader's Issues

Explicitly setting ValidationMode per call

Hello @DevTrevi.
It would be nice to have an overload of GetValidationResult, Verify (and of course, IRulesValidator.GetRulesValidationResult) methods in which the consumer may specify ValidationMode, overriding the same setting in DgcItalianRulesValidatorOptions.
In fact, I'm facing cases in which the Green Pass validation mode (basic "3G" / strict "2G") needs to be set dynamically, depending on conditions known to the consumer only.
Now I'm forced to create a DgcReaderService instance for each call, and that's not optimal, in my opinion.

Thanks

Problems with Mono

Ciao, intanto grazie per aver sviluppato questa libreria molto utile.

Ho fatto dei test e pur supportando .NET Standard 2.0, purtroppo però ha dei problemi con la gestione dei certificati quanto utilizzata in ambiate Mono (Es. Xamarin).

Credo dipenda dal fatto che System.Security.Cryptography.X509Certificates in Mono non implementa tutte le funzionalità o non si comporta ugualmente, mentre sembra funzionare benissimo con Bouncy Castle.

Probabilmente utilizzando solamente Bouncy Castle anche per il .Net Standard si potrebbe rendere compatibile anche per per Mono.

Can not get a valid TrustList

Buongiorno,

Stavo provando ad utilizzare l'sdk (v1.3.0) seguendo le istruzioni riportate nel Readme.
Il download della lista dei certificati dal server del governo (utilizzando la classe ItalianTrustListProvider) sembra fallire (durante la chiamata a GetValidationResult), impedendo quindi la verifica della firma.
Provando con Postman la chiamata GET riesce invece correttamente, escluderei dunque un problema di rete.

Le uniche informazioni stampate dal logger sono:

warn: DgcReader.DgcReaderService[0]
      HCERT signature verification failed: Can not get a valid TrustList. Make sure that the application can connect to the remote server and try again.
fail: DgcReader.DgcReaderService[0]
      Validation failed: Can not get a valid TrustList. Make sure that the application can connect to the remote server and try again.

Il codice è il seguente:

var httpClient = new HttpClient();
var trustListProvider = new ItalianTrustListProvider(httpClient, new ItalianTrustListProviderOptions()
{
    RefreshInterval = TimeSpan.FromHours(24),
    MinRefreshInterval = TimeSpan.FromHours(1),
    SaveCertificate = true,
    UseAvailableListWhileRefreshing = true
});

var rulesValidator = new DgcItalianRulesValidator(httpClient, new DgcItalianRulesValidatorOptions() { 
    ValidationMode = ValidationMode.Basic3G            
});// Note: this implementation is both a IRulesValidator and a IBlacklistProvider

// Create an instance of the DgcReaderService
var dgcReader = new DgcReaderService(trustListProvider, rulesValidator, rulesValidator, logger);

// Decode and validate the qr code data.
// The result will contain all the details of the validated object
var result = await dgcReader.GetValidationResult(qrTxt);

Sto sbagliando qualcosa io?
Grazie

Issue dopo che eseguo la validazione con Verify [Migrato alla nuova versione]

"Non è stato possibile caricare il file o l'assembly 'Microsoft.Extensions.Configuration.Abstractions, Version=3.1.22.0, Culture=neutral, PublicKeyToken=adb9793829ddae60' o una delle relative dipendenze. Impossibile trovare il file specificato."

Ciao, questo è e.message del seguente codice:

try {
    string acceptanceCountry = "IT";    // Specify the 2-letter ISO code of the acceptance country

    // Decode and validate the qr code data.
    // The result will contain all the details of the validated object
    var result = await dgc.Verify(decodedQrcode.ToString(), acceptanceCountry);


    return result;
} catch (Exception e) {
    Console.WriteLine($"Error verifying DGC: {e.Message}");
}

Il tutto è configurato come segue:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var httpClient = new HttpClient();

// You can use the constructor
var rulesValidator = DgcItalianRulesValidator.Create(httpClient,
   new DgcItalianRulesValidatorOptions
   {
       RefreshInterval = TimeSpan.FromHours(24),
       MinRefreshInterval = TimeSpan.FromHours(1),
       BasePath = args[0],
       UseAvailableValuesWhileRefreshing = true
   });

var trustListProvider = ItalianTrustListProvider.Create(httpClient,
   new ItalianTrustListProviderOptions
   {
       RefreshInterval = TimeSpan.FromHours(24),
       MinRefreshInterval = TimeSpan.FromHours(1),
       BasePath = args[0],
       SaveCertificate = true
   });

var drlBlacklistProvider = ItalianDrlBlacklistProvider.Create(httpClient);

// Create an instance of the DgcReaderService
var dgcReader = DgcReaderService.Create(
   trustListProviders: new[] { trustListProvider },
   blackListProviders: new IBlacklistProvider[] { rulesValidator, drlBlacklistProvider },
   rulesValidators: new[] { rulesValidator }
);

Non capisco se c'è qualcosa di sbagliato nell'utilizzo,
inoltre non ho ben capito dal readme del progetto se devo ancora utilizzare VerifyForItaly o se devo utilizzare gli altri metodi.

Inoltre, col metodo che descrivi nel readme, non capisco dove utilizzare il metodo booster o super green pass,

Grazie mille e scusa il disturbo

VerifyForItaly not throwing Exception

Hi! I just updated my code with the last library version, I initialize all classes like this:

_httpClient = new HttpClient();

var dgcReaderServiceLoggerProxy = new GreenPassLoggerProxy<DgcReaderService>(logger);
var rulesValidatorLoggerProxy = new GreenPassLoggerProxy<DgcItalianRulesValidator>(logger);
var trustListProviderLoggerProxy = new GreenPassLoggerProxy<ItalianTrustListProvider>(logger);
var blacklistProviderLoggerProxy = new GreenPassLoggerProxy<ItalianDrlBlacklistProvider>(logger);

var trustListProvider = new ItalianTrustListProvider(_httpClient, null, trustListProviderLoggerProxy);
var drlBlacklistProvider = new ItalianDrlBlacklistProvider(_httpClient, null, blacklistProviderLoggerProxy);
var rulesValidator = new DgcItalianRulesValidator(_httpClient, null, rulesValidatorLoggerProxy);

_greenPassReaderService = DgcReaderService.Create(
    trustListProviders: new[] { trustListProvider },
    blackListProviders: new IBlacklistProvider[] { rulesValidator, drlBlacklistProvider },
    rulesValidators: new[] { rulesValidator },
    logger: dgcReaderServiceLoggerProxy);

And I invoke the Verify method like this (for example):

validationResult = await _greenPassReaderService.VerifyForItaly(
    greenPassQRCodeData,
    ValidationMode.Strict2G,
    throwOnError: true);

I made in the past some automatic test with some friends Green Passes to test the library, and now I have two tests failing. Those tests are related to already expired Covid molecular tests, which before the update were correctly failing.

It seems that the method VerifyForItaly doesn't throw the exception, even if throwOnError is set to true!

Full logs:

Loading trustlist from file
Public key data for NJpCsMLQco4= from country IT found using DgcReader.TrustListProviders.Italy.ItalianTrustListProvider
HCERT signature verification succeeded using certificate NJpCsMLQco4=
Loading rules from file
Test entries are considered not valid when validation mode is Strict2G
Validation failed: Certificate is not valid

If you read the last log line, it says that the certificate is not valid, so I was expecting it to throw an Exception, but it doesn't!
Am I missing something?

Also, this is an output of that specific ValidationResult:
image

If you need that test Green Pass raw code, I can send you it in private.

Thanks a lot.

ASN1 corrupted data exception on linux

Environment: Linux OL7 with dotnet-runtime-5.0
Latest nuget packages (2.2.1) or d21ca6d when calling ItalianTrustListProvider.RefreshTrustlist() throws exception

DgcReader.TrustListProviders.Italy.ItalianTrustListProvider[0]
   Error getting trustlist from server: ASN1 corrupted data.
   System.Security.Cryptography.CryptographicException: ASN1 corrupted data.
    ---> System.Formats.Asn1.AsnContentException: The provided data is tagged with 'Application' class value '13', but it should have 
 been 'Universal' class value '16'.
   at System.Formats.Asn1.AsnDecoder.CheckExpectedTag(Asn1Tag tag, Asn1Tag expectedTag, UniversalTagNumber tagNumber
   at System.Formats.Asn1.AsnDecoder.ReadSequence(ReadOnlySpan source, AsnEncodingRules ruleSet, Int32& contentOffset, Int32& 
       contentLength, Int32& bytesConsumed, Nullable expectedTag)
   at System.Formats.Asn1.AsnValueReader.ReadSequence(Nullable expectedTag)
   at System.Security.Cryptography.Asn1.Pkcs12.PfxAsn.DecodeCore(AsnValueReader& reader, Asn1Tag expectedTag, ReadOnlyMemory rebind, PfxAsn& decoded)
    at System.Security.Cryptography.Asn1.Pkcs12.PfxAsn.Decode(AsnValueReader& reader, Asn1Tag expectedTag, ReadOnlyMemory rebind, PfxAsn& decoded)
        --- End of inner exception stack trace ---

I already solved this issue in another library. It's related to Italian data and how dotnet handles cryptography on Linux and MacOS runtimes. Basically, platforms <> Windows do not automatically convert the Byte array rawData to base 64, hence the X509Certificate constructor cannot read it. Reference.

I'm going to submit a pull request in a while.

Marco.

TypeLoadException: Non è stato possibile caricare il tipo 'Microsoft.Extensions.Logging.LoggerExtensions'

Buongiorno,
ho creato un progetto di prova della libreria con .NET Framework 4.6.1, utilizzando l'ultima versione di questo pacchetto NuGET.

Tutto funziona correttamente, tranne nel momento che richiamo la "dgcReader.Verify()".
Quello statement lancia un'eccezione come segue:
TypeLoadException: Non è stato possibile caricare il tipo 'Microsoft.Extensions.Logging.LoggerExtensions' dall'assembly 'DgcReader.Providers.Abstractions, Version=2.5.1.0, Culture=neutral, PublicKeyToken=null'.

Di seguito il codice di prova da me realizzato:

// Create an instance of the DgcReaderService
var dgcReader = DgcReader.DgcReaderService.Create(
    trustListProviders: new[] { trustListProvider },
    blackListProviders: new DgcReader.Interfaces.BlacklistProviders.IBlacklistProvider[] { rulesValidator, drlBlacklistProvider },
    rulesValidators: new[] { rulesValidator });

var decoded = dgcReader.Decode(greenPassContent).Result;
var verification = dgcReader.Verify(greenPassContent, "IT", throwOnError: true).Result;

Di seguito la lista dei package reference del progetto:

<ItemGroup>
    <PackageReference Include="DgcReader">
      <Version>2.5.1</Version>
    </PackageReference>
    <PackageReference Include="DgcReader.BlacklistProviders.Italy">
      <Version>2.5.1</Version>
    </PackageReference>
    <PackageReference Include="DgcReader.Deserializers.Italy">
      <Version>2.5.1</Version>
    </PackageReference>
    <PackageReference Include="DgcReader.Providers.Abstractions">
      <Version>2.5.1</Version>
    </PackageReference>
    <PackageReference Include="DgcReader.RuleValidators.Italy">
      <Version>2.5.1</Version>
    </PackageReference>
    <PackageReference Include="DgcReader.TrustListProviders.Abstractions">
      <Version>2.5.1</Version>
    </PackageReference>
    <PackageReference Include="DgcReader.TrustListProviders.Italy">
      <Version>2.5.1</Version>
    </PackageReference>
    <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions">
      <Version>5.0.0</Version>
    </PackageReference>
    <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions">
      <Version>5.0.0</Version>
    </PackageReference>
    <PackageReference Include="Microsoft.Extensions.Logging.Abstractions">
      <Version>5.0.0</Version>
    </PackageReference>
    <PackageReference Include="Newtonsoft.Json">
      <Version>13.0.1</Version>
    </PackageReference>
    <PackageReference Include="ZXing.Net">
      <Version>0.16.6</Version>
    </PackageReference>
    <PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0" />
    <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="5.0.0" />
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.0" />
    <PackageReference Include="System.Net.Http" Version="4.3.4" />
    <PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="5.0.0" />
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="5.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="1.1.6">
      <IncludeAssets>All</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="1.1.6" />
    <PackageReference Include="Microsoft.Data.Sqlite" Version="1.1.1">
      <IncludeAssets>All</IncludeAssets>
    </PackageReference>
  </ItemGroup>
  <ItemGroup>
    <Content Include="sqlite3.dll">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
  </ItemGroup>

Check SuperGreenPass for over 50 in Italy

I don't know if what i am asking is correct, but with the new rules in Italy from the 15 February 2022 to the 15 June 2022 as reported from ilsole24ore:

Obbligo di Green Pass rafforzato per tutti i lavoratori (pubblici e privati) e i liberi professionisti di almeno 50 anni. Chi non è ancora vaccinato dovrà effettuare la prima dose del vaccino entro il 31 gennaio per ottenere un Green Pass rafforzato valido a partire dal 15 febbraio (il certificato verde è rilasciato subito dopo la prima dose ma è attivato il quindicesimo giorno successivo alla somministrazione)

So from the 15th i need to check if the person is above 50 and then i need to validate the certificate with ValidationMode.Basic3G, if not so i need to validate it with ValidationMode.Strict2G.

It's possible to implement a new DgcItalianRulesValidatorOptions or check it direcly into the code for this case?

Because right now if i understand correctly i would need to call first DgcReaderService with no argument only to decode the DGC and check the DateOfBirth, then call DgcReaderService with the correct ValidationMode.

Exemption certificate validation fails during "Rules Validation"

Hello,

I am testing an Exemption Certificate that gets correctly validated by VerificaC19.

This is my code:

var _trustListProvider = ItalianTrustListProvider.Create(_httpClient, new ItalianTrustListProviderOptions()
            {
                RefreshInterval = TimeSpan.FromMinutes(refreshIntervalMinutes),
                MinRefreshInterval = TimeSpan.FromMinutes(minRefreshIntervalMinutes),
                MaxFileAge = TimeSpan.FromDays(60),
                BasePath = basePath,
                SaveCertificate = true,
                UseAvailableListWhileRefreshing = true
            });

var _rulesValidator = DgcItalianRulesValidator.Create(_httpClient, new DgcItalianRulesValidatorOptions
            {
                RefreshInterval = TimeSpan.FromMinutes(refreshIntervalMinutes),
                MinRefreshInterval = TimeSpan.FromMinutes(minRefreshIntervalMinutes),
                MaxFileAge = TimeSpan.FromDays(60),
                BasePath = basePath,
                UseAvailableValuesWhileRefreshing = true,
                ValidationMode = ValidationMode.Basic3G
            });
var  _blacklistProvider = ItalianDrlBlacklistProvider.Create(_httpClient,
                    new ItalianDrlBlacklistProviderOptions
                    {
                        RefreshInterval = TimeSpan.FromMinutes(refreshIntervalMinutes),
                        MinRefreshInterval = TimeSpan.FromMinutes(minRefreshIntervalMinutes),
                        MaxFileAge = TimeSpan.FromDays(60),
                        BasePath = basePath,
                        UseAvailableValuesWhileRefreshing = true,
                    });
var reader = DgcReaderService.Create(_trustListProvider, _blacklistProvider, _rulesValidator);
var res = await reader.VerifyForItaly(qr, ValidationMode.Basic3G, throwOnError: false);

The validation fails with Status NeedRulesVerification and RulesValidation field set to null. The signature is correctly detected as Valid and the Dgc Name and Birth is correctly parsed. The StatusMessage field is: Riferimento a un oggetto non impostato su un'istanza di oggetto.

This is the Stack Trace I get by setting the throwOnError parameter to true:

   at DgcReader.DgcReaderService.<Verify>d__5.MoveNext()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at DgcReader.ItalianValidationResultsExtensions.<VerifyForItaly>d__4.MoveNext()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()

I have already tried to re-download the updated rules, but with no luck. I am on version 2.5.0.
Am I doing something wrong?
Please let me know if you need more details

Allow BlacklistProvider not to await the first download

When application is launched for the first time, it can take a long time before the full Italian Blacklist is downloaded.
It may be useful to allow to skip the await of the refresh method even for the first download, when the list is empty
This is related to #55

Validazione vaccinazione

Buongiorno,
mi è capitato un caso in cui la libreria in fase di validazione restituisce NotValid, mentre l'app C19 restituisce valido.
Il caso è una seconda dose di vaccino il cui ultimo giorno valido è oggi (oggi è esattamente il 180esimo giorno dopo la somministrazione).

Il problema credo sia dovuto a questo confronto all'interno del file DgcItalianRulesValidator:

if (result.ValidUntil < result.ValidationInstant)
                    result.ItalianStatus = DgcItalianResultStatus.NotValid;

Dato che ValidUntil contiene solo la data (l'ora è 00:00:00), mentre ValidationInstant contiene data e anche ora attuale, in questo caso restiuisce NotValid.

Guardando invece il codice dell'sdk ufficiale, se ho trovato il punto corretto, il controllo viene fatto solo con le date.
Questo il codice all'interno del file VerificationViewModel.kt:

            val startDate: LocalDate =
                LocalDate.parse(clearExtraTime(it.last().certificateValidFrom))

            val endDate: LocalDate =
                LocalDate.parse(clearExtraTime(it.last().certificateValidUntil))

            Log.d("dates", "start:$startDate end: $endDate")
            return when {
                startDate.plusDays(
                    Integer.parseInt(recoveryCertStartDay)
                        .toLong()
                ).isAfter(LocalDate.now()) -> CertificateStatus.NOT_VALID_YET
                LocalDate.now()
                    .isAfter(
                        startDate.plusDays(
                            Integer.parseInt(recoveryCertEndDay)
                                .toLong()
                        )
                    ) -> CertificateStatus.NOT_VALID
                else -> return if (scanMode == ScanMode.BOOSTER) CertificateStatus.TEST_NEEDED else CertificateStatus.VALID
            }

Non andrebbe fatto anche nella libreria il confronto solo tra date (solo per la verifica delle vaccinazioni, mentre per i tamponi è importante anche l'ora)?
Grazie per la risposta e per l'ottimo lavoro fatto.

The UVCI Blacklist inside Rules is not checked during validation

Hello,

Today we noticed that the well-known Mickey Mouse's certificate returns "Valid" in the SDK. It seems that the validation of the UVCI Blacklist inside the Italian Rules is not checked, more precisely, this function doesn't seem to be called:

image

If you need the certificate for testing let me know.

Meanwhile we probably have found also another bug, we will report it later today once confirmed in a separate issue.
As always thank you!

Rule validator providers should support validation for multiple countries

Some countries endopoints (i.e. German endopoint) provides support for validation rules of multiple countries, but the current IRulesValidator interface does not provide an option to specify the desired validation country, assuming that a validator implementation will support rules for just a single country.

Discussed in #9

Originally posted by axunonb November 26, 2021
Looking especially for information about implementing TrustListProviders and ValidatorRules usable for Germany.
Can't even figure out the CertUpdateUrlor CertStatusUrl...

Xamarin - Initial qrCode validation result takes more than 3 minutes

Hi @DevTrevi,

I am using Xamarin (.NET Standard 2.0) shared Library.
I instantiated the service:

var httpClient = new HttpClient();
var trustListProvider = ItalianTrustListProvider.Create(httpClient,
 new ItalianTrustListProviderOptions
 {
   RefreshInterval = TimeSpan.FromHours(24),
   MinRefreshInterval = TimeSpan.FromHours(1),
   BasePath = System.IO.Path.Combine(Xamarin.Essentials.FileSystem.AppDataDirectory,"tl"),
   SaveCertificate = true
  });
var drlBlacklistProvider = ItalianDrlBlacklistProvider.Create(httpClient,
 new ItalianDrlBlacklistProviderOptions
 {
   RefreshInterval = TimeSpan.FromHours(24),
   MinRefreshInterval = TimeSpan.FromHours(1),
   BasePath = System.IO.Path.Combine(Xamarin.Essentials.FileSystem.AppDataDirectory, "bl"),
   UseAvailableValuesWhileRefreshing = true,
  });
var rulesValidator = DgcItalianRulesValidator.Create(httpClient,
 new DgcItalianRulesValidatorOptions
 {
   RefreshInterval = TimeSpan.FromHours(24),
   MinRefreshInterval = TimeSpan.FromHours(1),
   BasePath = System.IO.Path.Combine(Xamarin.Essentials.FileSystem.AppDataDirectory, "rl"),
   ValidationMode = ValidationMode.Strict2G
  });

DgcReaderService dgcReader = DgcReaderService.Create(
 trustListProviders: new[] { trustListProvider },
 blackListProviders: new IBlacklistProvider[] { rulesValidator, drlBlacklistProvider },
 rulesValidators: new[] { rulesValidator });

And when I try to get ValidationResult, only for first (newly installed app or cache deleted ) call:

Stopwatch sw = new Stopwatch();
sw.Start();
string code = @"HC1:6BFOXN%TS3DH0YOJ58S S-W5HDC *M0II5XHC9B5G2+$N IOP-IA%NFQGRJPC%OQHIZC4.OI1RM8ZA.A5:S9MKN4NN3F85QNCY0O%0VZ001HOC9JU0D0HT0HB2PL/IB*09B9LW4T*8+DCMH0LDK2%K:XFE70*LP$V25$0Q:J:4MO1P0%0L0HD+9E/HY+4J6TH48S%4K.GJ2PT3QY:GQ3TE2I+-CPHN6D7LLK*2HG%89UV-0LZ 2ZJJ524-LH/CJTK96L6SR9MU9DHGZ%P WUQRENS431T1XCNCF+47AY0-IFO0500TGPN8F5G.41Q2E4T8ALW.INSV$ 07UV5SR+BNQHNML7 /KD3TU 4V*CAT3ZGLQMI/XI%ZJNSBBXK2:UG%UJMI:TU+MMPZ5$/PMX19UE:-PSR3/$NU44CBE6DQ3D7B0FBOFX0DV2DGMB$YPF62I$60/F$Z2I6IFX21XNI-LM%3/DF/U6Z9FEOJVRLVW6K$UG+BKK57:1+D10%4K83F+1VWD1NE";
DgcReader.Models.DgcValidationResult result = await dgcReader.GetValidationResult(code, "IT");
sw.Stop();
Logger.Instance.Info($"GetValidationResult took {sw.Elapsed} to finish.");

it takes more than 3 minutes to finish (tested on 3 different Android and iOS devices):
GetValidationResult took 00:05:32.9229188 to finish.
GetValidationResult took 00:03:30.3414527 to finish.
GetValidationResult took 00:03:14.6817884 to finish.

After the first call of "GetValidationResult", every other call takes 1-6 seconds to get the result (which is ok), even if the app restarts.

Any idea why is this happening?

Validation failed with "The minimum version of the App implementation is 1.2.9"

With last night release of Italian rules, it's mandatory a minimum implementation version 1.2.9.

Unfortunately, the ReferenceSdkMinVersion constant, defined in SdkConstants, is set to 1.1.5; this leds to an exception during validation:

Validation failed: The minimum version of the App implementation is 1.2.9. Please update the package with the latest implementation in order to get a reliable result

Workaround: enable the IgnoreMinimumSdkVersion option:

public void ConfigureServices(IServiceCollection services)
{
   ...
   services.AddDgcReader()
       .AddItalianTrustListProvider()
       .AddItalianRulesValidator(o =>      // <-- Register the DgcItalianRulesValidator service
               {
                   o.IgnoreMinimumSdkVersion = true
                   ...
               });
}

IMHO this is an issue since this project is an up-to-date implementation and ReferenceSdkMinVersion needs to be updated.

Problem with ItalianDrlBlacklistProvider and SQLite dependencies

Ciao @DevTrevi,

I recently updated DgcReader to version 2.1.0 and I'm working out to add ItalianDrlBlacklistProvider, in order to obtain DRL blacklist.

Unfortunately, invoking VerifyForItaly the following exception occurs:
System.IO.FileNotFoundException: 'Non è stato possibile caricare il file o l'assembly 'SQLitePCLRaw.batteries_v2' o una delle relative dipendenze. Impossibile trovare il file specificato.'

This is how services are configured:

serviceCollection
    .AddLogging(builder => builder.AddNLog())
    .AddDgcReader()
    .AddItalianTrustListProvider(o =>
    {
        ...
    })
    .AddItalianRulesValidator(o =>
    {
        ...
    })
    .AddItalianDrlBlacklistProvider(o =>
    {
        o.RefreshInterval = Options.RefreshInterval;
        o.MinRefreshInterval = Options.MinRefreshInterval;
        o.BasePath = Options.BasePath;
        o.MaxFileAge = Options.MaxFileAge;
    });

The same thing happens when explicitly instancing DgcReader without using DI.

All other functions of your library work like a charm.

I'm using VS2019, targeting .NET Framework 4.7.

Where am I wrong or forgetting something?

Thanks

Inserire l'apposito header User-agent nelle richieste verso le API

Inserire all'interno delle richieste verso le API l'apposito header User-Agent nella forma

User-Agent: <sdk>-<sdk-technology>/<sdk-version>

È possibile omettere -<sdk-technology> se la tecnologia è già specificata nel nome (ad esempio verificac19-sdk-php).

Ad esempio nel caso verificac19-sdk per Node.js lo User-Agent sarà

User-Agent: verificac19-sdk-node/0.9.3

Testing multiple ValidationMode

Use case: I would like to test a DCC for both Basic3G and Strict2G in Italy, and return the highest validation mode it can pass (or NotValid if none).

Does this SDK support this use case without configuring and instantiating multiple DgcReaderService?

DgcRulesValidationException during Booster Validation in 2.2.1 for Super Green Pass

Hello,

as always thank you for your work.
I've updated to version 2.2.1, and now I'm having an issue (which was not present in 2.2.0) where the validation of a Super-Green Pass in "Booster" mode throws a DgcRulesValidationException with "Certificate is not valid".

This is my code:

var res = await reader.VerifyForItaly(qrTxt, ValidationMode.Booster); // the exception is thrown here
result.IsValid = res.Status is DgcResultStatus.Valid;
// True if an additional test is needed to confirm the Boost
result.TestNeeded = res.GetItalianResultStatus() == DgcItalianResultStatus.TestNeeded;

In 2.2.0 the exception was not thrown, and the "result.TestNeeded" variable was set to true.

Here's the stack trace:

   at DgcReader.DgcReaderService.<Verify>d__5.MoveNext()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at DgcReader.ItalianValidationResultsExtensions.<VerifyForItaly>d__4.MoveNext()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()

.NET Framework 4.5.2

For now I'm reverting back to 2.2.0.
Thank you

Booster Vaccination with 2/1 doses gives wrong result

There is a problem in the ValidationMode.Booster, where it's required to have at least 3 doses for the vaccination to be considered "Booster".
I had COVID followed by 1 dose of Pfizer. Now I have done the "Booster" dose with Moderna, so my Booster Green Pass has 2 / 1 Doses. This is correctly validated as a Booster in the official App.

Here's the wrong fregment of code in DgcItalianRulesValidator.cs:

// Complete cycle
if (validationMode == ValidationMode.Booster)
{
    // Min num of doses to be considered "booster":
    // J&J: required full cycle with at least 2 doses, other vaccines 3 doses
    var boostedDoseNumber = vaccination.MedicinalProduct == VaccineProducts.JeJVacineCode ? 2 : 3;

    // If less thant the minimum "booster" doses, requires a test
    if (vaccination.DoseNumber < boostedDoseNumber)
        result.ItalianStatus = DgcItalianResultStatus.TestNeeded;
    else
        result.ItalianStatus = DgcItalianResultStatus.Valid;
}

The official SDK has an additional check where if the number of doses is > than the total number of doses, then the test is not needed.

If possible, can I have an ETA for the next release with this fix?
Thanks a lot

Problemi con Blacklist

Ciao, innanzitutto grazie per la disponibilità e per il lavoro fatto.
Ho un problema che non riconosce i certificati annullati me li ritrovo sempre validi e mi riporta blacklistcheck: not blacklisted, la decodifica avviene correttamente, ho provato sia con framework 4.7, core 3.1 e .net 6 sia su windows 10 che windows 11, la stessa cosa se utilizzo Verify o VerifyforItaly, se utilizzo ItalianDrlBlacklistProvider mi riporta status: needsruleverification.
Cortesemente riesci a dirmi dove sbaglio?

   private void VerGreenPass(string code)
   {   
        ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
        var httpClient = new HttpClient();            

        var trustListProvider = ItalianTrustListProvider.Create(httpClient, new ItalianTrustListProviderOptions
        {
            RefreshInterval = TimeSpan.FromHours(24),
            MinRefreshInterval = TimeSpan.FromHours(1),
            SaveCertificate = true,
        });
     
        var rulesValidator = DgcItalianRulesValidator.Create(httpClient,
            new DgcItalianRulesValidatorOptions
            {
                RefreshInterval = TimeSpan.FromHours(24),
                MinRefreshInterval = TimeSpan.FromHours(1),
                ValidationMode = ValidationMode.Strict2G
                
            });
        
        //var blacklistProvider = ItalianDrlBlacklistProvider.Create(httpClient,

            //new ItalianDrlBlacklistProviderOptions
            //{
            //   RefreshInterval = TimeSpan.FromHours(24),
            //    MinRefreshInterval = TimeSpan.FromHours(1)                
            //});           
   
        var dgcReader = DgcReaderService.Create(trustListProvider, rulesValidator, rulesValidator, null);

       
        var result = dgcReader.GetValidationResult(code, "IT");

     }

Logger null check in DgcItalianRulesValidator

Hi and thanks a lot for you work!

I think I found a little issue here:
image

Maybe in the Strict2G if, the _logger should be guarded with ?.

I'm very sorry but at the moment I don't have time to make a pull request!

DgcReaderService should support multiple RuleValidators simultaneusly

For some use cases, it will be useful to use multiple RuleValidators at once, allowing the application to choose for which country the rules should be validated.

This issue is also related to issue #5 (Verify DGC for any country)

Discussed in #9

Originally posted by axunonb November 26, 2021
Looking especially for information about implementing TrustListProviders and ValidatorRules usable for Germany.
Can't even figure out the CertUpdateUrlor CertStatusUrl...

Verify DGC for any country

Hello @DevTrevi ,

I am from an airline IT team and we are creating an application to use DGC for retrieving Vaccination information. This information is needed to determine whether traveler is allowed to fly to particular destination based on destination country covid rules. We are able to decode the DGC QR code using your library but struggling with Verification process. Our use case is to accept DGC for all countries. We referred the below official docs, but couldn't figure out how a third party can verify a DGC for any country
https://ec.europa.eu/health/sites/default/files/ehealth/docs/digital-green-certificates_v4_en.pdf
https://ec.europa.eu/health/sites/default/files/ehealth/docs/digital-green-certificates_v5_en.pdf

Xamarin.Android Access to the path "/DgcReaderData\Blacklist\Italy" is denied

Buongiorno,
sto cercando di integrare i pacchetti Nuget per un'app sviluppata con Xamarin.Android.

Il codice che sto provando è questo:

        var httpClient = new HttpClient();
        var trustListProvider = new ItalianTrustListProvider(httpClient);
        var drlBlacklistProvider = new ItalianDrlBlacklistProvider(httpClient);
        var rulesValidator = new DgcItalianRulesValidator(httpClient);

        var dgcReader = DgcReaderService.Create(
                trustListProviders: new[] { trustListProvider },
                blackListProviders: new IBlacklistProvider[] { rulesValidator, drlBlacklistProvider },
                rulesValidators: new[] { rulesValidator });
        
        string qrCodeData = "xxx";
        string acceptanceCountry = "IT";    // Specify the 2-letter ISO code of the acceptance country
        try
        {
            // Decode and validate the signature.
            // If anything fails, an exception is thrown containing the error details
            var result = await dgcReader.Verify(qrCodeData, acceptanceCountry);
        }
        catch (Exception e)
        {
            Console.WriteLine($"Error verifying DGC: {e.Message}");
        }

Il sistema va in eccezione con questo messaggio:
Access to the path \"/DgcReaderData\\Blacklist\\Italy\" is denied.

Come posso cambiare il path in cui vengono salvate le informazioni?

Rimuovere la modalità scuola

Rimuovere la modalità scuola secondo il DECRETO-LEGGE 4 febbraio 2022, n. 5

La condizione sanitaria che consente la didattica in presenza di
cui al comma 1, lettera b), numero 2, primo periodo,  e  lettera  c),
numero 2), primo periodo, puo' essere controllata  dalle  istituzioni
scolastiche mediante l'applicazione  mobile  per  la  verifica  delle
certificazioni verdi COVID-19 di cui al decreto  del  Presidente  del
Consiglio dei ministri adottato ai sensi dell'articolo 9,  comma  10,
del  decreto-legge  22  aprile   2021,   n.   52,   convertito,   con
modificazioni, dalla legge 17  giugno  2021,  n.  87.  L'applicazione
mobile  di  cui  al  primo  periodo  e'  tecnicamente   adeguata   al
conseguimento delle  finalita'  del  presente  comma  e  puo'  essere
impiegata anche nelle more dell'aggiornamento del decreto di  cui  al
primo periodo. 

Question about italian trust list endpoint

Hi! I noticed a strange behaviour, not with your library, but in general when you make an http get request to https://get.dgc.gov.it/v1/dgc/signercertificate/status.

Please, consider the following code:

var httpClient = new HttpClient();
var response = await httpClient.GetAsync("https://get.dgc.gov.it/v1/dgc/signercertificate/status");
var body = await response.Content.ReadAsStringAsync();

I am on Windows 11, and I run it from these .NET framework versions

  • .NET Core 3.1: it works
  • .NET 4.8: it doesn't work
  • .NET 6: it doesn't work

When it doesn't work, the error is Cannot estabilish a secure SSL/TLS channel:
image

Also, when you make the request with browser, it works.

I investigated it a little and I found these things:

  • The server wants a TLS3.1 handshake
  • Windows 10 doesn't implement it
  • Windows 11 should implement it
  • Chromium implements his own version of TLS3.1 that's why it works even if in the OS it's not implemented
  • If a publish a web app with that code on Azure, it works

But I really don't understand why in .NET Core 3.1 it works and with the next .NET versions not.

I'd like to know you opinion because I'm very curious about it!

Thanks!

Check if json files have been updated before refreshing from server

Ciao Davide, ho bisogno di farti una domanda a riguardo della libreria dgcReader.
Per la mia necessità, dispongo di un server aziendale che tramite le tre funzioni di update, periodicamente aggiorna i files JSON (rules, blacklist etc), e di n° clients che sono connessi in rete locale ma senza connessione ad internet.
Il loro Path è la cartella di rete dove il server scarica i JSON ed è quindi raggiungibile in intranet.
Volevo capire se è possibile fare in modo che la libreria apra i files in lettura e non in scrittura. Questo per evitare concorrenze di scritture sullo stesso file.
Per ora funziona, ma non vorrei che in produzione diventasse problematico.
Grazie mille per la tua disponibilità.

Elia

SSL connection could not be enstabilished in NET 6.0

Hello again,

I am still having issues with TLS Handshake when updating data, this time with NET 6.0 and 5.0.

The inner exeption is: Authentication failed because the remote party sent a TLS alert: 'HandshakeFailure'.

I had this issue in the past with .NET 4.7, and I "solved" it by manually specifiying the TLS protocol with: ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;, right before the HttpClient initialization.

I was not expecting this to happen with newer versions of the framework, so I highly suspect it has something to do with my environment, but I couldn't fix it.

I have also tried to create a new simple project like this:

  • Created a new Console Application project targeting NET 6.0 and installed the dependencies from nuget, this is the structure:
    image

  • Added this code in Program.cs:

using DgcReader;
using DgcReader.BlacklistProviders.Italy;
using DgcReader.RuleValidators.Italy;
using DgcReader.RuleValidators.Italy.Models;
using DgcReader.TrustListProviders.Italy;
string qr= "HC1:....";
var httpClient = new HttpClient();

var basePath = Directory.GetCurrentDirectory();

var refreshIntervalMinutes = 60;
var minRefreshIntervalMinutes = 10;

var trustListProvider = ItalianTrustListProvider.Create(httpClient, new ItalianTrustListProviderOptions()
{
    RefreshInterval = TimeSpan.FromMinutes(refreshIntervalMinutes),
    MinRefreshInterval = TimeSpan.FromMinutes(minRefreshIntervalMinutes),
    MaxFileAge = TimeSpan.FromDays(60),
    BasePath = basePath,
    SaveCertificate = true,
    UseAvailableListWhileRefreshing = true
});

var rulesValidator = DgcItalianRulesValidator.Create(httpClient, new DgcItalianRulesValidatorOptions
{
    RefreshInterval = TimeSpan.FromMinutes(refreshIntervalMinutes),
    MinRefreshInterval = TimeSpan.FromMinutes(minRefreshIntervalMinutes),
    MaxFileAge = TimeSpan.FromDays(60),
    BasePath = basePath,
    UseAvailableValuesWhileRefreshing = true,
    ValidationMode = ValidationMode.Basic3G
});

var blacklistProvider = ItalianDrlBlacklistProvider.Create(httpClient,
                    new ItalianDrlBlacklistProviderOptions
                    {
                       RefreshInterval = TimeSpan.FromMinutes(refreshIntervalMinutes),
                        MinRefreshInterval = TimeSpan.FromMinutes(minRefreshIntervalMinutes),
                        MaxFileAge = TimeSpan.FromDays(60),
                        BasePath = basePath,
                        UseAvailableValuesWhileRefreshing = true,
                    });

try
{
    var reader = DgcReaderService.Create(trustListProvider, blacklistProvider, rulesValidator);
    var res = await reader.VerifyForItaly(qr, ValidationMode.Basic3G, throwOnError: true); // The exception is thrown here, the data is not downloaded
}
catch (Exception ex)
{
    Console.WriteLine(ex);
}
  • I have also tried to clear the Nuget Cache

  • This time adding ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12 does not make any difference

Sorry to bother you about this, but do you have any advice?
Thank you

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.