Getting Started with IPWorks Auth JWT

Requirements: IPWorks Auth

Introduction

The JWT component supports signing, encrypting, decrypting and verifying JSON Web Tokens (JWTs).

Specify a set of claims via the Claim* properties or add your own claims with AddClaim. Call Sign to create a signed JWT using a variety of signing algorithms including HMAC, RSA, and ECDSA. Use Verify to verify the signature of any received JWT. See the algorithm notes sections below for more details about specific algorithms.

Use Encrypt to create an encrypted JWT using a variety of algorithms including ECDH, RSA, and AES. Use Decrypt to decrypt the payload of any received JWT. See the algorithm notes sections below for more details about specific algorithms.

Contents

Signing

The Sign method may be used to sign a payload with a variety of algorithms. Before calling the Sign method set SigningAlgorithm to the algorithm which will be used to sign the message. The result of signing is a compact serialized JWT string. For instance:

eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOlsiYXVkaWVuY2UiXSwiaXNzIjoiaXNzdWVyIn0.mlFETSma4WUcUSjNSUWA1n9QBcQHCkHN-y4zeBsCVqI

The component will use the values present in the Claim* properties to build the encoded JWT. After calling this method the EncodedJWT property will hold the compact serialized JWT. The following properties are applicable when calling this method:

  • SigningAlgorithm (required)
  • Certificate (conditional - required for ECDSA and RSA)
  • Key (conditional - required for HMAC)
  • ClaimAudience
  • ClaimExp
  • ClaimIssuedAt
  • ClaimIssuer
  • ClaimJWTId
  • ClaimNotBefore
  • Claims
  • HeaderParams
  • KeyId

Notes for HMAC Algorithms (HS256, HS384, HS512)

When SigningAlgorithm is set to a HMAC algorithm, Key must be set to a key of appropriate length for the algorithm. The key should be the same number of bits as the algorithm being used. For instance a 256 bit key would be used for HS256.

The key must be known by both parties in order for signing and verification to take place. To use an existing HMAC key provide the bytes to the Key property. For instance:

//HMAC SHA-256 Key
byte[] key = new byte[] { 170, 171, 221, 209, 7, 181, 48, 178, 48, 118, 242, 132, 36, 218, 74, 140, 216, 165, 161, 70, 11, 42, 246, 205, 235, 231, 19, 48, 87, 141, 122, 10 };

//Sign the payload using HS256
Jwt jwt = new Jwt();
jwt.SigningAlgorithm = JwtSigningAlgorithms.saHS256;
jwt.ClaimAudience = "audience";
jwt.ClaimIssuer = "issuer";
jwt.ClaimExp = "1498508071";
jwt.KeyB = key;
jwt.Sign();

string signedData = jwt.EncodedJWT;

Notes for RSA Algorithms (RS256, RS384, RS512, PS256, PS384, PS512)

The RSA based algorithms use asymmetric encryption. Signing is done with a private key and verification is done with a public key. The private key may be in PFX or PEM format. For instance:

Jwt jwt = new Jwt();
jwt.SigningAlgorithm = JwtSigningAlgorithms.saRS256;
jwt.Certificate = new Certificate(CertStoreTypes.cstPFXFile, "..\\jwt.pfx", "test", "*");
jwt.ClaimAudience = "audience";
jwt.ClaimIssuer = "issuer";
jwt.ClaimExp = "1498508071";
jwt.Sign();

string signedMessage = jwt.EncodedJWT;

Notes for ECDSA Algorithms (ES256, ES384, ES512)

ECDSA algorithms require a valid ECC private key to sign. The ECC component can be used to create or import an ECC key into the Certificate format accepted by the JWS component. For instance:

//Create an ECC key with SHA-256
nsoftware.IPWorksEncrypt.Ecc ecc = new nsoftware.IPWorksEncrypt.Ecc();
ecc.HashAlgorithm = nsoftware.IPWorksEncrypt.EccHashAlgorithms.ehaSHA256;
ecc.CreateKey();

string privKey = ecc.Key.PrivateKey;

//Sign the payload using ES256
Jwt jwt = new Jwt();
jwt.SigningAlgorithm = JwtSigningAlgorithms.saES256;
jwt.Certificate = new Certificate(CertStoreTypes.cstPEMKeyBlob, privKey, "", "*");
jwt.ClaimAudience = "audience";
jwt.ClaimIssuer = "issuer";
jwt.ClaimExp = "1498508071";
jwt.Sign();

