mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 18:31:52 +00:00
wizard encrypt
This commit is contained in:
committed by
Drew Ansbacher
parent
0abc53423e
commit
ae01c0e0c4
@@ -1,7 +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 { HttpService } from 'src/app/services/api/http.service'
|
||||
import { StateService } from 'src/app/services/state.service'
|
||||
|
||||
@Component({
|
||||
@@ -18,15 +18,10 @@ export class ProductKeyPage {
|
||||
private stateService: StateService,
|
||||
private apiService: ApiService,
|
||||
private loadingCtrl: LoadingController,
|
||||
private httpService: HttpService
|
||||
) {}
|
||||
|
||||
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({
|
||||
@@ -36,7 +31,7 @@ export class ProductKeyPage {
|
||||
|
||||
try {
|
||||
const state = await this.apiService.verifyProductKey(this.productKey)
|
||||
this.stateService.productKey = this.productKey
|
||||
this.httpService.productKey = this.productKey
|
||||
if(state['is-recovering']) {
|
||||
await this.navCtrl.navigateForward(`/loading`, { animationDirection: 'forward', animation: iosTransitionAnimation })
|
||||
} else if (!!state['tor-address']) {
|
||||
@@ -47,6 +42,7 @@ export class ProductKeyPage {
|
||||
}
|
||||
} catch (e) {
|
||||
this.error = e.message
|
||||
this.httpService.productKey = undefined
|
||||
} finally {
|
||||
loader.dismiss()
|
||||
}
|
||||
|
||||
@@ -3,24 +3,33 @@ import { Subject } from 'rxjs'
|
||||
export abstract class ApiService {
|
||||
protected error$: Subject<string> = new Subject();
|
||||
watchError$ = this.error$.asObservable();
|
||||
abstract verifyProductKey (key: string): Promise<{ "is-recovering": boolean, "tor-address": string }>;
|
||||
abstract verifyProductKey (key: string): Promise<VerifyProductKeyRes>;
|
||||
abstract getEmbassyDrives (): Promise<EmbassyDrive[]>;
|
||||
abstract getRecoveryDrives (): Promise<RecoveryDrive[]>;
|
||||
abstract getDataTransferProgress (): Promise<TransferProgress>;
|
||||
abstract getDataTransferProgress (): Promise<TransferProgressRes>;
|
||||
abstract verifyRecoveryPassword (logicalname: string, password: string): Promise<boolean>;
|
||||
abstract setupEmbassy (setupInfo: {
|
||||
embassyLogicalname: string,
|
||||
embassyPassword: string
|
||||
recoveryLogicalname?: string,
|
||||
recoveryPassword?: string
|
||||
}): Promise<{ "tor-address": string }>
|
||||
}): Promise<SetupEmbassyRes>
|
||||
}
|
||||
|
||||
export interface TransferProgress {
|
||||
export interface VerifyProductKeyRes {
|
||||
"is-recovering": boolean
|
||||
"tor-address": string
|
||||
}
|
||||
|
||||
export interface TransferProgressRes {
|
||||
'bytes-transfered': number;
|
||||
'total-bytes': number;
|
||||
}
|
||||
|
||||
export interface SetupEmbassyRes {
|
||||
"tor-address": string
|
||||
}
|
||||
|
||||
export interface EmbassyDrive {
|
||||
logicalname: string;
|
||||
labels: string[];
|
||||
|
||||
@@ -9,6 +9,7 @@ import { map, take } from 'rxjs/operators'
|
||||
export class HttpService {
|
||||
private unauthorizedApiResponse$ = new Subject()
|
||||
fullUrl: string
|
||||
productKey: string
|
||||
|
||||
constructor (
|
||||
private readonly http: HttpClient,
|
||||
@@ -21,11 +22,11 @@ export class HttpService {
|
||||
return this.unauthorizedApiResponse$.asObservable()
|
||||
}
|
||||
|
||||
async rpcRequest<T> (rpcOpts: RPCOptions): Promise<T> {
|
||||
rpcOpts.params = rpcOpts.params || { }
|
||||
async rpcRequest<T> (body: RPCOptions): Promise<T> {
|
||||
|
||||
const httpOpts = {
|
||||
method: Method.POST,
|
||||
body: rpcOpts,
|
||||
body,
|
||||
url: `this.fullUrl`,
|
||||
}
|
||||
|
||||
@@ -39,45 +40,35 @@ export class HttpService {
|
||||
if (isRpcSuccess(res)) return res.result
|
||||
}
|
||||
|
||||
async httpRequest<T> (httpOpts: HttpOptions): Promise<T> {
|
||||
if (httpOpts.withCredentials !== false) {
|
||||
httpOpts.withCredentials = true
|
||||
}
|
||||
async httpRequest<T> (httpOpts: {
|
||||
body: RPCOptions;
|
||||
url: string;
|
||||
}): Promise<T> {
|
||||
|
||||
const urlIsRelative = httpOpts.url.startsWith('/')
|
||||
const url = urlIsRelative ?
|
||||
this.fullUrl + httpOpts.url :
|
||||
httpOpts.url
|
||||
|
||||
Object.keys(httpOpts.params || { }).forEach(key => {
|
||||
if (httpOpts.params[key] === undefined) {
|
||||
delete httpOpts.params[key]
|
||||
}
|
||||
})
|
||||
|
||||
const options = {
|
||||
responseType: httpOpts.responseType || 'json',
|
||||
body: httpOpts.body,
|
||||
responseType: 'arraybuffer',
|
||||
body: await AES_CTR.encryptPbkdf2( 'asdf', encodeUtf8( JSON.stringify(httpOpts.body))),
|
||||
observe: 'events',
|
||||
reportProgress: false,
|
||||
withCredentials: httpOpts.withCredentials,
|
||||
headers: httpOpts.headers,
|
||||
params: httpOpts.params,
|
||||
timeout: httpOpts.timeout,
|
||||
headers: {
|
||||
'Content-Encoding': 'aesctr256',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
// one minute
|
||||
timeout: 60000,
|
||||
} as any
|
||||
|
||||
let req: Observable<{ body: T }>
|
||||
switch (httpOpts.method) {
|
||||
case Method.GET: req = this.http.get(url, options) as any; break
|
||||
case Method.POST: req = this.http.post(url, httpOpts.body, options) as any; break
|
||||
case Method.PUT: req = this.http.put(url, httpOpts.body, options) as any; break
|
||||
case Method.PATCH: req = this.http.patch(url, httpOpts.body, options) as any; break
|
||||
case Method.DELETE: req = this.http.delete(url, options) as any; break
|
||||
}
|
||||
const req = this.http.post(url, httpOpts.body, options)
|
||||
|
||||
return (httpOpts.timeout ? withTimeout(req, httpOpts.timeout) : req)
|
||||
return (withTimeout(req, 60000))
|
||||
.toPromise()
|
||||
.then(res => res.body)
|
||||
.then(res => AES_CTR.decryptPbkdf2('asdf', new Uint8Array(res)))
|
||||
.then(res => JSON.parse(decodeUtf8(res)))
|
||||
.catch(e => { throw new HttpError(e) })
|
||||
}
|
||||
}
|
||||
@@ -178,8 +169,8 @@ function withTimeout<U> (req: Observable<U>, timeout: number): Observable<U> {
|
||||
}
|
||||
|
||||
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<Uint8Array>
|
||||
encryptPbkdf2: (secretKey: string, messageBuffer: Uint8Array) => Promise<Uint8Array>
|
||||
decryptPbkdf2: (secretKey, arr: Uint8Array) => Promise<Uint8Array>
|
||||
}
|
||||
|
||||
export const AES_CTR: AES_CTR = {
|
||||
@@ -191,10 +182,12 @@ export const AES_CTR: AES_CTR = {
|
||||
|
||||
return window.crypto.subtle.encrypt(algorithm, key, messageBuffer)
|
||||
.then(encrypted => new Uint8Array(encrypted))
|
||||
.then(cipher => ({ cipher, counter, salt }))
|
||||
.then(cipher => new Uint8Array([...counter,...salt,...cipher]))
|
||||
},
|
||||
decryptPbkdf2: async (secretKey: string, a: { cipher: Uint8Array, counter: Uint8Array, salt: Uint8Array }) => {
|
||||
const { cipher, counter, salt } = a
|
||||
decryptPbkdf2: async (secretKey: string, arr: Uint8Array) => {
|
||||
const counter = arr.slice(0, 16)
|
||||
const salt = arr.slice(16, 32)
|
||||
const cipher = arr.slice(32)
|
||||
const { key } = await pbkdf2(secretKey, { name: 'AES-CTR', length: 256 }, salt)
|
||||
const algorithm = { name: 'AES-CTR', counter, length: 64 };
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { pauseFor } from '../state.service'
|
||||
import { ApiService } from './api.service'
|
||||
import { ApiService, EmbassyDrive, RecoveryDrive, SetupEmbassyRes, TransferProgressRes, VerifyProductKeyRes } from './api.service'
|
||||
import { HttpService } from './http.service'
|
||||
|
||||
@Injectable({
|
||||
@@ -12,64 +11,45 @@ export class LiveApiService extends ApiService {
|
||||
private readonly http: HttpService
|
||||
) { super() }
|
||||
|
||||
async verifyProductKey(key) {
|
||||
await pauseFor(2000)
|
||||
return {
|
||||
"is-recovering": false,
|
||||
"tor-address": null
|
||||
}
|
||||
async verifyProductKey() {
|
||||
return this.http.rpcRequest<VerifyProductKeyRes>({
|
||||
method: 'verifyProductKey',
|
||||
params: {}
|
||||
})
|
||||
}
|
||||
|
||||
async getDataTransferProgress() {
|
||||
tries = Math.min(tries + 1, 4)
|
||||
return {
|
||||
'bytes-transfered': tries,
|
||||
'total-bytes': 4
|
||||
}
|
||||
return this.http.rpcRequest<TransferProgressRes>({
|
||||
method: 'getDataTransferProgress',
|
||||
params: {}
|
||||
})
|
||||
}
|
||||
|
||||
async getEmbassyDrives() {
|
||||
return [
|
||||
{
|
||||
logicalname: 'Name1',
|
||||
labels: ['label 1', 'label 2'],
|
||||
capacity: 1600.66666,
|
||||
used: 200.1255312,
|
||||
},
|
||||
{
|
||||
logicalname: 'Name2',
|
||||
labels: [],
|
||||
capacity: 1600.01234,
|
||||
used: 0.00,
|
||||
}
|
||||
]
|
||||
return this.http.rpcRequest<EmbassyDrive[]>({
|
||||
method: 'getEmbassyDrives',
|
||||
params: {}
|
||||
})
|
||||
}
|
||||
|
||||
async getRecoveryDrives() {
|
||||
await pauseFor(2000)
|
||||
return [
|
||||
{
|
||||
logicalname: 'Name1',
|
||||
version: '0.3.3',
|
||||
name: 'My Embassy'
|
||||
},
|
||||
{
|
||||
logicalname: 'Name2',
|
||||
version: '0.2.7',
|
||||
name: 'My Embassy'
|
||||
}
|
||||
]
|
||||
return this.http.rpcRequest<RecoveryDrive[]>({
|
||||
method: 'getRecoveryDrives',
|
||||
params: {}
|
||||
})
|
||||
}
|
||||
|
||||
async verifyRecoveryPassword(logicalname, password) {
|
||||
await pauseFor(2000)
|
||||
return password.length > 8
|
||||
return this.http.rpcRequest<boolean>({
|
||||
method: 'verifyRecoveryPassword',
|
||||
params: {logicalname, password}
|
||||
})
|
||||
}
|
||||
|
||||
async setupEmbassy (setupInfo) {
|
||||
await pauseFor(2000)
|
||||
return { "tor-address": 'asdfasdfasdf.onion' }
|
||||
return this.http.rpcRequest<SetupEmbassyRes>({
|
||||
method: 'setupEmbassy',
|
||||
params: setupInfo
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
let tries = 0
|
||||
|
||||
@@ -8,8 +8,6 @@ import { ApiService, EmbassyDrive, RecoveryDrive } from './api/api.service'
|
||||
export class StateService {
|
||||
polling = false
|
||||
|
||||
productKey: string
|
||||
|
||||
embassyDrive: EmbassyDrive;
|
||||
embassyPassword: string
|
||||
recoveryDrive: RecoveryDrive;
|
||||
|
||||
Reference in New Issue
Block a user