To understand how digital signatures and JWT work, I tried to verify a JSON Web Token using RS256 algorithm. However, when I decrypt the signature part of a JWT it gives non-string values, so I cannot compare the value with the calculated hash value. Can someone tell me what part I am misunderstanding in my code? I used a RS256 algorithm JWT token, and all values are given in https://jwt.io/. If you scroll down and select RS256 option, you can get base64url encoded JWT and public/private keys. I guess that I am decrypting the wrong part of the JWT, but cannot find it out.
const base64url = require('base64url')
const crypto = require('crypto')
const fs = require('fs')
function readKeyPair(path) {
return {
publicKey: fs.readFileSync(path.publicPath),
privateKey: fs.readFileSync(path.privatePath)
}
}
function encryptWithPrivateKey(privateKey, message) {
const bufferMessage = Buffer.from(message, 'utf8');
return crypto.privateEncrypt(privateKey, bufferMessage)
}
function decryptWithPublicKey(publicKey, buffer) {
return crypto.publicDecrypt(publicKey, buffer);
}
function hashMessage(message, algorithm) {
const hash = crypto.createHash(algorithm);
hash.update(message);
const hashValue = hash.digest('hex')
return hashValue;
}
const JWT = (
'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZS' +
'I6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.POstGetfAytaZ' +
'S82wHcjoTyoqhMyxXiWdR7Nn7A29DNSl0EiXLdwJ6xC6AfgZWF1bOsS_TuYI3OG85AmiExR' +
'EkrS6tDfTQ2B3WXlrr-wp5AokiRbz3_oB4OxG-W9KcEEbDRcZc0nH3L7LzYptiy1PtAylQG' +
'xHTWZXtGz4ht0bAecBgmpdgXMguEIcoqPJ1n3pIWk_dUZegpqx0Lka21H6XxUTxiy8Ocaar' +
'A8zdnPUnV6AmNP3ecFawIFYdvJB_cm-GvpCSbr8G8y_Mllj8f4x9nBH8pQux89_6gUY618i' +
'Yv7tuPWBFfEbLxtF2pZS6YC1aSfLQxeNe8djT9YjpvRZA'
)
const KEY_PAIR_PATH = {
publicPath: 'rsa_pub.pem',
privatePath: 'rsa_priv.pem'
}
const jwtParts = JWT.split('.')
const header = base64url.decode(jwtParts[0])
const payload = base64url.decode(jwtParts[1])
const signature = base64url.toBuffer(jwtParts[2])
console.log(header)
console.log(payload)
console.log(signature)
const keyPair = readKeyPair(KEY_PAIR_PATH)
const decryptedHashValue = decryptWithPublicKey(keyPair.publicKey, signature);
const newHash = hashMessage(jwtParts[0] + '.' + jwtParts[1], 'SHA256')
console.log()
console.log(decryptedHashValue.toString())
console.log()
console.log(newHash)
and this is output of the code
{"alg":"RS256","typ":"JWT"}
{"sub":"1234567890","name":"John Doe","admin":true,"iat":1516239022}
<Buffer 3c eb 2d 19 eb 5f 03 2b 5a 65 2f 36 c0 77 23 a1 3c a8 aa 13 32 c5 78 96 75 1e cd 9f b0 36 f4 33 52 97 41 22 5c b7 70 27 ac 42 e8 07 e0 65 61 75 6c eb ... 206 more bytes>
010 `�He �A����O��H7��Rb�'��!9���Ct�_S
8041fb8cba9e4f8cc1483790b05262841f27fdcb211bc039ddf8864374db5f53