From cb78c848d664924b0a2445da94a897518ce55b21 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Fri, 24 May 2024 13:36:23 +0530 Subject: [PATCH] Impl --- web/apps/auth/src/services/steam.ts | 30 +++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/web/apps/auth/src/services/steam.ts b/web/apps/auth/src/services/steam.ts index f53259687..8a9fcdf18 100644 --- a/web/apps/auth/src/services/steam.ts +++ b/web/apps/auth/src/services/steam.ts @@ -24,12 +24,30 @@ export class Steam { } generate({ timestamp }: { timestamp: number } = { timestamp: Date.now() }) { + // Same as regular TOTP. const counter = Math.floor(timestamp / 1000 / this.period); - const digest = new Uint8Array( - sha1HMACDigest(this.secret.buffer, uintToArray(counter)), - ); - return `${timestamp}`; + // Same as regular HOTP, but algorithm is fixed to SHA-1. + const digest = sha1HMACDigest(this.secret.buffer, uintToArray(counter)); + + // Same calculation as regular HOTP. + const offset = digest[digest.length - 1] & 15; + let otp = + ((digest[offset] & 127) << 24) | + ((digest[offset + 1] & 255) << 16) | + ((digest[offset + 2] & 255) << 8) | + (digest[offset + 3] & 255); + + // However, instead of using this as the OTP, use it to index into + // the steam OTP alphabet. + const alphabet = "23456789BCDFGHJKMNPQRTVWXY"; + const N = alphabet.length; + const steamOTP = []; + for (let i = 0; i < 5; i++) { + steamOTP.push(alphabet[otp % N]); + otp = Math.trunc(otp / N); + } + return steamOTP.join(""); } } @@ -38,7 +56,7 @@ export class Steam { const uintToArray = (n: number): Uint8Array => { const result = new Uint8Array(8); for (let i = 7; i >= 0; i--) { - result[i] = n & 0xff; + result[i] = n & 255; n >>= 8; } return result; @@ -52,5 +70,5 @@ const sha1HMACDigest = (key: ArrayBuffer, message: Uint8Array) => { const hmac = new jsSHA("SHA-1", "UINT8ARRAY"); hmac.setHMACKey(key, "ARRAYBUFFER"); hmac.update(message); - return hmac.getHMAC("ARRAYBUFFER"); + return hmac.getHMAC("UINT8ARRAY"); };