string signedMessage = jwt.EncodedJWT;

To use an existing ECC Key populate the Rx, Ry, and K values of Key property in the ECC component first. For instance:

//Import an existing ECC private key
nsoftware.IPWorksEncrypt.Ecc ecc = new nsoftware.IPWorksEncrypt.Ecc();

byte[] x_bytes = new byte[] { 171, 170, 196, 151, 94, 196, 231, 12, 128, 232, 17, 61, 45, 105, 41, 209, 192, 187, 112, 242, 110, 178, 95, 240, 36, 55, 83, 171, 190, 176, 78, 13 };
byte[] y_bytes = new byte[] { 197, 75, 134, 245, 245, 28, 199, 9, 7, 117, 1, 54, 49, 178, 135, 252, 62, 89, 35, 180, 117, 80, 231, 23, 110, 250, 28, 124, 219, 253, 224, 156 };
byte[] k_bytes = new byte[] { 81, 65, 201, 24, 235, 249, 162, 148, 169, 150, 109, 181, 61, 238, 145, 122, 31, 30, 151, 94, 239, 90, 222, 217, 63, 103, 54, 2, 176, 232, 248, 168 };

ecc.Key.RxB = x_bytes;
ecc.Key.RyB = y_bytes;
ecc.Key.KB = k_bytes;

string privKey = ecc.Key.PrivateKey;

//Sign the payload using ES256
Jwt jwt = new Jwt();
jwt.SigningAlgorithm = JwtSigningAlgorithms.saES256;
jwt.Certificate = new Certificate(CertStoreTypes.cstPEMKeyBlob, privKey, "", "*");
jwt.ClaimAudience = "audience";
jwt.ClaimIssuer = "issuer";
jwt.ClaimExp = "1498508071";
jwt.Sign();

string signedMessage = jwt.EncodedJWT;

Notes for Unsecured (none)

To create a JWS token without any security set SigningAlgorithm to jwtNone. For instance:

Jwt jwt = new Jwt();
jwt.SigningAlgorithm = JwtSigningAlgorithms.saNone;
jwt.ClaimAudience = "audience";
jwt.ClaimIssuer = "issuer";
jwt.ClaimExp = "1498508071";
jwt.Sign();

string unsecuredMessage = jwt.EncodedJWT;

Verifying

The Verify method may be used to verify a received JWS message. Before calling the Verify method set EncodedJWT to a valid compact serialized JWT. For instance:

eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOlsiYXVkaWVuY2UiXSwiaXNzIjoiaXNzdWVyIn0.mlFETSma4WUcUSjNSUWA1n9QBcQHCkHN-y4zeBsCVqI

Key or SignerCert should be set to the HMAC key or public certificate respectively. If the correct Key or SignerCert is not known ahead of time the KeyId parameter of the SignerInfo event may be used to identify the correct key.

If this method returns without error verification was successful. If verification fails then this method fails with an error. After calling this method the claims will be parsed and the Claim* properties will be populated. The the HeaderParams property will contain the headers. Headers of the parsed message are also available through the HeaderParam event.

The following properties are applicable when calling this method:

  • EncodedJWT (required)
  • Key (conditional - required for HMAC)
  • SignerCert (conditional - required for ECDSA and RSA)
  • SigningAlgorithm (only if StrictValidation is True)
  • StrictValidation

After calling this method the following properties are populated:

  • ClaimAudience
  • ClaimExp
  • ClaimIssuedAt
  • ClaimIssuer
  • ClaimJWTId
  • ClaimNotBefore
  • Claims
  • ClaimSubject
  • HeaderParams

Notes for HMAC Algorithms (HS256, HS384, HS512)

When verifying a message originally signed with a HMAC algorithm Key must be set to the same key used during signing. The key must be known by both parties in order for signing and verification to take place. For instance:

byte[] key = new byte[] { 170, 171, 221, 209, 7, 181, 48, 178, 48, 118, 242, 132, 36, 218, 74, 140, 216, 165, 161, 70, 11, 42, 246, 205, 235, 231, 19, 48, 87, 141, 122, 10 };

Jwt jwt = new Jwt();
jwt.KeyB = key;
jwt.EncodedJWT = signedData;
jwt.Verify();

string issuer = jwt.ClaimIssuer;

Notes for RSA Algorithms (RS256, RS384, RS512, PS256, PS384, PS512)

