1
|
{"version":3,"file":"aes.js","names":["_olmlib","require","_crypto","zeroSalt","Uint8Array","encryptAES","data","key","name","ivStr","iv","decodeBase64","crypto","getRandomValues","aesKey","hmacKey","deriveKeys","encodedData","TextEncoder","encode","ciphertext","subtleCrypto","encrypt","counter","length","hmac","sign","encodeBase64","mac","decryptAES","verify","Error","plaintext","decrypt","TextDecoder","decode","hkdfkey","importKey","keybits","deriveBits","salt","info","hash","slice","aesProm","hmacProm","Promise","all","ZERO_STR","calculateKeyCheck"],"sources":["../../src/crypto/aes.ts"],"sourcesContent":["/*\nCopyright 2020 - 2021 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { decodeBase64, encodeBase64 } from \"./olmlib\";\nimport { subtleCrypto, crypto, TextEncoder } from \"./crypto\";\n\n// salt for HKDF, with 8 bytes of zeros\nconst zeroSalt = new Uint8Array(8);\n\nexport interface IEncryptedPayload {\n [key: string]: any; // extensible\n /** the initialization vector in base64 */\n iv: string;\n /** the ciphertext in base64 */\n ciphertext: string;\n /** the HMAC in base64 */\n mac: string;\n}\n\n/**\n * encrypt a string\n *\n * @param data - the plaintext to encrypt\n * @param key - the encryption key to use\n * @param name - the name of the secret\n * @param ivStr - the initialization vector to use\n */\nexport async function encryptAES(\n data: string,\n key: Uint8Array,\n name: string,\n ivStr?: string,\n): Promise<IEncryptedPayload> {\n let iv: Uint8Array;\n if (ivStr) {\n iv = decodeBase64(ivStr);\n } else {\n iv = new Uint8Array(16);\n crypto.getRandomValues(iv);\n\n // clear bit 63 of the IV to stop us hitting the 64-bit counter boundary\n // (which would mean we wouldn't be able to decrypt on Android). The loss\n // of a single bit of iv is a price we have to pay.\n iv[8] &= 0x7f;\n }\n\n const [aesKey, hmacKey] = await deriveKeys(key, name);\n const encodedData = new TextEncoder().encode(data);\n\n const ciphertext = await subtleCrypto.encrypt(\n {\n name: \"AES-CTR\",\n counter: iv,\n length: 64,\n },\n aesKey,\n encodedData,\n );\n\n const hmac = await subtleCrypto.sign({ name: \"HMAC\" }, hmacKey, ciphertext);\n\n return {\n iv: encodeBase64(iv),\n ciphertext: encodeBase64(ciphertext),\n mac: encodeBase64(hmac),\n };\n}\n\n/**\n * decrypt a string\n *\n * @param data - the encrypted data\n * @param key - the encryption key to use\n * @param name - the name of the secret\n */\nexport async function decryptAES(data: IEncryptedPayload, key: Uint8Array, name: string): Promise<string> {\n const [aesKey, hmacKey] = await deriveKeys(key, name);\n\n const ciphertext = decodeBase64(data.ciphertext);\n\n if (!(await subtleCrypto.verify({ name: \"HMAC\" }, hmacKey, decodeBase64(data.mac), ciphertext))) {\n throw new Error(`Error decrypting secret ${name}: bad MAC`);\n }\n\n const plaintext = await subtleCrypto.decrypt(\n {\n name: \"AES-CTR\",\n counter: decodeBase64(data.iv),\n length: 64,\n },\n aesKey,\n ciphertext,\n );\n\n return new TextDecoder().decode(new Uint8Array(plaintext));\n}\n\nasync function deriveKeys(key: Uint8Array, name: string): Promise<[CryptoKey, CryptoKey]> {\n const hkdfkey = await subtleCrypto.importKey(\"raw\", key, { name: \"HKDF\" }, false, [\"deriveBits\"]);\n const keybits = await subtleCrypto.deriveBits(\n {\n name: \"HKDF\",\n salt: zeroSalt,\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore: https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/879\n info: new TextEncoder().encode(name),\n hash: \"SHA-256\",\n },\n hkdfkey,\n 512,\n );\n\n const aesKey = keybits.slice(0, 32);\n const hmacKey = keybits.slice(32);\n\n const aesProm = subtleCrypto.importKey(\"raw\", aesKey, { name: \"AES-CTR\" }, false, [\"encrypt\", \"decrypt\"]);\n\n const hmacProm = subtleCrypto.importKey(\n \"raw\",\n hmacKey,\n {\n name: \"HMAC\",\n hash: { name: \"SHA-256\" },\n },\n false,\n [\"sign\", \"verify\"],\n );\n\n return Promise.all([aesProm, hmacProm]);\n}\n\n// string of zeroes, for calculating the key check\nconst ZERO_STR = \"\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\";\n\n/** Calculate the MAC for checking the key.\n *\n * @param key - the key to use\n * @param iv - The initialization vector as a base64-encoded string.\n * If omitted, a random initialization vector will be created.\n * @returns An object that contains, `mac` and `iv` properties.\n */\nexport function calculateKeyCheck(key: Uint8Array, iv?: string): Promise<IEncryptedPayload> {\n return encryptAES(ZERO_STR, key, \"\", iv);\n}\n"],"mappings":"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"}
|