{"id":13592404,"url":"https://github.com/unverbuggt/mkdocs-encryptcontent-plugin","last_synced_at":"2025-04-08T18:19:40.786Z","repository":{"id":37927803,"uuid":"228263468","full_name":"unverbuggt/mkdocs-encryptcontent-plugin","owner":"unverbuggt","description":"A MkDocs plugin that encrypt/decrypt markdown content with AES","archived":false,"fork":false,"pushed_at":"2024-10-27T13:24:39.000Z","size":2317,"stargazers_count":130,"open_issues_count":4,"forks_count":16,"subscribers_count":4,"default_branch":"version3","last_synced_at":"2024-10-30T01:43:43.194Z","etag":null,"topics":["aes","encryption-decryption","highlightjs","jinja2","mkdocs-plugin","protected-resources","python"],"latest_commit_sha":null,"homepage":"https://unverbuggt.github.io/mkdocs-encryptcontent-plugin/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/unverbuggt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-12-15T22:42:26.000Z","updated_at":"2024-10-27T13:24:42.000Z","dependencies_parsed_at":"2023-11-11T21:24:28.026Z","dependency_job_id":"b2301dd5-82dc-4e14-8716-f64e6a85e1d8","html_url":"https://github.com/unverbuggt/mkdocs-encryptcontent-plugin","commit_stats":{"total_commits":265,"total_committers":6,"mean_commits":"44.166666666666664","dds":0.2075471698113207,"last_synced_commit":"f08ba85b7c5968cdf8bb857c86957b033550013e"},"previous_names":[],"tags_count":35,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unverbuggt%2Fmkdocs-encryptcontent-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unverbuggt%2Fmkdocs-encryptcontent-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unverbuggt%2Fmkdocs-encryptcontent-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unverbuggt%2Fmkdocs-encryptcontent-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/unverbuggt","download_url":"https://codeload.github.com/unverbuggt/mkdocs-encryptcontent-plugin/tar.gz/refs/heads/version3","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247898519,"owners_count":21014722,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aes","encryption-decryption","highlightjs","jinja2","mkdocs-plugin","protected-resources","python"],"created_at":"2024-08-01T16:01:08.889Z","updated_at":"2025-04-08T18:19:40.762Z","avatar_url":"https://github.com/unverbuggt.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"[![PyPI Version](https://img.shields.io/pypi/v/mkdocs-encryptcontent-plugin.svg)](https://pypi.org/project/mkdocs-encryptcontent-plugin/)\r\n[![PyPI downloads](https://img.shields.io/pypi/dm/mkdocs-encryptcontent-plugin.svg)](https://pypi.org/project/mkdocs-encryptcontent-plugin/)\r\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\r\n\r\n# mkdocs-encryptcontent-plugin\r\n\r\nThis plugin allows you to have password protected articles and pages in MKdocs.\r\n\r\nThe content is encrypted with AES-256 in Python using PyCryptodome and decrypted in the browser with Crypto-JS or Webcrypto.\r\n\r\n*It has been tested in Python Python 3.8+*\r\n\r\n**Usecase**\r\n\r\n\u003e I want to be able to protect the content of the page with a password.\r\n\u003e\r\n\u003e Define a password to protect each page independently or a global password to protect them all.\r\n\u003e\r\n\u003e If a global password exists, all articles and pages are protected with this password.\r\n\u003e\r\n\u003e If a password is defined in an article or a page, it is always used even if there is a global password.\r\n\u003e\r\n\u003e If a password is defined as an empty character string, content encryption is disabled.\r\n\u003e\r\n\u003e Additionally password levels can be defined in mkdocs.yml or external yaml file with user/password credentials.\r\n\r\n## New features (compared to version 2.5.x)\r\n\r\n* Stronger cryptography (PBKDF2 for key derivation)\r\n* Faster cryptography (Webcrypto as alternative to crypto-js)\r\n* Allow password inventory or levels in mkdocs.yml or external file for credential handling\r\n* Allow user name + password as credentials\r\n* If credential is reused in different levels it also decrypts all of their content\r\n* Optional adding of credentials to URLs for sharing\r\n* Optional tamper check by signing generated files with Ed25519\r\n* New [Documentation](https://unverbuggt.github.io/mkdocs-encryptcontent-plugin/) and [Test bench](https://unverbuggt.github.io/mkdocs-encryptcontent-plugin/testbench/)\r\n\r\n## Upgrading from version 2.5.x\r\n\r\nThe `use_secret` functionality was discontinued in the plugin configuration and as a meta tag.\r\n\r\nIn order to use environment variables in user names or passwords, use the \r\n[special yaml tag](https://www.mkdocs.org/user-guide/configuration/#special-yaml-tags) `!ENV`.\r\n\r\n## Todos for 3.1.x\r\n* outsource some functionality to separate plugins, like:\r\n    * Filename obfuscation\r\n    * Signing of generated files\r\n* find a better way for search decryption\r\n* add better alternative to PBKDF2\r\n* optional server side keystore (allows throtteling)\r\n    * still no waterproof solution...\r\n* ...to be defined\r\n\r\n\r\n# Table of Contents\r\n* [Installation](#Installation)\r\n* [Usage](#Usage)\r\n\t* [Password inventory](#Password-inventory)\r\n\t\t* [Password inventory in external file](#Password-inventory-in-external-file)\r\n\t* [Global password protection](#Global-password-protection)\r\n\t\t* [Global passwords in inventory](#Global-passwords-in-inventory)\r\n\t* [Secret from environment](#Secret-from-environment)\r\n\t* [Default vars customization](#Default-vars-customization)\r\n\t* [Translations](#Translations)\r\n\t\t* [Custom per-page strings](#Custom-per-page-strings)\r\n\t* [Obfuscate pages](#Obfuscate-pages)\r\n\t* [Example plugin configuration](#Example-plugin-configuration)\r\n* [Features](#Features)\r\n\t* [Override default templates](#Override-default-templates)\r\n\t* [Add button](#Add-button)\r\n\t* [Tag encrypted page](#Tag-encrypted-page)\r\n\t* [Remember password](#Remember-password)\r\n\t* [Share link generation](#Share-link-generation)\r\n\t\t* [Incomplete Share links](#Incomplete-Share-links)\r\n\t* [Storage of additional variables in keystore](#Storage-of-additional-variables-in-keystore)\r\n\t* [Modify generated pages](#Modify-generated-pages)\r\n\t\t* [Encrypt something](#Encrypt-something)\r\n\t\t* [Inject decrypt-form.tpl to theme](#Inject-decrypt-form.tpl-to-theme)\r\n\t\t* [Mix encrypted and normal content](#Mix-encrypted-and-normal-content)\r\n\t* [Search encryption](#Search-encryption)\r\n\t\t* [Search index encryption](#Search-index-encryption)\r\n\t\t* [Search index encryption for mkdocs-material](#Search-index-encryption-for-mkdocs-material)\r\n\t* [Javascript extensions](#Javascript-extensions)\r\n\t\t* [Reload user-defined scripts](#Reload-user-defined-scripts)\r\n\t\t* [HighlightJS support](#HighlightJS-support)\r\n\t\t* [Arithmatex support](#Arithmatex-support)\r\n\t\t* [Mermaid.js support](#Mermaid.js-support)\r\n\t\t* [mkdocs-glightbox](#mkdocs-glightbox)\r\n\t* [Security](#Security)\r\n\t\t* [Crypto-js or crypto-es or webcrypto?](#Crypto-js-or-crypto-es-or-webcrypto?)\r\n\t\t* [File name obfuscation](#File-name-obfuscation)\r\n\t\t* [Signing of generated files](#Signing-of-generated-files)\r\n\r\n\r\n# Installation\r\n\r\nInstall the package with pip:\r\n\r\n```bash\r\npip install mkdocs-encryptcontent-plugin\r\n```\r\n\r\nInstall the package from source with pip:\r\n\r\n```bash\r\ncd mkdocs-encryptcontent-plugin/\r\npython setup.py sdist bdist_wheel\r\npip install --force-reinstall --no-deps dist/mkdocs_encryptcontent_plugin-3.0.4-py3-none-any.whl\r\n```\r\n\r\nEnable the plugin in your `mkdocs.yml`:\r\n\r\n```yaml\r\nplugins:\r\n    - search: {}\r\n    - encryptcontent: {}\r\n```\r\n\u003e **NOTE:** If you have no `plugins` entry in your configuration file yet, you'll likely also want to add the `search` plugin.\r\n\u003e MkDocs enables it by default if there is no `plugins` entry set, but now you have to enable it explicitly.\r\n\r\n# Usage\r\n\r\nAdd a tag like `password: secret password` to your pages [Meta-Data](https://www.mkdocs.org/user-guide/writing-your-docs/#yaml-style-meta-data) to protect them.\r\n\r\nAlternatively add a meta tag like `level: secret` to use one or more secrets defined at the\r\nplugin's `password_inventory` or `password_file` in your \"mkdocs.yml\" (see below).\r\n\r\n\r\n## Password inventory\r\n\r\nWith the `password_inventory` you can define protection levels (assigned with the meta tag `level` in markdown files).\r\n\r\n```yaml\r\nplugins:\r\n    - encryptcontent:\r\n        password_inventory:\r\n          classified: 'password1'\r\n          confidential:\r\n            - 'password2'\r\n            - 'password3'\r\n          secret:\r\n            user4: 'password4'\r\n            user5: 'password5'\r\n```\r\n\r\nThese levels may be only one password (f.ex. classified), a list of multiple passwords (f.ex. confidential)\r\nor multiple username/password pairs (f.ex. secret).\r\nIt is possible to reuse credentials at different levels.\r\n\r\n\u003eNote that a \"list of multiple passwords\" comes with a downside: All entries may be tested because unlike \"user/password pairs\"\r\n\u003ethere is no hint to determine the distinct entry to try\r\n\u003e(At least I found no hint that wouldn't make it easier for a brute force attacker).\r\n\u003eThis means, that a high `kdf_pow` could cause long waiting time even if the right password was entered.\r\n\r\nThe plugin will generate one secret key for each level, which is then used to encrypt the assigned sites.\r\n\r\nTo indicate that your Markdown file should be encrypted for level \"secret\", add the following metadata at the beginning of the file:\r\n\r\n```markdown\r\n---\r\nlevel: secret\r\n---\r\nThis is the first paragraph of the document.\r\n```\r\n\r\n\r\n### Password inventory in external file\r\n\r\nYou can define password levels in an external yaml file and link it with `password_file`.\r\nThe intention is to separate sensitive information from configuration options.\r\n\r\n```yaml\r\nplugins:\r\n    - encryptcontent:\r\n        password_file: 'passwords.yml'\r\n```\r\n\r\npasswords.yml:\r\n```yaml\r\nclassified: 'password1'\r\nconfidential:\r\n    - 'password2'\r\n    - 'password3'\r\nsecret:\r\n    user4: 'password4'\r\n    user5: 'password5'\r\n```\r\n\r\n## Global password protection\r\n\r\nAdd `global_password: your_password` in plugin configuration variable, to protect all pages with this password by default\r\n\r\n```yaml\r\nplugins:\r\n    - encryptcontent:\r\n        global_password: 'your_password'\r\n```\r\n\r\nIf the password meta tag is defined in a markdown file, it will **ALWAYS** override the global password.\r\n\r\n\u003e **NOTE** Keep in mind that if the `password:` tag exists without value in a page, it will **not be protected** !\r\n\u003e Use this to **disable** `global_password` on specific pages.\r\n\r\n### Global passwords in inventory\r\n\r\nYou can add the special level `_global`, which will be applied globally on all sites like this:\r\n\r\n```yaml\r\nplugins:\r\n    - encryptcontent:\r\n        password_inventory:\r\n            _global: 'either define one password'\r\n            _global:\r\n                - 'or define'\r\n                - 'multiple passwords'\r\n            _global:\r\n                user1: 'or use user'\r\n                user2: 'and password pairs'\r\n```\r\n\r\n\u003e **NOTE** Add the meta tag `level:` (without a value) to pages which should be excluded from global password level.\r\n\u003e Also note that it is always possible to set the page to a different level than the global one with the `level` meta tag.\r\n\r\n## Secret from environment\r\n\r\nIt is possible to read values from environment variable\r\n(as discribed [here](https://www.mkdocs.org/user-guide/configuration/#environment-variables)).\r\nThis replaces the deprecated `use_secret` option from previous versions.\r\n\r\n```yaml\r\nplugins:\r\n    - encryptcontent:\r\n        password_inventory:\r\n            secret:\r\n                user1: !ENV PASSWORD1_FROM_ENV\r\n                user2: !ENV [PASSWORD2_FROM_ENV, 'Password if PASSWORD2_FROM_ENV undefined or empty']\r\n                user3: !ENV [PASSWORD3_FROM_ENV, FALLBACK_PASSWORD3_FROM_ENV, 'Password if neither PASSWORD3_FROM_ENV nor FALLBACK_PASSWORD3_FROM_ENV defined']\r\n```\r\n\r\n## Default vars customization\r\n\r\nOptionally you can use some extra variables in plugin configuration to customize default strings.\r\n\r\n```yaml\r\nplugins:\r\n    - encryptcontent:\r\n        title_prefix: '[LOCK]'\r\n        summary: 'another informational message to encrypted content'\r\n        placeholder: 'another password placeholder'\r\n        decryption_failure_message: 'another informational message when decryption fails'\r\n        encryption_info_message: \"another information message when you don't have access !\"\r\n        input_class: 'md-search__form md-search__input'\r\n        button_class: 'md-search__icon'\r\n```\r\n\r\nDefault prefix title is `[Protected]`.\r\n\r\nDefault summary message is `This content is protected with AES encryption.`.\r\n\r\nDefault password palceholder is `Provide password and press ENTER`.\r\n\r\nDefault decryption failure message is `Invalid password.`.\r\n\r\nDefaut encryption information message is `Contact your administrator for access to this page.`.\r\n\r\n\u003e **NOTE** Adding a prefix to the title does not change the default navigation path !\r\n\r\n## Translations\r\n\r\nIf the plugin is used in conjunction with the [static-i18n](https://ultrabug.github.io/mkdocs-static-i18n/)\r\nplugin you can provide `translations` for the used `i18n_page_locale`.\r\n\r\n```yaml\r\n    - encryptcontent:\r\n        #...\r\n        translations:\r\n          de:\r\n            title_prefix: '[Verschlüsselt] '\r\n            summary: 'Der Inhalt dieser Seite ist mit AES verschlüsselt. '\r\n            placeholder: 'Mit Strg+Enter wird das Passwort global gesetzt'\r\n            password_button_text: 'Entschlüsseln'\r\n            decryption_failure_message: 'Falsches passwort.'\r\n            encryption_info_message: 'Bitte wenden Sie sich an den Systemadministrator um auf diese Seite zuzugreifen.'\r\n```\r\n\r\n### Custom per-page strings\r\n\r\nYou can set the  meta tag `encryption_summary` to customize `summary` and `encryption_info_message` on every page.\r\n\r\n## Obfuscate pages\r\n\r\nIf you want to make it harder for search engines to scrape you pages content,\r\nyou can set `obfuscate: SomeNotSoSecretPassword` meta tag in markdown.\r\n\r\nThe page then will display `summary` and `encryption_info_message` together with a button labeled with\r\n`password_button_text`. In order to view the pages content one hast to press the button first.\r\n\r\nIf a `password` or `level` is set, then the `obfuscate` feature will be disabled.\r\nIf you want to use `obfuscate` in a configuration where `global_password` or `_global` level is defined,\r\nyou'll need to set the `password:` or rather `level:` meta tag (with no password/level defined) to undefine the password on this page.\r\n\r\nThe keys to all obfuscated pages are also saved in every keystore, so they are decrypted if someone entered\r\ncorrect credentials.\r\n\r\n\r\n## Example plugin configuration\r\n\r\n```yaml\r\nplugins:\r\n    - encryptcontent:\r\n        title_prefix: ''\r\n        summary: ''\r\n        placeholder: 'Password'\r\n        placeholder_user: User\r\n        password_button_text: 'ENTER'\r\n        decryption_failure_message: 'Wrong user name or password.'\r\n        encryption_info_message: 'Legitimation required.'\r\n        translations:\r\n          de:\r\n            title_prefix: ''\r\n            summary: ''\r\n            placeholder: 'Passwort'\r\n            placeholder_user: Benutzer\r\n            password_button_text: 'ENTER'\r\n            decryption_failure_message: 'Falscher Benutzer oder Passwort.'\r\n            encryption_info_message: 'Legitimation erforderlich.'\r\n        html_template_path: \"decrypt-form.tpl.html\" # override default html template\r\n        password_button: True\r\n        input_class: 'w3-input' # CSS class used for input username and password\r\n        button_class: 'w3-button w3-theme-l1 w3-hover-theme' # CSS class for password_button\r\n        hljs: False\r\n        arithmatex: False\r\n        mermaid2: False\r\n        remember_keys: true # keys from keystore will temporarily saved to sessionStorage\r\n        remember_password: false # the entered credentials are not saved\r\n        remember_prefix: encryptcontent_plugin_ # use different prefixes if other sites are running on the same domain\r\n        encrypted_something: # additionally encrypt some html elements\r\n          #myNav: [div, id]\r\n          myToc: [div, id]\r\n          myTocButton: [div, id]\r\n        search_index: 'dynamically' # dynamically encrypt mkdocs search index\r\n        webcrypto: true # use browsers webcrypto support\r\n        #selfhost: true # use self-hosted crypto-js\r\n        #selfhost_download: true # download crypt-js for self-hosting\r\n        #selfhost_dir: 'theme_override' # where to download crypto-js\r\n        #reload_scripts:\r\n        #  - '#theme'\r\n        password_file: 'passwords.yml' # file with password inventory\r\n        threshold_warning_min_entropy: 100 # warn if password entropy is below this value\r\n        #kdf_pow: 4 # default for crypto-js: 4, default for webcrypto: 5\r\n        sign_files: 'encryptcontent-plugin.json' # save ed25519 signatures here\r\n        #hash_filenames: # add hash to file names of assets (to make them impossible to guess\r\n        #  extensions:\r\n        #    - 'png'\r\n        #    - 'jpg'\r\n        #    - 'jpeg'\r\n        #    - 'svg'\r\n        #  except:\r\n        #    - 'logo.svg'\r\n```\r\n\r\n# Features\r\n\r\n## Override default templates\r\n\r\nRelated to [issue #32](https://github.com/unverbuggt/mkdocs-encryptcontent-plugin/issues/32)\r\n\r\nYou can override the default templates with your own templates by providing an actual replacement\r\npath in the `html_template_path` *(HTML)* and `js_template_path` *(JS)* directives. \r\nOverridden templates **completely** replace the default templates. You **must** therefore copy the\r\ndefault templates as a starting point to keep this plugin working.\r\n\r\n```yaml\r\nplugins:\r\n    - encryptcontent:\r\n        html_template_path: \"/root/real/path/mkdocs_poc/my_html_template.html\"\r\n        js_template_path: \"/root/real/path/mkdocs_poc/my_js_template.js\"\r\n        form_class: 'md-content__inner md-typeset'\r\n        input_class: 'md-input'\r\n        button_class: 'md-button md-button--primary'\r\n```\r\n\r\nUse `form_class`, `input_class` and `button_class` to optionally set a CSS class for the password input field and the button.\r\n\r\nWhen overriding the default templates, you can add and use your own Jinja variables\r\nand enrich your template, by defining `html_extra_vars` and `js_extra_vars` directives in key/value format.\r\nAdded values can be used in your Jinja templates via the variable `extra`.\r\n\r\n```yaml\r\nplugins:\r\n    - encryptcontent:\r\n        html_extra_vars:\r\n            my_extra: \"extra value\"\r\n            \u003ckey\u003e: \u003cvalue\u003e\r\n        js_extra_vars:\r\n            my_extra: \"extra value\"\r\n            \u003ckey\u003e: \u003cvalue\u003e\r\n```\r\n\r\nFor example, you can modify your HTML template, to add a new title with your own text variable.\r\n\r\n```jinja\r\n[ ... ] \r\n\u003ch2\u003e{{ extra.my_extra }}\u003c/h2\u003e\r\n[ ... ]\r\n```\r\n\r\n\u003e **NOTE** Issues related to template override will not be addressed.\r\n\r\n## Add button\r\n\r\nAdd `password_button: True` in plugin configuration variable, to add a button to the right of the password field.\r\n\r\nWhen enabled, it allows to decrypt the content just like the classic keypress ENTER.\r\n\r\nOptionally, you can add `password_button_text: 'custom_text_button'` to customize the button text.\r\n \r\n```yaml\r\nplugins:\r\n    - encryptcontent:\r\n        password_button: True\r\n        password_button_text: 'custom_text_button'\r\n```\r\n\r\n## Tag encrypted page\r\n\r\n\u003e **Enable by default**\r\n\r\nRelated to [issue #7](https://github.com/unverbuggt/mkdocs-encryptcontent-plugin/issues/7)\r\n\r\nThis feature adds an additional attribute `encrypted` with value `True` to the mkdocs type `mkdocs.nav.page` object.\r\n\r\nYou can add `tag_encrypted_page: False` in plugin configuration, to disable tagging of encrypted pages. \r\n\r\nWhen enabled, it is possible to use the `encrypted` attribute in the jinja template of your theme, as a condition to perform custom modification.\r\n\r\n```jinja\r\n{%- for nav_item in nav %}\r\n    {% if nav_item.encrypted %}\r\n        \u003c!-- Do something --\u003e \r\n    {% endif %}\r\n{%- endfor %}\r\n```\r\n\r\nFor example, you can use conditional check to add a custom class:\r\n\r\n```jinja\r\n\u003ca {% if nav_item.encrypted %}class=\"mkdocs-encrypted-class\"{% endif %}href=\"{{ nav_item.url|url }}\"\u003e{{ nav_item.title }}\u003c/a\u003e\r\n```\r\n\r\n## Remember password\r\n\r\nRelated to [issue #6](https://github.com/unverbuggt/mkdocs-encryptcontent-plugin/issues/6)\r\n\r\nBy default the plugin will save the decrypted AES keys to session storage of the browser (can be disabled by setting `remember_keys: False`).\r\nThis is enabled for convenience, so you are able to browse between multiple encrypted pages without having to re-enter the password.\r\n\r\nAdditionally it is possible to save the entered user/password in session storage (setting `remember_password: True`). Use this for\r\nadditional convenience during `mkdocs serve`, because the AES key are regenerated every time MkDocs starts\r\n(rendering the old ones invalid and requiring to re-enter a valid credential again).\r\n\r\nTo avoid problems when multiple sites are hosted within the same domain, it is possible to customize the name of\r\nthe keys saved to storage with `remember_prefix`.\r\n\r\n\u003e **This feature is not really secure !** decryption keys are store in clear text inside session storage.\r\n\u003e\r\n\u003e Instead of using these features, I recommend to use a password manager with its browser plugin.\r\n\u003e For example **KeepassXC** allows you to detect the password field\r\n\u003e `mkdocs-content-password` and fill it automatically in a much more secure way.\r\n\r\nIt is also possible to save the used credentials permanently to local storage (setting `session_storage: False`), but\r\nthis should only be done for testing purposes. The local storage of a browser is most likely readable\r\nfor every other process that can access the file system. \r\n\r\nThe session storage however should only be located in memory and be forgotten after the browser tab is closed.\r\n\r\n```yaml\r\nplugins:\r\n    - encryptcontent:\r\n        remember_keys : True\r\n        remember_password: False\r\n        remember_prefix: secretsite_\r\n```\r\n\r\n## Share link generation\r\n\r\nIt is possible to share valid credentials by adding them to the hash part of the URL.\r\nThe plugin can also generate share links for certain pages if the meta tag `sharelink: true`\r\nis defined in markdown.\r\nIt will use the first credential for the pages level or the pages password.\r\nThe credentials for auto-generated links are base64url encoded.\r\n\r\n```yaml\r\nplugins:\r\n    - encryptcontent:\r\n        sharelinks: True\r\n        sharelinks_output: 'sharelinks.txt' # generated share links are saved here\r\n```\r\n\u003e One condition applies: The user name must not contain the \":\" character (Passwords may use that character).\r\n\r\nHowever if `sharelinks: True` is enabled in the plugin configuration you can generate share links yourself:\\\r\n`https://your-domain.com/your-site/protected-page/#!username:password` for user/password or\\\r\n`https://your-domain.com/your-site/protected-page/#!password` for only password.\r\n\r\n\u003e Then another condition applies: If non-aphanumeric characters are used in user/password,\r\n\u003e they need to be URLencoded (f.ex. %20 = space character). Some browsers may do that automatically (Do a copy/paste from the browsers address bar then).\r\n\r\n### Incomplete Share links\r\n\r\nSince version 3.0.3 it is possible to leave out one part of the password when share links are generated via meta tag.\r\nTo do this use the \":\" character in a password to divide the part that is incorporated to the share link and the part that remains secret,\r\nlike \"PartThatIsEncodedToTheShareLink:PartThatRemainsSecret\". \r\nThe feature is enabled by setting the option `sharelinks_incomplete: true`.\r\nIf the password that is read from the share link ends with the \":\" character, then an additional password input field is displayed for entering the secret part.\r\n\r\n\u003e If the feature is used, then passwords must not end with the \":\" character.\r\n\r\n\r\n## Storage of additional variables in keystore\r\n\r\nSince version 3.0.3 it is possible to set arbitrary session store variables after decryption.\r\nThese can be used by javascript functions f. ex. to read API tokens or show the user name or set visibility of menu entries.\r\nThe variables are encrypted together with the content keys in the keystore.\r\n\r\n```yaml\r\nplugins:\r\n    - encryptcontent:\r\n        additional_storage_file: 'additional_storage.yaml'\r\n```\r\n\r\nThe file may contain a `userpass:` dictionary, wich refers to user names\r\nand/or a `password:` dictionary, that refers to password-only credentials.\r\nIt may contain a arbitrary number of key/value pairs,\r\nbut keep in mind to check if the key name is reasonable and not already used by other parts of the page\r\n(as it will be overwritten after decryption).\r\n\r\n```yaml\r\nuserpass:\r\n  alice:\r\n    username: Alice McAliceface\r\n    userid: 1\r\n    token: uCZDqa2vzuSPFX-o9TebinUAnD9sePJqpPYhavMkCH7gGo7lhjWRS17-HgBys9UKnFR37zXO4Q_f1_ywZJqBlA==\r\n\r\npassword:\r\n  Head32_Sculpture_bovine_:\r\n    username: Head McPassword\r\n```\r\n## Modify generated pages\r\n\r\n### Encrypt something\r\n\r\nRelated to [issue #9](https://github.com/unverbuggt/mkdocs-encryptcontent-plugin/issues/9)\r\n\r\nAdd `encrypted_something: {}` in the plugin configuration variable, to encrypt something else on the page.\r\n\r\nThe syntax of this new variable **MUST** follow the yaml format of a dictionary. \r\nChild elements of `encrypted_something` are build with a key `\u003cunique name\u003e` in string format and a list as value.\r\nThe list has to be constructed with the name of an HTML tag `\u003chtml tag\u003e` as first item\r\nand `id` or `class` as the second item.\r\n\r\n```yaml\r\nplugins:\r\n    - encryptcontent:\r\n        encrypted_something:\r\n            \u003cuniqe name\u003e: [\u003chtml tag\u003e, \u003c'class' or 'id'\u003e]\r\n```\r\n\r\nThe `\u003cunique name\u003e` key identifies the name of a specific element of the page that will be\r\nsearched by Beautiful Soup.\r\nThe first value of the list (`\u003chtml tag\u003e`) identifies the type of HTML tag in which the name is present.\r\nThe second value of the list (`'id'` or `'class'`) specifies the type of the attribute which contains\r\nthe unique name in the html tag.\r\n\r\nPrefer to use an `'id'`, however depending on the template of your theme, it is not always possible to use the id.\r\nSo we can use the class attribute to define your unique name inside the html tag. \r\nBeautiful Soup will encrypt all HTML elements discovered with the class.\r\n\r\nWhen the feature is enabled every element is decrypted upon successfull content decryption on the page.\r\n\r\n\u003e Use this to hide the table of contents on the page or sub pages in the menu\r\n\r\nBy default **every child item** are encrypted and the encrypted elements have set\r\n`style=\"display:none;\"` to hide their content.\r\n\r\n#### How to use it?! Examples\r\n\r\nYou can use the `page.encrypted` tag to add attributes to html tags in the HTML templates of your theme\r\nor identify usable tag ids or classes that are already in the theme.\r\n\r\nThen add these elements in the format of a yaml dictionary under the variable `encrypted_something`.\r\n\r\n1. For example, encrypt ToC in a theme where ToC is under 'div' element like this :\r\n\r\n```jinja\r\n\u003cdiv class=\"..\" {% if page.encrypted %}id=\"mkdocs-encrypted-toc\"{% endif %}\u003e\r\n    \u003cul class=\"..\"\u003e\r\n        \u003cli class=\"..\"\u003e\u003ca href=\"{{ toc_item.url }}\"\u003e{{ toc_item.title }}\u003c/a\u003e\u003c/li\u003e\r\n        \u003cli\u003e\u003ca href=\"{{ toc_item.url }}\"\u003e{{ toc_item.title }}\u003c/a\u003e\u003c/li\u003e\r\n    \u003c/ul\u003e\r\n\u003c/div\u003e\r\n```\r\n\r\nSet your configuration like this : \r\n\r\n```yaml\r\nplugins:\r\n    - encryptcontent:\r\n        encrypted_something:\r\n            mkdocs-encrypted-toc: [div, id]\r\n```\r\n\r\n2. Other example, with multiple targets. You are using a custom version of Material theme and\r\nwant to encrypt ToC content and Footer.\r\n\r\nMaterial generates 2 `\u003cnav\u003e` structures with the same template `toc.html`, so you need to use a `class`\r\ninstead of an id for this part.\r\nThe footer part, is generated by the `footer.html` template in a classic div so an `id` is sufficient\r\n\r\nAfter modification, your template looks like this :\r\n\r\ntoc.html:\r\n```jinja\r\n\u003cnav class=\"md-nav md-nav--secondary {% if page.encrypted %}mkdocs-encrypted-toc{% endif %}\" aria-label=\"{{ lang.t('toc.title') }}\"\u003e\r\n    \u003clabel class=\"md-nav__title\" for=\"__toc\"\u003e ... \u003c/label\u003e\r\n    \u003cul class=\"md-nav__list\" data-md-scrollfix\u003e ... \u003c/ul\u003e\r\n\u003c/nav\u003e\r\n```\r\nfooter.html:\r\n```jinja\r\n\u003cfooter class=\"md-footer\"\u003e\r\n    \u003cdiv class=\"md-footer-nav\" {% if page.encrypted %}id=\"mkdocs-encrypted-footer\"{% endif %}\u003e ... \u003c/div\u003e\r\n    \u003cdiv class=\"md-footer-meta md-typeset\" {% if page.encrypted %}id=\"mkdocs-encrypted-footer-meta\"{% endif %}\u003e\r\n\u003c/footer\u003e\r\n```\r\n\r\nYour configuration would look like this :\r\n```yaml\r\nplugins:\r\n    - encryptcontent:\r\n        encrypted_something:\r\n            mkdocs-encrypted-toc: [nav, class]\r\n            mkdocs-encrypted-footer: [div, id]\r\n            mkdocs-encrypted-footer-meta: [div, id]\r\n```\r\n\r\n3. If you are using unmodified mkdocs-material, then this example will encrypt menu, toc and footer\r\nBut you'd need the Navigation pruning feature to hide the title of encrypted pages from navigation (or see 2.).\r\n\r\n```yaml\r\nplugins:\r\n    - encryptcontent:\r\n        encrypted_something:\r\n            md-footer__inner: [nav, class]\r\n            md-nav: [nav, class]\r\n```\r\n\r\n### Inject decrypt-form.tpl to theme\r\n\r\nSome themes or plugins might interfere with the way this plugin encrypts the content of a page.\r\nIn this case this feature will find and encrypt a unique tag in the same way as `encrypted_something`\r\ndoes and additionally inject its `decrypt-form.tpl.html` in front of it.\r\n\r\n```yaml\r\nplugins:\r\n    - encryptcontent:\r\n        inject:\r\n            \u003cuniq name\u003e: [\u003chtml tag\u003e, \u003c'class' or 'id'\u003e]\r\n```\r\n\r\nThis is an example for mkdocs-material:\r\n```yaml\r\nplugins:\r\n  - blog\r\n  - encryptcontent:\r\n        encrypted_something:\r\n            md-footer__inner: [nav, class] #Footer\r\n            md-nav: [nav, class] #Menu and toc\r\n        inject:\r\n            md-content: [div, class]\r\n```\r\n\r\n\u003e This feature overrides the normal practice of replacing the rendered content of a page.\r\n\r\n### Mix encrypted and normal content\r\n\r\nIt is possible to only encrypt parts of the page and also to remove parts on successful decryption.\r\n\r\nFirst install PyMdown Extensions by entering `pip install --upgrade pymdown-extensions`,\r\nthen enable them in your `mkdocs.yml`:\r\n```yaml\r\nmarkdown_extensions:\r\n    - pymdownx.blocks.html\r\n```\r\n\r\nThis is an example of a mixed markdown page:\r\n\r\n```\r\ntitle: This page mixes encrypted and normal content\r\nlevel: secret\r\ninject_id: protected\r\ndelete_id: teaser\r\n\r\n/// html | div#teaser\r\n## Teaser\r\n\r\nYou won't believe which secrets this page will unveil.\r\nFind out more after you enter the correct password...\r\n///\r\n\r\n/// html | div#protected\r\n## Secret\r\n\r\nWell, the princess is another castle.\r\n///\r\n```\r\n\r\nThe markdown extension enables us to wrap a div tag around content by `/// html | div#some-id`.\r\nIt ends with `///`. The meta tag `inject_id` defines which div id we would like to encrypt\r\n(it also injects the decryption form here). And the div id found at `delete_id` will be deleted\r\non successful decryption.\r\n\r\n## Search encryption\r\n\r\n### Search index encryption\r\n\r\n\u003e **Default value is \"encrypted\"**\r\n\r\nRelated to [issue #13](https://github.com/CoinK0in/mkdocs-encryptcontent-plugin/issues/13)\r\n\r\n\u003e :warning: **The configuration mode \"clear\" of this functionality can cause DATA LEAK**\r\n\u003e\r\n\u003e The unencrypted content of each page is accessible through the search index.\r\n\u003e Not encrypting the search index means completely removing the protection provided by this plugin.\r\n\u003e You have been warned \r\n\r\nThis feature allows you to control the behavior of the encryption plugin with the search index. \r\nThree configuration modes are possible:\r\n\r\n * **clear** : Search index is not encrypted. Search is possible even on protected pages.\r\n * **dynamically** : Search index is encrypted on build. Search is possible once the pages have been decrypted.\r\n * **encrypted** : Search index of encrypted pages is removed on build. Search is not possible on encrypted pages.\r\n\r\nYou can set `search_index: '\u003cmode_name\u003e'` in your `mkdocs.yml` to change the search index encryption mode. Possible values are `clear`, `dynamically`, `encrypted`. The default mode is \"**encrypted**\".\r\n\r\n```yaml\r\nplugins:\r\n    - encryptcontent:\r\n        search_index: 'dynamically'\r\n```\r\n\r\nThis functionality modifies the search index created by the “search” plug-in.\r\nSome themes might override the default search plug-in provided by mkdocs, \r\nbut so far the structure of the `search/search_index.json` file is consistent.\r\n\r\n\u003e The modification of the search index is carried out last (if `encryptcontent` is also last in `plugins`).\r\n\u003e But always double-check the generated index after `mkdocs build` to see if your information is protected.\r\n\r\nWhen the configuration mode is set to \"**dynamically**\", the \r\n[javascripts contribution files](https://github.com/unverbuggt/mkdocs-encryptcontent-plugin/tree/master/encryptcontent/contrib/templates/search)\r\nare used to override the default search plugin files provided by MkDocs. \r\nThey include a process of decrypting and keeping the search index in a SessionStorage.\r\n\r\n### Search index encryption for mkdocs-material\r\n\r\n[Material for MkDocs](https://squidfunk.github.io/mkdocs-material/) uses a different search plugin that\r\ncannot \"easily\" be overridden like the default search plugin.\r\nHowever this Plugin will still remove encrypted pages (`encrypted`) or encrypt the search entries (`dynamically`)\r\nfor `mkdocs-material`.\r\n\r\nIn order to be able to decrypt the search index (`dynamically`) `mkdocs-material` needs to be customized (patched).\r\n\r\nPatches for different versions can be found [here](https://github.com/unverbuggt/mkdocs-encryptcontent-plugin/tree/version3/patches).\r\n\r\n#### Material 8.x\r\n\r\nYou'll need some [prerequisites](https://squidfunk.github.io/mkdocs-material/customization/#environment-setup)\r\nand also execute these commands:\r\n\r\n```bash\r\ngit clone https://github.com/squidfunk/mkdocs-material\r\ncd mkdocs-material\r\npip install mkdocs-minify-plugin\r\npip install mkdocs-redirects\r\nnpm install\r\n\r\n#copy material_search_worker.patch to mkdocs-material\r\npatch -p 0 \u003c material_search_worker8.patch\r\n\r\npip install --force-reinstall .\r\n#pip install --force-reinstall --no-deps . #faster if mkdocs-material was already installed\r\n```\r\n\r\n#### Material 9.x\r\n\r\nFollow the instructions for [Theme development](https://squidfunk.github.io/mkdocs-material/customization/#theme-development) carefully.\r\n\r\nApply the patch before [Building the theme](https://squidfunk.github.io/mkdocs-material/customization/#building-the-theme):\r\n\r\n```bash\r\npatch -p 0 \u003c material_browser_request9.patch # until Material 9.3\r\npatch -p 0 \u003c material_browser_request9_4p.patch # Material 9.4+\r\n```\r\n\r\n\r\n## Javascript extensions\r\n\r\n### Reload user-defined scripts\r\n\r\nRelated to [issue #14](https://github.com/unverbuggt/mkdocs-encryptcontent-plugin/issues/14)\r\n\r\nYou can set `reload_scripts:` in your `mkdocs.yml` with list of script sources\r\nor script ids, to reload and execute some js lib after decryption process.\r\n\r\n```yaml\r\nplugins:\r\n    - encryptcontent:\r\n        reload_scripts:\r\n            - 'js/example.js'\r\n            - '#autoexec'\r\n```\r\n\r\nIt is also possible to reload a script id like `\u003cscript id=\"autoexec\"\u003econsole.log('test');\u003c/script\u003e`\r\nthat was encrypted within the page\r\n(related to [issue #30](https://github.com/unverbuggt/mkdocs-encryptcontent-plugin/issues/30)).\r\n\r\n\r\n### HighlightJS support\r\n\r\n\u003e **Enable by default**\r\n\r\nIf HighlightJS module is detected in your theme to improve code color rendering, reload renderer after\r\ndecryption process.\r\nIf HighlightJS module is not correctly detected, you can force the detection by adding `hljs: True`\r\non the plugin configuration\r\nor set `hljs: False` to disable this feature.\r\n\r\nWhen enabled the following part of the template is added to force reloading decrypted content.\r\n\r\n```jinja\r\n{% if hljs %}\r\ndocument.getElementById(\"mkdocs-decrypted-content\").querySelectorAll('pre code').forEach((block) =\u003e {\r\n    hljs.highlightElement(block);\r\n});\r\n{% endif %}\r\n```\r\n\r\n\r\n### Arithmatex support\r\n\r\n\u003e **Enable by default**\r\n\r\nRelated to [issue #12](https://github.com/unverbuggt/mkdocs-encryptcontent-plugin/issues/12)\r\n\r\nIf Arithmatex markdown extension is detected in your markdown extensions to improve math equations rendering,\r\nreload renderer after decryption process.\r\nIf the Arithmatex markdown extension is not correctly detected, you can force the detection by adding\r\n`arithmatex: True` on the plugin configuration\r\nor set `arithmatex: False` to disable this feature.\r\n \r\nWhen enabled, the following part of the template is added to force math equations rendering on decrypted content.\r\n\r\n```jinja\r\n{% if arithmatex %}\r\nMathJax.typesetPromise()\r\n{% endif %}\r\n```\r\n\r\n\u003e **NOTE** It has been tested in Arithmatex `generic` mode only. \r\n\r\n\r\n### Mermaid.js support\r\n\r\n#### mkdocs-mermaid2-plugin\r\n\r\n\u003e **Enable by default**\r\n\r\nRelated to [issue #22](https://github.com/unverbuggt/mkdocs-encryptcontent-plugin/issues/22).\r\n\r\nIf mermaid2 plugin is detected in your configuration to generate graph from text, reload renderer after\r\ndecryption process.\r\nIf the Mermaid2 plugin is not correctly detected, you can force the detection by adding `mermaid2: True`\r\non the plugin configuration\r\nor set `mermaid2: False` to disable this feature.\r\n \r\nWhen enabled, the following part of the template is added to force graph rendering on decrypted content.\r\n\r\n```jinja\r\n{% if mermaid2 %}\r\nmermaid.contentLoaded();\r\n{% endif %}\r\n```\r\n\r\n\u003e **NOTE** it currently only works with mermaid version \u003c 10. Also encryptcontent needs to be injected,\r\n\u003e because the mermaid2 plugin otherwise won't detect the page content correctly.\r\n\r\nactivate the plugin like this:\r\n\r\n```yaml\r\nplugins:\r\n    - mermaid2:\r\n        version: 9.4.3\r\n\r\nmarkdown_extensions:\r\n    - pymdownx.blocks.html\r\n```\r\n\r\nExample usage:\r\n\r\n````\r\npassword: 1234\r\ninject_id: inject\r\n\r\n\r\n/// html | div#inject\r\n\r\n```mermaid\r\ngraph LR\r\n    hello --\u003e world\r\n    world --\u003e again\r\n    again --\u003e hello\r\n```\r\n\r\n///\r\n````\r\n\r\n#### mkdocs-material\r\n\r\n\u003e **Enable by default**\r\n\r\nAdd support for mermaid graphs by adding the `pymdownx.superfences` to `markdown_extensions` as \r\ndescribed [here]( https://squidfunk.github.io/mkdocs-material/reference/diagrams/).\r\n\r\nAfter successful decryption all subscriptions of the document are recalled to render the marmaid graph,\r\nsee [here](https://github.com/unverbuggt/mkdocs-encryptcontent-plugin/pull/81).\r\n\r\n```jinja\r\n{%- if material %}\r\ndocument$.next(document);\r\n{%- endif %}\r\n```\r\n\r\n\r\n### mkdocs-glightbox\r\n\r\nRelated to [issue #62](https://github.com/unverbuggt/mkdocs-encryptcontent-plugin/issues/62).\r\n\r\nThe plugin would add click events to all image of a page, but it can't do that if the page was encrypted.\r\nThat's why we need to add it to `reload_scripts` section to call it after successful decryption.\r\n\r\n```yaml\r\nplugins:\r\n  - glightbox:\r\n      zoomable: true\r\n      draggable: true\r\n      skip_classes:\r\n        - skip-lightbox\r\n  - encryptcontent:\r\n      reload_scripts:\r\n      - '#init-glightbox'\r\n```\r\n## Security\r\n\r\n### Crypto-js or crypto-es or webcrypto?\r\n\r\nBy default the plugin uses the crypto-js library for page decryption, but using\r\nthe browser's built-in webcrypto engine is also possible (set `webcrypto: true`).\r\n\r\nThe main advantage of webcrypto over crypto-js is that it is much faster, allowing higher\r\ncalculation difficulty for key derivation (`kdf_pow`). Also it may be easier to implement\r\nkey derivation functions other than PBKDF2 with webcrypto in the future.\r\n\r\nOn the other hand crypto-js is implemented in pure Javascript without any dependencies and well\r\ntested (but it probably won't receive any updates as development stalled in 2021, see [here](https://github.com/brix/crypto-js/#discontinued))\r\nand we know nothing about how good or bad webcrypto is implemented in different browsers.\r\n\r\nThere is a new variation of [crypto-js](https://github.com/brix/crypto-js), called [crypto-es](https://github.com/entronad/crypto-es).\r\nIt provides the same functions, but is implemented in modern javascript and can be activated by setting `esm: true`.  \r\nIf `webcrypto: true` and `esm: true` is set, then webcrypto will be loaded as a\r\njavascript module (speeding up material theme with instant loading feature).\r\n\r\n\u003e Crypto-js causes a bug when browsing through encrypted pages,\r\n\u003e if used in `mkdocs-material` together with the `navigation.instant` feature.\r\n\u003e It is advised to use `webcrypto: true` or crypto-es with `esm: true` in this case.\r\n\r\n#### Self-host Crypto-js or Crypto-es\r\n\r\nIf you enable `selfhost` then you'll choose to upload crypto-js to your web server rather than using cloudflare CDN.\r\nThe self-host location is \"SITE_URL/assets/javascripts/cryptojs/\".\r\n\r\nAdditionally if you set `selfhost_download` then the required files will be automatically downloaded if needed.\r\nThe files are checked for their MD5 hash and saved to `docs_dir` or `selfhost_dir` (relative to `mkdocs.yml`).\r\n\r\n```yaml\r\nplugins:\r\n    - encryptcontent:\r\n        selfhost: True\r\n        selfhost_download: False\r\n        selfhost_dir: 'theme_overrides'\r\n```\r\n\r\n#### KDF key generation caching\r\n\r\nEither way (webcrypto or crypto-js) the [KDF](https://en.wikipedia.org/wiki/Key_derivation_function)\r\nkey generation needs to be done for each credential.\r\nThis may take some additional time when building the site, especially when there are many different ones.\r\nThat's why these keys and salt are cached by default to a yaml file named \"encryptcontent.cache\".\r\n\r\n```yaml\r\nplugins:\r\n    - encryptcontent:\r\n        cache_file: 'encryptcontent.cache' # change file name if needed\r\n```\r\n\r\nCaching can be disabled by setting `cache_file: ''`.\r\n\r\n\r\n### File name obfuscation\r\n\r\nImagine your pages contain many images and you labeled them \"1.jpg\", \"2.jpg\" and so on for some reason.\r\nIf you'd like to encrypt one of these pages, an attacker could try guessing the image file names\r\nand would be able to download them despite not having the password to the page.\r\n\r\nThis feature should make it impossible or at least way harder for an external attacker to guess the file names.\r\nPlease also check and disable directory listing for that matter.\r\nKeep in mind that your hosting provider is still able to see all your images and files.\r\n\r\nTo counter file name guessing you could activate the feature like this:\r\n\r\n```yaml\r\nplugins:\r\n    - encryptcontent:\r\n        selfhost: true\r\n        selfhost_download: false\r\n        hash_filenames:\r\n          extensions:\r\n            - 'png'\r\n            - 'jpg'\r\n            - 'jpeg'\r\n            - 'svg'\r\n          except:\r\n            - 'lilien.svg'\r\n```\r\n\r\nAt `extensions` we define which file name extensions to obfuscate\r\n(extension is taken from the part after the last \".\",\r\nso the extension of \"image.jpg\" is \"jpg\" and of \"archive.tar.gz\" is \"gz\").\r\n\r\nYou can define multiple exceptions at the `except` list.\r\nThe file names that end with these strings will be skipped.\r\nYou should use this if some images are used by themes or other plugins.\r\nOtherwise, you'd need to change these file names to the obfuscated ones.\r\n\r\nThe file names are obfuscated in a way that the corresponding file is hashed with MD5\r\nand the hash is added to the file name\r\n(If the file content is not changed the file name remains the same), like this:\r\n\r\nsome_image_1_bb80db433751833b8f8b4ad23767c0fc.jpg\r\n(\"bb80db433751833b8f8b4ad23767c0fc\" being the MD5 hash of said image.)\r\n\r\n\u003e The file name obfuscation is currently applied to the whole site - not just the encrypted pages...\r\n\r\n### Signing of generated files\r\n\r\nAn attacker would most likely have a hard time brute forcing your encrypted content, given a good\r\npassword entropy. It would be much easier for him to fish for passwords by modifying the\r\ngenerated pages, if he is able to hack your web space.\r\n\r\nThis feature will sign all encrypted pages and used javascript files with Ed25519. It will also generate\r\nan example [canary script](https://en.wikipedia.org/wiki/Domestic_canary#Miner's_canary), which can be\r\ncustomized to alert if files were modified.\r\n\r\n\u003e **NOTE** If Mkdocs is running with `mkdocs serve`, then signature verification of encrypted pages\r\n\u003e will fail, because the files are modified by Mkdocs to enable live reload.\r\n\r\n```yaml\r\n      sign_files: 'signatures.json'\r\n      sign_key: 'encryptcontent.key' #optional\r\n      canary_template_path: '/path/to/canary.tpl.py' #optional\r\n```\r\n\r\nFirst an Ed25519 private key is generated at \"encryptcontent.key\" (besides `mkdocs.yml`), however you can supply an\r\nexisting private key as long as it's in PEM format.\r\n\r\nAfter generation the signatures are saved to \"signatures.json\" in `site_dir`, so this file also needs to be uploaded\r\nto the web space. The canary script will download this file and compare the URLs to its own list and then download\r\nall files and verify the signatures.\r\n\r\nAs long as the private key used for signing remains secret, the canary script will be able to determine\r\nif someone tampered with the files on the server. But you should run the canary script from another machine\r\nthat is not related to the server, otherwise the attacker could also modify the canary script and sign with his\r\nprivate key instead.\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funverbuggt%2Fmkdocs-encryptcontent-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funverbuggt%2Fmkdocs-encryptcontent-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funverbuggt%2Fmkdocs-encryptcontent-plugin/lists"}