The RSA based algorithms use asymmetric encryption. Signing is done with a private key and verification is done with a public key. The public key is typically in PEM format. For instance:

Jwt jwt = new Jwt();
jwt.SignerCert = new Certificate("..\\jwt.cer"); 
jwt.EncodedJWT = signedData;
jwt.Verify();

string issuer = jwt.ClaimIssuer;

Notes for ECDSA Algorithms (ES256, ES384, ES512)

ECDSA algorithms require a valid ECC public key to verify the message. If the key was originally created with the ECC component the PEM encoded PublicKey may be used directly with the Certificate property. An example PEM encoded public certificate created by the ECC component:

-----BEGIN PUBLIC KEY-----
MIIBMjCB7AYHKoZIzj0CATCB4AIBATAsBgcqhkjOPQEBAiEA/////wAAAAEAAAAAAAAAAAAA
AAD///////////////8wRAQg/////wAAAAEAAAAAAAAAAAAAAAD///////////////wEIFrG
NdiqOpPns+u9VXaYhrxlHQawzFOw9jvOPD4n0mBLBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt
6zOg9KE5RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA
//////////+85vqtpxeehPO5ysL8YyVRAgEBA0EEIC5rbLp11Mnz6cBXLLriaDIov3rm8RAY
x/OR0bOKiff0cQy+sLVaxjseqFk/+Xvl4ORSv5Z6HdHv5GyEpA0UoA==
-----END PUBLIC KEY-----

The following is an example of verifying using a PEM public key:
Jwt jwt = new Jwt();
jwt.SignerCert = new Certificate(CertStoreTypes.cstPublicKeyFile, pubKey, "", "*");
jwt.EncodedJWT = signedData;
jwt.Verify();

string issuer = jwt.ClaimIssuer;

To use an ECC public key created by other means the ECC component may be used to import the key parameters. Populate the Rx and Ry of the ECC component first to obtain the PEM formatted public key. For instance:

The following is an example of verifying using existing public key parameters:
//Import an existing ECC public key
nsoftware.IPWorksEncrypt.Ecc ecc = new nsoftware.IPWorksEncrypt.Ecc();

byte[] x_bytes = new byte[] { 171, 170, 196, 151, 94, 196, 231, 12, 128, 232, 17, 61, 45, 105, 41, 209, 192, 187, 112, 242, 110, 178, 95, 240, 36, 55, 83, 171, 190, 176, 78, 13 };
byte[] y_bytes = new byte[] { 197, 75, 134, 245, 245, 28, 199, 9, 7, 117, 1, 54, 49, 178, 135, 252, 62, 89, 35, 180, 117, 80, 231, 23, 110, 250, 28, 124, 219, 253, 224, 156 };

ecc.Key.RxB = x_bytes;
ecc.Key.RyB = y_bytes;

string pubKey = ecc.Key.PublicKey;

Jwt jwt = new Jwt();
jwt.SignerCert = new Certificate(CertStoreTypes.cstPublicKeyFile, pubKey, "", "*");
jwt.EncodedJWT = signedData;
jwt.Verify();

string issuer = jwt.ClaimIssuer;

Notes for Unsecured (none)

To parse a JWS token without any security call the Verify method without setting Key or Certificate. For instance:

Jwt jwt = new Jwt();
jwt.EncodedJWT = signedData;
jwt.Verify();

string issuer = jwt.ClaimIssuer;

Encrypting

The Encrypt method may be used to encrypt a payload with a variety of algorithms. To create an encrypted JWT JSON Web Encryption (JWE) is performed by first generating a random key used to encrypt the content. The content encryption key is used to encrypt the content using the algorithm specified by ContentEncryptionAlgorithm. The content encryption key is then encrypted itself using the algorithm specified by EncryptionAlgorithm. The content encryption key is not directly exposed in the API as it is randomly generated.

After calling this method the compact serialized JWT is written to EncodedJWT. For instance:

eyJhbGciOiJBMjU2S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.4tcAnZJ00u4GY2kLOanPOL4CtvcfraZ8SIi6bOZ27qYBI2rHITPc1Q.c_9rCTdPn-saLCti2ZEyWQ.eLwqqo5BGNa70RlsvT-vTh7Gk0hjpJYY_9Zc39Vim_qEtjyMcxZygBpkfx9brzQr9rUbuiAhoCMXKip2-lKT6w.NkuLDPmWxWL4BaTWHWicIQ

