Skip to content

Commit 1df51d0

Browse files
committed
Merge branch 'development'
# Conflicts: Resolved conflict in readme file only # README.md
2 parents a10219a + d6b2e22 commit 1df51d0

63 files changed

Lines changed: 1038 additions & 379 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@
2424

2525
## [SmartHealthCard.Token](https://www.nuget.org/packages/SmartHealthCard.Token/0.1.0-alpha.1): Encode, Decode & Verifiy SMART Health Card JWS tokens
2626
```
27-
Install-Package SmartHealthCard.QRCode -Version 0.1.0-alpha.2
27+
Install-Package SmartHealthCard.QRCode -Version 0.1.0-alpha.3
2828
```
2929

3030

3131
## [SmartHealthCard.QRCode](https://www.nuget.org/packages/SmartHealthCard.QRCode/0.1.0-alpha.1): Encode SMART Health Card JWS token QR Code images
3232
```
33-
Install-Package SmartHealthCard.QRCode -Version 0.1.0-alpha.2
33+
Install-Package SmartHealthCard.QRCode -Version 0.1.0-alpha.1
3434
```
3535

3636
 

ReadMeOpenSSLCreateECCkeys.txt

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
Taken from : https://www.scottbrady91.com/OpenSSL/Creating-Elliptical-Curve-Keys-using-OpenSSL
2+
3+
Recently, I have been using OpenSSL to generate private keys and X509 certificates
4+
for Elliptical Curve Cryptography (ECC) and then using them in ASP.NET Core for token signing.
5+
6+
In this article, I�m going to show you how to use OpenSSL to generate private and public
7+
keys on the curve of your choice. Check out my other article for how to do the same for RSA
8+
keys.
9+
10+
OpenSSL ECDSA Cheat Sheet
11+
-------------------------------------------------------------------
12+
# find your curve
13+
openssl ecparam -list_curves
14+
15+
# generate a private key for a curve
16+
openssl ecparam -name prime256v1 -genkey -noout -out private-key.pem
17+
18+
# generate corresponding public key
19+
openssl ec -in private-key.pem -pubout -out public-key.pem
20+
21+
# optional: create a self-signed certificate
22+
openssl req -new -x509 -key private-key.pem -out cert.pem -days 360
23+
24+
# optional: convert pem to pfx
25+
openssl pkcs12 -export -inkey private-key.pem -in cert.pem -out cert.pfx
26+
Generating an Elliptical Curve Private Key Using OpenSSL
27+
To start, you will need to choose the curve you will be working with. You can use the
28+
following command to see a list of
29+
supported curve names and descriptions.
30+
31+
openssl ecparam -list_curves
32+
In this example, I am using prime256v1 (secp256r1), which is suitable for JWT signing;
33+
this is the curve used for JOSE�s ES256.
34+
-------------------------------------------------------------------
35+
36+
You can now generate a private key:
37+
38+
openssl ecparam -name prime256v1 -genkey -noout -out private-key.pem
39+
This should give you a PEM file containing your EC private key, which looks something
40+
like the following:
41+
42+
-----BEGIN EC PRIVATE KEY-----
43+
MHcCAQEEIKEubpBiHkZQYlORbCy8gGTz8tzrWsjBJA6GfFCrQ98coAoGCCqGSM49
44+
AwEHoUQDQgAEOr6rMmRRNKuZuwws/hWwFTM6ECEEaJGGARCJUO4UfoURl8b4JThG
45+
t8VDFKeR2i+ZxE+xh/wTBaJ/zvtSqZiNnQ==
46+
-----END EC PRIVATE KEY-----
47+
48+
Creating an EC Public Key from a Private Key Using OpenSSL
49+
Now that you have your private key, you can use it to generate another PEM, containing
50+
only your public key.
51+
52+
openssl ec -in private-key.pem -pubout -out public-key.pem
53+
This should give you another PEM file, containing the public key:
54+
55+
-----BEGIN PUBLIC KEY-----
56+
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEOr6rMmRRNKuZuwws/hWwFTM6ECEE
57+
aJGGARCJUO4UfoURl8b4JThGt8VDFKeR2i+ZxE+xh/wTBaJ/zvtSqZiNnQ==
58+
-----END PUBLIC KEY-----
59+
60+
Creating an EC Self-Signed Certificate Using OpenSSL
61+
Now that you have a private key, you could use it to generate a self-signed certificate.
62+
This is not required, but it allows you to use the key
63+
for server/client authentication, or gain X509 specific functionality in technologies
64+
such as JWT and SAML.
65+
66+
openssl req -new -x509 -key private-key.pem -out cert.pem -days 360
67+
This will again generate another PEM file, this time containing the certificate created
68+
by your private key:
69+
70+
-----BEGIN CERTIFICATE-----
71+
MIIB4DCCAYWgAwIBAgIUH53ssiPt4JEGx+VJyntCpHL+TdAwCgYIKoZIzj0EAwIw
72+
RTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGElu
73+
dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDA3MTgxMTE4NDNaFw0yMTA3MTMx
74+
MTE4NDNaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYD
75+
VQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwWTATBgcqhkjOPQIBBggqhkjO
76+
PQMBBwNCAAQ6vqsyZFE0q5m7DCz+FbAVMzoQIQRokYYBEIlQ7hR+hRGXxvglOEa3
77+
xUMUp5HaL5nET7GH/BMFon/O+1KpmI2do1MwUTAdBgNVHQ4EFgQU9yjFBqAZOMv+
78+
cD6a3KHTWuYrcFEwHwYDVR0jBBgwFoAU9yjFBqAZOMv+cD6a3KHTWuYrcFEwDwYD
79+
VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNJADBGAiEAwCpA5Nx083qqUqU6LUd0
80+
vzZLK4etuInxNvXohXH5LiACIQDSI63J4DiN3dq2sPPLw5iQi9MMefcV1iAySbKT
81+
B9BaAw==
82+
-----END CERTIFICATE-----
83+
84+
You could leave things there, but if you are working on Windows, you may prefer a PFX
85+
file that contains both the certificate and the private key for you to export and use.
86+
87+
You can do this using OpenSSL�s pkcs12 command:
88+
89+
openssl pkcs12 -export -inkey private-key.pem -in cert.pem -out cert.pfx
90+
OpenSSL will ask you to create a password for the PFX file. Feel free to leave this blank.
91+
92+
This should leave you with a certificate that Windows can both install and export the
93+
EC private key from.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
How to pubish to Nuget:
1+
How to publish to Nuget:
22

