Sample code for 30+ languages & platforms
Visual FoxPro

Validate JWS with Multiple Signatures using the General JSON Serialization Format

See more JSON Web Signatures (JWS) Examples

Validates and recovers data and headers from a JSON Web Signature (JWS) containing 3 signatures.

Note: Chilkat supports all of the following JWS algorithms:

   +--------------+-------------------------------+--------------------+
   | "alg" Param  | Digital Signature or MAC      | Implementation     |
   | Value        | Algorithm                     | Requirements       |
   +--------------+-------------------------------+--------------------+
   | HS256        | HMAC using SHA-256            | Required           |
   | HS384        | HMAC using SHA-384            | Optional           |
   | HS512        | HMAC using SHA-512            | Optional           |
   | RS256        | RSASSA-PKCS1-v1_5 using       | Recommended        |
   |              | SHA-256                       |                    |
   | RS384        | RSASSA-PKCS1-v1_5 using       | Optional           |
   |              | SHA-384                       |                    |
   | RS512        | RSASSA-PKCS1-v1_5 using       | Optional           |
   |              | SHA-512                       |                    |
   | ES256        | ECDSA using P-256 and SHA-256 | Recommended+       |
   | ES384        | ECDSA using P-384 and SHA-384 | Optional           |
   | ES512        | ECDSA using P-521 and SHA-512 | Optional           |
   | PS256        | RSASSA-PSS using SHA-256 and  | Optional           |
   |              | MGF1 with SHA-256             |                    |
   | PS384        | RSASSA-PSS using SHA-384 and  | Optional           |
   |              | MGF1 with SHA-384             |                    |
   | PS512        | RSASSA-PSS using SHA-512 and  | Optional           |
   |              | MGF1 with SHA-512             |                    |
   +--------------+-------------------------------+--------------------+

Chilkat Visual FoxPro Downloads

Visual FoxPro
LOCAL lnSuccess
LOCAL loSbRsaJwk
LOCAL loRsaKey
LOCAL loSbEccJwk
LOCAL loEccKey
LOCAL lcHmacKey
LOCAL loSbJws
LOCAL loJws
LOCAL loSbKeyId
LOCAL lnBCaseSensitive
LOCAL loProtHeader
LOCAL lnNumSignatures
LOCAL i
LOCAL v

lnSuccess = 0

* This requires the Chilkat API to have been previously unlocked.
* See Global Unlock Sample for sample code.

* First, prepare the public keys that will be needed for each signature.

* ---------------------------------------------------
* Use the following RSA key loaded from JWK format.
loSbRsaJwk = CreateObject('Chilkat.StringBuilder')
loSbRsaJwk.Append('{"kty":"RSA",')
loSbRsaJwk.Append('"n":"ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddx')
loSbRsaJwk.Append("HmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMs")
loSbRsaJwk.Append("D1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSH")
loSbRsaJwk.Append("SXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdV")
loSbRsaJwk.Append("MTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8")
loSbRsaJwk.Append('NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ",')
loSbRsaJwk.Append('"e":"AQAB"')
loSbRsaJwk.Append("}")

loRsaKey = CreateObject('Chilkat.PublicKey')
lnSuccess = loRsaKey.LoadFromString(loSbRsaJwk.GetAsString())
IF (lnSuccess = 0) THEN
    ? loRsaKey.LastErrorText
    RELEASE loSbRsaJwk
    RELEASE loRsaKey
    CANCEL
ENDIF

* ---------------------------------------------------
* Use the following ECC public key loaded from JWK format.
loSbEccJwk = CreateObject('Chilkat.StringBuilder')
loSbEccJwk.Append('{"kty":"EC",')
loSbEccJwk.Append('"crv":"P-256",')
loSbEccJwk.Append('"x":"f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",')
loSbEccJwk.Append('"y":"x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0"')
loSbEccJwk.Append("}")

loEccKey = CreateObject('Chilkat.PublicKey')
lnSuccess = loEccKey.LoadFromString(loSbEccJwk.GetAsString())
IF (lnSuccess = 0) THEN
    ? loEccKey.LastErrorText
    RELEASE loSbRsaJwk
    RELEASE loRsaKey
    RELEASE loSbEccJwk
    RELEASE loEccKey
    CANCEL
