(rfc jws) - Json Web Signature

Library (rfc jws)

This library provides Json Web Signature (JWS) APIs. JWS is defined in RFC 7515.

The library supports ES256K defined in RFC 8812section 3.1.

It also supports EdDSA of both Ed25519 and Ed448 defined in RFC 8037.

The following examples show how to sign and verify JWS token

;; Signing
(import (rnrs)
        (rfc jws)
        (rfc jwk) ;; to convert key pair to JWK
        (crypto))

;; Generate Ed25519 key pair
(define keypair (generate-key-pair Ed25519))

;; JWS header with crit
(define jws-header
  (jws-header-builder
   (alg 'EdDSA)
   (crit '("sagittarius:iss" "sagittarius:sub"))
   (custom-parameters '(("sagittarius:iss" "Sagittarius Scheme")
                        ("sagittarius:sub" "JWS test")))))

(define payload
  (string->utf8 "Payload can be anything as long as a bytevector"))

;; Get signer
(define signer (private-key->jws-signer (keypair-private keypair)))

;; The JWS object is not signed yet
(define unsecure-jws-object (make-jws-object jws-header payload))

(let ((jws-object (jws:sign unsecure-jws-object signer)))
  (jws:serialize jws-object)
  ;; -> eyJzYWdpdHRhcml1czpzdWIiOiJKV1MgdGVzdCIsInNhZ2l0dGFyaXVzOmlzcyI6IlNhZ2l0dGFyaXVzIFNjaGVtZSIsImFsZyI6IkVkRFNBIiwiY3JpdCI6WyJzYWdpdHRhcml1czppc3MiLCJzYWdpdHRhcml1czpzdWIiXX0.UGF5bG9hZCBjYW4gYmUgYW55dGhpbmcgYXMgbG9uZyBhcyBhIGJ5dGV2ZWN0b3I.5Aj_AJh4DW01kV80XtFbxRRMw2ktxIrQ5-UXoCwKVWI0Ke0q0t3vpcFnESL39zYDwi3Ps8eLxfmEb-TvhkQGBg
  (jwk->json-string (public-key->jwk (keypair-public keypair)))
  ;; -> {"kty":"OKP","crv":"Ed25519","x":"o_t1R4fWf7obqTZWlXxrgPG09BMU-zuhqHvb9_ayOew"}
  )
;; Verify
(import (rnrs)
        (rfc jws)
        (rfc jwk) ;; to convert JWK to public key
        (crypto))

;; JWS string
(define jws-string
  "eyJzYWdpdHRhcml1czpzdWIiOiJKV1MgdGVzdCIsInNhZ2l0dGFyaXVzOmlzcyI6IlNhZ2l0dGFyaXVzIFNjaGVtZSIsImFsZyI6IkVkRFNBIiwiY3JpdCI6WyJzYWdpdHRhcml1czppc3MiLCJzYWdpdHRhcml1czpzdWIiXX0.UGF5bG9hZCBjYW4gYmUgYW55dGhpbmcgYXMgbG9uZyBhcyBhIGJ5dGV2ZWN0b3I.5Aj_AJh4DW01kV80XtFbxRRMw2ktxIrQ5-UXoCwKVWI0Ke0q0t3vpcFnESL39zYDwi3Ps8eLxfmEb-TvhkQGBg")

;; Ed25519 public key
(define jwk
  (json-string->jwk
   "{\"kty\":\"OKP\",\"crv\":\"Ed25519\",\"x\":\"o_t1R4fWf7obqTZWlXxrgPG09BMU-zuhqHvb9_ayOew\"}"))

;; Parse the string
(define jws-object (jws:parse jws-string))

;; Make a verifier from the JWK
(define verifier (public-key->jws-verifier jwk))

(when (jws:verify jws-object verifier '("sagittarius:iss" "sagittarius:sub"))
  (utf8->string (jws-object-payload jws-object))) ;; -> payload

The above examples only show the flavour of the APIs. In real world applications, the users of the library must consider a lot more to make the application secure.

JWS Object

Record Type <jws-object>

The record type of JWS objects. JWS object has 2 fields, header and payload.

Returns #t if the given obj is a JWS object otherwise #f.

Construct a newly allocated JWS object.

Jws-header must be a JWS header object.

payload must be a bytevector.

Returns the value of header field of given jws-object.

Returns the value of payload field of given jws-object.

The record type of signed JWS objects.

Signed JWS object is a sub record of JWS object, which has signaturefield.

Returns #t if the given obj is a signed JWS object otherwise #f.

This object can be obtained by jws:sign or jws:parse.

Returns the value of signature field of given signed-jws-object.

JWS Header

Record Type <jws-header>

The record type of JWS header.

This record type has the below fields:

The above fields have accessors prefixed jws-header-. For example, to read typ field, you can use jws-header-typ procedure.

Returns #t if the given obj is a JWS header, otherwise #f.

A builder macro of JWS header. The macro is generated by (record builder). see (record builder)for more details.

Serialize the given json-header to a S-exp representaion, to port or string.

If first form of write-jws-header is used, then it writes the serialized JWS header to current output port.

Construct JWS header from S-exp JSON representation of obj, from input port port or a string string.

If the first form of read-jws-header is used, then it reads from current input port.

JWS Operations

Parse the given compact JWS of string and return signed JWS object.

If the format of the given string is invalid, then an error is signaled.

Serialize the given jws-object to compact JWS form.

If the second form is used, then the payload is omitted. (Detached form)

Sign the given jws-object with the given signer and returns signed JWS object.

Verify the given jws-object with the given verifier. If the verification is success, then it returns #t.

Otherwise, it may return #f or signals an error, depending on the underlying verifier.

If the second form of jws:verify is used, then it uses the given critical-headers list to check crit header value.

JWS Verifiers

JWS verifier is a procedure takes 3 arguments, JWS header, signing content and signature.

This library doesn't support none algorithm verifier. It is obvious that if you want to support it, you just don't have to verify it.

key must be a JWK:oct or a bytevector.

Creates a MAC JWS verifier.

key must be a JWK:RSA or a RSA public key.

Creates a RSA JWS verifier.

key must be a JWK:EC or a ECDSA public key.

Creates a ECDSA JWS verifier.

key must be a JWK:OKP or a EdDSA public key.

Creates a EdDSA JWS verifier.

JWS Signers

JWS signer is a procedure takes 2 arguments, JWS header, signing content.

This library doesn't support none algorithm signer. If you want to support it, you need to create a JWS object with alg header with value of none.

key must be a JWK:oct or a bytevector.

Creates a MAC JWS signer.

key must be a JWK:RSA or a RSA private key.

Creates a RSA JWS signer.

key must be a JWK:EC or a ECDSA private key.

Creates a ECDSA JWS signer.

key must be a JWK:OKP or a EdDSA private key.

Creates a EdDSA JWS signer.