yeojz / otplib

:key: One Time Password (OTP) / 2FA for Node.js and Browser - Supports HOTP, TOTP and Google Authenticator

Home Page:https://otplib.yeojz.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Buffer to parse a hex string preventing Expo usage

trajano opened this issue · comments

There's a bunch of Buffer.from(newSecret, 'hex') code that is preventing this library from working in Expo specifically the one in

function hotpDigestToToken(hexDigest, digits) {
  const digest = Buffer.from(hexDigest, 'hex');
...
}

Which I can't find a way to override.

Also In my attempt, I used Uint8Array which I think may be a better choice than passing hex strings.

This is my workaround for now

const hexToUint8Array = (hexString) => {
  const length = hexString.length;
  const uint8Array = new Uint8Array(length / 2);

  for (let i = 0, j = 0; i < length; i += 2, j++) {
    uint8Array[j] = parseInt(hexString.substring(i, i + 2), 16);
  }
return uint8Array;

}
function hotpDigestToToken(hexDigest, digits) {
  const digest = hexToUint8Array(hexDigest);
  const offset = digest[digest.length - 1] & 0xf;
  const binary = (digest[offset] & 0x7f) << 24 | (digest[offset + 1] & 0xff) << 16 | (digest[offset + 2] & 0xff) << 8 | digest[offset + 3] & 0xff;
  const token = binary % Math.pow(10, digits);
  return padStart(String(token), digits, '0');
}

Also to avoid having to modify the code I just added a simplistic polyfill for this one scenario

if (!global.Buffer) {
  global.Buffer = {} as typeof global.Buffer;

  global.Buffer.from = (...args: any[]): any => {
    const hexString = args[0] as string;
    const length = hexString.length;
    const uint8Array = new Uint8Array(length / 2);

    for (let i = 0, j = 0; i < length; i += 2, j++) {
      uint8Array[j] = parseInt(hexString.substring(i, i + 2), 16);
    }
    return uint8Array;
  };
}