### Install Dependencies and Build Project Source: https://github.com/robinmoisson/staticrypt/blob/main/README.md Run these commands to install project dependencies and build the project. This ensures all components (browser, CLI, examples) are updated with the latest logic. ```bash npm install npm run build ``` -------------------------------- ### Install Staticrypt CLI Source: https://github.com/robinmoisson/staticrypt/blob/main/README.md Install Staticrypt as a local dependency using npm. This allows you to run it via npx. ```bash npm install staticrypt ``` -------------------------------- ### Initialize StatiCrypt Variables and Configuration Source: https://github.com/robinmoisson/staticrypt/blob/main/lib/password_template.html Initializes StatiCrypt-related variables and configuration objects. These variables are placeholders that get filled during the file generation process. The `templateConfig` object allows customization of behavior like remember expiration and passphrase keys. ```javascript const staticryptInitiator = /\*\\[|js_staticrypt|\\]\*/ 0; const templateError = "/\*\\[|template_error|\\]\*/0", templateToggleAltShow = "/\*\\[|template_toggle_show|\\]\*/0", templateToggleAltHide = "/\*\\[|template_toggle_hide|\\]\*/0", isRememberEnabled = /\*\\[|is_remember_enabled|\\]\*/ 0, staticryptConfig = /\*\\[|staticrypt_config|\\]\*/ 0; const templateConfig = { rememberExpirationKey: "staticrypt_expiration", rememberPassphraseKey: "staticrypt_passphrase", replaceHtmlCallback: null, clearLocalStorageCallback: null, }; const staticrypt = staticryptInitiator.init(staticryptConfig, templateConfig); ``` -------------------------------- ### Initialize Crypto Libraries Source: https://github.com/robinmoisson/staticrypt/blob/main/scripts/index_template.html Initializes global variables for crypto engine, codec, formatter, and staticrypt. These are likely placeholders or references to external libraries. ```javascript window.cryptoEngine = /\*[\[|js_crypto_engine|\]]\*/ 0; window.codec = /\*[\[|js_codec|\]]\*/ 0; window.formater = /\*[\[|js_formater|\]]\*/ 0; window.staticrypt = /\*[\[|js_staticrypt|\]]\*/ 0; ``` -------------------------------- ### StatiCrypt Initialization and Configuration Source: https://github.com/robinmoisson/staticrypt/blob/main/example/encrypted/example.html Initializes the StatiCrypt engine with configuration settings and template-specific options. Sets up the window.onload handler to attempt automatic decryption. ```javascript const templateError = "Bad password!", templateToggleAltShow = "Show password", templateToggleAltHide = "Hide password", isRememberEnabled = true, staticryptConfig = { "staticryptEncryptedMsgUniqueVariableName": "b6316cd49ce09d90d6cf34cd96603f083cd803602dc4e5c34d6cf1f2d871f236ea7e0d207814dee498ab00a44e18b94846ebb2538a18d5920e274768c25955cb3add357be6967f3b0a63669017427eb52fe6d5b2d8994f849c7d9f227062db040eac791ca7bcf7b6cd12799d3ad730d18eb63e9d533cb6277b9546c632668da3f4ca3af925e0bfdc22992bd43e2344f07dbae2c2e0bfa2e84976ab8bec4f320508008deb828196d74f7c2923c2be19111f21e285fae7400d64271e32c6f9a618", "isRememberEnabled": true, "rememberDurationInDays": 0, "staticryptSaltUniqueVariableName": "b93bbaf35459951c47721d1f3eaeb5b9" }; // you can edit these values to customize some of the behavior of StatiCrypt const templateConfig = { rememberExpirationKey: "staticrypt_expiration", rememberPassphraseKey: "staticrypt_passphrase", replaceHtmlCallback: null, clearLocalStorageCallback: null, }; // init the staticrypt engine const staticrypt = staticryptInitiator.init(staticryptConfig, templateConfig); // try to automatically decrypt on load if there is a saved password window.onload = async function () { const { isSuccessful } = await staticrypt.handleDecryptOnLoad(); // if we didn't decrypt anything on load, show the password prompt. ``` -------------------------------- ### Initialize Codec Source: https://github.com/robinmoisson/staticrypt/blob/main/example/encrypted/example.html Initializes the codec with a crypto engine, returning functions for encoding and decoding messages. ```javascript function init(cryptoEngine) { const exports = {} // ... (rest of the init function) ``` -------------------------------- ### init(staticryptConfig, templateConfig) Source: https://github.com/robinmoisson/staticrypt/blob/main/index.html Initializes the Staticrypt module, exposing functions callable by the password template. It takes configuration objects for both Staticrypt's encryption/decryption process and the template's behavior. ```APIDOC ## init(staticryptConfig, templateConfig) ### Description Initializes the Staticrypt module, exposing functions callable by the password template. It takes configuration objects for both Staticrypt's encryption/decryption process and the template's behavior. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters * **staticryptConfig** (object) - Configuration for Staticrypt: * **staticryptEncryptedMsgUniqueVariableName** (string) - Unique variable name for the encrypted message. * **isRememberEnabled** (boolean) - Whether remember functionality is enabled. * **rememberDurationInDays** (number) - Duration in days for remember functionality. * **staticryptSaltUniqueVariableName** (string) - Unique variable name for the salt. * **templateConfig** (object) - Configuration for the password template: * **rememberExpirationKey** (string) - Key for remember expiration. * **rememberPassphraseKey** (string) - Key for remember passphrase. * **replaceHtmlCallback** (function) - Callback function to replace HTML. * **clearLocalStorageCallback** (function) - Callback function to clear local storage. ``` -------------------------------- ### Initialize Staticrypt Module Source: https://github.com/robinmoisson/staticrypt/blob/main/index.html Initializes the Staticrypt module, exposing functions for password template integration. It sets up configuration for encryption and template interactions. ```javascript function init(staticryptConfig, templateConfig) { const exports = {}; async function decryptAndReplaceHtml(hashedPassword) { const { staticryptEncryptedMsgUniqueVariableName, staticryptSaltUniqueVariableName } = staticryptConfig; const { replaceHtmlCallback } = templateConfig; const result = await decode( staticryptEncryptedMsgUniqueVariableName, hashedPassword, staticryptSaltUniqueVariableName ); if (!result.success) { return false; } const plainHTML = result.decoded; if (typeof replaceHtmlCallback === "function") { replaceHtmlCallback(plainHTML); } else { document.write(plainHTML); document.close(); } return true; } return exports; } exports.init = init; ``` -------------------------------- ### Handle File Download with Browser Compatibility Source: https://github.com/robinmoisson/staticrypt/blob/main/index.html Handles the click event for the download link. It checks if a file has been generated and then uses browser-specific methods (MSBlobBuilder for IE/Edge) to initiate the download of the encrypted HTML file. ```javascript document.getElementById("download-link").addEventListener("click", function (e) { // only register the click event if there is actually a generated file if (htmlToDownload) { trackEvent("download_encrypted"); } const isIE = navigator.userAgent.indexOf("MSIE") !== -1 || !!document.documentMode === true; // >= 10 const isEdge = navigator.userAgent.indexOf("Edge") !== -1; // download with MS specific feature if (htmlToDownload && (isIE || isEdge)) { e.preventDefault(); const blobObject = new Blob([htmlToDownload]); window.navigator.msSaveOrOpenBlob(blobObject, "encrypted.html"); } return true; }); ``` -------------------------------- ### Set File to Download Source: https://github.com/robinmoisson/staticrypt/blob/main/scripts/index_template.html Fetches the password template, renders it with provided data, and sets the download link's href attribute. This function is called after form submission. ```javascript function setFileToDownload(data) { const request = new XMLHttpRequest(); request.open("GET", "lib/password_template.html", true); request.onload = function () { const renderedTmpl = formater.renderTemplate(request.responseText, data); const downloadLink = document.querySelector("a.download"); downloadLink.href = "data:text/html," + encodeURIComponent(renderedTmpl); downloadLink.removeAttribute("disabled"); htmlToDownload = renderedTmpl; }; request.send(); } ``` -------------------------------- ### Generate a random salt and config file Source: https://github.com/robinmoisson/staticrypt/blob/main/README.md Generates a random salt and creates a `.staticrypt.json` configuration file. This is useful for committing the config file to version control to ensure consistent salts for shareable links. ```bash staticrypt --salt ``` -------------------------------- ### Initialize Staticrypt Module Source: https://github.com/robinmoisson/staticrypt/blob/main/example/encrypted/example.html Initializes the Staticrypt module with configuration objects for encryption and template settings. This function exposes callable functions for password templates. ```javascript function init(staticryptConfig, templateConfig) { const exports = {}; // ... other code ... return exports; } exports.init = init; return exports; })()); ``` -------------------------------- ### Staticrypt Initialization Source: https://github.com/robinmoisson/staticrypt/blob/main/example/encrypted/example.html Initializes the Staticrypt functionality, which includes the crypto engine and utility functions for handling hexadecimal strings. ```javascript const staticryptInitiator = ((function(){ const exports = {}; const cryptoEngine = ((function(){ const exports = {}; const { subtle } = crypto; const IV_BITS = 16 * 8; const HEX_BITS = 4; const ENCRYPTION_ALGO = "AES-CBC"; /** * Translates between utf8 encoded hexadecimal strings * and Uint8Array bytes. ``` -------------------------------- ### Handle Form Submission for Encryption Source: https://github.com/robinmoisson/staticrypt/blob/main/scripts/index_template.html Listens for form submission to encrypt user input using a provided password and salt. It then prepares data for downloading the encrypted file. ```javascript document.getElementById("encrypt_form").addEventListener("submit", async function (e) { e.preventDefault(); trackEvent("generate_encrypted"); const unencrypted = document.getElementById("unencrypted_html").value, password = document.getElementById("password").value; const salt = cryptoEngine.generateRandomSalt(); const encryptedMsg = await encode(unencrypted, password, salt); const templateButton = document.getElementById("template_button").value, templateColorPrimary = document.getElementById("template_color_primary").value, templateColorSecondary = document.getElementById("template_color_secondary").value, templateInstructions = document.getElementById("template_instructions").value, isRememberEnabled = document.getElementById("remember").checked, templateTitle = document.getElementById("template_title").value.trim(), templatePlaceholder = document.getElementById("template_placeholder").value.trim(), rememberDurationInDays = document.getElementById("remember_in_days").value || 0, templateRemember = document.getElementById("template_remember").value; const data = { staticrypt_config: { staticryptEncryptedMsgUniqueVariableName: encryptedMsg, isRememberEnabled, rememberDurationInDays, staticryptSaltUniqueVariableName: salt, }, is_remember_enabled: JSON.stringify(isRememberEnabled), js_staticrypt: getScriptAsString("staticrypt"), template_button: templateButton ? templateButton : "DECRYPT", template_color_primary: templateColorPrimary || "#4CAF50", template_color_secondary: templateColorSecondary || "#76B852", template_instructions: templateInstructions || "", template_placeholder: templatePlaceholder || "Password", template_remember: templateRemember || "Remember me", template_title: templateTitle || "Protected Page", }; document.getElementById("encrypted_html_display").textContent = encryptedMsg; setFileToDownload(data); }); ``` -------------------------------- ### Staticrypt CLI Usage Source: https://github.com/robinmoisson/staticrypt/blob/main/README.md Basic command structure for encrypting files using the Staticrypt CLI. The password argument is optional if set via environment variables or a .env file. ```bash Usage: staticrypt [ ...] [options] ``` -------------------------------- ### Customize template color and title Source: https://github.com/robinmoisson/staticrypt/blob/main/README.md Encrypts a file using a custom primary color and title for the password prompt template. More template customizations are available via additional flags. ```bash # use your own custom template staticrypt test.html -t my/own/password_template.html # or customize the default template staticrypt test.html \ --template-color-primary "#fd45a4" \ --template-title "My custom title" \ --template-instructions "To unlock this file, you should..." \ # ... ``` -------------------------------- ### encode(msg, password, salt) Source: https://github.com/robinmoisson/staticrypt/blob/main/index.html Asynchronously encodes a message using a password and salt. It first hashes the password, then encrypts the message with the hashed password, and finally creates an HMAC signature using the hashed password and the encrypted message. The HMAC and the encrypted message are concatenated to form the final output. ```APIDOC ## encode(msg, password, salt) ### Description Asynchronously encodes a message using a password and salt. It first hashes the password, then encrypts the message with the hashed password, and finally creates an HMAC signature using the hashed password and the encrypted message. The HMAC and the encrypted message are concatenated to form the final output. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters * **msg** (string) - The message to encode. * **password** (string) - The password to use for encoding. * **salt** (string) - The salt to use for hashing the password. ### Returns * **string** - The encoded text (HMAC + encrypted message). ``` -------------------------------- ### Register Page Load Event Source: https://github.com/robinmoisson/staticrypt/blob/main/index.html Tracks the 'show_index' event when the window finishes loading. ```javascript window.onload = function () { trackEvent("show_index"); }; ``` -------------------------------- ### Encrypt a file using environment variable for password Source: https://github.com/robinmoisson/staticrypt/blob/main/README.md Encrypts a file using a password stored in the STATICRYPT_PASSWORD environment variable. Supports .env files. ```bash # the password is in the STATICRYPT_PASSWORD env variable, you won't be prompted staticrypt test.html ``` -------------------------------- ### Generate a shareable auto-decrypt link Source: https://github.com/robinmoisson/staticrypt/blob/main/README.md Creates a URL with an embedded hashed password for auto-decryption. The salt from `.staticrypt.json` must be consistent for the link to remain valid. ```bash # you can also pass '--share' without specifying the URL to get the `#staticrypt_pwd=...` staticrypt test.html --share https://example.com/encrypted.html # => https://example.com/encrypted.html#staticrypt_pwd=5bfbf1343c7257cd7be23ecd74bb37fa2c76d041042654f358b6255baeab898f ``` -------------------------------- ### Second Round Password Hashing (15k Iterations) Source: https://github.com/robinmoisson/staticrypt/blob/main/index.html Adds a second round of PBKDF2 hashing with SHA-256 to increase security and support older remember-me links. ```javascript function hashSecondRound(hashedPassword, salt) { return pbkdf2(hashedPassword, salt, 14000, "SHA-256"); } exports.hashSecondRound = hashSecondRound; ``` -------------------------------- ### Encrypt a file with password argument Source: https://github.com/robinmoisson/staticrypt/blob/main/README.md Encrypts a single HTML file using a password provided directly as an argument. Use with caution as passwords in arguments can be exposed. ```bash staticrypt test.html -p ``` -------------------------------- ### PBKDF2 Hashing Implementation Source: https://github.com/robinmoisson/staticrypt/blob/main/index.html A generic PBKDF2 function for salting and hashing passwords. It uses the Web Crypto API for key import and derivation. ```javascript async function pbkdf2(password, salt, iterations, hashAlgorithm) { const key = await subtle.importKey("raw", UTF8Encoder.parse(password), "PBKDF2", false, ["deriveBits"]); const keyBytes = await subtle.deriveBits({ name: "PBKDF2", hash: hashAlgorithm, iterations, salt: UTF8Encoder.parse(salt), }, key, 256); return HexEncoder.stringify(new Uint8Array(keyBytes)); } ``` -------------------------------- ### Handle Logout via Query Parameter or URL Fragment Source: https://github.com/robinmoisson/staticrypt/blob/main/example/encrypted/example.html Checks for a 'staticrypt_logout' key in the URL's query parameters or fragment. If found, it clears local storage and indicates that a logout has occurred. ```javascript function logoutIfNeeded() { const logoutKey = "staticrypt_logout"; // handle logout through query param const queryParams = new URLSearchParams(window.location.search); if (queryParams.has(logoutKey)) { clearLocalStorage(); return true; } // handle logout through URL fragment const hash = window.location.hash.substring(1); if (hash.includes(logoutKey)) { clearLocalStorage(); return true; } return false; } ``` -------------------------------- ### Fill Password Prompt Template Source: https://github.com/robinmoisson/staticrypt/blob/main/scripts/index_template.html This function is intended to populate a password prompt template with provided data. The specific implementation details are not shown in the provided source. ```javascript /** * Fill the password prompt template with data provided. */ ``` -------------------------------- ### Encrypt file with a hardcoded salt Source: https://github.com/robinmoisson/staticrypt/blob/main/README.md Encrypts a file using a specific salt value provided directly in the command. This is an alternative to committing the `.staticrypt.json` file for CI/CD environments. ```bash staticrypt test.html --salt 12345678901234567890123456789012 ``` -------------------------------- ### Second Round Password Hashing (15k Iterations) Source: https://github.com/robinmoisson/staticrypt/blob/main/index.html Adds a second round of PBKDF2 hashing with 14000 iterations using SHA-256. This increases security and supports compatibility with passwords hashed using the legacy round. ```javascript function hashSecondRound(hashedPassword, salt) { return pbkdf2(hashedPassword, salt, 14000, "SHA-256"); } ``` -------------------------------- ### Encrypt a file with password prompt Source: https://github.com/robinmoisson/staticrypt/blob/main/README.md Encrypts a single HTML file. The password will be prompted and not stored in the command history. ```bash staticrypt test.html ``` -------------------------------- ### Legacy Password Hashing (1k Iterations) Source: https://github.com/robinmoisson/staticrypt/blob/main/index.html Provides a lower iteration count for backward compatibility. Uses PBKDF2 with SHA-1. ```javascript function hashLegacyRound(password, salt) { return pbkdf2(password, salt, 1000, "SHA-1"); } exports.hashLegacyRound = hashLegacyRound; ``` -------------------------------- ### Encrypt multiple HTML files Source: https://github.com/robinmoisson/staticrypt/blob/main/README.md Encrypts multiple specified HTML files, placing encrypted versions in an 'encrypted' directory. Non-HTML files are copied as-is. ```bash # this will encrypt test_A.html and test_B.html staticrypt test_A.html test_B.html # => encrypted files are in encrypted/test_A.html and encrypted/test_B.html ``` -------------------------------- ### Generate a shareable auto-decrypt link with 'Remember-me' Source: https://github.com/robinmoisson/staticrypt/blob/main/README.md Generates a shareable auto-decrypt link that also enables the 'Remember-me' functionality, allowing auto-decryption of multiple pages or across sessions. The '&remember_me' parameter can also be appended manually. ```bash # add --share-remember to auto-enable "Remember-me" - useful if you want send one link to # autodecrypt multiple pages (you can also just append '&remember_me') staticrypt test.html --share --share-remember # => #staticrypt_pwd=5bfbf1343c7257cd7be23ecd74bb37fa2c76d041042654f358b6255baeab898f&remember_me ``` -------------------------------- ### Project Public PGP Key Source: https://github.com/robinmoisson/staticrypt/blob/main/SECURITY.md This is the public PGP key for the project. It can be used to verify the authenticity of communications or releases. ```text -----BEGIN PGP PUBLIC KEY BLOCK----- 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 m4zPXCE1QrrgPtbBL6GXiE5z =Ab3R -----END PGP PUBLIC KEY BLOCK----- ``` -------------------------------- ### Encrypt HTML with a Password Source: https://github.com/robinmoisson/staticrypt/blob/main/README.md Encrypts an HTML file using a specified password and saves it to a designated output folder. This is useful for creating individual password-protected pages for different users. ```bash staticrypt test.html -p -d john ``` -------------------------------- ### Legacy Password Hashing Round Source: https://github.com/robinmoisson/staticrypt/blob/main/example/encrypted/example.html Performs the initial password hashing using PBKDF2 with 1000 iterations and SHA-1. This function is primarily for backward compatibility with older versions. ```javascript function hashLegacyRound(password, salt) { return pbkdf2(password, salt, 1000, "SHA-1"); } ``` -------------------------------- ### Handle Page Decryption with Password Source: https://github.com/robinmoisson/staticrypt/blob/main/example/encrypted/example.html Encrypts a given password and then calls the function to decrypt the page using the generated hash. This is the primary entry point for decrypting a page when the user provides a password. ```javascript async function handleDecryptionOfPage(password, isRememberChecked) { const { staticryptSaltUniqueVariableName } = staticryptConfig; // decrypt and replace the whole page const hashedPassword = await cryptoEngine.hashPassword(password, staticryptSaltUniqueVariableName); return handleDecryptionOfPageFromHash(hashedPassword, isRememberChecked); } exports.handleDecryptionOfPage = handleDecryptionOfPage; ``` -------------------------------- ### decode(signedMsg, hashedPassword, salt, backwardCompatibleAttempt, originalPassword) Source: https://github.com/robinmoisson/staticrypt/blob/main/index.html Asynchronously decodes a signed message. It first separates the HMAC signature from the encrypted message. It then verifies the signature using the provided hashed password and salt. If the signature does not match, it attempts to use older hashing rounds for backward compatibility. If successful, it decrypts the message. ```APIDOC ## decode(signedMsg, hashedPassword, salt, backwardCompatibleAttempt, originalPassword) ### Description Asynchronously decodes a signed message. It first separates the HMAC signature from the encrypted message. It then verifies the signature using the provided hashed password and salt. If the signature does not match, it attempts to use older hashing rounds for backward compatibility. If successful, it decrypts the message. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters * **signedMsg** (string) - The signed and encrypted message. * **hashedPassword** (string) - The hashed password used for encoding. * **salt** (string) - The salt used during password hashing. * **backwardCompatibleAttempt** (int, optional) - Internal parameter for handling backward compatibility. Defaults to 0. * **originalPassword** (string, optional) - Internal parameter used in backward compatibility attempts. Defaults to "". ### Returns * **Object** - An object containing: * **success** (boolean) - True if decoding was successful, false otherwise. * **decoded** (string) - The decrypted message if successful. * **message** (string) - An error message if decoding failed. ``` -------------------------------- ### Handle Encrypted File Download Source: https://github.com/robinmoisson/staticrypt/blob/main/scripts/index_template.html Provides browser-specific download functionality for the encrypted HTML file. It uses Blob and msSaveOrOpenBlob for IE/Edge compatibility. ```javascript document.getElementById("download-link").addEventListener("click", function (e) { // only register the click event if there is actually a generated file if (htmlToDownload) { trackEvent("download_encrypted"); } const isIE = navigator.userAgent.indexOf("MSIE") !== -1 || !!document.documentMode === true; // >= 10 const isEdge = navigator.userAgent.indexOf("Edge") !== -1; // download with MS specific feature if (htmlToDownload && (isIE || isEdge)) { e.preventDefault(); const blobObject = new Blob([htmlToDownload]); window.navigator.msSaveOrOpenBlob(blobObject, "encrypted.html"); } return true; }); ``` -------------------------------- ### Encrypt Message with Password Source: https://github.com/robinmoisson/staticrypt/blob/main/example/encrypted/example.html Asynchronously encrypts a UTF-8 message using a hashed password and a cryptographically random Initialization Vector (IV). The IV is prepended to the ciphertext for decryption. ```javascript async function encrypt(msg, hashedPassword) { // Must be 16 bytes, unpredictable, and preferably cryptographically random. However, it need not be secret. // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/encrypt#parameters const iv = crypto.getRandomValues(new Uint8Array(IV_BITS / 8)); const key = await subtle.importKey("raw", HexEncoder.parse(hashedPassword), ENCRYPTION_ALGO, false, ["encrypt"]); const encrypted = await subtle.encrypt( { name: ENCRYPTION_ALGO, iv: iv, }, key, UTF8Encoder.parse(msg) ); // iv will be 32 hex characters, we prepend it to the ciphertext for use in decryption return HexEncoder.stringify(iv) + HexEncoder.stringify(new Uint8Array(encrypted)); } ``` -------------------------------- ### Handle Automatic Decryption on Page Load Source: https://github.com/robinmoisson/staticrypt/blob/main/lib/password_template.html Attempts to automatically decrypt content when the page loads using the initialized StatiCrypt engine. If decryption is successful, it proceeds. Otherwise, it prepares to show the password prompt. ```javascript window.onload = async function () { const { isSuccessful } = await staticrypt.handleDecryptOnLoad(); // if we didn't decrypt anything on load, show the password prompt. if (!isSuccessful) { // Code to show password prompt would go here } }; ``` -------------------------------- ### Track Event with Supabase Source: https://github.com/robinmoisson/staticrypt/blob/main/index.html Sends an event action to a Supabase endpoint to track usage analytics without storing personal data or IP addresses. Requires specific API keys for authentication. ```javascript function trackEvent(action) { const xhr = new XMLHttpRequest(); xhr.open("POST", "https://zlgpaemmniviswibzuwt.supabase.co/rest/v1/rpc/increment_analytics", true); xhr.setRequestHeader("Content-type", "application/json; charset=UTF-8"); xhr.setRequestHeader("apikey", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InpsZ3BhZW1tbml2aXN3aWJ6dXd0Iiwicm9sZSI6ImFub24iLCJpYXQiOjE2NjkxMjM0OTcsImV4cCI6MTk4NDY5OTQ5N30.wNoVDHG7F6INx-IPotMs3fL1nudfaF2qvQDgG-1PhNI"); xhr.setRequestHeader("Authorization", "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InpsZ3BhZW1tbml2aXN3aWJ6dXd0Iiwicm9sZSI6ImFub24iLCJpYXQiOjE2NjkxMjM0OTcsImV4cCI6MTk4NDY5OTQ5N30.wNoVDHG7F6INx-IPotMs3fL1nudfaF2qvQDgG-1PhNI"); xhr.send( JSON.stringify({ action_input: action, }) ); } ``` -------------------------------- ### Toggle Concept Explanation Visibility Source: https://github.com/robinmoisson/staticrypt/blob/main/index.html Toggles the visibility of the 'concept' explanation section and updates the associated toggle sign ('►' or '▼'). It maintains a state variable 'isConceptShown' to track the current visibility. ```javascript let isConceptShown = false; document.getElementById("toggle-concept").addEventListener("click", function (e) { e.preventDefault(); isConceptShown = !isConceptShown; document.getElementById("toggle-concept-sign").innerText = isConceptShown ? "▼" : "►"; document.getElementById("concept").classList.toggle("hidden"); }); ``` -------------------------------- ### Encrypt files in a directory without including directory name in output path Source: https://github.com/robinmoisson/staticrypt/blob/main/README.md Encrypts files from a directory, placing them directly into the 'encrypted' output directory without preserving the original directory's name. The '-r' flag ensures subdirectories are also processed. ```bash # if you don't want to include the directory name in the output path, you can use # `dir_to_encrypt/*` instead. `-r` will include potential subdirectories as well staticrypt dir_to_encrypt/* -r # => encrypted files are in encrypted/... ``` -------------------------------- ### PBKDF2 Password Hashing Function Source: https://github.com/robinmoisson/staticrypt/blob/main/index.html Asynchronously hashes a password using the PBKDF2 algorithm with specified parameters. Requires subtle crypto API. ```javascript async function pbkdf2(password, salt, iterations, hashAlgorithm) { const key = await subtle.importKey("raw", UTF8Encoder.parse(password), "PBKDF2", false, ["deriveBits"]); const keyBytes = await subtle.deriveBits( { name: "PBKDF2", hash: hashAlgorithm, iterations, salt: UTF8Encoder.parse(salt) }, key, 256 ); return HexEncoder.stringify(new Uint8Array(keyBytes)); } ``` -------------------------------- ### Generate Random Salt Source: https://github.com/robinmoisson/staticrypt/blob/main/example/encrypted/example.html Generates a random 128-bit salt for use in password hashing. Ensures unique salts for each operation. ```javascript function generateRandomSalt() { const bytes = crypto.getRandomValues(new Uint8Array(128 / 8)) return HexEncoder.stringify(new Uint8Array(bytes)) } ``` -------------------------------- ### Hash Password for Storage Source: https://github.com/robinmoisson/staticrypt/blob/main/index.html Salts and hashes a password in multiple steps to enhance security for storage. This function is designed to be iterated for increased security. ```javascript async function hashPassword(password, salt) { // we hash the password in multiple steps, each adding more iterations. ``` -------------------------------- ### PBKDF2 Password Hashing Source: https://github.com/robinmoisson/staticrypt/blob/main/example/encrypted/example.html Asynchronously hashes a password using PBKDF2 with specified salt, iterations, and algorithm. Suitable for securely storing password-derived keys. ```javascript async function pbkdf2(password, salt, iterations, hashAlgorithm) { const key = await subtle.importKey("raw", UTF8Encoder.parse(password), "PBKDF2", false, ["deriveBits"]) const keyBytes = await subtle.deriveBits( { name: "PBKDF2", hash: hashAlgorithm, iterations, salt: UTF8Encoder.parse(salt), }, key, 256 ) return HexEncoder.stringify(new Uint8Array(keyBytes)) } ``` -------------------------------- ### Handle Decryption on Page Load Source: https://github.com/robinmoisson/staticrypt/blob/main/example/encrypted/example.html Attempts to decrypt the page either from URL parameters or by checking the 'remember me' functionality in local storage. Returns whether the decryption was successful. ```javascript async function handleDecryptOnLoad() { let isSuccessful = await decryptOnLoadFromUrl(); if (!isSuccessful) { isSuccessful = await decryptOnLoadFromRememberMe(); } return { isSuccessful }; } exports.handleDecryptOnLoad = handleDecryptOnLoad; ``` -------------------------------- ### Hex String to Bytes Conversion Source: https://github.com/robinmoisson/staticrypt/blob/main/index.html Utility for converting hexadecimal strings to Uint8Array bytes. Throws an error for invalid or odd-length hex strings. ```javascript parse: function (hexString) { if (hexString.length % 2 !== 0) throw "Invalid hexString"; const arrayBuffer = new Uint8Array(hexString.length / 2); for (let i = 0; i < hexString.length; i += 2) { const byteValue = parseInt(hexString.substring(i, i + 2), 16); if (isNaN(byteValue)) { throw "Invalid hexString"; } arrayBuffer[i / 2] = byteValue; } return arrayBuffer; } ``` -------------------------------- ### Decrypt a file from the CLI Source: https://github.com/robinmoisson/staticrypt/blob/main/README.md Decrypts a file previously encrypted with Staticrypt using the `--decrypt` flag. The output is placed in a 'decrypted' directory by default. ```bash staticrypt encrypted/test.html --decrypt # => decrypted file is in decrypted/test.html ```