DataFlex
DataFlex
JWE Using General JWE JSON Serialization
See more JSON Web Encryption (JWE) Examples
This example duplicates the example A.4 in RFC 7516 for JSON Web Encryption (JWE).This example demonstrates the capability for encrypting the same plaintext to multiple recipients. Two recipients are present in this example.
Chilkat DataFlex Downloads
Use ChilkatAx-win32.pkg
Procedure Test
Boolean iSuccess
String sPlaintext
Handle hoJwe
Variant vJweProtHdr
Handle hoJweProtHdr
RecipientHdr1 Handle hoJweRecipientHdr1
Integer iRecipientIndex
Variant vJweRecipientHdr2
Handle hoJweRecipientHdr2
UnprotHdr Handle hoJweUnprotHdr
Handle hoSbJwk
Variant vRsaPrivKey
Handle hoRsaPrivKey
Variant vRsaPubKey
Handle hoRsaPubKey
String sAesWrappingKey
String sStrJwe
Handle hoJsonTemp
2 Handle hoJwe2
Boolean iCaseSensitive
String sOriginalPlaintext
Variant vSbJwe
Handle hoSbJwe
String sTemp1
Boolean bTemp1
Move False To iSuccess
// This requires the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
// Note: This example requires Chilkat v9.5.0.66 or greater.
Move "Live long and prosper." To sPlaintext
Get Create (RefClass(cComChilkatJwe)) To hoJwe
If (Not(IsComObjectCreated(hoJwe))) Begin
Send CreateComObject of hoJwe
End
// First build the JWE Protected Header: {"enc":"A128CBC-HS256"}
Get Create (RefClass(cComChilkatJsonObject)) To hoJweProtHdr
If (Not(IsComObjectCreated(hoJweProtHdr))) Begin
Send CreateComObject of hoJweProtHdr
End
Get ComAppendString Of hoJweProtHdr "enc" "A128CBC-HS256" To iSuccess
Get pvComObject of hoJweProtHdr to vJweProtHdr
Get ComSetProtectedHeader Of hoJwe vJweProtHdr To iSuccess
// The first recipient uses the RSAES-PKCS1-v1_5 algorithm to encrypt
// the CEK. The second uses AES Key Wrap to encrypt the CEK. Key ID
// values are supplied for both keys. The two JWE Per-Recipient
// Unprotected Header values used to represent these algorithms and key
// IDs are:
//
// {"alg":"RSA1_5","kid":"2011-04-29"}
//
// and
//
// {"alg":"A128KW","kid":"7"}
Get Create (RefClass(cComChilkatJsonObject)) To hoJweRecipientHdr1
If (Not(IsComObjectCreated(hoJweRecipientHdr1))) Begin
Send CreateComObject of hoJweRecipientHdr1
End
Get ComAppendString Of hoJweRecipientHdr1 "alg" "RSA1_5" To iSuccess
Get ComAppendString Of hoJweRecipientHdr1 "kid" "2011-04-29" To iSuccess
Move 0 To iRecipientIndex
Get pvComObject of hoJweRecipientHdr1 to vJweRecipientHdr1
Get ComSetRecipientHeader Of hoJwe iRecipientIndex vJweRecipientHdr1 To iSuccess
Get Create (RefClass(cComChilkatJsonObject)) To hoJweRecipientHdr2
If (Not(IsComObjectCreated(hoJweRecipientHdr2))) Begin
Send CreateComObject of hoJweRecipientHdr2
End
Get ComAppendString Of hoJweRecipientHdr2 "alg" "A128KW" To iSuccess
Get ComAppendString Of hoJweRecipientHdr2 "kid" "7" To iSuccess
Move 1 To iRecipientIndex
Get pvComObject of hoJweRecipientHdr2 to vJweRecipientHdr2
Get ComSetRecipientHeader Of hoJwe iRecipientIndex vJweRecipientHdr2 To iSuccess
// Set the Shared Unprotected Header: {"jku":"https://server.example.com/keys.jwks"}
Get Create (RefClass(cComChilkatJsonObject)) To hoJweUnprotHdr
If (Not(IsComObjectCreated(hoJweUnprotHdr))) Begin
Send CreateComObject of hoJweUnprotHdr
End
Get ComAppendString Of hoJweUnprotHdr "jku" "https://server.example.com/keys.jwks" To iSuccess
Get pvComObject of hoJweUnprotHdr to vJweUnprotHdr
Get ComSetUnprotectedHeader Of hoJwe vJweUnprotHdr To iSuccess
// Note: The intent of specifying a "kid" (an acronym for "Key ID") is that
// the software would somehow download the keys.jwks from https://server.example.com/keys.jwks,
// and would select the key (whatever format it may be, such as RSA, or an AES key wrap key, etc.),
// and then automatically use it.
// This example keeps the "kid" and "jku" in their respective headers, but does not actually fetch
// the keys from some URL. We'll just provide the keys directly..
// Recipient 0 uses this RSA key:
Get Create (RefClass(cComChilkatStringBuilder)) To hoSbJwk
If (Not(IsComObjectCreated(hoSbJwk))) Begin
Send CreateComObject of hoSbJwk
End
Get ComAppend Of hoSbJwk '{"kty":"RSA",' To iSuccess
Get ComAppend Of hoSbJwk '"n":"sXchDaQebHnPiGvyDOAT4saGEUetSyo9MKLOoWFsueri23bOdgWp4Dy1Wl' To iSuccess
Get ComAppend Of hoSbJwk "UzewbgBHod5pcM9H95GQRV3JDXboIRROSBigeC5yjU1hGzHHyXss8UDpre" To iSuccess
Get ComAppend Of hoSbJwk "cbAYxknTcQkhslANGRUZmdTOQ5qTRsLAt6BTYuyvVRdhS8exSZEy_c4gs_" To iSuccess
Get ComAppend Of hoSbJwk "7svlJJQ4H9_NxsiIoLwAEk7-Q3UXERGYw_75IDrGA84-lA_-Ct4eTlXHBI" To iSuccess
Get ComAppend Of hoSbJwk "Y2EaV7t7LjJaynVJCpkv4LKjTTAumiGUIuQhrNhZLuF_RJLqHpM2kgWFLU" To iSuccess
Get ComAppend Of hoSbJwk '7-VTdL1VbC2tejvcI2BlMkEpk1BzBZI0KQB0GaDWFLN-aEAw3vRw",' To iSuccess
Get ComAppend Of hoSbJwk '"e":"AQAB",' To iSuccess
Get ComAppend Of hoSbJwk '"d":"VFCWOqXr8nvZNyaaJLXdnNPXZKRaWCjkU5Q2egQQpTBMwhprMzWzpR8Sxq' To iSuccess
Get ComAppend Of hoSbJwk "1OPThh_J6MUD8Z35wky9b8eEO0pwNS8xlh1lOFRRBoNqDIKVOku0aZb-ry" To iSuccess
Get ComAppend Of hoSbJwk "nq8cxjDTLZQ6Fz7jSjR1Klop-YKaUHc9GsEofQqYruPhzSA-QgajZGPbE_" To iSuccess
Get ComAppend Of hoSbJwk "0ZaVDJHfyd7UUBUKunFMScbflYAAOYJqVIVwaYR5zWEEceUjNnTNo_CVSj" To iSuccess
Get ComAppend Of hoSbJwk "-VvXLO5VZfCUAVLgW4dpf1SrtZjSt34YLsRarSb127reG_DUwg9Ch-Kyvj" To iSuccess
Get ComAppend Of hoSbJwk 'T1SkHgUWRVGcyly7uvVGRSDwsXypdrNinPA4jlhoNdizK2zF2CWQ",' To iSuccess
Get ComAppend Of hoSbJwk '"p":"9gY2w6I6S6L0juEKsbeDAwpd9WMfgqFoeA9vEyEUuk4kLwBKcoe1x4HG68' To iSuccess
Get ComAppend Of hoSbJwk "ik918hdDSE9vDQSccA3xXHOAFOPJ8R9EeIAbTi1VwBYnbTp87X-xcPWlEP" To iSuccess
Get ComAppend Of hoSbJwk 'krdoUKW60tgs1aNd_Nnc9LEVVPMS390zbFxt8TN_biaBgelNgbC95sM",' To iSuccess
Get ComAppend Of hoSbJwk '"q":"uKlCKvKv_ZJMVcdIs5vVSU_6cPtYI1ljWytExV_skstvRSNi9r66jdd9-y' To iSuccess
Get ComAppend Of hoSbJwk "BhVfuG4shsp2j7rGnIio901RBeHo6TPKWVVykPu1iYhQXw1jIABfw-MVsN" To iSuccess
Get ComAppend Of hoSbJwk '-3bQ76WLdt2SDxsHs7q7zPyUyHXmps7ycZ5c72wGkUwNOjYelmkiNS0",' To iSuccess
Get ComAppend Of hoSbJwk '"dp":"w0kZbV63cVRvVX6yk3C8cMxo2qCM4Y8nsq1lmMSYhG4EcL6FWbX5h9yuv' To iSuccess
Get ComAppend Of hoSbJwk "ngs4iLEFk6eALoUS4vIWEwcL4txw9LsWH_zKI-hwoReoP77cOdSL4AVcra" To iSuccess
Get ComAppend Of hoSbJwk 'Hawlkpyd2TWjE5evgbhWtOxnZee3cXJBkAi64Ik6jZxbvk-RR3pEhnCs",' To iSuccess
Get ComAppend Of hoSbJwk '"dq":"o_8V14SezckO6CNLKs_btPdFiO9_kC1DsuUTd2LAfIIVeMZ7jn1Gus_Ff' To iSuccess
Get ComAppend Of hoSbJwk "7B7IVx3p5KuBGOVF8L-qifLb6nQnLysgHDh132NDioZkhH7mI7hPG-PYE_" To iSuccess
Get ComAppend Of hoSbJwk 'odApKdnqECHWw0J-F0JWnUd6D2B_1TvF9mXA2Qx-iGYn8OVV1Bsmp6qU",' To iSuccess
Get ComAppend Of hoSbJwk '"qi":"eNho5yRBEBxhGBtQRww9QirZsB66TrfFReG_CcteI1aCneT0ELGhYlRlC' To iSuccess
Get ComAppend Of hoSbJwk "tUkTRclIfuEPmNsNDPbLoLqqCVznFbvdB7x-Tl-m0l_eFTj2KiqwGqE9PZ" To iSuccess
Get ComAppend Of hoSbJwk 'B9nNTwMVvH3VRRSLWACvPnSiwP8N5Usy-WRXS-V7TbpxIhvepTfE0NNo"' To iSuccess
Get ComAppend Of hoSbJwk "}" To iSuccess
// Load this JWK into a Chilkat private key object.
Get Create (RefClass(cComChilkatPrivateKey)) To hoRsaPrivKey
If (Not(IsComObjectCreated(hoRsaPrivKey))) Begin
Send CreateComObject of hoRsaPrivKey
End
Get ComGetAsString Of hoSbJwk To sTemp1
Get ComLoadJwk Of hoRsaPrivKey sTemp1 To iSuccess
If (iSuccess = False) Begin
Get ComLastErrorText Of hoRsaPrivKey To sTemp1
Showln sTemp1
Procedure_Return
End
// Get the public key for encryption. (The RSA private key is used for decryption.)
Get Create (RefClass(cComChilkatPublicKey)) To hoRsaPubKey
If (Not(IsComObjectCreated(hoRsaPubKey))) Begin
Send CreateComObject of hoRsaPubKey
End
Get pvComObject of hoRsaPubKey to vRsaPubKey
Get ComToPublicKey Of hoRsaPrivKey vRsaPubKey To iSuccess
Move 0 To iRecipientIndex
Get pvComObject of hoRsaPubKey to vRsaPubKey
Get ComSetPublicKey Of hoJwe iRecipientIndex vRsaPubKey To iSuccess
// Recipient 1 uses AES Key Wrap
Move "GawgguFyGrWKav7AX4VKUg" To sAesWrappingKey
Move 1 To iRecipientIndex
Get ComSetWrappingKey Of hoJwe iRecipientIndex sAesWrappingKey "base64url" To iSuccess
// OK.. everything has been specified.
// Now encrypt. Chilkat will use the general JSON serialization because it is only
// possible serializationto use given there are multiple recipients.
Get ComEncrypt Of hoJwe sPlaintext "utf-8" To sStrJwe
Get ComLastMethodSuccess Of hoJwe To bTemp1
If (bTemp1 = False) Begin
Get ComLastErrorText Of hoJwe To sTemp1
Showln sTemp1
Procedure_Return
End
// The strJwe is in the most compact form possible (a single line).
// Let's load it into a JSON object and examine in a non-compact pretty-printed format:
Get Create (RefClass(cComChilkatJsonObject)) To hoJsonTemp
If (Not(IsComObjectCreated(hoJsonTemp))) Begin
Send CreateComObject of hoJsonTemp
End
Get ComLoad Of hoJsonTemp sStrJwe To iSuccess
Set ComEmitCompact Of hoJsonTemp To False
Get ComEmit Of hoJsonTemp To sTemp1
Showln sTemp1
// The JWE looks like this:
// (Note: Because of random values used in the encryption process, your encrypted results will be different.)
// {
// "protected": "eyJlbmMiOiJBMTI4Q0JDLUhTMjU2In0",
// "unprotected": {
// "jku": "https://server.example.com/keys.jwks"
// },
// "recipients": [
// {
// "header": {
// "alg": "RSA1_5",
// "kid": "2011-04-29"
// },
// "encrypted_key": "WlUggejR-vStJVNKgjG2mQrVv74aga1FFutT8E-n-yJEOTsOVnGjhj1NW_Snd9DqHAhFrc7NEvKCFplKWGnusBZxxjm1JpdUa0MIpkGmncJHQQdfm21vcbEUbDmfqVY79SnEis3tih1D3qmyp_Bxti4byDAHJIOJv_cj0Sx8oHZzgGtOLjtHsydyo1MtBIqI0w86i_uhUuraihZ3ngj67YZ6uqpR6lulkPIVohfF3oJ0D3Ay_XOCHWlHYkTg6VZsa0FDrPtfB2pG3TxTBPwI4IMj5uF_D3zrg51dCYKU1Gah71ujLaXRE5q9XF7oOknxiWQuWc7Ox8JP03lSx-DiVA"
// },
// {
// "header": {
// "alg": "A128KW",
// "kid": "7"
// },
// "encrypted_key": "8diBP2aUUB_Jl5WxCuMJLN6HsppE3rhSjcecee0fBcwB31zbPAVejQ"
// }
// ],
// "iv": "JqahFKx5Z8SFT_LnkfOq0Q",
// "ciphertext": "YcSdjlszsaY1ADcs4Vw85H_WoAqnkDIJaJsTkmCj05s",
// "tag": "G3KF2CZ-DMhm0cqUbhJKMA"
// }
// To decrypt, we don't need both recipient keys. We can decrypt with one key or the other.
// The FindRecipient method can be used to find a particular recipient index.
// First, load the JWE..
Get Create (RefClass(cComChilkatJwe)) To hoJwe2
If (Not(IsComObjectCreated(hoJwe2))) Begin
Send CreateComObject of hoJwe2
End
Get ComLoadJwe Of hoJwe2 sStrJwe To iSuccess
If (iSuccess = False) Begin
Get ComLastErrorText Of hoJwe2 To sTemp1
Showln sTemp1
Procedure_Return
End
// Let's say we have the AES key wrap key, and we know the "kid" equals "7".
Move False To iCaseSensitive
Get ComFindRecipient Of hoJwe2 "kid" "7" iCaseSensitive To iRecipientIndex
If (iRecipientIndex < 0) Begin
Showln "Unable to find recipient with kid=7"
Procedure_Return
End
// Set the AES wrap key for the recipient index.
Get ComSetWrappingKey Of hoJwe2 iRecipientIndex sAesWrappingKey "base64url" To iSuccess
// Decrypt
Get ComDecrypt Of hoJwe2 iRecipientIndex "utf-8" To sOriginalPlaintext
Get ComLastMethodSuccess Of hoJwe2 To bTemp1
If (bTemp1 = False) Begin
Get ComLastErrorText Of hoJwe2 To sTemp1
Showln sTemp1
Procedure_Return
End
Showln "original text decrypted with AES key wrap key: "
Showln sOriginalPlaintext
// Now, let's do the same with the RSA private key:
Get ComFindRecipient Of hoJwe2 "kid" "2011-04-29" iCaseSensitive To iRecipientIndex
If (iRecipientIndex < 0) Begin
Showln "Unable to find recipient with kid=2011-04-29"
Procedure_Return
End
// Set the RSA private key for the recipient index.
Get pvComObject of hoRsaPrivKey to vRsaPrivKey
Get ComSetPrivateKey Of hoJwe2 iRecipientIndex vRsaPrivKey To iSuccess
// Decrypt
Get ComDecrypt Of hoJwe2 iRecipientIndex "utf-8" To sOriginalPlaintext
Get ComLastMethodSuccess Of hoJwe2 To bTemp1
If (bTemp1 = False) Begin
Get ComLastErrorText Of hoJwe2 To sTemp1
Showln sTemp1
Procedure_Return
End
Showln "original text decrypted with RSA private key: "
Showln sOriginalPlaintext
// ---------------------------------------------------------------------------------
// It should also be possible to decrypt the JWE as shown in RFC 7516, Appendix A.4.7
// because it was produced using the same keys.
Get Create (RefClass(cComChilkatStringBuilder)) To hoSbJwe
If (Not(IsComObjectCreated(hoSbJwe))) Begin
Send CreateComObject of hoSbJwe
End
Get ComAppend Of hoSbJwe "{" To iSuccess
Get ComAppend Of hoSbJwe '"protected":' To iSuccess
Get ComAppend Of hoSbJwe '"eyJlbmMiOiJBMTI4Q0JDLUhTMjU2In0",' To iSuccess
Get ComAppend Of hoSbJwe '"unprotected":' To iSuccess
Get ComAppend Of hoSbJwe '{"jku":"https://server.example.com/keys.jwks"},' To iSuccess
Get ComAppend Of hoSbJwe '"recipients":[' To iSuccess
Get ComAppend Of hoSbJwe '{"header":' To iSuccess
Get ComAppend Of hoSbJwe '{"alg":"RSA1_5","kid":"2011-04-29"},' To iSuccess
Get ComAppend Of hoSbJwe '"encrypted_key":' To iSuccess
Get ComAppend Of hoSbJwe '"UGhIOguC7IuEvf_NPVaXsGMoLOmwvc1GyqlIKOK1nN94nHPoltGRhWhw7Zx0-' To iSuccess
Get ComAppend Of hoSbJwe "kFm1NJn8LE9XShH59_i8J0PH5ZZyNfGy2xGdULU7sHNF6Gp2vPLgNZ__deLKx" To iSuccess
Get ComAppend Of hoSbJwe "GHZ7PcHALUzoOegEI-8E66jX2E4zyJKx-YxzZIItRzC5hlRirb6Y5Cl_p-ko3" To iSuccess
Get ComAppend Of hoSbJwe "YvkkysZIFNPccxRU7qve1WYPxqbb2Yw8kZqa2rMWI5ng8OtvzlV7elprCbuPh" To iSuccess
Get ComAppend Of hoSbJwe "cCdZ6XDP0_F8rkXds2vE4X-ncOIM8hAYHHi29NX0mcKiRaD0-D-ljQTP-cFPg" To iSuccess
Get ComAppend Of hoSbJwe 'wCp6X-nZZd9OHBv-B3oWh2TbqmScqXMR4gp_A"},' To iSuccess
Get ComAppend Of hoSbJwe '{"header":' To iSuccess
Get ComAppend Of hoSbJwe '{"alg":"A128KW","kid":"7"},' To iSuccess
Get ComAppend Of hoSbJwe '"encrypted_key":' To iSuccess
Get ComAppend Of hoSbJwe '"6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ"}],' To iSuccess
Get ComAppend Of hoSbJwe '"iv":' To iSuccess
Get ComAppend Of hoSbJwe '"AxY8DCtDaGlsbGljb3RoZQ",' To iSuccess
Get ComAppend Of hoSbJwe '"ciphertext":' To iSuccess
Get ComAppend Of hoSbJwe '"KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY",' To iSuccess
Get ComAppend Of hoSbJwe '"tag":' To iSuccess
Get ComAppend Of hoSbJwe '"Mz-VPPyU4RlcuYv1IwIvzw"' To iSuccess
Get ComAppend Of hoSbJwe "}" To iSuccess
Get pvComObject of hoSbJwe to vSbJwe
Get ComLoadJweSb Of hoJwe2 vSbJwe To iSuccess
If (iSuccess = False) Begin
Get ComLastErrorText Of hoJwe2 To sTemp1
Showln sTemp1
Procedure_Return
End
// We can decrypt with either key. Let's use the AES key wrap key...
Get ComFindRecipient Of hoJwe2 "kid" "7" iCaseSensitive To iRecipientIndex
If (iRecipientIndex < 0) Begin
Showln "Unable to find recipient with kid=7"
Procedure_Return
End
// Set the AES wrap key for the recipient index.
Get ComSetWrappingKey Of hoJwe2 iRecipientIndex sAesWrappingKey "base64url" To iSuccess
// Decrypt
Get ComDecrypt Of hoJwe2 iRecipientIndex "utf-8" To sOriginalPlaintext
Get ComLastMethodSuccess Of hoJwe2 To bTemp1
If (bTemp1 = False) Begin
Get ComLastErrorText Of hoJwe2 To sTemp1
Showln sTemp1
Procedure_Return
End
Showln "original text decrypted from published JWE, with AES key wrap key: "
Showln sOriginalPlaintext
// The output:
// original text decrypted with AES key wrap key:
// Live long and prosper.
// original text decrypted with RSA private key:
// Live long and prosper.
// original text decrypted from published JWE, with AES key wrap key:
// Live long and prosper.
End_Procedure