Decode Jwt Token in Node - without Library - javascript

I have a following code to decode the Jwt token in Javascript (ref: How to decode jwt token in javascript)
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c';
function parseJwt(token) {
var base64Url = token.split('.')[1];
var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
console.log(JSON.parse((atob(base64))))
};
parseJwt(token);
I am getting the payload which I needed from above code
But I am implementing it in node where we dont have "atob" function to decode the base64 encoded string
Seems we need to use Buffer in node. Did my research and came up with below solution which didn't work.
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c';
function parseJwt(token) {
const base64Url = token.split('.')[1];
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
const buff = new Buffer(base64, 'base64');
const payloadinit = buff.toString('ascii');
const payload = JSON.parse(payloadinit);
console.log(payload)
};
parseJwt(token);
Please let me know if there is any better approach - No libraries(Jwt, or decode-Jwt)

Actually I have tried it in independent environment and above code works like charm for getting Jwt token pay load
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c'
const base64Url = token.split('.')[1];
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
const buff = new Buffer(base64, 'base64');
const payloadinit = buff.toString('ascii');
const payload = JSON.parse(payloadinit);
console.log(payload);
https://repl.it/#Punith/RuralSeveralAdaware

const DecodeJWT= (token) => {
try {
return JSON.parse(atob(token.split('.')[1]));
} catch (e) {
return null;
}
};
simple & easy way

Related

I need to replicate this from Java to JavaScript (NodeJs)

