@import url('https://fonts.googleapis.com/css2?family=Syne:wght@600;700;800&family=Figtree:ital,wght@0,400;0,500;0,600;1,400&family=JetBrains+Mono:wght@400;500&display=swap'); :root{ --bg:#111520;--sf:#181d2e;--sf2:#1e2436;--sf3:#252b40; --b:rgba(255,255,255,.07);--b2:rgba(255,255,255,.13); --cyan:#22d3ee;--cyan-bg:rgba(34,211,238,.08);--cyan-b:rgba(34,211,238,.25); --purple:#a78bfa;--purple-bg:rgba(167,139,250,.08);--purple-b:rgba(167,139,250,.25); --green:#34d399;--green-bg:rgba(52,211,153,.08);--green-b:rgba(52,211,153,.25); --amber:#fbbf24;--amber-bg:rgba(251,191,36,.08);--amber-b:rgba(251,191,36,.25); --red:#f87171;--red-bg:rgba(248,113,113,.08);--red-b:rgba(248,113,113,.25); --pink:#f472b6;--pink-bg:rgba(244,114,182,.08);--pink-b:rgba(244,114,182,.25); --orange:#fb923c;--orange-bg:rgba(251,146,60,.08);--orange-b:rgba(251,146,60,.25); --indigo:#818cf8;--indigo-bg:rgba(129,140,248,.08);--indigo-b:rgba(129,140,248,.25); --t1:#e2e8f0;--t2:#94a3b8;--t3:#64748b; --r:12px;--rs:8px; } *,*::before,*::after{box-sizing:border-box;margin:0;padding:0} html{scroll-behavior:smooth} body{font-family:'Figtree',sans-serif;background:var(--bg);color:var(--t1);line-height:1.65;min-height:100vh} h1,h2,h3,h4{font-family:'Syne',sans-serif;line-height:1.2} a{color:var(--cyan);text-decoration:none} a:hover{text-decoration:underline} code,pre,.mono{font-family:'JetBrains Mono',monospace} img{max-width:100%} /* NAV */ .site-nav{position:sticky;top:0;z-index:100;background:rgba(17,21,32,.9);backdrop-filter:blur(14px);border-bottom:1px solid var(--b);height:54px;display:flex;align-items:center;padding:0 1.5rem;gap:1.5rem} .nav-brand{font-family:'Syne',sans-serif;font-weight:800;font-size:.9rem;color:var(--cyan);letter-spacing:.06em;white-space:nowrap;flex-shrink:0} .nav-brand span{color:var(--t2);font-weight:600} .nav-links{display:flex;gap:1.25rem;list-style:none;overflow-x:auto;scrollbar-width:none;align-items:center} .nav-links::-webkit-scrollbar{display:none} .nav-links a{font-size:.775rem;font-weight:500;color:var(--t3);white-space:nowrap;letter-spacing:.03em;transition:color .15s;padding:.25rem 0} .nav-links a:hover,.nav-links a.active{color:var(--t1);text-decoration:none} .nav-links a.active{border-bottom:1.5px solid var(--cyan);color:var(--cyan)} /* WRAPPER */ .wrap{max-width:1180px;margin:0 auto;padding:3rem 1.5rem} .wrap-sm{max-width:820px;margin:0 auto;padding:3rem 1.5rem} /* HERO */ .hero{text-align:center;padding:4rem 0 2.5rem} .hero-eyebrow{font-size:.75rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--cyan);margin-bottom:1rem;display:block} .hero h1{font-size:clamp(2rem,5vw,3.25rem);font-weight:800;color:var(--t1);margin-bottom:1rem} .hero h1 .accent{color:var(--cyan)} .hero-sub{font-size:1.05rem;color:var(--t2);max-width:560px;margin:0 auto 1.75rem} /* BADGES */ .badges{display:flex;flex-wrap:wrap;gap:.4rem;justify-content:center} .badge{display:inline-flex;align-items:center;padding:.25rem .7rem;border-radius:100px;font-size:.72rem;font-weight:600;letter-spacing:.02em;border:1px solid} .bc{background:var(--cyan-bg);color:var(--cyan);border-color:var(--cyan-b)} .bp{background:var(--purple-bg);color:var(--purple);border-color:var(--purple-b)} .bg{background:var(--green-bg);color:var(--green);border-color:var(--green-b)} .ba{background:var(--amber-bg);color:var(--amber);border-color:var(--amber-b)} .br{background:var(--red-bg);color:var(--red);border-color:var(--red-b)} .bk{background:var(--pink-bg);color:var(--pink);border-color:var(--pink-b)} .bo{background:var(--orange-bg);color:var(--orange);border-color:var(--orange-b)} .bi{background:var(--indigo-bg);color:var(--indigo);border-color:var(--indigo-b)} /* CARD */ .card{background:var(--sf);border:1px solid var(--b);border-radius:var(--r);padding:1.5rem;margin-bottom:1.5rem} .card-sm{background:var(--sf2);border:1px solid var(--b);border-radius:var(--rs);padding:1rem} .card-sm+.card-sm{margin-top:.75rem} .card.ac{border-left:3px solid var(--cyan)} .card.ap{border-left:3px solid var(--purple)} .card.ag{border-left:3px solid var(--green)} .card.aa{border-left:3px solid var(--amber)} .card.ar{border-left:3px solid var(--red)} .card.ak{border-left:3px solid var(--pink)} .card.ao{border-left:3px solid var(--orange)} .card.ai{border-left:3px solid var(--indigo)} /* SECTION TITLE */ .st{font-size:1.35rem;font-weight:700;color:var(--t1);margin-bottom:1rem;display:flex;align-items:center;gap:.75rem} .st .dot{width:7px;height:7px;border-radius:50%;flex-shrink:0} .st2{font-size:1.1rem;font-weight:700;color:var(--t1);margin-bottom:.75rem} /* PARA */ p{color:var(--t2);font-size:.95rem} .lead{color:var(--t1);font-size:1rem} /* CODE BLOCK */ .cb{background:rgba(0,0,0,.4);border:1px solid var(--b2);border-radius:var(--rs);padding:1rem 1.25rem;font-family:'JetBrains Mono',monospace;font-size:.8rem;line-height:1.75;overflow-x:auto;color:var(--t2);white-space:pre} .cb .cm{color:var(--green)} .cb .kw{color:var(--cyan)} .cb .st{color:var(--amber)} .cb .num{color:var(--purple)} /* FEATURE ROW */ .feat{display:flex;align-items:flex-start;gap:.875rem;padding:.875rem 1rem;background:var(--sf2);border-radius:var(--rs);border:1px solid var(--b)} .feat+.feat{margin-top:.625rem} .feat-icon{width:34px;height:34px;border-radius:8px;display:flex;align-items:center;justify-content:center;flex-shrink:0;font-size:.85rem;font-weight:700} .feat-title{font-weight:600;color:var(--t1);font-size:.9rem;margin-bottom:.2rem} .feat-desc{font-size:.82rem;color:var(--t2)} /* WORKFLOW STEPS */ .steps{border-left:2px solid var(--b2);padding-left:1.25rem;display:flex;flex-direction:column;gap:1rem} .step{position:relative} .step::before{content:'';position:absolute;left:-1.45rem;top:.3rem;width:8px;height:8px;border-radius:50%;background:var(--cyan);border:2px solid var(--bg)} .step-n{font-size:.7rem;font-weight:700;letter-spacing:.08em;color:var(--cyan);text-transform:uppercase;margin-bottom:.2rem} .step-t{font-weight:600;color:var(--t1);font-size:.9rem;margin-bottom:.25rem} .step-d{font-size:.83rem;color:var(--t2)} /* BUTTONS */ .btn{display:inline-flex;align-items:center;gap:.4rem;padding:.6rem 1.2rem;border-radius:var(--rs);font-weight:600;font-size:.85rem;cursor:pointer;transition:all .15s;border:1px solid transparent;font-family:'Figtree',sans-serif;letter-spacing:.02em} .btn-p{background:var(--cyan);color:#0f1117;border-color:var(--cyan)} .btn-p:hover{filter:brightness(1.1);text-decoration:none;color:#0f1117} .btn-g{background:var(--sf2);color:var(--t1);border-color:var(--b2)} .btn-g:hover{background:var(--sf3);text-decoration:none;color:var(--t1)} .btn:disabled{opacity:.4;cursor:not-allowed} .btn-row{display:flex;flex-wrap:wrap;gap:.75rem} /* TOOL GRID */ .tool-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(290px,1fr));gap:1.25rem} .tc{background:var(--sf);border:1px solid var(--b);border-radius:var(--r);padding:1.4rem;display:flex;flex-direction:column;gap:.75rem;transition:border-color .2s,transform .2s;text-decoration:none} .tc:hover{border-color:var(--b2);transform:translateY(-2px);text-decoration:none} .tc-header{display:flex;align-items:center;gap:.625rem} .tc-dot{width:9px;height:9px;border-radius:50%;flex-shrink:0} .tc-name{font-family:'Syne',sans-serif;font-weight:700;font-size:1.05rem} .tc-desc{font-size:.84rem;color:var(--t2);flex:1} .tc-feats{list-style:none;font-size:.8rem;color:var(--t3);display:flex;flex-direction:column;gap:.3rem} .tc-feats li::before{content:'› ';color:var(--t3)} /* STATS */ .stats{display:grid;grid-template-columns:repeat(4,1fr);gap:1rem} .stat{background:var(--sf2);border-radius:var(--r);padding:1.25rem;text-align:center;border:1px solid var(--b)} .stat-n{font-family:'Syne',sans-serif;font-size:2rem;font-weight:800;color:var(--cyan);display:block} .stat-l{font-size:.78rem;color:var(--t3);margin-top:.2rem} /* TABS */ .tab-bar{display:flex;gap:.4rem;flex-wrap:wrap;margin-bottom:1.5rem} .tb{padding:.45rem 1rem;border-radius:var(--rs);font-size:.8rem;font-weight:600;cursor:pointer;border:1px solid var(--b);background:var(--sf2);color:var(--t2);font-family:'Figtree',sans-serif;transition:all .15s} .tb:hover{border-color:var(--b2);color:var(--t1)} .tb.on{background:var(--cyan);color:#0f1117;border-color:var(--cyan)} .tp{display:none} .tp.on{display:block;animation:fi .3s ease} /* UPLOAD */ .uzone{border:2px dashed var(--b2);border-radius:var(--r);padding:2.5rem 2rem;text-align:center;cursor:pointer;transition:all .2s;margin-bottom:.75rem} .uzone:hover,.uzone.drag{border-color:var(--cyan);background:var(--cyan-bg)} .uzone-icon{margin:0 auto .75rem;opacity:.4;display:block} /* STATUS */ .s-ok{background:var(--green-bg);border:1px solid var(--green-b);color:var(--green);border-radius:var(--rs);padding:.75rem 1rem;font-size:.875rem} .s-err{background:var(--red-bg);border:1px solid var(--red-b);color:var(--red);border-radius:var(--rs);padding:.75rem 1rem;font-size:.875rem} .s-inf{background:var(--cyan-bg);border:1px solid var(--cyan-b);color:var(--cyan);border-radius:var(--rs);padding:.75rem 1rem;font-size:.875rem} /* PROBE CHIP */ .probe{font-family:'JetBrains Mono',monospace;font-size:.68rem;background:var(--sf3);border:1px solid var(--b);display:inline-block;padding:.18rem .5rem;border-radius:5px;margin:.15rem;color:var(--t2)} /* PGP */ .pgp-block{background:rgba(0,0,0,.45);border:1px solid var(--green-b);border-radius:var(--rs);padding:1.5rem;font-family:'JetBrains Mono',monospace;font-size:.72rem;color:var(--green);overflow-x:auto;white-space:pre;line-height:1.5} .cmd{background:rgba(0,0,0,.35);border:1px solid var(--b2);border-radius:var(--rs);padding:.75rem 1rem;font-family:'JetBrains Mono',monospace;font-size:.82rem;color:var(--t2);margin:.4rem 0;overflow-x:auto;white-space:pre} /* CRYPTO */ .addr-row{display:flex;align-items:center;gap:.75rem;background:var(--sf3);border:1px solid var(--b2);border-radius:var(--rs);padding:.75rem 1rem;margin:.5rem 0} .addr-text{font-family:'JetBrains Mono',monospace;font-size:.78rem;color:var(--t1);flex:1;word-break:break-all} /* TABLE */ .dt{width:100%;border-collapse:collapse;font-size:.875rem} .dt th{background:var(--sf2);padding:.7rem 1rem;text-align:left;color:var(--t2);font-weight:600;font-size:.78rem;letter-spacing:.05em;text-transform:uppercase;border-bottom:1px solid var(--b2)} .dt td{padding:.7rem 1rem;border-bottom:1px solid var(--b);color:var(--t1)} .dt tr:hover td{background:var(--sf2)} /* FORM */ label{font-size:.875rem;font-weight:500;color:var(--t2);display:block;margin-bottom:.4rem} input[type=text],input[type=email],textarea,select,.inp{background:var(--sf2);border:1px solid var(--b2);border-radius:var(--rs);color:var(--t1);padding:.6rem .875rem;font-family:'Figtree',sans-serif;font-size:.875rem;width:100%;transition:border-color .15s} input[type=text]:focus,textarea:focus,select:focus{outline:none;border-color:var(--cyan)} .file-info{background:var(--sf2);border:1px solid var(--b);border-radius:var(--rs);padding:.875rem;margin:.5rem 0;font-size:.85rem} .prog-bar{width:100%;height:5px;background:var(--sf3);border-radius:3px;overflow:hidden;margin:.4rem 0} .prog-fill{height:100%;background:var(--cyan);transition:width .3s} /* GRID HELPERS */ .g2{display:grid;grid-template-columns:1fr 1fr;gap:1.5rem} .g3{display:grid;grid-template-columns:repeat(3,1fr);gap:1.25rem} .gc3{display:grid;grid-template-columns:2fr 1fr;gap:1.5rem} /* DIVIDER */ hr{border:none;border-top:1px solid var(--b);margin:2rem 0} .spacer{height:1.5rem} /* FOOTER */ .site-footer{border-top:1px solid var(--b);padding:3rem 2rem;margin-top:4rem;text-align:center} .footer-btns{display:flex;flex-wrap:wrap;gap:.625rem;justify-content:center;margin-bottom:2rem} .footer-nav{display:flex;gap:1.5rem;justify-content:center;flex-wrap:wrap;margin-bottom:1rem;list-style:none} .footer-nav a{font-size:.78rem;color:var(--t3)} .footer-nav a:hover{color:var(--t2);text-decoration:none} .footer-copy{font-size:.78rem;color:var(--t3)} /* JS POPUP */ .js-pop{position:fixed;inset:0;background:rgba(17,21,32,.97);display:flex;align-items:center;justify-content:center;z-index:9999;padding:1.5rem} .js-pop-box{background:var(--sf);border:1px solid var(--b2);border-radius:var(--r);padding:2rem;max-width:480px;width:100%;text-align:center} .js-pop h2{font-size:1.4rem;color:var(--red);margin-bottom:.75rem} .js-pop p{font-size:.9rem;color:var(--t2);margin-bottom:1.25rem} .js-enabled .js-pop{display:none} /* QUICK NAV */ .qnav{position:sticky;top:54px;z-index:90;background:rgba(17,21,32,.85);backdrop-filter:blur(10px);border-bottom:1px solid var(--b);padding:.6rem 1.5rem} .qnav-inner{max-width:1180px;margin:0 auto;display:flex;flex-wrap:wrap;gap:.4rem;align-items:center} .qn{padding:.35rem .875rem;background:var(--sf2);border:1px solid var(--b);border-radius:var(--rs);font-size:.775rem;font-weight:500;color:var(--t2);cursor:pointer;transition:all .15s;white-space:nowrap} .qn:hover{border-color:var(--b2);color:var(--t1)} .qn.on{background:var(--cyan-bg);border-color:var(--cyan-b);color:var(--cyan)} /* RESPONSIVE */ @media(max-width:768px){ .g2,.g3,.gc3,.stats,.stats-grid{grid-template-columns:1fr} .site-nav{padding:0 1rem;gap:1rem} .wrap,.wrap-sm{padding:2rem 1rem} .hero{padding:2.5rem 0 1.5rem} } @keyframes fi{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
Hashcat Rule Minimizer

minimizer

Eliminate functionally redundant Hashcat rules using signature-based deduplication. SQLite-backed storage, parallel workers, multibyte mode, and a built-in 33-word probe set — no wordlist required.

Pure Python CPU-only · No GPU Signature-based dedup SQLite storage Preserves file order Parallel workers Multibyte / Unicode
What does it do?

Two rules are functionally equivalent if they produce identical output on every possible input word. This tool checks a carefully chosen probe set (33 words) covering short/long words, mixed-case, digits, specials, and repeated chars — plus an optional 11-word multibyte set for non-ASCII wordlists.

Rules producing the same transformed strings for all probes are indistinguishable in a real attack. The rule appearing earlier in the file is kept and the later one is discarded, preserving the original frequency/priority ranking. Signature storage uses a temporary SQLite database so the signature map never occupies Python heap memory regardless of ruleset size.

Example: rule c (capitalize) and chain l c on already-lowercase inputs produce identical output → same signature → only the first occurrence survives.
Key Features
Built-in 33-word probe set
Covers short (len 2–4), typical bases (7–9), long (10+), mixed-case, digits, specials, repeated chars, and leet-substitution targets. Works out of the box.
Signature-based dedup via SQLite
Computes output tuple per rule, stores signatures in a temp SQLite DB — no heap pressure regardless of ruleset size. Deleted automatically on completion.
🌐
Multibyte / Unicode mode
--multibyte: process words as UTF-8 bytes and activate 11 additional non-ASCII probes (Polish, German, French, Russian, CJK).
Parallel workers
--workers N distributes signature computation across CPU cores. --workers 0 auto-detects core count. Deduplication always runs on the main process.
Progress & statistics
Two tqdm progress bars (computing + deduplicating) plus counters: rules loaded, kept, removed, and % reduction.
🔍
Debug & rule trace
--debug logs every keep/drop decision. --debug-rule "RULE" traces a single rule against all probes and exits — no input file needed.
Built-in Probe Set (33 words + 11 multibyte)

These words are always used — no wordlist needed. They exercise every important Hashcat rule category. Use --multibyte to additionally activate 11 non-ASCII words.

Category 1 — ASCII (33 words, always active):

ababcabcd passroottestadminlogin letmeinwelcomepasswordsunshine footballbaseballprincessdragon12 qwertyuiopiloveyou12monkey12345superman123mustang2024 PasswordAdminUserMySecretHelloWorld pass123admin2024test1234user9999 p@ssw0rds3cur1tyaaaabbbb masterleeteliteaccess

Category 2 — Multibyte UTF-8 (11 words, active with --multibyte):

hasłożółwźródło straßemünchenübermensch cafénaïve пароль密码パスワード

Use --list-probes (or --list-probes --multibyte) to see the full list with byte counts and UTF-8 encodings.

Installation & Usage
# Clone the repository git clone https://github.com/A113L/minimizer.git cd minimizer # Install optional dependency pip install tqdm # Basic minimization (built-in probe set only) python minimizer.py my_rules.rule -o minimized.rule # Use parallel workers (0 = auto-detect CPU count) python minimizer.py my_rules.rule -o minimized.rule --workers 8 # Add your own probe words python minimizer.py my_rules.rule --extra-probes password admin 123456 # Sample extra probes from a wordlist python minimizer.py my_rules.rule --probe-file rockyou.txt --probe-words 100 # Enable UTF-8/multibyte mode (non-ASCII wordlists) python minimizer.py my_rules.rule -o minimized.rule --multibyte # Trace a single rule against the probe set (no input file needed) python minimizer.py --debug-rule "l r \$1" # Combine all sources python minimizer.py rules.txt \ --extra-probes "letmein" "welcome" \ --probe-file /usr/share/wordlists/fasttrack.txt \ --probe-words 50 \ -o final.rule
How the Signature is Computed
Step 1
Probe set assembly
Built-in 33 words + --extra-probes + sampled words from --probe-file (deduplicated). With --multibyte, 11 additional UTF-8 words are added.
Step 2
Rule application
A pure-Python interpreter applies every rule atom (all GPU-compatible Hashcat opcodes) to each probe word. Unsupported opcodes are grouped together as a single equivalence class — the first such rule in the file is kept.
Step 3
Signature tuple
For each rule, collect transformed outputs for all probes into a tuple: ("Abc", "Def", ...). In multibyte mode, invalid UTF-8 byte sequences are wrapped in an InvalidUTF8Bytes object rather than silently decoded.
Step 4
SQLite deduplication
Signatures are stored in a temporary SQLite database via INSERT OR IGNORE. The rule appearing first in the file wins. The temp DB is deleted unconditionally on completion (including on error or Ctrl+C).
Get the Source

Minimizer is open source and hosted on GitHub. MIT licensed.

View minimizer on GitHub