33
1. Rev the version in the project package dialog and save
44
2. Right click the project and select Pack

SmartHealthCard.DecoderDemo/Program.cs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
using SmartHealthCard.Token;
22
using SmartHealthCard.Token.Certificates;
3+
using SmartHealthCard.Token.Exceptions;
34
using SmartHealthCard.Token.Model.Jwks;
45
using SmartHealthCard.Token.Model.Shc;
6+
using SmartHealthCard.Token.Providers;
7+
using SmartHealthCard.Token.Support;
58
using System;
69
using System.Collections.Generic;
710
using System.Security.Cryptography.X509Certificates;
11+
using System.Threading;
812
using System.Threading.Tasks;
913

1014
namespace SHC.DecoderDemo
@@ -61,10 +65,15 @@ static async Task DecoderDemoRunner()
6165
//Or decode and verify, returning the Smart Health Card as a JSON string, throws exceptions if not valid
6266
//string DecodedSmartHealthCardJson = await Decoder.DecodeToJsonAsync(SmartHealthCardJwsToken, Verify: true);
6367
}
64-
catch (Exception Exec)
68+
catch (SmartHealthCardDecoderException DecoderException)
6569
{
6670
Console.WriteLine("The SMART Health Card JWS token was invalid, please see message below:");
67-
Console.WriteLine(Exec.Message);
71+
Console.WriteLine(DecoderException.Message);
72+
}
73+
catch (Exception Exception)
74+
{
75+
Console.WriteLine("Oops, there is an unexpected development exception");
76+
Console.WriteLine(Exception.Message);
6877
}
6978
}
7079
}
@@ -78,7 +87,7 @@ public MyJwksProvider(X509Certificate2 Certificate)
7887
this.Certificate = Certificate;
7988
}
8089

