diff --git a/src/abstractions/api.service.ts b/src/abstractions/api.service.ts index 07cc8118d0..befcbe8aae 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 9c153efca9..7c19a3487f 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 0000000000..45fbe22b52 --- /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 4a72e469ad..cfdfe68b37 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 43aa0e0fd2..9d362329f9 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;