Skip to content

Instantly share code, notes, and snippets.

@cnorthwood
Created April 26, 2021 11:04
Show Gist options
  • Save cnorthwood/4e12055fb374dc86ddedfa6b6e552e0a to your computer and use it in GitHub Desktop.
Save cnorthwood/4e12055fb374dc86ddedfa6b6e552e0a to your computer and use it in GitHub Desktop.
import crypto from "crypto";
const TOKEN_ALPHABET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
function encode(bytes: Buffer) {
let encodedString = "";
const mainCount = Math.floor(bytes.length / 5) * 5;
let i = 0;
for (; i < mainCount; ) {
const byte1 = bytes[i++];
const byte2 = bytes[i++];
const byte3 = bytes[i++];
const byte4 = bytes[i++];
const byte5 = bytes[i++];
encodedString +=
TOKEN_ALPHABET[byte1 >>> 3] +
TOKEN_ALPHABET[((byte1 << 2) | (byte2 >>> 6)) & 31] +
TOKEN_ALPHABET[(byte2 >>> 1) & 31] +
TOKEN_ALPHABET[((byte2 << 4) | (byte3 >>> 4)) & 31] +
TOKEN_ALPHABET[((byte3 << 1) | (byte4 >>> 7)) & 31] +
TOKEN_ALPHABET[(byte4 >>> 2) & 31] +
TOKEN_ALPHABET[((byte4 << 3) | (byte5 >>> 5)) & 31] +
TOKEN_ALPHABET[byte5 & 31];
}
/* eslint-disable security/detect-object-injection */
const remain = bytes.length - mainCount;
if (remain === 1) {
const byte = bytes[i];
encodedString += TOKEN_ALPHABET[byte >>> 3] + TOKEN_ALPHABET[(byte << 2) & 31];
} else if (remain === 2) {
const byte1 = bytes[i++];
const byte2 = bytes[i];
encodedString +=
TOKEN_ALPHABET[byte1 >>> 3] +
TOKEN_ALPHABET[((byte1 << 2) | (byte2 >>> 6)) & 31] +
TOKEN_ALPHABET[(byte2 >>> 1) & 31] +
TOKEN_ALPHABET[(byte2 << 4) & 31];
} else if (remain === 3) {
const byte1 = bytes[i++];
const byte2 = bytes[i++];
const byte3 = bytes[i];
encodedString +=
TOKEN_ALPHABET[byte1 >>> 3] +
TOKEN_ALPHABET[((byte1 << 2) | (byte2 >>> 6)) & 31] +
TOKEN_ALPHABET[(byte2 >>> 1) & 31] +
TOKEN_ALPHABET[((byte2 << 4) | (byte3 >>> 4)) & 31] +
TOKEN_ALPHABET[(byte3 << 1) & 31];
} else if (remain === 4) {
const byte1 = bytes[i++];
const byte2 = bytes[i++];
const byte3 = bytes[i++];
const byte4 = bytes[i];
encodedString +=
TOKEN_ALPHABET[byte1 >>> 3] +
TOKEN_ALPHABET[((byte1 << 2) | (byte2 >>> 6)) & 31] +
TOKEN_ALPHABET[(byte2 >>> 1) & 31] +
TOKEN_ALPHABET[((byte2 << 4) | (byte3 >>> 4)) & 31] +
TOKEN_ALPHABET[((byte3 << 1) | (byte4 >>> 7)) & 31] +
TOKEN_ALPHABET[(byte4 >>> 2) & 31] +
TOKEN_ALPHABET[(byte4 << 3) & 31];
}
/* eslint-enable security/detect-object-injection */
return encodedString;
}
export async function generateRandomToken(size: number) {
return encode(
await new Promise((resolve, reject) => {
crypto.randomBytes(size, (err, buf) => {
if (err) {
reject(err);
} else {
resolve(buf);
}
});
}),
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment