mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 20:14:49 +00:00
encryption integration fixes
This commit is contained in:
committed by
Drew Ansbacher
parent
6d12c4acfb
commit
8d944cddff
@@ -1,6 +1,7 @@
|
|||||||
import { Component } from '@angular/core'
|
import { Component } from '@angular/core'
|
||||||
import { AlertController, iosTransitionAnimation, LoadingController, ModalController, NavController } from '@ionic/angular'
|
import { AlertController, iosTransitionAnimation, LoadingController, ModalController, NavController } from '@ionic/angular'
|
||||||
import { ApiService, DiskInfo } from 'src/app/services/api/api.service'
|
import { ApiService, DiskInfo } from 'src/app/services/api/api.service'
|
||||||
|
import { ErrorToastService } from 'src/app/services/error-toast.service'
|
||||||
import { StateService } from 'src/app/services/state.service'
|
import { StateService } from 'src/app/services/state.service'
|
||||||
import { PasswordPage } from '../password/password.page'
|
import { PasswordPage } from '../password/password.page'
|
||||||
|
|
||||||
@@ -22,11 +23,18 @@ export class EmbassyPage {
|
|||||||
private readonly alertCtrl: AlertController,
|
private readonly alertCtrl: AlertController,
|
||||||
private readonly stateService: StateService,
|
private readonly stateService: StateService,
|
||||||
private readonly loadingCtrl: LoadingController,
|
private readonly loadingCtrl: LoadingController,
|
||||||
|
private readonly errorToastService: ErrorToastService,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
async ngOnInit () {
|
async ngOnInit () {
|
||||||
this.storageDrives = await this.apiService.getDrives()
|
try {
|
||||||
this.loading = false
|
this.storageDrives = await this.apiService.getDrives()
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
this.errorToastService.present(e.message)
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async chooseDrive (drive: DiskInfo) {
|
async chooseDrive (drive: DiskInfo) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { HttpClient, HttpErrorResponse, HttpHeaders, HttpParams } from '@angular/common/http'
|
import { HttpClient, HttpErrorResponse, HttpHeaders, HttpParams } from '@angular/common/http'
|
||||||
import { Observable, from, interval, race, Subject } from 'rxjs'
|
import { Observable, from, interval, race } from 'rxjs'
|
||||||
import { map, take } from 'rxjs/operators'
|
import { map, take } from 'rxjs/operators'
|
||||||
import * as aesjs from 'aes-js'
|
import * as aesjs from 'aes-js'
|
||||||
import * as pbkdf2 from 'pbkdf2'
|
import * as pbkdf2 from 'pbkdf2'
|
||||||
@@ -44,24 +44,32 @@ export class HttpService {
|
|||||||
this.fullUrl + httpOpts.url :
|
this.fullUrl + httpOpts.url :
|
||||||
httpOpts.url
|
httpOpts.url
|
||||||
|
|
||||||
|
const encryptedBody = await AES_CTR.encryptPbkdf2(this.productKey, encodeUtf8( JSON.stringify(httpOpts.body)))
|
||||||
const options = {
|
const options = {
|
||||||
responseType: 'arraybuffer',
|
responseType: 'arraybuffer',
|
||||||
body: await AES_CTR.encryptPbkdf2(this.productKey, encodeUtf8( JSON.stringify(httpOpts.body))),
|
body: encryptedBody.buffer,
|
||||||
observe: 'events',
|
observe: 'events',
|
||||||
reportProgress: false,
|
reportProgress: false,
|
||||||
|
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Encoding': 'aesctr256',
|
'Content-Encoding': 'aesctr256',
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
} as any
|
} as any
|
||||||
|
|
||||||
const req = this.http.post(url, httpOpts.body, options)
|
const req = this.http.post(url, options.body, options)
|
||||||
|
|
||||||
return (withTimeout(req, 60000))
|
return (withTimeout(req, 60000))
|
||||||
.toPromise()
|
.toPromise()
|
||||||
.then(res => AES_CTR.decryptPbkdf2(this.productKey, new Uint8Array(res)))
|
.then(res => AES_CTR.decryptPbkdf2(this.productKey, (res as any).body as ArrayBuffer))
|
||||||
.then(res => JSON.parse(decodeUtf8(res)))
|
.then(res => JSON.parse(res))
|
||||||
.catch(e => { throw new HttpError(e) })
|
.catch(e => {
|
||||||
|
if(!e.status && !e.statusText) {
|
||||||
|
throw new EncryptionError(e)
|
||||||
|
} else {
|
||||||
|
throw new HttpError(e)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,6 +94,12 @@ function HttpError (e: HttpErrorResponse): void {
|
|||||||
this.details = null
|
this.details = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function EncryptionError (e: HttpErrorResponse): void {
|
||||||
|
this.code = null
|
||||||
|
this.message = 'Invalid Key'
|
||||||
|
this.details = null
|
||||||
|
}
|
||||||
|
|
||||||
function isRpcError<Error, Result> (arg: { error: Error } | { result: Result}): arg is { error: Error } {
|
function isRpcError<Error, Result> (arg: { error: Error } | { result: Result}): arg is { error: Error } {
|
||||||
return !!(arg as any).error
|
return !!(arg as any).error
|
||||||
}
|
}
|
||||||
@@ -162,26 +176,32 @@ function withTimeout<U> (req: Observable<U>, timeout: number): Observable<U> {
|
|||||||
|
|
||||||
type AES_CTR = {
|
type AES_CTR = {
|
||||||
encryptPbkdf2: (secretKey: string, messageBuffer: Uint8Array) => Promise<Uint8Array>
|
encryptPbkdf2: (secretKey: string, messageBuffer: Uint8Array) => Promise<Uint8Array>
|
||||||
decryptPbkdf2: (secretKey, arr: Uint8Array) => Promise<Uint8Array>
|
decryptPbkdf2: (secretKey, arr: ArrayBuffer) => Promise<string>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AES_CTR: AES_CTR = {
|
export const AES_CTR: AES_CTR = {
|
||||||
encryptPbkdf2: async (secretKey: string, messageBuffer: Uint8Array) => {
|
encryptPbkdf2: async (secretKey: string, messageBuffer: Uint8Array) => {
|
||||||
const salt = window.crypto.getRandomValues(new Uint8Array(16))
|
const salt = window.crypto.getRandomValues(new Uint8Array(16))
|
||||||
const counter = window.crypto.getRandomValues(new Uint8Array(16))
|
const counter = window.crypto.getRandomValues(new Uint8Array(16))
|
||||||
const key = pbkdf2.pbkdf2Sync(secretKey, salt, 1, 256 / 8, 'sha256');
|
|
||||||
var aesCtr = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(counter));
|
const key = pbkdf2.pbkdf2Sync(secretKey, salt, 1000, 256 / 8, 'sha256');
|
||||||
var encryptedBytes = aesCtr.encrypt(messageBuffer);
|
|
||||||
|
const aesCtr = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(counter));
|
||||||
|
const encryptedBytes = aesCtr.encrypt(messageBuffer);
|
||||||
return new Uint8Array([...counter,...salt,...encryptedBytes])
|
return new Uint8Array([...counter,...salt,...encryptedBytes])
|
||||||
},
|
},
|
||||||
decryptPbkdf2: async (secretKey: string, arr: Uint8Array) => {
|
decryptPbkdf2: async (secretKey: string, arr: ArrayBuffer) => {
|
||||||
const counter = arr.slice(0, 16)
|
const buff = new Uint8Array(arr)
|
||||||
const salt = arr.slice(16, 32)
|
const counter = buff.slice(0, 16)
|
||||||
const cipher = arr.slice(32)
|
const salt = buff.slice(16, 32)
|
||||||
const key = pbkdf2.pbkdf2Sync(secretKey, salt, 1, 256 / 8, 'sha256');
|
|
||||||
|
|
||||||
var aesCtr = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(counter));
|
const cipher = buff.slice(32)
|
||||||
return aesCtr.decrypt(cipher);
|
const key = pbkdf2.pbkdf2Sync(secretKey, salt, 1000, 256 / 8, 'sha256');
|
||||||
|
|
||||||
|
const aesCtr = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(counter));
|
||||||
|
const decryptedBytes = aesCtr.decrypt(cipher);
|
||||||
|
|
||||||
|
return aesjs.utils.utf8.fromBytes(decryptedBytes);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
42
setup-wizard/src/app/services/error-toast.service.ts
Normal file
42
setup-wizard/src/app/services/error-toast.service.ts
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import { Injectable } from '@angular/core'
|
||||||
|
import { ToastController } from '@ionic/angular'
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class ErrorToastService {
|
||||||
|
private toast: HTMLIonToastElement
|
||||||
|
|
||||||
|
constructor (
|
||||||
|
private readonly toastCtrl: ToastController,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
async present (message: string): Promise<void> {
|
||||||
|
if (this.toast) return
|
||||||
|
|
||||||
|
this.toast = await this.toastCtrl.create({
|
||||||
|
header: 'Error',
|
||||||
|
message,
|
||||||
|
duration: 0,
|
||||||
|
position: 'top',
|
||||||
|
cssClass: 'error-toast',
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
side: 'end',
|
||||||
|
icon: 'close',
|
||||||
|
handler: () => {
|
||||||
|
this.dismiss()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
await this.toast.present()
|
||||||
|
}
|
||||||
|
|
||||||
|
async dismiss (): Promise<void> {
|
||||||
|
if (this.toast) {
|
||||||
|
await this.toast.dismiss()
|
||||||
|
this.toast = undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -53,6 +53,16 @@ ion-item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.error-toast {
|
||||||
|
--border-color: var(--ion-color-danger);
|
||||||
|
width: 40%;
|
||||||
|
min-width: 400px;
|
||||||
|
--end: 8px;
|
||||||
|
right: 8px;
|
||||||
|
left: unset;
|
||||||
|
top: 64px;
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-width:1000px) {
|
@media (min-width:1000px) {
|
||||||
.alertlike-modal {
|
.alertlike-modal {
|
||||||
.modal-wrapper {
|
.modal-wrapper {
|
||||||
|
|||||||
Reference in New Issue
Block a user