font-obfuscator-kit
v0.1.0
Published
Build mapped webfonts and obfuscate text for DOM font obfuscation.
Downloads
89
Readme
font-obfuscator-kit
font-obfuscator-kit is a small npm package for:
- Building a mapped
woff2font (PUA codepoints -> real glyphs). - Obfuscating text so DOM text nodes become unreadable in Elements.
Install
npm install ./font-obfuscatorPrerequisites
The build-font command depends on Python fonttools:
python3 -m pip install fonttools brotli zopfli1) Prepare charset file
Create charset.txt with the characters you want to obfuscate.
Example (letters + numbers + common code symbols):
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.$(){}[]<>+-*/%!=&|^~?:;,'"`\#@Note: if you also want to obfuscate spaces, append one trailing space at the end of this line.
2) Build mapped font
npx font-obf build-font \
--src-font ~/Downloads/HackNerdFont-Regular.ttf \
--charset-file ./charset.txt \
--out-font ./dist/code-obf.woff2 \
--out-map ./dist/code-obf-map.json3) Obfuscate text
npx font-obf obfuscate \
--charset-file ./charset.txt \
--text "Closure and counterA"Or obfuscate a full file:
npx font-obf obfuscate \
--charset-file ./charset.txt \
--in-file ./input.txt \
--out-file ./dist/input.obf.txtBrowser usage pattern
<style>
@font-face {
font-family: "CodeObf";
src: url("./code-obf.woff2") format("woff2");
font-display: swap;
}
.obf-scope { font-family: "CodeObf", sans-serif; }
</style>Then replace letters in text nodes with obfuscated characters (using the same mapping rule / map file) after page load.
API
const {
createCharMapFromCharset,
obfuscateText,
deobfuscateText,
obfuscateDomTextNodes
} = require("font-obfuscator-kit");TypeScript: built-in .d.ts is included.
For browser-side usage (VuePress / client runtime), import from:
import { createCharMapFromCharset, obfuscateDomTextNodes } from "font-obfuscator-kit/browser";VuePress integration
If you want:
- Markdown source stays normal text
- Final page looks normal
- DevTools Elements text nodes show obfuscated chars
Use runtime obfuscation in client.
VuePress v2 (.vuepress/client.ts)
import { defineClientConfig } from "vuepress/client";
import { createCharMapFromCharset, obfuscateDomTextNodes } from "font-obfuscator-kit/browser";
const CHARSET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.$(){}[]<>+-*/%!=&|^~?:;,'\"`\\#@";
const charMap = createCharMapFromCharset(CHARSET, { baseCodepoint: "0xE100" });
function runObfuscation() {
const root = document.querySelector(".theme-default-content") || document.body;
obfuscateDomTextNodes(root, charMap, {
excludeTags: ["SCRIPT", "STYLE", "NOSCRIPT", "TEXTAREA", "INPUT", "CODE", "PRE"]
});
}
export default defineClientConfig({
enhance({ router }) {
if (typeof window === "undefined") return;
window.addEventListener("DOMContentLoaded", runObfuscation, { once: true });
router.afterEach(() => {
window.requestAnimationFrame(runObfuscation);
});
}
});Full runnable sample:
examples/vuepress-v2-ts
Then in .vuepress/styles/index.scss:
@font-face {
font-family: "CodeObf";
src: url("/assets/code-obf.woff2") format("woff2");
font-display: swap;
}
.theme-default-content {
font-family: "CodeObf", var(--vp-font-family-base);
}VuePress v1 (.vuepress/enhanceApp.js)
import { createCharMapFromCharset, obfuscateDomTextNodes } from "font-obfuscator-kit/browser";
const CHARSET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.$(){}[]<>+-*/%!=&|^~?:;,'\"`\\#@";
const charMap = createCharMapFromCharset(CHARSET, { baseCodepoint: "0xE100" });
function runObfuscation() {
const root = document.querySelector(".theme-default-content") || document.body;
obfuscateDomTextNodes(root, charMap);
}
export default ({ router }) => {
if (typeof window === "undefined") return;
window.addEventListener("load", runObfuscation);
router.afterEach(() => setTimeout(runObfuscation, 0));
};Limitations
- This is obfuscation, not strong encryption.
- If attacker gets both font and mapping rule, text can be recovered.
