diff --git a/keyserver/src/utils/aes-crypto-utils.js b/keyserver/src/utils/aes-crypto-utils.js --- a/keyserver/src/utils/aes-crypto-utils.js +++ b/keyserver/src/utils/aes-crypto-utils.js @@ -6,6 +6,7 @@ generateKeyCommon, encryptCommon, decryptCommon, + generateIVCommon, } from 'lib/media/aes-crypto-utils-common.js'; // crypto.webcrypto was introduced in Node 15.10.0. @@ -16,11 +17,16 @@ return generateKeyCommon(commonCrypto); } +function generateIV(): Promise { + return generateIVCommon(commonCrypto); +} + function encrypt( keyBytes: Uint8Array, plaintext: Uint8Array, + initializationVector?: ?Uint8Array, ): Promise { - return encryptCommon(commonCrypto, keyBytes, plaintext); + return encryptCommon(commonCrypto, keyBytes, plaintext, initializationVector); } function decrypt( @@ -30,4 +36,4 @@ return decryptCommon(commonCrypto, keyBytes, sealedData); } -export { generateKey, encrypt, decrypt }; +export { generateKey, encrypt, decrypt, generateIV }; diff --git a/lib/media/aes-crypto-utils-common.js b/lib/media/aes-crypto-utils-common.js --- a/lib/media/aes-crypto-utils-common.js +++ b/lib/media/aes-crypto-utils-common.js @@ -14,21 +14,31 @@ return new Uint8Array(keyData); } +async function generateIVCommon(commonCrypto: Crypto): Promise { + return commonCrypto.getRandomValues(new Uint8Array(IV_LENGTH)); +} + async function encryptCommon( commonCrypto: Crypto, keyBytes: Uint8Array, plaintext: Uint8Array, + initializationVector?: ?Uint8Array, ): Promise { if (keyBytes.length !== KEY_SIZE) { throw new Error('Invalid AES key size'); } + if (initializationVector && initializationVector.length !== IV_LENGTH) { + throw new Error('Invalid IV size'); + } // we're creating the buffer now so we can avoid reallocating it later const outputBuffer = new ArrayBuffer( plaintext.length + IV_LENGTH + TAG_LENGTH, ); - const ivBytes = new Uint8Array(outputBuffer, 0, IV_LENGTH); - const iv = commonCrypto.getRandomValues(ivBytes); + + const iv = initializationVector + ? initializationVector + : commonCrypto.getRandomValues(new Uint8Array(outputBuffer, 0, IV_LENGTH)); const algorithm = { name: 'AES-GCM', iv: iv, tagLength: TAG_LENGTH * 8 }; const key = await commonCrypto.subtle.importKey( @@ -81,4 +91,4 @@ return new Uint8Array(plaintextBuffer); } -export { generateKeyCommon, encryptCommon, decryptCommon }; +export { generateKeyCommon, encryptCommon, decryptCommon, generateIVCommon };