Skip to content

Instantly share code, notes, and snippets.

@ronnieroyston
Last active August 22, 2023 21:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ronnieroyston/b15bc38341b70e5e63da6327375555d0 to your computer and use it in GitHub Desktop.
Save ronnieroyston/b15bc38341b70e5e63da6327375555d0 to your computer and use it in GitHub Desktop.
JSON Web Signature (JWS) Token via Asymmetric RSA Key Pair (RSASSA-PKCS1-v1_5) Using Node.js Crypto Module
import { Buffer } from 'node:buffer';
import fs from "node:fs";
import url from 'node:url';
import path from "node:path";
const {createSign, createVerify, generateKeyPairSync} = await import('node:crypto');
var claims = {name:"Joe",roles:["member","admin"]};
var { privateKey, publicKey } = generateKeyPairSync("rsa", {
modulusLength: 2048,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
}
});
(async function () {
let jws = await returnJWS(claims);
console.log("\x1b[37mYour JWS token is: " + consoleString(jws));
console.log("Paste JSON Web Token In Terminal Then Press Enter.")
})();
function returnJWS(claims){
let headerObject = {
alg: 'RS256',
typ: 'JWT',
kid: 'public'
};
let headerString = JSON.stringify(headerObject);
let encodedHeader = Buffer.from(headerString).toString('base64url');
let payloadString = JSON.stringify(claims);
let encodedPayload = Buffer.from(payloadString).toString('base64url');
const sign = createSign('SHA256');
sign.write(encodedHeader + '.' + encodedPayload);
sign.end();
let signature = sign.sign(privateKey, 'base64url');
let jsonWebToken = encodedHeader + '.' + encodedPayload + '.' + signature;
return jsonWebToken;
}
function validateJWS(jwt){
try {
let jwtParts = jwt.split('.');
let jwtHeader = jwtParts[0];
let jwtPayload = jwtParts[1];
let jwtSignature = jwtParts[2];
let valid = false;
let header = JSON.parse(Buffer.from(jwtHeader, 'base64url').toString('utf-8'));
let alg = header.alg;
if(alg === "RS256"){ // MUST verify alg is not set to none
let verify = createVerify('SHA256');
verify.write(jwtHeader + '.' + jwtPayload);
verify.end();
valid = verify.verify(publicKey, jwtSignature, 'base64url');
if(valid){
return JSON.parse(Buffer.from(jwtPayload, 'base64url').toString('utf-8'));
} else {
throw (error)
}
} else {
throw (error)
}
} catch (e) {
//console.log (e);
return "\x1b[31mInvalid Token!\x1b[37m";
}
}
function generatePrivateKey (str) {
return new Promise(function(resolve, reject) {
try {
let key = createPrivateKey({
key: str,
format: 'pem',
encoding: 'utf-8'
})
resolve (key);
} catch (e) {
reject (e);
}
});
}
function generatePublicKey (str) {
return new Promise(function(resolve, reject) {
try {
let key = createPublicKey({
key: str,
format: 'pem',
encoding: 'utf-8'
})
resolve (key);
} catch (e) {
reject (e);
}
});
}
export default {returnJWS, validateJWS};
process.stdin.setEncoding('utf8');
process.stdin.on('readable', async () => {
let chunk;
while ((chunk = process.stdin.read()) !== null) {
console.log(await validateJWS(chunk));
}
});
function consoleString(token){
let tokenParts = token.split(/(\.)/);
let colors = ["32m","31m","33m","34m","36m"];
let color = "\x1b[X";
let str = ""
tokenParts.forEach(function(part,index){
if(part != "."){
str += color.replace("X",colors.shift())
}
str += part;
str += "\x1b[37m"
})
return str;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment