PureBasic
PureBasic
Decrypt a JWE to a String
See more JSON Web Encryption (JWE) Examples
Demonstrates Jwe.Decrypt, which decrypts a recipient of a loaded JWE and returns the plaintext, decoded using the given charset. Before decrypting, the example inspects the JWE protected header and, under application policy, accepts only permitted algorithms and selects an acceptable recipient.
Background. A received JWE should never be trusted to specify safe algorithms. The example reads the
alg and enc values from the protected header (via GetProtectedHeader) and enforces an allowlist, rejecting anything not permitted. It then selects the recipient the application holds a key for — using FindRecipient to locate a recipient by a per-recipient header value such as kid, falling back to index 0 for a single-recipient compact JWE — and only then supplies the key and decrypts.Chilkat PureBasic Downloads
IncludeFile "CkStringBuilder.pb"
IncludeFile "CkJwe.pb"
IncludeFile "CkJsonObject.pb"
Procedure ChilkatExample()
success.i = 0
jwe.i = CkJwe::ckCreate()
If jwe.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
; Load the JWE compact serialization to be decrypted.
jweCompact.s = "eyJhbGciOiJBMjU2S1ciLCJlbmMiOiJBMjU2R0NNIn0.<...>.<iv>.<ciphertext>.<tag>"
success = CkJwe::ckLoadJwe(jwe,jweCompact)
If success = 0
Debug CkJwe::ckLastErrorText(jwe)
CkJwe::ckDispose(jwe)
ProcedureReturn
EndIf
; Application policy: before decrypting, inspect the JWE header and accept only algorithms the
; application trusts. Never assume the algorithms in a received JWE are safe -- a sender could
; specify a weak or unexpected algorithm.
protHeader.i = CkJsonObject::ckCreate()
If protHeader.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
success = CkJwe::ckGetProtectedHeader(jwe,protHeader)
If success = 0
Debug CkJwe::ckLastErrorText(jwe)
CkJwe::ckDispose(jwe)
CkJsonObject::ckDispose(protHeader)
ProcedureReturn
EndIf
; Read the alg (key-management) and enc (content-encryption) header values into StringBuilder
; objects so they can be compared.
sbAlg.i = CkStringBuilder::ckCreate()
If sbAlg.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
success = CkJsonObject::ckStringOfSb(protHeader,"alg",sbAlg)
If success = 0
Debug CkJsonObject::ckLastErrorText(protHeader)
CkJwe::ckDispose(jwe)
CkJsonObject::ckDispose(protHeader)
CkStringBuilder::ckDispose(sbAlg)
ProcedureReturn
EndIf
sbEnc.i = CkStringBuilder::ckCreate()
If sbEnc.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
success = CkJsonObject::ckStringOfSb(protHeader,"enc",sbEnc)
If success = 0
Debug CkJsonObject::ckLastErrorText(protHeader)
CkJwe::ckDispose(jwe)
CkJsonObject::ckDispose(protHeader)
CkStringBuilder::ckDispose(sbAlg)
CkStringBuilder::ckDispose(sbEnc)
ProcedureReturn
EndIf
Debug "JWE algorithms: alg=" + CkStringBuilder::ckGetAsString(sbAlg) + " enc=" + CkStringBuilder::ckGetAsString(sbEnc)
; Enforce an allowlist of acceptable algorithms. Reject anything not permitted by policy. String
; values are compared using StringBuilder.ContentsEqual.
bCaseSensitive.i = 1
If CkStringBuilder::ckContentsEqual(sbAlg,"A256KW",bCaseSensitive) <> 1
Debug "Rejecting JWE: key-management algorithm is not permitted by policy."
CkJwe::ckDispose(jwe)
CkJsonObject::ckDispose(protHeader)
CkStringBuilder::ckDispose(sbAlg)
CkStringBuilder::ckDispose(sbEnc)
ProcedureReturn
EndIf
If CkStringBuilder::ckContentsEqual(sbEnc,"A256GCM",bCaseSensitive) <> 1
Debug "Rejecting JWE: content-encryption algorithm is not permitted by policy."
CkJwe::ckDispose(jwe)
CkJsonObject::ckDispose(protHeader)
CkStringBuilder::ckDispose(sbAlg)
CkStringBuilder::ckDispose(sbEnc)
ProcedureReturn
EndIf
; Select an acceptable recipient. For a multi-recipient JWE, FindRecipient locates the recipient
; this application holds a key for by a per-recipient header value such as "kid". A compact JWE
; has a single recipient at index 0, so FindRecipient returns -1; fall back to index 0 in that case.
recipientIndex.i = CkJwe::ckFindRecipient(jwe,"kid","recipient-key-1",bCaseSensitive)
If recipientIndex < 0
recipientIndex = 0
EndIf
; Provide the key for the selected recipient. In production, obtain the key from a secure source
; rather than hard-coding it.
base64Key.s = "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU="
success = CkJwe::ckSetWrappingKey(jwe,recipientIndex,base64Key,"base64")
If success = 0
Debug CkJwe::ckLastErrorText(jwe)
CkJwe::ckDispose(jwe)
CkJsonObject::ckDispose(protHeader)
CkStringBuilder::ckDispose(sbAlg)
CkStringBuilder::ckDispose(sbEnc)
ProcedureReturn
EndIf
; Decrypt the selected recipient and return the plaintext, decoded using the given charset.
content.s = CkJwe::ckDecrypt(jwe,recipientIndex,"utf-8")
If CkJwe::ckLastMethodSuccess(jwe) = 0
Debug CkJwe::ckLastErrorText(jwe)
CkJwe::ckDispose(jwe)
CkJsonObject::ckDispose(protHeader)
CkStringBuilder::ckDispose(sbAlg)
CkStringBuilder::ckDispose(sbEnc)
ProcedureReturn
EndIf
Debug content
CkJwe::ckDispose(jwe)
CkJsonObject::ckDispose(protHeader)
CkStringBuilder::ckDispose(sbAlg)
CkStringBuilder::ckDispose(sbEnc)
ProcedureReturn
EndProcedure