From 36aa33ed5a00804a1b272bf2a2e401982150a220 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Fri, 24 May 2024 13:08:41 +0530 Subject: [PATCH] Move to separate file --- web/apps/auth/package.json | 1 + web/apps/auth/src/services/code.ts | 27 ----------------- web/apps/auth/src/services/steam.ts | 46 +++++++++++++++++++++++++++++ web/docs/dependencies.md | 4 +++ 4 files changed, 51 insertions(+), 27 deletions(-) create mode 100644 web/apps/auth/src/services/steam.ts diff --git a/web/apps/auth/package.json b/web/apps/auth/package.json index 463ff06e8..268f6f5c6 100644 --- a/web/apps/auth/package.json +++ b/web/apps/auth/package.json @@ -7,6 +7,7 @@ "@ente/accounts": "*", "@ente/eslint-config": "*", "@ente/shared": "*", + "jssha": "~3.3.1", "otpauth": "^9" } } diff --git a/web/apps/auth/src/services/code.ts b/web/apps/auth/src/services/code.ts index ac71a9adc..b5497f672 100644 --- a/web/apps/auth/src/services/code.ts +++ b/web/apps/auth/src/services/code.ts @@ -215,30 +215,3 @@ export const generateOTPs = (code: Code): [otp: string, nextOTP: string] => { } return [otp, nextOTP]; }; - -/** - * Steam OTPs. - * - * Steam's algorithm is a custom variant of TOTP that uses a 26-character - * alphabet instead of digits. - * - * A Dart implementation of the algorithm can be found in - * https://github.com/elliotwutingfeng/steam_totp/blob/main/lib/src/steam_totp_base.dart - * (MIT license), and we use that as a reference. Our implementation is written - * in the style of the other TOTP/HOTP classes that are provided by the otpauth - * JS library that we use for the normal TOTP/HOTP generation - * https://github.com/hectorm/otpauth/blob/master/src/hotp.js (MIT license). - */ -class Steam { - secret: string; - period: number; - - constructor({ secret }: { secret: string }) { - this.secret = secret; - this.period = 30; - } - - generate({ timestamp }: { timestamp: number } = { timestamp: Date.now() }) { - return `${timestamp}`; - } -} diff --git a/web/apps/auth/src/services/steam.ts b/web/apps/auth/src/services/steam.ts new file mode 100644 index 000000000..e6007287f --- /dev/null +++ b/web/apps/auth/src/services/steam.ts @@ -0,0 +1,46 @@ +import jsSHA from "jssha"; + +/** + * Steam OTPs. + * + * Steam's algorithm is a custom variant of TOTP that uses a 26-character + * alphabet instead of digits. + * + * A Dart implementation of the algorithm can be found in + * https://github.com/elliotwutingfeng/steam_totp/blob/main/lib/src/steam_totp_base.dart + * (MIT license), and we use that as a reference. Our implementation is written + * in the style of the other TOTP/HOTP classes that are provided by the otpauth + * JS library that we use for the normal TOTP/HOTP generation + * https://github.com/hectorm/otpauth/blob/master/src/hotp.js (MIT license). + */ +export class Steam { + secret: string; + period: number; + + constructor({ secret }: { secret: string }) { + this.secret = secret; + this.period = 30; + } + + async generate( + { timestamp }: { timestamp: number } = { timestamp: Date.now() }, + ) { + const counter = Math.floor(timestamp / 1000 / this.period); + // const digest = new Uint8Array( + // sha1HMACDigest(this.secret, uintToBuf(counter)), + // ); + + return `${timestamp}`; + } +} + +// We don't necessarily need this dependency, we could use SubtleCrypto here +// instead too. However, SubtleCrypto has an async interface, and we already +// have a transitive dependency on jssha via otpauth, so just using it here +// doesn't increase our bundle size any further. +const sha1HMACDiggest = (key: ArrayBuffer, message: ArrayBuffer) => { + const hmac = new jsSHA("SHA-1", "ARRAYBUFFER"); + hmac.setHMACKey(key, "ARRAYBUFFER"); + hmac.update(message); + return hmac.getHMAC("ARRAYBUFFER"); +}; diff --git a/web/docs/dependencies.md b/web/docs/dependencies.md index 83a2b2799..3ea8fb240 100644 --- a/web/docs/dependencies.md +++ b/web/docs/dependencies.md @@ -198,3 +198,7 @@ some cases. - [otpauth](https://github.com/hectorm/otpauth) is used for the generation of the actual OTP from the user's TOTP/HOTP secret. + +- However, otpauth doesn't support steam OTPs. For these, we need to compute + the SHA-1, and we use the same library, `jssha` that `otpauth` uses (since + it is already part of our bundle).