{"version":3,"sources":["jsdelivr-header.js","/npm/fernet-web@1.0.1/dist/index.js"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA,eCmBe,MAAM,OAMjB,WAAA,CAAY,EAAY,GACpB,KAAK,WAAa,EAClB,KAAK,cAAgB,CACzB,CAMA,2BAAa,CAAe,GACxB,MAAM,EAAmB,EAAgB,MAAM,EAAG,IAC5C,EAAsB,EAAgB,MAAM,IAMlD,MAAO,CAAE,iBALgB,OAAO,OAAO,UAAU,MAAO,EAAkB,CACtE,KAAM,OACN,KAAM,YACP,EAAO,CAAC,SAAU,SAEA,oBADO,OAAO,OAAO,UAAU,MAAO,EAAqB,WAAW,EAAO,CAAC,UAAW,YAElH,CAOA,mBAAa,CAAO,GAChB,IAAI,EAAkB,IAAI,WAAW,IAChB,MAAjB,EAEA,EAAkB,WAAW,KAAK,OAAO,KAAK,EAAc,QAAQ,KAAM,KAAK,QAAQ,KAAM,OAAO,GAAK,EAAE,WAAW,KAItH,OAAO,gBAAgB,GAE3B,MAAM,QAAa,OAAO,eAAe,GACzC,OAAO,IAAI,OAAO,EAAK,WAAY,EAAK,cAC5C,CAMA,aAAM,CAAQ,GACV,MAAM,GAAkB,IAAI,aAAc,OAAO,GAC3C,EAAW,IAAI,WAAW,IAEhC,OAAO,gBAAgB,GAEvB,MAAM,QAAyB,OAAO,OAAO,QAAQ,CAAE,KAAM,UAAW,GAAI,GAAY,KAAK,cAAe,GAEtG,EAAU,IAAI,WAAW,CAAC,MAE1B,EAAa,IAAI,YAAY,GAC7B,EAAO,IAAI,SAAS,GACpB,EAAc,KAAK,MACnB,EAAgB,KAAK,MAAM,EAAc,KAC/C,EAAK,aAAa,EAAG,OAAO,IAAgB,GAC5C,MAAM,EAAY,IAAI,WAAW,GAE3B,EAAK,IAAI,WAAW,GAEpB,EAAa,IAAI,WAAW,GAE5B,EAAiB,IAAI,WAAW,IAC/B,KACA,KACA,KACA,IAGD,EAAO,IAAI,iBAAiB,OAAO,OAAO,KAAK,CAAE,KAAM,OAAQ,KAAM,WAAc,KAAK,WAAY,IAEpG,EAAe,IAAI,WAAW,IAC7B,KACA,KACA,KACA,KACA,IAMP,IAAI,EAAa,GACjB,EAAa,SAAQ,IACjB,EAAW,KAAK,OAAO,aAAa,GAAM,IAK9C,OAHoB,OAAO,KAAK,EAAW,KAAK,KAC3C,QAAQ,MAAO,KACf,QAAQ,MAAO,IAExB,CAMA,aAAM,CAAQ,GAGV,MAAM,EAAc,WAAW,KAAK,OAAO,KAAK,EAAU,QAAQ,KAAM,KAAK,QAAQ,KAAM,OAAO,GAAK,EAAE,WAAW,KAE9G,EAAU,EAAY,MAAM,EAAG,GAC/B,EAAY,EAAY,MAAM,EAAG,GACjC,EAAK,EAAY,MAAM,EAAG,IAC1B,EAAa,EAAY,MAAM,IAAK,IACpC,EAAO,EAAY,OAAO,IAE1B,QAAkB,OAAO,OAAO,QAAQ,CAC1C,KAAM,UACN,GAAI,GACL,KAAK,cAAe,GACjB,GAAmB,IAAI,aAAc,OAAO,GAE5C,EAAiB,IAAI,WAAW,IAC/B,KACA,KACA,KACA,IAGP,UAD2B,OAAO,OAAO,OAAO,CAAE,KAAM,OAAQ,KAAM,WAAa,KAAK,WAAY,EAAM,GAEtG,MAAM,IAAI,kBAAkB,8CAEhC,OAAO,CACX,EAKJ,MAAM,0BAA0B,MAK5B,WAAA,CAAY,GACR,MAAM,EACV","file":"/npm/fernet-web@1.0.1/dist/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/fernet-web@1.0.1/dist/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","/**\r\n * @author Rich Miles\r\n * @date December 05, 2022\r\n *\r\n * This code provides an implementation of the Fernet symmetric encryption algorithm\r\n * using the Web Crypto API.\r\n *\r\n * @warning This code is provided as is, without any warranty or guarantees. Use at your own risk.\r\n *\r\n * @example\r\n * // Create a new Fernet instance using a secret key\r\n * const fernet = await Fernet.create(\"-lf4DsgLkOaE1GbtIQKNGU1NPQByMDKP2a6Enl9rclE=\");\r\n *\r\n * // Encrypt a message\r\n * const encryptedToken = await fernet.encrypt(\"Hello world!\");\r\n *\r\n * // Decrypt the encrypted message\r\n * const decryptedMessage = await fernet.decrypt(encryptedToken);\r\n *\r\n * // Print the decrypted message\r\n * console.log(decryptedMessage); // Hello world!\r\n */\r\n/**\r\n * Fernet is a simple and secure way to encrypt and decrypt messages using symmetric encryption.\r\n */\r\nexport default class Fernet {\r\n    /**\r\n     * Create a new Fernet instance with the provided signing and encryption keys.\r\n     * @param signingKey - A CryptoKey to use for signing messages.\r\n     * @param encryptionKey - A CryptoKey to use for encrypting and decrypting messages.\r\n     */\r\n    constructor(signingKey, encryptionKey) {\r\n        this.signingKey = signingKey;\r\n        this.encryptionKey = encryptionKey;\r\n    }\r\n    /**\r\n     * Generate signing and encryption keys from a secret key.\r\n     * @param secretKeyBuffer - A Uint8Array containing the secret key to use.\r\n     * @returns A tuple containing the signing and encryption keys.\r\n     */\r\n    static async initializeKeys(secretKeyBuffer) {\r\n        const signingKeyBuffer = secretKeyBuffer.slice(0, 16);\r\n        const encryptionKeyBuffer = secretKeyBuffer.slice(16);\r\n        const signingKey = await crypto.subtle.importKey(\"raw\", signingKeyBuffer, {\r\n            name: \"HMAC\",\r\n            hash: \"SHA-256\",\r\n        }, false, [\"verify\", \"sign\"]);\r\n        const encryptionKey = await crypto.subtle.importKey(\"raw\", encryptionKeyBuffer, \"AES-CBC\", false, [\"encrypt\", \"decrypt\"]);\r\n        return { signingKey, encryptionKey };\r\n    }\r\n    /**\r\n     * Create a new Fernet instance with a secret key.\r\n     * @param secretKey_b64 - A base64-encoded string representation of the secret key to use.\r\n     * If null, a new secret key will be generated.\r\n     * @returns A new Fernet instance.\r\n    */\r\n    static async create(secretKey_b64) {\r\n        var secretKeyBuffer = new Uint8Array(32);\r\n        if (secretKey_b64 != null) {\r\n            // Decode the URL-safe base64-encoded secret key\r\n            secretKeyBuffer = Uint8Array.from(window.atob(secretKey_b64.replace(/_/g, '/').replace(/-/g, '+')), c => c.charCodeAt(0));\r\n        }\r\n        else {\r\n            // Create a new secret key from scratch to use for this session\r\n            crypto.getRandomValues(secretKeyBuffer);\r\n        }\r\n        const keys = await Fernet.initializeKeys(secretKeyBuffer);\r\n        return new Fernet(keys.signingKey, keys.encryptionKey);\r\n    }\r\n    /**\r\nEncrypt a message into a Fernet token.\r\n@param plainText - The message to encrypt.\r\n@returns A base64-encoded Fernet token.\r\n*/\r\n    async encrypt(plainText) {\r\n        const plainTextBuffer = new TextEncoder().encode(plainText);\r\n        const ivBuffer = new Uint8Array(16); // create a new array to store the IV\r\n        // generate the random IV\r\n        crypto.getRandomValues(ivBuffer);\r\n        // Encrypt the plain text\r\n        const encryptedMessage = await crypto.subtle.encrypt({ name: \"AES-CBC\", iv: ivBuffer }, this.encryptionKey, plainTextBuffer);\r\n        // Version is always the first byte and always 128 (0x80)\r\n        const version = new Uint8Array([0x80]);\r\n        // The time bytes are a big-endian encoded uint64 of unix epoch time (seconds)\r\n        const timeBuffer = new ArrayBuffer(8);\r\n        const view = new DataView(timeBuffer);\r\n        const currentTime = Date.now();\r\n        const unixEpochTime = Math.round(currentTime / 1000);\r\n        view.setBigUint64(0, BigInt(unixEpochTime), false);\r\n        const timestamp = new Uint8Array(timeBuffer);\r\n        // Convert the IV to a Uint8Array\r\n        const iv = new Uint8Array(ivBuffer);\r\n        // Convert the encrtyped message to a Uint8Array\r\n        const ciphertext = new Uint8Array(encryptedMessage);\r\n        // Concatenate the unsigned component\r\n        const unsigned_token = new Uint8Array([\r\n            ...version,\r\n            ...timestamp,\r\n            ...iv,\r\n            ...ciphertext,\r\n        ]);\r\n        // Compute the HMAC signature\r\n        const hmac = new Uint8Array(await crypto.subtle.sign({ name: \"HMAC\", hash: \"SHA-256\", }, this.signingKey, unsigned_token));\r\n        // Concatenate the header with the signature\r\n        const signed_token = new Uint8Array([\r\n            ...version,\r\n            ...timestamp,\r\n            ...iv,\r\n            ...ciphertext,\r\n            ...hmac\r\n        ]);\r\n        // Convert the signed token array to a URL-Safe base64 string\r\n        // Note: The signed_token array is a Uint8Array, but the btoa function expects a string.\r\n        // Originally, this was using String.fromCharCode(signed_token), but that was causing\r\n        // a stack overflow with large arrays. This is a workaround that avoids the stack overflow.\r\n        let tokenChars = [];\r\n        signed_token.forEach(byte => {\r\n            tokenChars.push(String.fromCharCode(byte));\r\n        });\r\n        const fernetToken = window.btoa(tokenChars.join(\"\"))\r\n            .replace(/\\+/g, \"-\")\r\n            .replace(/\\//g, \"_\");\r\n        return fernetToken;\r\n    }\r\n    /**\r\n     * Decrypt a Fernet token and return the plain text message.\r\n     * @param token_b64 - A base64-encoded Fernet token.\r\n     * @returns The decrypted message as a string.\r\n     */\r\n    async decrypt(token_b64) {\r\n        // Decode the base64-encoded secret key\r\n        // Convert the URL-safe base 64 value to a Uint8Array\r\n        const tokenBuffer = Uint8Array.from(window.atob(token_b64.replace(/_/g, '/').replace(/-/g, '+')), c => c.charCodeAt(0));\r\n        // Decompose the token into its various parts\r\n        const version = tokenBuffer.slice(0, 1);\r\n        const timestamp = tokenBuffer.slice(1, 9);\r\n        const iv = tokenBuffer.slice(9, 25);\r\n        const ciphertext = tokenBuffer.slice(25, -32);\r\n        const hmac = tokenBuffer.slice(-32);\r\n        // Decrypt the cipher text\r\n        const decrypted = await crypto.subtle.decrypt({\r\n            name: \"AES-CBC\",\r\n            iv: iv,\r\n        }, this.encryptionKey, ciphertext);\r\n        const decryptedMessage = new TextDecoder().decode(decrypted);\r\n        // Verify the HMAC signature\r\n        const unsigned_token = new Uint8Array([\r\n            ...version,\r\n            ...timestamp,\r\n            ...iv,\r\n            ...ciphertext,\r\n        ]);\r\n        const verification = await crypto.subtle.verify({ name: \"HMAC\", hash: \"SHA-256\" }, this.signingKey, hmac, unsigned_token);\r\n        if (!verification) {\r\n            throw new InvalidTokenError(\"Token is invalid or has been tampered with\");\r\n        }\r\n        return decryptedMessage;\r\n    }\r\n}\r\n/**\r\n * The InvalidTokenError class is used to indicate that a Fernet token failed to verify.\r\n*/\r\nclass InvalidTokenError extends Error {\r\n    /*\r\n    Create a new InvalidTokenError instance.\r\n    @param message - A string describing the error that occurred.\r\n    */\r\n    constructor(message) {\r\n        super(message);\r\n    }\r\n}\r\n"]}