Towards The Tokenization of Data

We live in a 20th Century world of data, and where we just gather it and care little about its trustworthiness. But, there is a better way…

Photo by Shubham Dhage on Unsplash

Towards The Tokenization of Data

We live in a 20th Century world of data, and where we just gather it and care little about its trustworthiness. But, there is a better way, and that’s to use signed tokens to protect and/or define trustworthiness. To protect, we can encrypt our data, and for the trustworthiness, we can use a digital signature. One of the most widely used methods for this is JSON Web Tokens (JWT).

With this we have:

  • A header. This defines the token type (such as JWT) and the signing method that we will use.
  • A payload. This defines the main payload data, and is defined in a simple JSON format. This might include the user’s ID, their email address, and so on. The fields are flexible and can be created for any purpose.
  • A signature. This is either a public key signature (with RSA or ECDSA) or an HMAC signature (and which uses a given hashing method and a secret password).

The registered claim names are:

  • “iss” (Issuer). This identifies the issuer of the token.
  • “sub” (Subject). This defines the subject of the token.
  • “aud” (Audience). This defines the general audience for the token.
  • “exp” (Expiration Time). This defines the time that the token will expire.
  • “nbf” (Not Before). This defines the time that the token will start.
  • “iat” (Issued At). This defines the time that the token was created.
  • “jti” (JWT ID). This defines the ID of the token.

Overall. the format of the token is header.payload.signature. So:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJmcmVkQGhvbWUiLCJzdWIiOiJNeSBlbWFpbCIsIm5iZiI6MTY1OTEwMTA3OSwiaWF0IjoxNjU5MTAxMDc5LCJleHAiOjE2NTkxODc0NzksImp0aSI6IklEMTI0NTY3OSJ9.MXS5U2jGMyYbbs7Ek03IB_z2_1lWZCMnqIRo-TIJb6o

has three fields:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
eyJpc3MiOiJmcmVkQGhvbWUiLCJzdWIiOiJNeSBlbWFpbCIsIm5iZiI6MTY1OTEwMTA3OSwiaWF0IjoxNjU5MTAxMDc5LCJleHAiOjE2NTkxODc0NzksImp0aSI6IklEMTI0NTY3OSJ9
MXS5U2jGMyYbbs7Ek03IB_z2_1lWZCMnqIRo-TIJb6o

and which identify the header, the payload and the signature. If we do a Base64 decoding of “eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9”, we get:

{"alg":"HS256","typ":"JWT"}

and for “eyJpc3MiOiJmcmVkQGhvbWUiLCJzdWIiOiJNeSBlbWFpbCIsIm5iZiI6MTY1OTEwMTA3OSwiaWF0IjoxNjU5MTAxMDc5LCJleHAiOjE2NTkxODc0NzksImp0aSI6IklEMTI0NTY3OSJ9”, we get:

{"iss":"fred@home","sub":"My email", "nbf":1659101079,"iat":1659101079,"exp":1659187479,"jti":"ID1245679"}

We can see that this token is not encrypted.

Overall, these tokens provide an excellent way to gain access to networked services, and where a user can gain a token and then pass it to the required services.

The signature methods

The methods that just provide a signature include HS256 (HMAC SHA-256), ES256 (ECDSA using P-256 and SHA-256) and RS256 ( RSASSA-PKCS1-v1_5 with the SHA-256). HS256 just has a password to provide the signature, while ES256 and RS256 require a private key to sign the token and a public key to provide it.

For HS256, there are multiple ways of defining the password such as with UTF8, Base64 or Hex. If JavaScript these can be defined with:

KJUR.jws.JWS.sign("HS256", sHeader, sPayload, {utf8: "Qwerty123"});
KJUR.jws.JWS.sign("HS256", sHeader, sPayload, {b64u: "
UXdlcnR5MTIz"});
KJUR.jws.JWS.sign("HS256", sHeader, sPayload, {hex: "
517765727479313233"});

Some JavaScript coding for creating a JWT is [here]:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jsrsasign/10.5.26/jsrsasign-all-min.js"></script>
<script>

    function gojwt(method,iss,sub,id,password) {
     
var oHeader = { alg: method, typ: 'JWT' };
        var oPayload = {};
var tNow = KJUR.jws.IntDate.get('now');
var tEnd = KJUR.jws.IntDate.get('now + 1day');
oPayload.iss = iss;
oPayload.sub = sub;
oPayload.nbf = tNow;
oPayload.iat = tNow;
oPayload.exp = tEnd;
oPayload.jti = id

       var sHeader = JSON.stringify(oHeader);
var sPayload = JSON.stringify(oPayload);
var sJWT = KJUR.jws.JWS.sign(method, sHeader, sPayload, password);
       document.getElementById("JWT").innerHTML = "Header:\n" +sHeader;
document.getElementById("JWT").innerHTML += "\nPayload:\n" +sPayload;
document.getElementById("JWT").innerHTML += "\nJWT Signature:\n"+ sJWT;

        var isValid = KJUR.jws.JWS.verifyJWT(sJWT, password, {alg: [method],iss: [iss],sub: [sub]});
    document.getElementById("JWT").innerHTML += "\nValid JWT: " + isValid;
    }


    }</script>

A sample run is [here]:

Header:
{"alg":"HS256","typ":"JWT"}
Payload:
{"iss":"fred@home","sub":"My email","nbf":1659107653,"iat":1659107653,"exp":1659194053,"jti":"ID124567"}
JWT Signature:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJmcmVkQGhvbWUiLCJzdWIiOiJNeSBlbWFpbCIsIm5iZiI6MTY1OTEwNzY1MywiaWF0IjoxNjU5MTA3NjUzLCJleHAiOjE2NTkxOTQwNTMsImp0aSI6IklEMTI0NTY3In0.SGRudayphGDRjlhYZzz9Y3cgsCvAua00j5j_M4dSb9M
Valid: true

Here is the demo:

https://asecuritysite.com/javascript/jwt

Conclusions

The logging-in to different network services just seems so out-of-date these days. With JWT, we can authenticate once and then gain a signed token. This token can be passed to network services to provide access. In the next article, I will outline how public key encryption is used to sign JWTs (“jots”).

Here’s the code:

https://asecuritysite.com/javascript/jwt