From 6cfb3c9867ef1fe95dc69671a19a129625c050f2 Mon Sep 17 00:00:00 2001 From: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com> Date: Fri, 2 Apr 2021 15:33:07 -0700 Subject: [PATCH] Use synchronous crypto for sealed sender --- ts/Crypto.ts | 83 ++++++------------------------------ ts/util/synchronousCrypto.ts | 15 +++++-- 2 files changed, 25 insertions(+), 73 deletions(-) diff --git a/ts/Crypto.ts b/ts/Crypto.ts index dfb4e1564..e47daf53c 100644 --- a/ts/Crypto.ts +++ b/ts/Crypto.ts @@ -4,6 +4,14 @@ import pProps from 'p-props'; import { chunk } from 'lodash'; +import { + CipherType, + encrypt, + decrypt, + hash, + sign, +} from './util/synchronousCrypto'; + export function typedArrayToArrayBuffer(typedArray: Uint8Array): ArrayBuffer { const ab = new ArrayBuffer(typedArray.length); // Create a new Uint8Array backed by the ArrayBuffer and copy all values from @@ -79,8 +87,8 @@ export async function deriveMasterKeyFromGroupV1( } export async function computeHash(data: ArrayBuffer): Promise { - const hash = await crypto.subtle.digest({ name: 'SHA-512' }, data); - return arrayBufferToBase64(hash); + const digest = await crypto.subtle.digest({ name: 'SHA-512' }, data); + return arrayBufferToBase64(digest); } // High-level Operations @@ -331,21 +339,7 @@ export async function hmacSha256( key: ArrayBuffer, plaintext: ArrayBuffer ): Promise { - const algorithm: HmacImportParams = { - name: 'HMAC', - hash: 'SHA-256', - }; - const extractable = false; - - const cryptoKey = await window.crypto.subtle.importKey( - 'raw', - key, - algorithm, - extractable, - ['sign'] - ); - - return window.crypto.subtle.sign(algorithm, cryptoKey, plaintext); + return sign(key, plaintext); } export async function _encryptAes256CbcPkcsPadding( @@ -405,32 +399,7 @@ export async function encryptAesCtr( plaintext: ArrayBuffer, counter: ArrayBuffer ): Promise { - const extractable = false; - const algorithm = { - name: 'AES-CTR', - counter: new Uint8Array(counter), - length: 128, - }; - - const cryptoKey = await crypto.subtle.importKey( - 'raw', - key, - // `algorithm` appears to be an instance of AesCtrParams, - // which is not in the param's types, so we need to pass as `any`. - // TODO: just pass the string "AES-CTR", per the docs? - // eslint-disable-next-line @typescript-eslint/no-explicit-any - algorithm as any, - extractable, - ['encrypt'] - ); - - const ciphertext = await crypto.subtle.encrypt( - algorithm, - cryptoKey, - plaintext - ); - - return ciphertext; + return encrypt(key, plaintext, counter, CipherType.AES256CTR); } export async function decryptAesCtr( @@ -438,31 +407,7 @@ export async function decryptAesCtr( ciphertext: ArrayBuffer, counter: ArrayBuffer ): Promise { - const extractable = false; - const algorithm = { - name: 'AES-CTR', - counter: new Uint8Array(counter), - length: 128, - }; - - const cryptoKey = await crypto.subtle.importKey( - 'raw', - key, - // `algorithm` appears to be an instance of AesCtrParams, - // which is not in the param's types, so we need to pass as `any`. - // TODO: just pass the string "AES-CTR", per the docs? - // eslint-disable-next-line @typescript-eslint/no-explicit-any - algorithm as any, - extractable, - ['decrypt'] - ); - const plaintext = await crypto.subtle.decrypt( - algorithm, - cryptoKey, - ciphertext - ); - - return plaintext; + return decrypt(key, ciphertext, counter, CipherType.AES256CTR); } export async function encryptAesGcm( @@ -526,7 +471,7 @@ export async function decryptAesGcm( // Hashing export async function sha256(data: ArrayBuffer): Promise { - return crypto.subtle.digest('SHA-256', data); + return hash(data); } // Utility diff --git a/ts/util/synchronousCrypto.ts b/ts/util/synchronousCrypto.ts index 3d70a2c0c..1fcc1e8b6 100644 --- a/ts/util/synchronousCrypto.ts +++ b/ts/util/synchronousCrypto.ts @@ -20,13 +20,19 @@ export function hash(data: ArrayBuffer): ArrayBuffer { ); } +export enum CipherType { + AES256CBC = 'aes-256-cbc', + AES256CTR = 'aes-256-ctr', +} + export function encrypt( key: ArrayBuffer, data: ArrayBuffer, - iv: ArrayBuffer + iv: ArrayBuffer, + cipherType: CipherType = CipherType.AES256CBC ): ArrayBuffer { const cipher = crypto.createCipheriv( - 'aes-256-cbc', + cipherType, Buffer.from(key), Buffer.from(iv) ); @@ -41,10 +47,11 @@ export function encrypt( export function decrypt( key: ArrayBuffer, data: ArrayBuffer, - iv: ArrayBuffer + iv: ArrayBuffer, + cipherType: CipherType = CipherType.AES256CBC ): ArrayBuffer { const cipher = crypto.createDecipheriv( - 'aes-256-cbc', + cipherType, Buffer.from(key), Buffer.from(iv) );