Haardik
Haardik

Reputation: 227

nodejs crypto and CryptoJS giving different base64(sha256(data)) outputs

I have a node server and a react-native app. On the node server, all cryptography is done using the crypto module. On the react-native app, all cryptography is done through the crypto-js library because crypto is not available.

I have this sample code on Repl.it - https://repl.it/repls/UprightExtraneousDesigner#index.js

Copy-pasted to prevent link decay:

const crypto = require("crypto");
const base64url = require("base64url");
const CryptoJS = require("crypto-js");

let publicKey = "6rjJnHqufRdGq7LxP6UyJEDbE84YRUKyZNYc27rUBqQZ";

const hash1 = crypto.createHash("sha256").update(Buffer.from(publicKey)).digest();
const hash2 = CryptoJS.SHA256(publicKey);

const kid1 = base64url.encode(hash1)

const kid2 = CryptoJS.enc.Base64.stringify(hash2);

console.log("KID1: ", kid1);
console.log("KID2: ", kid2);

But, for some reason, they're giving me slightly different results. The output im getting is

KID1:  qlm-6fOvD0F2qxOYDCvOkkohHfXL6nd_SpBDsBOWawE
KID2:  qlm+6fOvD0F2qxOYDCvOkkohHfXL6nd/SpBDsBOWawE=

There's three differences here:

  1. KID1 has a - at index 3, whereas KID2 has a +
  2. KID1 has an _ at index 31, whereas KID2 has a /
  3. KID1 has no padding, whereas KID2 has padding at the end

Due to the discrepancies here, I'm getting problems on my server. Can someone explain to me why this is happening and how can I fix it? I think it has something to do with the characters being used in the different base64 implementations, but im not sure how to fix that.

Upvotes: 3

Views: 3459

Answers (2)

Dez
Dez

Reputation: 5838

Do the base64 conversion using the tools provided by the Node.js crypto module.

const hash1 = crypto.createHash("sha256").update(Buffer.from(publicKey)).digest('base64');

Upvotes: 3

Marco
Marco

Reputation: 7277

base64url is, as the name implies, for URLs.

I'm pretty sure + gets converted to - because + in the context of URLs means "space", / gets converted to _ because / is a path delimiter in URLs etc..

Replacing base64url with the npm module js-base64 and adjusting the code like this:

const jsbase = require("js-base64")

const kid1 = jsbase.Base64.encode(hash1)

Makes it produce the same result as CryptoJS.enc.Base64.stringify.

Upvotes: 4

Related Questions