ENDIF

* ---------------------------------------------------
* The HMAC key (in base64url format)
lcHmacKey = "AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow"

* The code below will verify each of the signatures in this JWS:

* { 
*   "payload": "SW4gb3VyIHZpbGxhZ2UsIGZvbGtzIHNheSBHb2QgY3J1bWJsZXMgdXAgdGhlIG9sZCBtb29uIGludG8gc3RhcnMu",
*   "signatures": [
*     { 
*       "protected": "eyJhbGciOiJSUzI1NiIsImtpZCI6Im15UnNhS2V5In0",
*       "signature": "IPMQ02niTQDwLzsRZSCaEm9VEyAX_AVe3HWjniNt9kW-a8d6ZVbd2k6jGae8s1yIh0cgxDnXQ6-p6_sBI0cnMO0xpuJANhh2vFtNJl5lisad94-H3mB3lSfafRqxeYp5D8bh39BPv7y3PrUNVMQdKEJp_D5oJ0ROPTIYx3EG8eJQOx1HO0KqhcUo401XR6KSsIyFm5joBLNKTVzxZUTT1RRZZtwTdeZkbGevugIOX_9gHAtARpV6WaFA4Vvjnq8X9wPgqjWNCQRupadhTPz0JAsa-wy5vXQjsFlXAn43mDPpMfna5Ab3F5pS4yDwkbX6nRn7XBxH1SnnNJRFholQZw"
*     },
*     { 
*       "protected": "eyJhbGciOiJFUzI1NiIsImtpZCI6Im15RWNLZXkifQ",
*       "signature": "1OQtaT3pgZmkDxvlfghvxL_8kX16WIen6u1MadEq1pA4qytA0--_EwZDNk00GDPWFpoJtKznibMZzLOg_UhHIw"
*     },
*     { 
*       "protected": "eyJhbGciOiJIUzI1NiIsImtpZCI6Im15TWFjS2V5In0",
*       "signature": "YY8yVjmJJfy7YJOn3uUydG8WCY2PEuCvOLil5Ks5lnw"
*     }
*   ]
* }

loSbJws = CreateObject('Chilkat.StringBuilder')
loSbJws.Append("{ ")
loSbJws.Append('  "payload": "SW4gb3VyIHZpbGxhZ2UsIGZvbGtzIHNheSBHb2QgY3J1bWJsZXMgdXAgdGhlIG9sZCBtb29uIGludG8gc3RhcnMu",')
loSbJws.Append('  "signatures": [')
loSbJws.Append("    { ")
loSbJws.Append('      "protected": "eyJhbGciOiJSUzI1NiIsImtpZCI6Im15UnNhS2V5In0",')
loSbJws.Append('      "signature": "IPMQ02niTQDwLzsRZSCaEm9VEyAX_AVe3HWjniNt9kW-a8d6ZVbd2k6jGae8s1yIh0cgxDnXQ6-p6_sBI0cnMO0xpuJANhh2vFtNJl5lisad94-H3mB3lSfafRqxeYp5D8bh39BPv7y3PrUNVMQdKEJp_D5oJ0ROPTIYx3EG8eJQOx1HO0KqhcUo401XR6KSsIyFm5joBLNKTVzxZUTT1RRZZtwTdeZkbGevugIOX_9gHAtARpV6WaFA4Vvjnq8X9wPgqjWNCQRupadhTPz0JAsa-wy5vXQjsFlXAn43mDPpMfna5Ab3F5pS4yDwkbX6nRn7XBxH1SnnNJRFholQZw"')
loSbJws.Append("    },")
loSbJws.Append("    { ")
loSbJws.Append('      "protected": "eyJhbGciOiJFUzI1NiIsImtpZCI6Im15RWNLZXkifQ",')
loSbJws.Append('      "signature": "1OQtaT3pgZmkDxvlfghvxL_8kX16WIen6u1MadEq1pA4qytA0--_EwZDNk00GDPWFpoJtKznibMZzLOg_UhHIw"')
loSbJws.Append("    },")
loSbJws.Append("    { ")
loSbJws.Append('      "protected": "eyJhbGciOiJIUzI1NiIsImtpZCI6Im15TWFjS2V5In0",')
loSbJws.Append('      "signature": "YY8yVjmJJfy7YJOn3uUydG8WCY2PEuCvOLil5Ks5lnw"')
loSbJws.Append("    }")
loSbJws.Append("  ]")
loSbJws.Append("}")