The component will use the values present in the Claim* properties to build the encoded JWT. After calling this method the EncodedJWT property will hold the compact serialized JWT. The following properties are applicable when calling this method:

  • EncryptionAlgorithm (required)
  • Key (conditional - required for AES)
  • KeyPassword (conditional - required for PBES)
  • RecipientCert (conditional - required for ECDH and RSA)
  • ClaimAudience
  • ClaimExp
  • ClaimIssuedAt
  • ClaimIssuer
  • ClaimJWTId
  • ClaimNotBefore
  • Claims
  • CompressionAlgorithm
  • ContentEncryptionAlgorithm
  • HeaderParams
  • KeyId

Notes for AES Algorithms (A128KW, A192KW, A256KW, A128GCMKW, A192GCMKW, A256GCMKW)

When EncryptionAlgorithm is set to a AES algorithm Key must be set to a key of appropriate length for the algorithm. For instance a 256 bit key would be used for A256KW.

To use an existing AES key provide the bytes to the Key property. For instance:

byte[] key = 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 };

//Encrypt the payload using A256KW
Jwt jwt = new Jwt();
jwt.KeyB = key;
jwt.ClaimAudience = "audience";
jwt.ClaimIssuer = "issuer";
jwt.ClaimExp = "1498508071";
jwt.EncryptionAlgorithm = JwtEncryptionAlgorithms.eaA256KW;
jwt.Encrypt();

string encryptedData = jwt.EncodedJWT;

Notes for RSA Algorithms (RSA1_5, RSA-OEAP, RSA-OAEP-256)

The RSA based algorithms use asymmetric encryption. Encrypting is done with a public key and decryption is done with a private key. The public certificate should be in PEM (base64) format. For instance:

Jwt jwt = new Jwt();
jwt.Certificate = new Certificate("..\\recipient.cer");
jwt.ClaimAudience = "audience";
jwt.ClaimIssuer = "issuer";
jwt.ClaimExp = "1498508071";
jwt.EncryptionAlgorithm = JwtEncryptionAlgorithms.eaRSA_OAEP;
jwt.Encrypt();

string encryptedData = jwt.EncodedJWT;

Notes for ECDH Algorithms (ECDH-ES, ECDH-ES+A128KW, ECDH-ES+A192KW, ECDH-ES+A256KW)

ECDH algorithms require a valid ECC public key to encrypt the message. If the key was originally created with the ECC component the PEM encoded PublicKey may be used directly with the Certificate property. An example PEM encoded public certificate created by the ECC component:

-----BEGIN PUBLIC KEY-----
MIIBMjCB7AYHKoZIzj0CATCB4AIBATAsBgcqhkjOPQEBAiEA/////wAAAAEAAAAAAAAAAAAA
AAD///////////////8wRAQg/////wAAAAEAAAAAAAAAAAAAAAD///////////////wEIFrG
NdiqOpPns+u9VXaYhrxlHQawzFOw9jvOPD4n0mBLBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt
6zOg9KE5RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA
//////////+85vqtpxeehPO5ysL8YyVRAgEBA0EEIC5rbLp11Mnz6cBXLLriaDIov3rm8RAY
x/OR0bOKiff0cQy+sLVaxjseqFk/+Xvl4ORSv5Z6HdHv5GyEpA0UoA==
-----END PUBLIC KEY-----

The following is an example of encrypting using a public key file:
Jwt jwt = new Jwt();
jwt.Certificate = new Certificate(CertStoreTypes.cstPublicKeyFile, pubKeyFile, "", "*");
jwt.ClaimAudience = "audience";
jwt.ClaimIssuer = "issuer";
jwt.ClaimExp = "1498508071";
jwt.EncryptionAlgorithm = JwtEncryptionAlgorithms.eaECDH_ES_A256KW;
jwt.Encrypt();

string encryptedData = jwt.EncodedJWT;

To use an ECC public key created by other means the ECC component may be used to import the key parameters. Populate the Rx and Ry properties of the ECC component first to obtain the PEM formatted public key. For instance:

byte[] x_bytes = new byte[] { 171, 170, 196, 151, 94, 196, 231, 12, 128, 232, 17, 61, 45, 105, 41, 209, 192, 187, 112, 242, 110, 178, 95, 240, 36, 55, 83, 171, 190, 176, 78, 13 };
byte[] y_bytes = new byte[] { 197, 75, 134, 245, 245, 28, 199, 9, 7, 117, 1, 54, 49, 178, 135, 252, 62, 89, 35, 180, 117, 80, 231, 23, 110, 250, 28, 124, 219, 253, 224, 156 };

