Search code examples
javascriptnode.jsjwthmaccryptojs

Decrypting signature and Veryifying JWT


I understand that there exist other libraries which make my life easier to work with JWT (in node.js).

In this case, I am using "crypto-js" to learn JWT in a manual way. The following gives me the token:

var header = {
    "alg": "HS256",
    "typ": "JWT"
};
var wordArrayHeader = CryptoJS.enc.Utf8.parse(JSON.stringify(header));
var base64Header = CryptoJS.enc.Base64.stringify(wordArrayHeader);

var payload = {
    "sub": "1234567890",
    "name": "John Doe",
    "admin": true
};
var wordArrayPayload = CryptoJS.enc.Utf8.parse(JSON.stringify(payload));
var base64Payload = CryptoJS.enc.Base64.stringify(wordArrayPayload);

var signature = CryptoJS.HmacSHA256(base64Header + "." + base64Payload , "secret");
var base64Sign = CryptoJS.enc.Base64.stringify(signature);
var token = base64Header + "." + base64Payload + "." + base64Sign;

I am unable to do the exact opposite, to verify the token. For example, the following throws me an error when decrypting the signature:

var token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ";
var base64Header = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
var base64Payload = "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9";
var base64Sign = "TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ";

var parsedSignArray = CryptoJS.enc.Base64.parse(base64Sign);
var parsedSign = parsedSignArray.toString(CryptoJS.enc.Utf8);
var decrypted = CryptoJS.HmacSHA256.decrypt(parsedSign , "secret");
console.log(decrypted);

What am I missing here? BTW, just for this example, I am using token from http://jwt.io


Solution

  • There is no such thing as CryptoJS.HmacSHA256.decrypt. Since HMAC, as well as hash functions in general, are one-way functions the only way to verify the "signature" would be to run the same one way function over the same string and then compare it with the one that you've got:

    var signature = CryptoJS.HmacSHA256(base64Header + "." + base64Payload , "secret").toString(CryptoJS.enc.Base64);
    var valid = signature == base64Sign;