81-
public Task<JsonWebKeySet> GetJwksAsync(Uri WellKnownJwksUri)
90+
public Task<Result<JsonWebKeySet>> GetJwksAsync(Uri WellKnownJwksUri, CancellationToken? CancellationToken = null)
8291
{
8392
//In production the default implementation of this IJwksProvider interface would
8493
//retrieve the JWKS file from the provided 'WellKnownJwksUri' URL that is found in
@@ -87,8 +96,10 @@ public Task<JsonWebKeySet> GetJwksAsync(Uri WellKnownJwksUri)
8796
//own JWKS which we have generated from our certificate as seen below.
8897
//This allows you to test before you have a publicly exposed endpoint for you JWKS.
8998
SmartHealthCardJwks SmartHealthCardJwks = new SmartHealthCardJwks();
90-
SmartHealthCard.Token.Model.Jwks.JsonWebKeySet Jwks = SmartHealthCardJwks.GetJsonWebKeySet(new List<X509Certificate2>() { Certificate });
91-
return Task.FromResult(Jwks);
99+
JsonWebKeySet Jwks = SmartHealthCardJwks.GetJsonWebKeySet(new List<X509Certificate2>() { Certificate });
100+
return Task.FromResult(Result<JsonWebKeySet>.Ok(Jwks));
92101
}
102+
103+
93104
}
94105
}

SmartHealthCard.EncoderDemo/Program.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using SmartHealthCard.QRCode;
22
using SmartHealthCard.Token;
33
using SmartHealthCard.Token.Certificates;
4+
using SmartHealthCard.Token.Exceptions;
45
using SmartHealthCard.Token.Model.Shc;
56
using System;
67
using System.Collections.Generic;
@@ -58,8 +59,22 @@ static async Task EncoderDemoRunner()
5859
//Instantiate the Smart Health Card Encoder
5960
SmartHealthCardEncoder SmartHealthCardEncoder = new SmartHealthCardEncoder();
6061

61-
//Get the Smart Health Card JWS Token
62-
string SmartHealthCardJwsToken = await SmartHealthCardEncoder.GetTokenAsync(Certificate, SmartHealthCard);
62+
string SmartHealthCardJwsToken = string.Empty;
63+
try
64+
{
65+
//Get the Smart Health Card JWS Token
66+
SmartHealthCardJwsToken = await SmartHealthCardEncoder.GetTokenAsync(Certificate, SmartHealthCard);
67+
}
68+
catch (SmartHealthCardEncoderException EncoderException)
69+
{
70+
Console.WriteLine("The SMART Health Card Encoder has found an error, please see message below:");
71+
Console.WriteLine(EncoderException.Message);
72+
}
73+
catch (Exception Exception)
74+
{
75+
Console.WriteLine("Oops, there is an unexpected development exception");
76+
Console.WriteLine(Exception.Message);
77+
}
6378

6479
//Instantiate the Smart Health Card QR Code Factory
6580
SmartHealthCardQRCodeEncoder SmartHealthCardQRCodeEncoder = new SmartHealthCardQRCodeEncoder();

SmartHealthCard.QRCode/SmartHealthCard.QRCode.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<TargetFramework>net5.0</TargetFramework>

SmartHealthCard.QRCode/SmartHealthCardQRCodeDecoder.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,9 @@ public SmartHealthCardQRCodeDecoder(
4242
/// <param name="QRCodeRawDataList"></param>
4343
/// <returns></returns>
4444
public string GetToken(List<string> QRCodeRawDataList)
45-
{
46-
IQRCodeDecoder QRCodeDecoder = new QRCodeDecoder();
45+
{
4746
IEnumerable<Chunk> ChunkList = QRCodeDecoder.GetQRCodeChunkList(QRCodeRawDataList);
48-
INumericalModeDecoder NumericalModeDecoder = new NumericalModeDecoder();
49-
string test = NumericalModeDecoder.Decode(ChunkList);
50-
return test;
47+
return NumericalModeDecoder.Decode(ChunkList);
5148
}
5249
}
5350
}

