diff --git a/src/background/main.background.ts b/src/background/main.background.ts index 07c8cb0fc5..4807f1afc7 100644 --- a/src/background/main.background.ts +++ b/src/background/main.background.ts @@ -5,6 +5,7 @@ import { AppIdService, CryptoService, TokenService, + TotpService, UserService, UtilsService, } from 'jslib/services'; @@ -17,6 +18,7 @@ import { PlatformUtilsService as PlatformUtilsServiceAbstraction, StorageService as StorageServiceAbstraction, TokenService as TokenServiceAbstraction, + TotpService as TotpServiceAbstraction, UserService as UserServiceAbstraction, UtilsService as UtilsServiceAbstraction, } from 'jslib/abstractions'; @@ -46,7 +48,6 @@ import LockService from '../services/lock.service'; import PasswordGenerationService from '../services/passwordGeneration.service'; import SettingsService from '../services/settings.service'; import SyncService from '../services/sync.service'; -import TotpService from '../services/totp.service'; export default class MainBackground { messagingService: MessagingServiceAbstraction; @@ -68,7 +69,7 @@ export default class MainBackground { lockService: LockService; syncService: SyncService; passwordGenerationService: PasswordGenerationService; - totpService: TotpService; + totpService: TotpServiceAbstraction; autofillService: AutofillService; containerService: ContainerService; diff --git a/src/services/autofill.service.ts b/src/services/autofill.service.ts index 38b1cce136..0dfea5d9a7 100644 --- a/src/services/autofill.service.ts +++ b/src/services/autofill.service.ts @@ -8,13 +8,13 @@ import AutofillPageDetails from '../models/domain/autofillPageDetails'; import AutofillScript from '../models/domain/autofillScript'; import CipherService from './cipher.service'; -import TotpService from './totp.service'; import { UtilsService } from 'jslib/services'; import { PlatformUtilsService, TokenService, + TotpService, UtilsService as UtilsServiceAbstraction, } from 'jslib/abstractions'; diff --git a/src/services/totp.service.ts b/src/services/totp.service.ts deleted file mode 100644 index 946f39f390..0000000000 --- a/src/services/totp.service.ts +++ /dev/null @@ -1,117 +0,0 @@ -import ConstantsService from './constants.service'; - -import { StorageService } from 'jslib/abstractions'; - -const b32Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'; - -const TotpAlgorithm = { - name: 'HMAC', - hash: { name: 'SHA-1' }, -}; - -export default class TotpService { - constructor(private storageService: StorageService) { - } - - async getCode(keyb32: string): Promise { - const epoch = Math.round(new Date().getTime() / 1000.0); - const timeHex = this.leftpad(this.dec2hex(Math.floor(epoch / 30)), 16, '0'); - const timeBytes = this.hex2bytes(timeHex); - const keyBytes = this.b32tobytes(keyb32); - - if (!keyBytes.length || !timeBytes.length) { - return null; - } - - const hashHex = await this.sign(keyBytes, timeBytes); - if (!hashHex) { - return null; - } - - const offset = this.hex2dec(hashHex.substring(hashHex.length - 1)); - // tslint:disable-next-line - let otp = (this.hex2dec(hashHex.substr(offset * 2, 8)) & this.hex2dec('7fffffff')) + ''; - otp = (otp).substr(otp.length - 6, 6); - return otp; - } - - async isAutoCopyEnabled(): Promise { - return !(await this.storageService.get(ConstantsService.disableAutoTotpCopyKey)); - } - - // Helpers - - private leftpad(s: string, l: number, p: string): string { - if (l + 1 >= s.length) { - s = Array(l + 1 - s.length).join(p) + s; - } - return s; - } - - private dec2hex(d: number): string { - return (d < 15.5 ? '0' : '') + Math.round(d).toString(16); - } - - private hex2dec(s: string): number { - return parseInt(s, 16); - } - - private hex2bytes(s: string): Uint8Array { - const bytes = new Uint8Array(s.length / 2); - for (let i = 0; i < s.length; i += 2) { - bytes[i / 2] = parseInt(s.substr(i, 2), 16); - } - return bytes; - } - - private buff2hex(buff: ArrayBuffer): string { - const bytes = new Uint8Array(buff); - const hex: string[] = []; - bytes.forEach((b) => { - // tslint:disable-next-line - hex.push((b >>> 4).toString(16)); - // tslint:disable-next-line - hex.push((b & 0xF).toString(16)); - }); - return hex.join(''); - } - - private b32tohex(s: string): string { - s = s.toUpperCase(); - let cleanedInput = ''; - - for (let i = 0; i < s.length; i++) { - if (b32Chars.indexOf(s[i]) < 0) { - continue; - } - - cleanedInput += s[i]; - } - s = cleanedInput; - - let bits = ''; - let hex = ''; - for (let i = 0; i < s.length; i++) { - const byteIndex = b32Chars.indexOf(s.charAt(i)); - if (byteIndex < 0) { - continue; - } - bits += this.leftpad(byteIndex.toString(2), 5, '0'); - } - for (let i = 0; i + 4 <= bits.length; i += 4) { - const chunk = bits.substr(i, 4); - hex = hex + parseInt(chunk, 2).toString(16); - } - return hex; - } - - private b32tobytes(s: string): Uint8Array { - return this.hex2bytes(this.b32tohex(s)); - } - - private async sign(keyBytes: Uint8Array, timeBytes: Uint8Array) { - const key = await window.crypto.subtle.importKey('raw', keyBytes, TotpAlgorithm, false, ['sign']); - const signature = await window.crypto.subtle.sign(TotpAlgorithm, key, timeBytes); - return this.buff2hex(signature); - } -}