From d7f3f9425ececd041bc1a3e0be3f9da157ac55c3 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Wed, 11 Jul 2018 13:30:06 -0400 Subject: [PATCH] user public key apis --- src/abstractions/api.service.ts | 3 ++ src/abstractions/crypto.service.ts | 1 + src/models/response/userKeyResponse.ts | 9 ++++++ src/services/api.service.ts | 8 ++++++ src/services/crypto.service.ts | 38 +++++++++++++------------- 5 files changed, 40 insertions(+), 19 deletions(-) create mode 100644 src/models/response/userKeyResponse.ts diff --git a/src/abstractions/api.service.ts b/src/abstractions/api.service.ts index 07cc8118d09..befcbe8aaea 100644 --- a/src/abstractions/api.service.ts +++ b/src/abstractions/api.service.ts @@ -71,6 +71,7 @@ import { TwoFactorProviderResponse } from '../models/response/twoFactorProviderR import { TwoFactorRecoverResponse } from '../models/response/twoFactorRescoverResponse'; import { TwoFactorU2fResponse } from '../models/response/twoFactorU2fResponse'; import { TwoFactorYubiKeyResponse } from '../models/response/twoFactorYubiKeyResponse'; +import { UserKeyResponse } from '../models/response/userKeyResponse'; export abstract class ApiService { urlsSet: boolean; @@ -195,5 +196,7 @@ export abstract class ApiService { getEventsOrganizationUser: (organizationId: string, id: string, start: string, end: string, token: string) => Promise>; + getUserPublicKey: (id: string) => Promise; + fetch: (request: Request) => Promise; } diff --git a/src/abstractions/crypto.service.ts b/src/abstractions/crypto.service.ts index 9c153efca99..7c19a3487f1 100644 --- a/src/abstractions/crypto.service.ts +++ b/src/abstractions/crypto.service.ts @@ -31,6 +31,7 @@ export abstract class CryptoService { makeEncKey: (key: SymmetricCryptoKey) => Promise<[SymmetricCryptoKey, CipherString]>; encrypt: (plainValue: string | ArrayBuffer, key?: SymmetricCryptoKey) => Promise; encryptToBytes: (plainValue: ArrayBuffer, key?: SymmetricCryptoKey) => Promise; + rsaEncrypt: (data: ArrayBuffer, publicKey?: ArrayBuffer, key?: SymmetricCryptoKey) => Promise; decryptToUtf8: (cipherString: CipherString, key?: SymmetricCryptoKey) => Promise; decryptFromBytes: (encBuf: ArrayBuffer, key: SymmetricCryptoKey) => Promise; randomNumber: (min: number, max: number) => Promise; diff --git a/src/models/response/userKeyResponse.ts b/src/models/response/userKeyResponse.ts new file mode 100644 index 00000000000..45fbe22b525 --- /dev/null +++ b/src/models/response/userKeyResponse.ts @@ -0,0 +1,9 @@ +export class UserKeyResponse { + userId: string; + publicKey: string; + + constructor(response: any) { + this.userId = response.UserId; + this.publicKey = response.PublicKey; + } +} diff --git a/src/services/api.service.ts b/src/services/api.service.ts index 4a72e469add..cfdfe68b370 100644 --- a/src/services/api.service.ts +++ b/src/services/api.service.ts @@ -78,6 +78,7 @@ import { TwoFactorProviderResponse } from '../models/response/twoFactorProviderR import { TwoFactorRecoverResponse } from '../models/response/twoFactorRescoverResponse'; import { TwoFactorU2fResponse } from '../models/response/twoFactorU2fResponse'; import { TwoFactorYubiKeyResponse } from '../models/response/twoFactorYubiKeyResponse'; +import { UserKeyResponse } from '../models/response/userKeyResponse'; export class ApiService implements ApiServiceAbstraction { urlsSet: boolean = false; @@ -649,6 +650,13 @@ export class ApiService implements ApiServiceAbstraction { return new ListResponse(r, EventResponse); } + // User APIs + + async getUserPublicKey(id: string): Promise { + const r = await this.send('GET', '/users/' + id + '/public-key', null, true, true); + return new UserKeyResponse(r); + } + // Helpers fetch(request: Request): Promise { diff --git a/src/services/crypto.service.ts b/src/services/crypto.service.ts index 43aa0e0fd2a..9d362329f97 100644 --- a/src/services/crypto.service.ts +++ b/src/services/crypto.service.ts @@ -356,6 +356,25 @@ export class CryptoService implements CryptoServiceAbstraction { return encBytes.buffer; } + async rsaEncrypt(data: ArrayBuffer, publicKey?: ArrayBuffer, key?: SymmetricCryptoKey): Promise { + if (publicKey == null) { + publicKey = await this.getPublicKey(); + } + if (publicKey == null) { + throw new Error('Public key unavailable.'); + } + + let type = EncryptionType.Rsa2048_OaepSha1_B64; + const encBytes = await this.cryptoFunctionService.rsaEncrypt(data, publicKey, 'sha1'); + let mac: string = null; + if (key != null && key.macKey != null) { + type = EncryptionType.Rsa2048_OaepSha1_HmacSha256_B64; + const macBytes = await this.cryptoFunctionService.hmac(encBytes, key.macKey, 'sha256'); + mac = Utils.fromBufferToB64(macBytes); + } + return new CipherString(type, Utils.fromBufferToB64(encBytes), null, mac); + } + async decrypt(cipherString: CipherString, key?: SymmetricCryptoKey): Promise { const iv = Utils.fromB64ToArray(cipherString.iv).buffer; const data = Utils.fromB64ToArray(cipherString.data).buffer; @@ -530,25 +549,6 @@ export class CryptoService implements CryptoServiceAbstraction { return await this.cryptoFunctionService.aesDecrypt(data, iv, theKey.encKey); } - private async rsaEncrypt(data: ArrayBuffer, publicKey?: ArrayBuffer, key?: SymmetricCryptoKey) { - if (publicKey == null) { - publicKey = await this.getPublicKey(); - } - if (publicKey == null) { - throw new Error('Public key unavailable.'); - } - - let type = EncryptionType.Rsa2048_OaepSha1_B64; - const encBytes = await this.cryptoFunctionService.rsaEncrypt(data, publicKey, 'sha1'); - let mac: string = null; - if (key != null && key.macKey != null) { - type = EncryptionType.Rsa2048_OaepSha1_HmacSha256_B64; - const macBytes = await this.cryptoFunctionService.hmac(encBytes, key.macKey, 'sha256'); - mac = Utils.fromBufferToB64(macBytes); - } - return new CipherString(type, Utils.fromBufferToB64(encBytes), null, mac); - } - private async rsaDecrypt(encValue: string): Promise { const headerPieces = encValue.split('.'); let encType: EncryptionType = null;