SmartHealthCard.Test/Model/FhirDataSupport.cs

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ namespace SmartHealthCard.Test.Model
1010
{
1111
static class FhirDataSupport
1212
{
13-
public static Bundle GetCovid19FhirBundleExample1()
13+
public static Bundle GetCovid19DetectedFhirBundleExample()
1414
{
15-
Patient PatientResource = GetPatientResource("TestFamilyName", "TestGivenName", new DateTime(1973, 09, 30), "61481059995");
16-
15+
Patient PatientResource = GetPatientResource("Coyote", "Wile E", new DateTime(1973, 09, 30), "61481059995");
16+
1717
Coding Code = new Coding(system: "http://loinc.org", code: "94558-4"); //SARS-CoV-2 (COVID-19) Ag [Presence] in Respiratory specimen by Rapid immunoassay
1818
Coding Value = new Coding(system: "http://snomed.info/sct", code: "260373001"); //Detected
1919
Observation CovidResultObservationResource = GetObservationResource(
@@ -36,6 +36,32 @@ public static Bundle GetCovid19FhirBundleExample1()
3636
return Bundle;
3737
}
3838

39+
public static Bundle GetCovid19NotDetectedFhirBundleExample()
40+
{
41+
Patient PatientResource = GetPatientResource("Coyote", "Wile E", new DateTime(1973, 09, 30), "61481059995");
42+
43+
Coding Code = new Coding(system: "http://loinc.org", code: "94558-4"); //SARS-CoV-2 (COVID-19) Ag [Presence] in Respiratory specimen by Rapid immunoassay
44+
Coding Value = new Coding(system: "http://snomed.info/sct", code: "260415000"); //Not Detected
45+
Observation CovidResultObservationResource = GetObservationResource(
46+
ObsCode: Code,
47+
ObsValue: Value,
48+
EffectiveDate: new DateTime(2021, 05, 24),
49+
PerformerOrganisationName: "ACME Healthcare",
50+
IdentityAssuranceLevelCode: "IAL1.4");
51+
52+
List<Resource> BundleResourceList = new List<Resource>()
53+
{
54+
PatientResource,
55+
CovidResultObservationResource
56+
};
57+
58+
Bundle Bundle = new Bundle();
59+
Bundle.Type = Bundle.BundleType.Collection;
60+
Bundle.Entry = GetBundleResourceEntryList(BundleResourceList);
61+
62+
return Bundle;
63+
}
64+
3965
private static Patient GetPatientResource(string FamilyName, string GivenName, DateTime DateOfBirth, string PhoneNumber)
4066
{
4167
Patient Patient = new Patient();
@@ -77,7 +103,7 @@ private static Observation GetObservationResource(Coding ObsCode, Coding ObsValu
77103
{
78104
Coding = new List<Coding>()
79105
{
80-
new Coding(system: "http://loinc.org", code: "94558-4")
106+
ObsCode
81107
}
82108
};
83109

@@ -86,7 +112,7 @@ private static Observation GetObservationResource(Coding ObsCode, Coding ObsValu
86112
{
87113
Coding = new List<Coding>()
88114
{
89-
new Coding(system: "http://snomed.info/sct", code: "260373001")
115+
ObsValue
90116
}
91117
};
92118
Observation.Performer = new List<ResourceReference>()

SmartHealthCard.Test/ResourceData.Designer.cs

Lines changed: 30 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

SmartHealthCard.Test/ResourceData.resx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,16 @@
118118
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
119119
</resheader>
120120
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
121+
<data name="InvalidJwks" type="System.Resources.ResXFileRef, System.Windows.Forms">
122+
<value>Resources\InvalidJwks.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
123+
</data>
121124
<data name="SmartHealthCardCovidExample" type="System.Resources.ResXFileRef, System.Windows.Forms">
122125
<value>Resources\SmartHealthCardCovidExample.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
123126
</data>
127+
<data name="TestECC256Cert" type="System.Resources.ResXFileRef, System.Windows.Forms">
128+
<value>Resources\TestECC256Cert.pem;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
129+
</data>
130+
<data name="TestECC256Private_key" type="System.Resources.ResXFileRef, System.Windows.Forms">
131+
<value>Resources\TestECC256Private-key.pem;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
132+
</data>
124133
</root>

0 commit comments

Comments
 (0)