nsoftware.IPWorksEncrypt.Ecc ecc = new nsoftware.IPWorksEncrypt.Ecc();
ecc.Key.RxB = x_bytes;
ecc.Key.RyB = y_bytes;

string pubKey = ecc.Key.PublicKey;

Jwt jwt = new Jwt();
jwt.Certificate = new Certificate(CertStoreTypes.cstPublicKeyFile, pubKey, "", "*");
jwt.ClaimAudience = "audience";
jwt.ClaimIssuer = "issuer";
jwt.ClaimExp = "1498508071";
jwt.EncryptionAlgorithm = JwtEncryptionAlgorithms.eaECDH_ES_A256KW;
jwt.Encrypt();

string encryptedData = jwt.EncodedJWT;

Notes for PBES Algorithms (PBES2-HS256+A128KW, PBES2-HS384+A192KW, PBES2-HS512+A256KW

PBES algorithms derive a content encryption key from the KeyPassword property. Set KeyPassword to a shared secret. For instance:

Jwt jwt = new Jwt();
jwt.KeyPassword = "secret";
jwt.ClaimAudience = "audience";
jwt.ClaimIssuer = "issuer";
jwt.ClaimExp = "1498508071";
jwt.EncryptionAlgorithm = JwtEncryptionAlgorithms.eaPBES2_HS512_A256KW;
jwt.Encrypt();

string encryptedData = jwt.EncodedJWT;

Notes for Direct Shared Keys

When EncryptionAlgorithm is set to Direct the Key property must be set to a valid symmetric key that will be used directly by the ContentEncryptionAlgorithm. In this case a content encryption key is not generated randomly, the Key is used instead. The length of the specified Key must be valid for the selected ContentEncryptionAlgorithm. For instance:

byte[] key = new byte[] { 164, 62, 191, 60, 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 };

Jwt jwt = new Jwt();
jwt.EncryptionAlgorithm = JwtEncryptionAlgorithms.eaDir;
jwt.ContentEncryptionAlgorithm = JwtContentEncryptionAlgorithms.ceaA256GCM;
jwt.KeyB = key;
jwt.ClaimAudience = "audience";
jwt.ClaimIssuer = "issuer";
jwt.ClaimExp = "1498508071";
jwt.Encrypt();

string encryptedData = jwt.EncodedJWT;

Decrypting

The Decrypt method may be used to decrypt a received JWE message. Before calling the Decrypt method set EncodedJWT to a valid compact serialized JWT string. For instance:

eyJhbGciOiJBMjU2S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.4tcAnZJ00u4GY2kLOanPOL4CtvcfraZ8SIi6bOZ27qYBI2rHITPc1Q.c_9rCTdPn-saLCti2ZEyWQ.eLwqqo5BGNa70RlsvT-vTh7Gk0hjpJYY_9Zc39Vim_qEtjyMcxZygBpkfx9brzQr9rUbuiAhoCMXKip2-lKT6w.NkuLDPmWxWL4BaTWHWicIQ

The type and format of the private key depends on the algorithm used to encrypt the data. The following table summarizes the relationship:

Algorithm Private Key Location
AES Key
RSA and ECDH Certificate
PBES KeyPassword

If the correct Key or Certificate is not known ahead of time the KeyId parameter of the RecipientInfo event may be used to identify the correct key.

If this method returns without error decryption was successful. If decryption fails then this method fails with an error. After calling this method the payload will be present in the Claim* properties and the HeaderParams property will contain the headers. Headers of the parsed message are also available through the HeaderParam event.

The following properties are applicable when calling this method:

  • Certificate (conditional - required for RSA and ECDH)
  • EncodedJWT
  • Key (conditional - required for AES)
  • ContentEncryptionAlgorithm (only if StrictValidation is True)
  • EncryptionAlgorithm (only if StrictValidation is True)
  • HeaderParams
  • StrictValidation

After calling this method the following properties are populated:

  • ClaimAudience
  • ClaimExp
  • ClaimIssuedAt
  • ClaimIssuer
  • ClaimJWTId
  • ClaimNotBefore
  • Claims
  • ClaimSubject
  • HeaderParams

Notes for AES Algorithms (A128KW, A192KW, A256KW, A128GCMKW, A192GCMKW, A256GCMKW)

To decrypt messages that use AES encryption Key must be set to a key of appropriate length for the algorithm. For instance a 256 bit key would be used for A256KW. The key must be known by both parties in order for encryption and decryption to take place.

The following is an example of decrypting using an AES algorithm:
byte[] key = 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 };