I try to get the same functionality of java class to replicate in NodeJs, but I can't do it. I don't understand all the JavaCode, specialy when the instance sing() (what's return). for that can't replicate into NodeJs
Java Code
public String generateSignature(String key, String stringToSign) throws Exception {
Signature signatureInstance = Signature.getInstance("SHA256WithRSA");
ServiceKeyRep keyRep = new ServiceKeyRep(KeyRep.Type.PRIVATE, "RSA", "PKCS#8", Base64.getDecoder().decode(key));
PrivateKey resolvedPrivateKey = (PrivateKey) keyRep.readResolve();
signatureInstance.initSign(resolvedPrivateKey);
byte[] bytesToSign = stringToSign.getBytes("UTF-8");
signatureInstance.update(bytesToSign);
String signatureString = Base64.getEncoder().encodeToString(signatureBytes);
return signatureString;
}
And I try this on Node JS
const privateKey = fs.readFileSync('myKey.pem', 'utf-8');
const stringToSign = new Int8Array([ myData ]);
const data = Buffer.from(stringToSign);
const sign = crypto.sign("RSA-SHA256", data , privateKey);
const signature = sign.toString('base64');
//Printing the signature
console.log(`Signature:\n\n ${signature}`);
but when I print, the out is not the same
Using crypto library we can do something similar in JS. Adapt as appropriate, this is just a reference.
const fs = require('fs');
const crypto = require('crypto');
function generateSignature(key, stringToSign) {
const privateKey = fs.readFileSync(key, 'utf-8');
const sign = crypto.createSign('RSA-SHA256');
sign.update(stringToSign);
const signature = sign.sign(privateKey, 'base64');
return signature;
}
const key = 'myKey.pem';
const stringToSign = 'myData';
const signature = generateSignature(key, stringToSign);
console.log(`Signature:\n\n${signature}`);

How to use Node JS to decrypt a file that was encrypted using C#

I have files encrypted in C# (using DES, PKCS7). I need to decode these files in Node JS.
The code I use to decrypt in C# looks like this:
public string SSFile_Reader( string fileToDecrypt )
{
DESCryptoServiceProvider provider = new DESCryptoServiceProvider
{
Key = Encoding.UTF8.GetBytes( "13^07v90" ),
IV = Encoding.UTF8.GetBytes( "13^07v90" ),
Padding = PaddingMode.PKCS7
};
using( FileStream streamToDecrypt = new FileStream( fileToDecrypt, FileMode.Open, FileAccess.Read, FileShare.ReadWrite ) )
{
ICryptoTransform cryptoTransform = provider.CreateDecryptor();
string outputString = "";
using( CryptoStream stream2 = new CryptoStream( streamToDecrypt, cryptoTransform, CryptoStreamMode.Read ) )
{
try
{
using( StreamReader reader = new StreamReader( stream2 ) )
{
try
{
outputString = reader.ReadToEnd();
}
catch
{
//handle error here
}
stream2.Close();
streamToDecrypt.Close();
return outputString;
}
}
catch( Exception exception )
{
//handle error here
}
}
}
return '';
}
I literally need to convert the above to Node JS. I have tried the Node JS code below, but the output is just some random stuff rather than the original encrypted string:
const { Readable } = require("stream");
const { scrypt, scryptSync, randomFill, createCipheriv, createDecipheriv } = require('crypto');
const fs = require('fs');
const [, , pathToEncryptedFile] = process.argv;
if (!pathToEncryptedFile) {
console.log('No file to decrypt')
exit()
}
const keyAndIv = '31335e3037763930'; //hex equivalence of 13^07v90
const key = Buffer.from(keyAndIv, 'hex');
const iv = Buffer.from(keyAndIv, 'hex');
const decryptedData = '';
const decipher = createDecipheriv('des', key, iv);
const readableStream = Readable.from(fs.createReadStream(pathToEncryptedFile)
.pipe(decipher));
readableStream.on("data", (chunk) => {
decryptedData += chunk.toString()
})
readableStream.on('end', function () {
console.log({decryptedData})
});
readableStream.on('error', function (err) {
console.log({err})
});
I also tried using crypto-js to no avail (https://github.com/brix/crypto-js/issues/396).
This is an example of one of the files I need to decrypt: https://files.fm/u/6pewftkk2
I can also give the C# code that does the encryption if the C# code given above for the decryption does not suffice
One possible variant is to load the ciphertext completely from the file system and decrypt it:
var crypto = require('crypto')
var fs = require('fs')
const algorithm = 'des'; // defaults to 'des-cbc';
const password = 'Password used to generate key';
const key = '13^07v90';
const iv = '13^07v90';
const ciphertext = fs.readFileSync('<path to high_classes.ssdata>');
const decipher = crypto.createDecipheriv(algorithm, key, iv);
const plaintext = decipher.update(ciphertext, '', 'utf8') + decipher.final();
console.log(plaintext);
which outputs the following plaintext (for the linked file):
SSS1
SSS2
SSS3
Alternatively, especially for large data, the plaintext can also be streamed to a file. To do this, replace the last block with:
const decipher = crypto.createDecipheriv(algorithm, key, iv);
const readStream = fs.createReadStream('<path to high_classes.ssdata>');
const writeStream = fs.createWriteStream('<path to file where decrypted data should be saved>');
readStream.pipe(decipher).pipe(writeStream);
which creates a file containing the decrypted data.
Note that DES is outdated and insecure these days. Using the key as an IV is also insecure. Typically, a random IV is generated during encryption and passed to the other side along with the ciphertext (usually concatenated).

Javascript - query params from window.location.href

I'm new to Javascript syntax; sorry if this is too basic.
With this query:
const params = queryString.parse(window.location.href)
I am fetching:
{http://localhost:3000/#access_token: "accessToken", refresh_token: "refreshToken"}
and now I can easily do:
const refresh_token = params.refresh_token;
But how do I fetch "accessToken"?
It looks like the hash is malformed JSON. While it'd be parsable by adding a { to the left side, adding "s around word characters before a :, and JSON.parse-ing it:
// const { hash } = window.location;
// const badJSON = '{' + hash.slice(1);
// now, you'll have:
const badJSON = '{' + 'access_token: "accessToken", refresh_token: "refreshToken"}';
const json = badJSON.replace(/\w+(?=:)/g, '"$&"');
const obj = JSON.parse(json);
console.log(obj.access_token);
console.log(obj.refresh_token);
This is extremely awkward, and is a solution to an X/Y problem. It would be much better to fix whatever generates the URL so that its format is in the standard format so you can parse it with URLSearchParams. For example, the URL should be something like
http://localhost:3000/?access_token=accessToken&refresh_token=refreshToken
And then it can be parsed very easily:
const url = 'http://localhost:3000/?access_token=accessToken&refresh_token=refreshToken';
const params = new URLSearchParams(url.match(/\?.*/)[0]);
// in your real code, the above can be replaced with:
// const params = new URLSearchParams(window.location.search);
console.log(params.get('access_token'));
This did the trick:
getHashParams() {
const hashParams = {};
const r = /([^&;=]+)=?([^&;]*)/g;
const q = window.location.hash.substring(1);
let e = r.exec(q);
while (e) {
hashParams[e[1]] = decodeURIComponent(e[2]);
e = r.exec(q);
}
return hashParams;
}
and calling like so:
const params = this.getHashParams();
console.log(params);
logged:
{access_token: "aceessToken", refresh_token: "refreshToken"}

How to convert this signature method from crypto (node) to crypto-js (browser)?

I have a signature method that is meant to be used in Node.js but I'd like to implement it client-side with crypto-js. It should work in latest Chrome versions.
I have tried to follow some answers like this one: Decode a Base64 String using CryptoJS
But I either get errors such as "Error: Malformed UTF-8 data", or a different result than the expected hmacDigest.
I am not sure how I could find an alternative to the "binary" digest although I found this question:
How to get digest representation of CryptoJS.HmacSHA256 in JS
The method is supposed to answer the following:
"Message signature using HMAC-SHA512 of (URI path + SHA256(nonce + POST data)) and base64 decoded secret API key"
This is the Nodejs version (with crypto):
const crypto = require('crypto')
function sign(path, params, secret) {
const message = querystring.stringify(params)
const secretBase64 = Buffer.from(secret, 'base64')
const hash = crypto.createHash('sha256')
const hmac = crypto.createHmac('sha512', secretBase64)
const hashDigest = hash.update(params.nonce + message).digest('binary')
const hmacDigest = hmac.update(path + hashDigest, 'binary').digest('base64')
return hmacDigest
}
note: querystring is just an helper module that can also run in browsers: https://nodejs.org/api/querystring.html
This is my attempt (wip) at implementing with crypto-js:
import cryptojs from 'crypto-js')
function sign (path, params, secret) {
const message = querystring.stringify(params)
const secretParsed = cryptojs.enc.Base64.parse(secret)
const secretDecoded = cryptojs.enc.Utf8.stringify(secretParsed) // -> this throws an error as "Error: Malformed UTF-8 data"
const hash = cryptojs.SHA256(params.nonce + message).toString(cryptojs.enc.hex)
const hmac = cryptojs.HmacSHA512(path + hash, secretDecoded).toString(cryptojs.enc.hex)
return hmac
}
Try this ! I think this is what you looking for !
const crypto = require("crypto")
const sign = (path, params, secret) => {
const message = querystring.stringify(params)
const secret = Buffer.from(secret, 'base64')
let sign = params.nonce + message
let hash = crypto.createHmac('sha256', secret)
.update(sign)
.digest("base64").toString()
let encoded = encodeURIComponent(hash)
return encoded
}

Best approch to decode the PKCS12 file and get the encrypted private key from it using JavaScript

Please suggest any idea to decode the PKCS12 file and get the encrypted private key from it using JavaScript. I know that it can be done very easily using Java Keytool command and Java Security package. But I want it to be done by Java Script. Bellow is my actual requirement.
I have a ".p12" extention file which is one of the formats of pkcs12.
It should be decoded first and need to trace out the decoded file where exactly the encrypted Private key is placed.
Need to get that encrypted Private key and Decrypt it and send it to the receiver.
And all this Should be done only in JAVASCRIPT.
I think this might be what you are looking for:
"A native implementation of TLS (and various other cryptographic tools) in JavaScript."
https://github.com/digitalbazaar/forge#pkcs12
It sounds like this example is close:
// decode p12 from base64
var p12Der = forge.util.decode64(p12b64);
// get p12 as ASN.1 object
var p12Asn1 = forge.asn1.fromDer(p12Der);
// decrypt p12
var p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, 'password');
// look at pkcs12.safeContents
// generate p12, base64 encode
var p12Asn1 = forge.pkcs12.toPkcs12Asn1(
privateKey, certificateChain, 'password');
var p12Der = forge.asn1.ToDer(p12Asn1).getBytes();
var p12b64 = forge.util.encode64(p12Der);
Rgds....Hoonto/Matt
This will work Perfectly
// get p12 as ASN.1 object
var p12Asn1 = forge.asn1.fromDer(buffer);
// decrypt p12 using the password 'password'
var p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, password);
// get bags by type
var certBags = p12.getBags({bagType: forge.pki.oids.certBag});
var pkeyBags = p12.getBags({bagType: forge.pki.oids.pkcs8ShroudedKeyBag});
// fetching certBag
var certBag = certBags[forge.pki.oids.certBag][0];
// fetching keyBag
var keybag = pkeyBags[forge.pki.oids.pkcs8ShroudedKeyBag][0];
// generate pem from private key
var privateKeyPem = forge.pki.privateKeyToPem(keybag.key);
// generate pem from cert
var certificate = forge.pki.certificateToPem(certBag.cert);
Thanks to the examples from #Ujjawal and #hoonto I was able to get the following working well.
const decodePKCS12 = (
file // Dom File object
) => {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onload = evt => {
try {
const binary = evt && evt.target ? evt.target.result : null
if (!binary) {
reject(new Error('No file data'))
}
const p12Asn1 = asn1.fromDer(binary)
const p12 = pkcs12.pkcs12FromAsn1(p12Asn1)
const certBags = p12.getBags({bagType: pki.oids.certBag})
const pkeyBags = p12.getBags({bagType: pki.oids.pkcs8ShroudedKeyBag})
const certBag = certBags[pki.oids.certBag][0]
const keybag = pkeyBags[pki.oids.pkcs8ShroudedKeyBag][0]
const certificate = pki.certificateToPem(certBag.cert)
const privateKey = pki.privateKeyToPem(keybag.key)
resolve({certificate, privateKey})
} catch (e) {
reject(e)
}
}
reader.onerror = reject
reader.readAsBinaryString(file)
})
}

Categories

Resources