Ultimate Javascript Object Signing and Encryption (JOSE), JSON Web Token (JWT), JSON Web Encryption (JWE) and JSON Web Keys (JWK) Implementation for .NET and .NET Core
Minimallistic zero-dependency library for generating, decoding and encryption JSON Web Tokens. Supports full suite of JSON Web Algorithms and Json Web Keys. JSON parsing agnostic, can plug any desired JSON processing library. Extensively tested for compatibility with jose.4.j, Nimbus-JOSE-JWT and json-jwt libraries. JWE JSON Serialization cross-tested with JWCrypto.
Library is fully FIPS compliant since v2.1
-
v5.0 brings Linux, OSX and FreeBSD compatibility for ECDH encryption as long as managed
ECDsa
keys support. Fixes cross compatibility issues with encryption over NIST P-384, P-521 curves. And introduces new security fixes and controls. -
v4.1 added additional capabilities to manage runtime avaliable alg suite, see Customizing library for security. And also introduced default max limits for
PBKDF2
(PBES2-*
) max iterations according to OWASP PBKDF2 Recomendations. -
v4.0 introduced Json Web Key (JWK), RFC 7517 support. Latest stable. All new features will most likely appear based on given version.
-
v3.2 dropped
Newtonsoft.Json
support in favor ofSystem.Text.Json
onnetstandard2.1
-
v3.1 introduced JWE JSON Serialization defined in RFC 7516
-
v3.0 and above additionally targets
netstandard2.1
to leverage better .net crypto support on *nix systems and enable more supported algorithms. -
v2.1 and above added extra features support for .NET461+ and coming with 3 version of binaries (
NET4
,NET461
andnetstandard1.4
). -
v2.0 and above is .NET Core compatible and aimed to support both .NET framework (
NET40
) and .NET Core (netstandard1.4
) runtimes. -
v1.9 is built against .NET framework only and should be compatible with
NET40
and above. The version is not actively maintained anymore except critical bug fixes. -
WinRT compatible version (Windows 8.1 and Windows Phone 8.1) is avaliable as standalone project here: jose-rt.
-
PCLCrypto based experimental project living up here: jose-pcl.
⚠️ v4 -> v5:
- JWK EC keys now bridges to
ECDsa
by default instead ofCngKey
on .net 4.7.2+ and netstandard2.1+Jwk.ToJson()
/Jwk.FromJson()
now defaults toJWT.DefaultSettings.JsonMapper
if not provided explicitly.- Deflate decompression is limited to 250Kb by default. Check out customization section if need more.
⚠️ v3.0 -> v3.1 stricter argument validation extraHeaders argumentIn 3.1 and above an attempt to override
enc
oralg
header values inextraHeaders
will throwArgumentException
.
⚠️ v2 -> v3 update public sdk changesMoved:
Security.Cryptography.EccKey
toJose.keys.EccKey
Security.Cryptography.RsaKey
toJose.keys.RsaKey
.Net version | Windows | Linux | Mac OS | FreeBSD v14 |
---|---|---|---|---|
netcoreapp2.1 | ✅ | ✅ | ||
netcoreapp3.1 | ✅ | ✅ | ✅ | |
net 8.0 | ✅ | ✅ | ✅ | ✅ |
net 5.0 | ✅ | ✅ | ✅ | |
net 4.7 | ✅ | |||
net 4.6 | ✅ | |||
net 4.0 | ✅ |
Originally forked from https://github.com/johnsheehan/jwt . Almost re-written from scratch to support JWT encryption capabilities and unified interface for encoding/decoding/encryption and other features. Moved to separate project in February 2014.
AES Key Wrap implementation ideas and test data from http://www.cryptofreak.org/projects/rfc3394/ by Jay Miller
Signing
- HMAC signatures with HS256, HS384 and HS512.
- ECDSA signatures with ES256, ES384 and ES512.
- RSASSA-PKCS1-V1_5 signatures with RS256, RS384 and RS512.
- RSASSA-PSS signatures (probabilistic signature scheme with appendix) with PS256, PS384 and PS512.
- NONE (unprotected) plain text algorithm without integrity protection
Encryption
- RSAES OAEP 256 (using SHA-256 and MGF1 with SHA-256) encryption with A128CBC-HS256, A192CBC-HS384, A256CBC-HS512, A128GCM, A192GCM, A256GCM
- RSAES OAEP (using SHA-1 and MGF1 with SHA-1) encryption with A128CBC-HS256, A192CBC-HS384, A256CBC-HS512, A128GCM, A192GCM, A256GCM
- RSAES-PKCS1-V1_5 encryption with A128CBC-HS256, A192CBC-HS384, A256CBC-HS512, A128GCM, A192GCM, A256GCM
- Direct symmetric key encryption with pre-shared key A128CBC-HS256, A192CBC-HS384, A256CBC-HS512, A128GCM, A192GCM and A256GCM
- A128KW, A192KW, A256KW encryption with A128CBC-HS256, A192CBC-HS384, A256CBC-HS512, A128GCM, A192GCM, A256GCM
- A128GCMKW, A192GCMKW, A256GCMKW encryption with A128CBC-HS256, A192CBC-HS384, A256CBC-HS512, A128GCM, A192GCM, A256GCM
- ECDH-ES* with A128CBC-HS256, A128GCM, A192GCM, A256GCM
- ECDH-ES+A128KW*, ECDH-ES+A192KW*, ECDH-ES+A256KW* with A128CBC-HS256, A128GCM, A192GCM, A256GCM
- PBES2-HS256+A128KW, PBES2-HS384+A192KW, PBES2-HS512+A256KW with A128CBC-HS256, A192CBC-HS384, A256CBC-HS512, A128GCM, A192GCM, A256GCM
Compression
- DEFLATE compression
Signing
- HMAC signatures with HS256, HS384 and HS512.
- ECDSA signatures with ES256, ES384 and ES512.
- RSASSA-PKCS1-V1_5 signatures with RS256, RS384 and RS512.
- NONE (unprotected) plain text algorithm without integrity protection
Encryption
- RSAES OAEP 256 (using SHA-256 and MGF1 with SHA-256) encryption with A128CBC-HS256, A192CBC-HS384, A256CBC-HS512, A128GCM, A192GCM, A256GCM
- RSAES OAEP (using SHA-1 and MGF1 with SHA-1) encryption with A128CBC-HS256, A192CBC-HS384, A256CBC-HS512, A128GCM, A192GCM, A256GCM
- RSAES-PKCS1-V1_5 encryption with A128CBC-HS256, A192CBC-HS384, A256CBC-HS512, A128GCM, A192GCM, A256GCM
- Direct symmetric key encryption with pre-shared key A128CBC-HS256, A192CBC-HS384, A256CBC-HS512, A128GCM, A192GCM and A256GCM
- A128KW, A192KW, A256KW encryption with A128CBC-HS256, A192CBC-HS384, A256CBC-HS512, A128GCM, A192GCM, A256GCM
- A128GCMKW, A192GCMKW, A256GCMKW encryption with A128CBC-HS256, A192CBC-HS384, A256CBC-HS512, A128GCM, A192GCM, A256GCM
- PBES2-HS256+A128KW, PBES2-HS384+A192KW, PBES2-HS512+A256KW with A128CBC-HS256, A192CBC-HS384, A256CBC-HS512, A128GCM, A192GCM, A256GCM
- ECDH-ES* with A128CBC-HS256, A128GCM, A192GCM, A256GCM
- ECDH-ES+A128KW*, ECDH-ES+A192KW*, ECDH-ES+A256KW* with A128CBC-HS256, A128GCM, A192GCM, A256GCM
Compression
- DEFLATE compression
- RSA, EC, Oct keys
- X509 Chains, SHA1 & SHA2 thumbprints
- Types returned by crytographic methods MAY be different on Windows and Linux. e.g. GetRSAPrivateKey() on X509Certificate2 on Windows returns RsaCng and OpenSslRsa on *nix.
- It appears that Microsoft CNG implementation of BCryptSecretAgreement/NCryptSecretAgreement contains a bug for calculating Elliptic Curve Diffie-Hellman secret agreement
on keys higher than 256 bit (P-384 and P-521 NIST curves correspondingly). At least produced secret agreements do not match any other implementation in different languages. Starting version 5 we not recommending usage of
CngKey
keys with ECDH-ES family due to cross compatibility with other libraries. Please switch to useECDsa
,ECDiffieHellman
orJWK
instead, which are cross compatible on all curves and operating systems.
https://www.nuget.org/packages/jose-jwt/
Install-Package jose-jwt
Grab source and compile yourself:
dotnet restore
dotnet pack -c Release
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x@contoso.com" },
{ "exp", 1300819380 }
};
string token = Jose.JWT.Encode(payload, null, JwsAlgorithm.none);
Warning: When using a class
as the data structure of the payload, always use nullable data types for its properties. details
HS256, HS384, HS512 signatures require byte[]
array key or Jwk
key of type oct
of corresponding length
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x@contoso.com" },
{ "exp", 1300819380 }
};
var secretKey = new byte[]{164,60,194,0,161,189,41,38,130,89,141,164,45,170,159,209,69,137,243,216,191,131,47,250,32,107,231,117,37,158,225,234};
string token=Jose.JWT.Encode(payload, secretKey, JwsAlgorithm.HS256);
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x@contoso.com" },
{ "exp", 1300819380 }
};
Jwk key = new Jwk(new byte[]{164,60,194,0,161,189,41,38,130,89,141,164,45,170,159,209,69,137,243,216,191,131,47,250,32,107,231,117,37,158,225,234});
string token=Jose.JWT.Encode(payload, key, JwsAlgorithm.HS256);
NET40-NET45:
RS256, RS384, RS512 and PS256, PS384, PS512 signatures require RSACryptoServiceProvider
(usually private) key of corresponding length. CSP need to be forced to use Microsoft Enhanced RSA and AES Cryptographic Provider.
Which usually can be done be re-importing RSAParameters. See http://clrsecurity.codeplex.com/discussions/243156 for details.
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x@contoso.com" },
{ "exp", 1300819380 }
};
var privateKey=new X509Certificate2("my-key.p12", "password", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet).PrivateKey as RSACryptoServiceProvider;
string token=Jose.JWT.Encode(payload, privateKey, JwsAlgorithm.RS256);
NETCORE:
RS256, RS384, RS512 and PS256, PS384, PS512 signatures require RSA
(usually private) or Jwk
key of type RSA
of corresponding length.
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x@contoso.com" },
{ "exp", 1300819380 }
};
var privateKey=new X509Certificate2("my-key.p12", "password").GetRSAPrivateKey();
string token=Jose.JWT.Encode(payload, privateKey, JwsAlgorithm.RS256);
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x@contoso.com" },
{ "exp", 1300819380 }
};
Jwk privateKey = new Jwk(
e: "AQAB",
n: "qFZv0pea_jn5Mo4qEUmStuhlulso8n1inXbEotd_zTrQp9K0RK0hf7t0K4BjKVhaiqIam4tVVQvkmYeBeYr1MmnO_0N97dMBz_7fmvyv0hgHaBdQ5mR5u3LTlHo8tjRE7-GzZmGs6jMcyj7HbXobDPQJZpqNy6JjliDVXxW8nWJDetxGBlqmTj1E1fr2RCsZLreDOPSDIedG1upz9RraShsIDzeefOcKibcAaKeeVI3rkAU8_mOauLSXv37hlk0h6sStJb3qZQXyOUkVkjXIkhvNu_ve0v7LiLT4G_OxYGzpOQcCnimKdojzNP6GtVDaMPh-QkSJE32UCos9R3wI2Q",
p: "0qaOkT174vRG3E_67gU3lgOgoT6L3pVHuu7wfrIEoxycPa5_mZVG54SgvQUofGUYEGjR0lavUAjClw9tOzcODHX8RAxkuDntAFntBxgRM-IzAy8QzeRl_cbhgVjBTAhBcxg-3VySv5GdxFyrQaIo8Oy_PPI1L4EFKZHmicBd3ts",
q: "zJPqCDKqaJH9TAGfzt6b4aNt9fpirEcdpAF1bCedFfQmUZM0LG3rMtOAIhjEXgADt5GB8ZNK3BQl8BJyMmKs57oKmbVcODERCtPqjECXXsxH-az9nzxatPvcb7imFW8OlWslwr4IIRKdEjzEYs4syQJz7k2ktqOpYI5_UfYnw1s",
d: "lJhwb0pKlB2ivyDFO6thajotClrMA3nxIiSkIUbvVr-TToFtha36gyF6w6e6YNXQXs4HhMRy1_b-nRQDk8G4_f5urd_q-pOn5u4KfmqN3Xw-lYD3ddi9qF0NLeTVUNVFASeP0FFqbPYfdNwD-LyvwjhtT_ggMOAw3mYvU5cBfz6-3uPdhl3CwQFCTgwOud_BA9p2MPMUHG82wMK_sNO1I0TYpjm7TnwNBwiKbMf-i5CKnuohgoYrEDYLeMg3f32eBljlCFNYaoCtT-mr1Ze0OTJND04vbfLotV-BBKulIpbOOSeVpKG7gJxZHmv7in7PE5_WzaxKFVoHW3wR6v_GzQ",
dp: "KTWmTGmf092AA1euOmRQ5IsfIIxQ5qGDn-FgsRh4acSOGE8L7WrTrTU4EOJyciuA0qz-50xIDbs4_j5pWx1BJVTrnhBin9vNLrVo9mtR6jmFS0ko226kOUpwEVLgtdQjobWLjtiuaMW-_Iw4gKWNptxZ6T1lBD8UWHaPiEFW2-M",
dq: "Jn0lqMkvemENEMG1eUw0c601wPOMoPD4SKTlnKWPTlQS6YISbNF5UKSuFLwoJa9HA8BifDrD-Mfpo1M1HPmnoilEWUrfwMqqdCkOlbiJQhKY8AZ16QGH50kDXhmVVa8BRWdVQWBTUzWXS5kXMaeskVzextTgymPcOAhXN-ph7MU",
qi: "sRAPigJpl8S_vsf1zhJTrHM97xRwuB26R6Tm-J8sKRPb7p5xxNlmOBBFvWmWxdto8dBElNlydSZan373yBLxzW-bZgVp-B2RKT1B3WhTYW_Vo5DLhWi84XMncJxH7avtxtF9yksaeKe0e2n3J6TTan53mDg4KF8U0OEO2ciqO9g"
);
string token=Jose.JWT.Encode(payload, privateKey, JwsAlgorithm.RS256);
NET461 and above:
Accepts RSACryptoServiceProvider
, RSA
or Jwk
types of keys (see above).
NET40-NET45:
ES256, ES384, ES512 ECDSA signatures requires CngKey
(usually private) elliptic curve key of corresponding length. Normally existing CngKey
loaded via CngKey.Open(..)
method from Key Storage Provider.
But if you want to use raw key material (x,y) and d, jose-jwt provides convenient helper EccKey.New(x,y,d)
.
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x@contoso.com" },
{ "exp", 1300819380 }
};
byte[] x = { 4, 114, 29, 223, 58, 3, 191, 170, 67, 128, 229, 33, 242, 178, 157, 150, 133, 25, 209, 139, 166, 69, 55, 26, 84, 48, 169, 165, 67, 232, 98, 9 };
byte[] y = { 131, 116, 8, 14, 22, 150, 18, 75, 24, 181, 159, 78, 90, 51, 71, 159, 214, 186, 250, 47, 207, 246, 142, 127, 54, 183, 72, 72, 253, 21, 88, 53 };
byte[] d = { 42, 148, 231, 48, 225, 196, 166, 201, 23, 190, 229, 199, 20, 39, 226, 70, 209, 148, 29, 70, 125, 14, 174, 66, 9, 198, 80, 251, 95, 107, 98, 206 };
var privateKey=EccKey.New(x, y, d);
string token=Jose.JWT.Encode(payload, privateKey, JwsAlgorithm.ES256);
NETCORE:
ES256, ES384, ES512 ECDSA signatures can accept either CngKey
(see above), ECDsa
(usually private) or Jwk
of type EC
elliptic curve key of corresponding length.
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x@contoso.com" },
{ "exp", 1300819380 }
};
var privateKey=new X509Certificate2("ecc-key.p12", "password").GetECDsaPrivateKey();
string token=Jose.JWT.Encode(payload, privateKey, JwsAlgorithm.ES256);
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x@contoso.com" },
{ "exp", 1300819380 }
};
var privateKey = new Jwk(
crv: "P-256",
x: "BHId3zoDv6pDgOUh8rKdloUZ0YumRTcaVDCppUPoYgk",
y: "g3QIDhaWEksYtZ9OWjNHn9a6-i_P9o5_NrdISP0VWDU",
d: "KpTnMOHEpskXvuXHFCfiRtGUHUZ9Dq5CCcZQ-19rYs4"
);
string token=Jose.JWT.Encode(payload, privateKey, JwsAlgorithm.ES256);
NET461 and above:
Accepts CngKey
, ECDsa
and Jwk
types of keys (see above).
NET40-NET45:
RSA-OAEP-256, RSA-OAEP and RSA1_5 key management requires RSACryptoServiceProvider
(usually public) key of corresponding length.
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x@contoso.com" },
{ "exp", 1300819380 }
};
var publicKey=new X509Certificate2("my-key.p12", "password").PublicKey.Key as RSACryptoServiceProvider;
string token = Jose.JWT.Encode(payload, publicKey, JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM);
NETCORE:
RSA-OAEP-256, RSA-OAEP and RSA1_5 key management requires RSA
(usually public) or Jwk
key of type RSA
of corresponding length.
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x@contoso.com" },
{ "exp", 1300819380 }
};
var publicKey=new X509Certificate2("my-key.p12", "password").GetRSAPublicKey();
string token = Jose.JWT.Encode(payload, publicKey, JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM);
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x@contoso.com" },
{ "exp", 1300819380 }
};
Jwk publicKey = new Jwk("AQAB", "qFZv0pea_jn5Mo4qEUmStuhlulso8n1inXbEotd_zTrQp9K0RK0hf7t0K4BjKVhaiqIam4tVVQvkmYeBeYr1MmnO_0N97dMBz_7fmvyv0hgHaBdQ5mR5u3LTlHo8tjRE7-GzZmGs6jMcyj7HbXobDPQJZpqNy6JjliDVXxW8nWJDetxGBlqmTj1E1fr2RCsZLreDOPSDIedG1upz9RraShsIDzeefOcKibcAaKeeVI3rkAU8_mOauLSXv37hlk0h6sStJb3qZQXyOUkVkjXIkhvNu_ve0v7LiLT4G_OxYGzpOQcCnimKdojzNP6GtVDaMPh-QkSJE32UCos9R3wI2Q");
string token = Jose.JWT.Encode(payload, publicKey, JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM);
NET461:
Accepts RSACryptoServiceProvider
, RSA
, Jwk
(see above) and CngKey
types of keys.
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x@contoso.com" },
{ "exp", 1300819380 }
};
CngKey publicKey = CngKey.Open("connectionKeyId", CngProvider.MicrosoftSoftwareKeyStorageProvider, CngKeyOpenOptions.MachineKey));
string token = Jose.JWT.Encode(payload, publicKey, JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM);
Direct key management with pre-shared symmetric keys requires byte[]
array or Jwk
of type oct
key of corresponding length
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x@contoso.com" },
{ "exp", 1300819380 }
};
var secretKey = new byte[]{164,60,194,0,161,189,41,38,130,89,141,164,45,170,159,209,69,137,243,216,191,131,47,250,32,107,231,117,37,158,225,234};
string token = Jose.JWT.Encode(payload, secretKey, JweAlgorithm.DIR, JweEncryption.A128CBC_HS256);
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x@contoso.com" },
{ "exp", 1300819380 }
};
var secretKey = new Jwk(new byte[]{164,60,194,0,161,189,41,38,130,89,141,164,45,170,159,209,69,137,243,216,191,131,47,250,32,107,231,117,37,158,225,234});
string token = Jose.JWT.Encode(payload, secretKey, JweAlgorithm.DIR, JweEncryption.A128CBC_HS256);
AES128KW, AES192KW and AES256KW key management requires byte[]
array or Jwk
of type oct
key of corresponding length
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x@contoso.com" },
{ "exp", 1300819380 }
};
var secretKey = new byte[]{164,60,194,0,161,189,41,38,130,89,141,164,45,170,159,209,69,137,243,216,191,131,47,250,32,107,231,117,37,158,225,234};
string token = Jose.JWT.Encode(payload, secretKey, JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512);
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x@contoso.com" },
{ "exp", 1300819380 }
};
var secretKey = new Jwk(new byte[]{164,60,194,0,161,189,41,38,130,89,141,164,45,170,159,209,69,137,243,216,191,131,47,250,32,107,231,117,37,158,225,234});
string token = Jose.JWT.Encode(payload, secretKey, JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512);
AES128GCMKW, AES192GCMKW and AES256GCMKW key management requires byte[]
array or Jwk
of type oct
key of corresponding length
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x@contoso.com" },
{ "exp", 1300819380 }
};
var secretKey = new byte[]{164,60,194,0,161,189,41,38,130,89,141,164,45,170,159,209,69,137,243,216,191,131,47,250,32,107,231,117,37,158,225,234};
string token = Jose.JWT.Encode(payload, secretKey, JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512);
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x@contoso.com" },
{ "exp", 1300819380 }
};
var secretKey = new Jwk(new byte[]{164,60,194,0,161,189,41,38,130,89,141,164,45,170,159,209,69,137,243,216,191,131,47,250,32,107,231,117,37,158,225,234});
string token = Jose.JWT.Encode(payload, secretKey, JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512);
NET40-NET46 (windows only):
ECDH-ES and ECDH-ES+A128KW, ECDH-ES+A192KW, ECDH-ES+A256KW key management requires CngKey
(usually public) or Jwk
of type EC
elliptic curve key of corresponding length.
Normally existing CngKey
can be loaded via CngKey.Open(..)
method from Key Storage Provider.
But if you want to use raw key material (x,y) and d, jose-jwt provides convenient helper EccKey.New(x,y,usage:CngKeyUsages.KeyAgreement)
or use Jwk
instead.
Jwk
keys will use transparent bridging to CngKey
under the hood.
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x@contoso.com" },
{ "exp", 1300819380 }
};
byte[] x = { 4, 114, 29, 223, 58, 3, 191, 170, 67, 128, 229, 33, 242, 178, 157, 150, 133, 25, 209, 139, 166, 69, 55, 26, 84, 48, 169, 165, 67, 232, 98, 9 };
byte[] y = { 131, 116, 8, 14, 22, 150, 18, 75, 24, 181, 159, 78, 90, 51, 71, 159, 214, 186, 250, 47, 207, 246, 142, 127, 54, 183, 72, 72, 253, 21, 88, 53 };
var publicKey=EccKey.New(x, y, usage:CngKeyUsages.KeyAgreement);
string token = Jose.JWT.Encode(payload, publicKey, JweAlgorithm.ECDH_ES, JweEncryption.A256GCM);
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x@contoso.com" },
{ "exp", 1300819380 }
};
var publicKey = new Jwk(
crv: "P-256",
x: "BHId3zoDv6pDgOUh8rKdloUZ0YumRTcaVDCppUPoYgk",
y: "g3QIDhaWEksYtZ9OWjNHn9a6-i_P9o5_NrdISP0VWDU"
);
string token = Jose.JWT.Encode(payload, publicKey, JweAlgorithm.ECDH_ES, JweEncryption.A256GCM);
NET472 or NETCORE (all OS):
Accepts either CngKey
, Jwk
of type EC (see above) or additionally ECDsa
and ECDiffieHellman
as a key.
Jwk
keys will use transparent bridging to ECDiffieHellman
under the hood.
jose-jwt
provides convenient helper EcdhKey.New(x,y,usage:CngKeyUsages.KeyAgreement)
if one want to to constuct ECDiffieHellman
using raw key material (x,y) and d.
ECDsa
keys usually loaded from files.
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x@contoso.com" },
{ "exp", 1300819380 }
};
ECDsa publicKey = new X509Certificate2("ecc384.p12", "<password>").GetECDsaPublicKey();
string token = Jose.JWT.Encode(payload, publicKey, JweAlgorithm.ECDH_ES_A192KW, JweEncryption.A192GCM);
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x@contoso.com" },
{ "exp", 1300819380 }
};
byte[] x = { 4, 114, 29, 223, 58, 3, 191, 170, 67, 128, 229, 33, 242, 178, 157, 150, 133, 25, 209, 139, 166, 69, 55, 26, 84, 48, 169, 165, 67, 232, 98, 9 };
byte[] y = { 131, 116, 8, 14, 22, 150, 18, 75, 24, 181, 159, 78, 90, 51, 71, 159, 214, 186, 250, 47, 207, 246, 142, 127, 54, 183, 72, 72, 253, 21, 88, 53 };
ECDiffieHellman publicKey=EcdhKey.New(x, y, usage:CngKeyUsages.KeyAgreement);
string token = Jose.JWT.Encode(payload, publicKey, JweAlgorithm.ECDH_ES_A128KW, JweEncryption.A128GCM);
PBES2-HS256+A128KW, PBES2-HS384+A192KW, PBES2-HS512+A256KW key management requires string
passphrase to derive key from
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x@contoso.com" },
{ "exp", 1300819380 }
};
string token = Jose.JWT.Encode(payload, "top secret", JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512);
Iteration counts can be controlled by setting p2c
header value:
var headers = new Dictionary<string, object>
{
{ "p2c", 10000 }
};
string token = Jose.JWT.Encode(payload, "top secret", JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512, extraHeaders: headers);
Please see Adding extra headers for additional details.
Optional DEFLATE compression is supported
var payload = new Dictionary<string, object>()
{
{ "sub"<