Jwt jwt = new Jwt();
jwt.KeyB = key;
jwt.EncodedJWT = encryptedData;
jwt.Decrypt();

string issuer = jwt.ClaimIssuer;

Notes for RSA Algorithms (RSA1_5, RSA-OEAP, RSA-OAEP-256)

The RSA based algorithms use asymmetric encryption. Encrypting is done with a public key and decryption is done with a private key. The certificate with private key must be specified. For instance:

Jwt jwt = new Jwt();
jwt.Certificate = new Certificate(CertStoreTypes.cstPFXFile, "..\\jwt.pfx", "password", "*");
jwt.EncodedJWT = encryptedData;
jwt.Decrypt();

string issuer = jwt.ClaimIssuer;

Notes for ECDH Algorithms (ECDH-ES, ECDH-ES+A128KW, ECDH-ES+A192KW, ECDH-ES+A256KW)

ECDH algorithms require a valid ECC private key to decrypt the message. If the key was originally created with the ECC component the PEM encoded PrivateKey may be used directly with the Certificate property. For instance:

Jwt jwt = new Jwt();
jwt.Certificate = new Certificate(CertStoreTypes.cstPEMKeyFile, privKeyFile, "", "*");
jwt.EncodedJWT = encryptedData;
jwt.Decrypt();

string issuer = jwt.ClaimIssuer;

To use an ECC private key created by other means the ECC component may be used to import the key parameters. Populate the Rx, Ry, and KB properties of the ECC component first to obtain the PEM formatted public key. For instance:

nsoftware.IPWorksEncrypt.Ecc ecc = new nsoftware.IPWorksEncrypt.Ecc();

byte[] x_bytes = new byte[] { 171, 170, 196, 151, 94, 196, 231, 12, 128, 232, 17, 61, 45, 105, 41, 209, 192, 187, 112, 242, 110, 178, 95, 240, 36, 55, 83, 171, 190, 176, 78, 13 };
byte[] y_bytes = new byte[] { 197, 75, 134, 245, 245, 28, 199, 9, 7, 117, 1, 54, 49, 178, 135, 252, 62, 89, 35, 180, 117, 80, 231, 23, 110, 250, 28, 124, 219, 253, 224, 156 };
byte[] k_bytes = new byte[] { 81, 65, 201, 24, 235, 249, 162, 148, 169, 150, 109, 181, 61, 238, 145, 122, 31, 30, 151, 94, 239, 90, 222, 217, 63, 103, 54, 2, 176, 232, 248, 168 };

ecc.Key.RxB = x_bytes;
ecc.Key.RyB = y_bytes;
ecc.Key.KB = k_bytes;

string privKey = ecc.Key.PrivateKey;

Jwt jwt = new Jwt();
jwt.Certificate = new Certificate(CertStoreTypes.cstPEMKeyBlob, privKey, "", "*");
jwt.EncodedJWT = encryptedData;
jwt.Decrypt();

string issuer = jwt.ClaimIssuer;

Notes for PBES Algorithms (PBES2-HS256+A128KW, PBES2-HS384+A192KW, PBES2-HS512+A256KW

PBES algorithms derive a content encryption key from the KeyPassword property. Set KeyPassword to the shared secret. For instance:

Jwt jwt = new Jwt();
jwt.KeyPassword = "secret";
jwt.EncodedJWT = encryptedData;
jwt.Decrypt();

string issuer = jwt.ClaimIssuer;

Notes for Direct Shared Keys

When Direct encryption is used the Key property must be set to a valid symmetric key that will be used directly by the ContentEncryptionAlgorithm. For instance:

byte[] key = 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 };

Jwt jwt = new Jwt();
jwt.KeyB = key;
jwt.EncodedJWT = encryptedData;
jwt.Decrypt();

string issuer = jwt.ClaimIssuer;

Other Functionality

In addition to standard operations the component also supports a variety of other features including:

  • Adding custom header parameters with AddHeaderParam
  • Enforcing algorithm restrictions when verifying by setting StrictValidation
  • Inspect the JWT without verifying or decrypting by calling Parse


We appreciate your feedback.  If you have any questions, comments, or suggestions about this article please contact our support team at kb@nsoftware.com.