loJws = CreateObject('Chilkat.Jws')

lnSuccess = loJws.LoadJwsSb(loSbJws)
IF (lnSuccess = 0) THEN
    ? loJws.LastErrorText
    RELEASE loSbRsaJwk
    RELEASE loRsaKey
    RELEASE loSbEccJwk
    RELEASE loEccKey
    RELEASE loSbJws
    RELEASE loJws
    CANCEL
ENDIF

* The payload is easily accessible:
? "Payload: " + loJws.GetPayload("utf-8")

loSbKeyId = CreateObject('Chilkat.StringBuilder')
lnBCaseSensitive = 0

loProtHeader = CreateObject('Chilkat.JsonObject')
lnNumSignatures = loJws.NumSignatures
i = 0
DO WHILE i < lnNumSignatures
    lnSuccess = loJws.GetProtectedH(i,loProtHeader)
    IF (lnSuccess = 0) THEN
        ? loJws.LastErrorText
        RELEASE loSbRsaJwk
        RELEASE loRsaKey
        RELEASE loSbEccJwk
        RELEASE loEccKey
        RELEASE loSbJws
        RELEASE loJws
        RELEASE loSbKeyId
        RELEASE loProtHeader
        CANCEL
    ENDIF

    ? "--------------------------"
    ? STR(i) + ": "

    * Get the protected header.
    loProtHeader.EmitCompact = 0
    ? loProtHeader.Emit()

    * Get the key ID ("kid") member.

    * Note: In this example, the "kid" values are contained in the protected headers.
    * They could've just as easily been located in unprotected headers.  In that case,
    * we would've called GetUnprotectedH instead of GetProtectedH(i).

    loSbKeyId.Clear()
    loSbKeyId.Append(loProtHeader.StringOf("kid"))

    * Set the key based on key ID.
    IF (loSbKeyId.ContentsEqual("myRsaKey",lnBCaseSensitive) = 1) THEN
        loJws.SetPublicKey(i,loRsaKey)
    ENDIF

    IF (loSbKeyId.ContentsEqual("myEcKey",lnBCaseSensitive) = 1) THEN
        loJws.SetPublicKey(i,loEccKey)
    ENDIF

    IF (loSbKeyId.ContentsEqual("myMacKey",lnBCaseSensitive) = 1) THEN
        loJws.SetMacKey(i,lcHmacKey,"base64url")
    ENDIF

    * Validate this signature.
    v = loJws.Validate(i)
    IF (v < 0) THEN
        * Perhaps Chilkat was not unlocked or the trial expired..
        ? "Validate failed for some other reason."
        ? loJws.LastErrorText
    ELSE
        IF (v = 0) THEN
            ? "Invalid signature.  The key was incorrect, the JWS was invalid, or both."
        ELSE
            ? "Signature validated."
        ENDIF

    ENDIF

    i = i + 1
ENDDO

* The output of this program is:

* 	Payload: In our village, folks say God crumbles up the old moon into stars.
* 	--------------------------
* 	0: 
* 	{
* 	  "alg": "RS256",
* 	  "kid": "myRsaKey"
* 	}
* 
* 	Signature validated.
* 	--------------------------
* 	1: 
* 	{
* 	  "alg": "ES256",
* 	  "kid": "myEcKey"
* 	}
* 
* 	Signature validated.
* 	--------------------------
* 	2: 
* 	{
* 	  "alg": "HS256",
* 	  "kid": "myMacKey"
* 	}
* 
* 	Signature validated.

RELEASE loSbRsaJwk
RELEASE loRsaKey
RELEASE loSbEccJwk
RELEASE loEccKey
RELEASE loSbJws
RELEASE loJws
RELEASE loSbKeyId
RELEASE loProtHeader