From a4b769f98295eaf81a4324675fdbdb62611a4332 Mon Sep 17 00:00:00 2001 From: Drew Ansbacher Date: Thu, 26 Aug 2021 11:23:24 -0600 Subject: [PATCH] checkpoint --- .../app/pages/product-key/product-key.page.ts | 7 ++ .../src/app/services/api/http.service.ts | 66 +++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/setup-wizard/src/app/pages/product-key/product-key.page.ts b/setup-wizard/src/app/pages/product-key/product-key.page.ts index dbfdf8560..1f9c69dc8 100644 --- a/setup-wizard/src/app/pages/product-key/product-key.page.ts +++ b/setup-wizard/src/app/pages/product-key/product-key.page.ts @@ -1,6 +1,7 @@ import { Component } from '@angular/core' import { iosTransitionAnimation, LoadingController, NavController } from '@ionic/angular' import { ApiService } from 'src/app/services/api/api.service' +import { AES_CTR, decodeUtf8, encodeUtf8 } from 'src/app/services/api/http.service' import { StateService } from 'src/app/services/state.service' @Component({ @@ -20,6 +21,12 @@ export class ProductKeyPage { ) {} async submit () { + + const ret = await AES_CTR.encryptPbkdf2(this.productKey, encodeUtf8('hello world')) + const arr = await AES_CTR.decryptPbkdf2(this.productKey, ret) + + console.log(decodeUtf8(arr)) + if(!this.productKey) return this.error = "Must enter product key" const loader = await this.loadingCtrl.create({ diff --git a/setup-wizard/src/app/services/api/http.service.ts b/setup-wizard/src/app/services/api/http.service.ts index 5998200a8..01ae7bb27 100644 --- a/setup-wizard/src/app/services/api/http.service.ts +++ b/setup-wizard/src/app/services/api/http.service.ts @@ -176,3 +176,69 @@ function withTimeout (req: Observable, timeout: number): Observable { interval(timeout).pipe(take(1), map(() => { throw new Error('timeout') })), ) } + +type AES_CTR = { + encryptPbkdf2: (secretKey: string, messageBuffer: Uint8Array) => Promise<{ cipher: Uint8Array, counter: Uint8Array, salt: Uint8Array }> + decryptPbkdf2: (secretKey, a: { cipher: Uint8Array, counter: Uint8Array, salt: Uint8Array }) => Promise +} + +export const AES_CTR: AES_CTR = { + encryptPbkdf2: async (secretKey: string, messageBuffer: Uint8Array) => { + + const { key, salt } = await pbkdf2(secretKey, { name: 'AES-CTR', length: 256 }) + const counter = window.crypto.getRandomValues(new Uint8Array(16)) + const algorithm = { name: 'AES-CTR', counter, length: 64 } + + return window.crypto.subtle.encrypt(algorithm, key, messageBuffer) + .then(encrypted => new Uint8Array(encrypted)) + .then(cipher => ({ cipher, counter, salt })) + }, + decryptPbkdf2: async (secretKey: string, a: { cipher: Uint8Array, counter: Uint8Array, salt: Uint8Array }) => { + const { cipher, counter, salt } = a + const { key } = await pbkdf2(secretKey, { name: 'AES-CTR', length: 256 }, salt) + const algorithm = { name: 'AES-CTR', counter, length: 64 }; + + (window as any).stuff = { algorithm, key, cipher } + return window.crypto.subtle.decrypt(algorithm, key, cipher) + .then(decrypted => new Uint8Array(decrypted)) + }, +} + +async function pbkdf2 (secretKey: string, algorithm: AesKeyAlgorithm | HmacKeyGenParams, salt = window.crypto.getRandomValues(new Uint8Array(16))): Promise<{ salt: Uint8Array, key: CryptoKey, rawKey: Uint8Array }> { + const usages: KeyUsage[] = algorithm.name === 'AES-CTR' ? [ 'encrypt', 'decrypt' ] : [ 'sign' ] + const keyMaterial = await window.crypto.subtle.importKey( + 'raw', + encodeUtf8(secretKey), + 'PBKDF2', + false, + ['deriveBits', 'deriveKey'], + ) + + const key = await window.crypto.subtle.deriveKey( + { + name: 'PBKDF2', + salt, + iterations: 100000, + hash: 'SHA-256', + }, + keyMaterial, + algorithm, + true, + usages, + ) + + const rawKey = await window.crypto.subtle.exportKey('raw', key).then(r => new Uint8Array(r)) + return { salt, key, rawKey } +} + +export const encode16 = (buffer: Uint8Array) => buffer.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '') +export const decode16 = hexString => new Uint8Array(hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16))) + +export function encodeUtf8 (str: string): Uint8Array { + const encoder = new TextEncoder() + return encoder.encode(str) +} + +export function decodeUtf8 (arr: Uint8Array): string { + return new TextDecoder().decode(arr); +} \ No newline at end of file