Created
April 26, 2021 11:04
-
-
Save cnorthwood/4e12055fb374dc86ddedfa6b6e552e0a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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