3

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.

Haardik
  • 185
  • 2
  • 6

2 Answers2

4

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.

Marco
  • 7,007
  • 2
  • 19
  • 49
  • 3
    Wow.. I never knew there was a difference between the two. I gave you an upvote but I'm gonna accept the other answer as it solves this without using more libraries. – Haardik May 25 '20 at 23:42
3

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');
Dez
  • 5,702
  • 8
  • 42
  • 51