chore(i18n): finish translating code comments and scripts to English
CI / Format and clippy (push) Successful in 1m13s
CI / Dependency audit (push) Successful in 13s
CI / Tests (Linux) (push) Successful in 1m35s
Release / Create release (push) Successful in 7s
CI / Check desktop app (Linux) (push) Successful in 3m19s
Release / CLI (linux-aarch64) (push) Successful in 1m3s
Release / CLI (linux-x86_64) (push) Successful in 1m28s
Release / Desktop app (linux-aarch64) (push) Successful in 7m16s
Release / Desktop app (linux-x86_64) (push) Successful in 10m17s
Release / Desktop app (windows) (push) Successful in 4m54s
CI / Format and clippy (push) Successful in 1m13s
CI / Dependency audit (push) Successful in 13s
CI / Tests (Linux) (push) Successful in 1m35s
Release / Create release (push) Successful in 7s
CI / Check desktop app (Linux) (push) Successful in 3m19s
Release / CLI (linux-aarch64) (push) Successful in 1m3s
Release / CLI (linux-x86_64) (push) Successful in 1m28s
Release / Desktop app (linux-aarch64) (push) Successful in 7m16s
Release / Desktop app (linux-x86_64) (push) Successful in 10m17s
Release / Desktop app (windows) (push) Successful in 4m54s
Completes the English-only standardization for code, comments, scripts and CI templates (UI/CLI-facing strings stay bilingual pt-BR/en, untouched). Covers the remaining crates/, apps/gui/ui/ and apps/gui/src-tauri/ comments, .gitea/ workflow and template comments, .githooks/ hooks, and the scripts/ source comments for the files already renamed in a prior commit (check.sh, generate-logo.py, install-hooks.sh). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VAyr8d7HuAdUGB6aA5xmDD
This commit is contained in:
1 parent
bf059fd0bc
commit
55e19a8e5b
59 files changed
+935
-879
No files matched your search
@@ -1,14 +1,14 @@
|
||||
//! Regras de mutação sobre uma palavra do dicionário (estilo hashcat `-r`,
|
||||
//! bem mais simples) e força bruta por máscara (estilo hashcat `-a 3`).
|
||||
//! Wordlist mutation rules (lightweight hashcat `-r` style) and mask brute-force
|
||||
//! generator (hashcat `-a 3` style).
|
||||
//!
|
||||
//! Because each WPA-PSK candidate requires 4096 rounds of PBKDF2-HMAC-SHA1,
|
||||
//! mutation rules focus on high-yield patterns (capitalization, common numeric
|
||||
//! suffixes, single-character leetspeak) to keep the multiplier bounded.
|
||||
//!
|
||||
//!
|
||||
//! Em quebra de hash normal, regras são "de graça" — um hash SHA256 custa
|
||||
//! nanossegundos. Aqui não: cada candidato é um PBKDF2-HMAC-SHA1 de 4096
|
||||
//! iterações, então cada variante multiplica o tempo de verdade. As regras
|
||||
//! abaixo cobrem os padrões mais comuns (maiúscula inicial, sufixo numérico,
|
||||
//! leet simples) sem explodir pra centenas de variantes por palavra.
|
||||
|
||||
/// Quantas variantes [`expand`] gera por palavra base (pra calcular o
|
||||
/// multiplicador de tempo antes de rodar).
|
||||
/// Upper bound on variants produced by [`expand`] per base word.
|
||||
///
|
||||
pub const VARIANTS_PER_WORD: usize = 1 + 1 + 1 + SUFFIXES.len() + LEET_PAIRS.len();
|
||||
|
||||
const SUFFIXES: &[&str] = &[
|
||||
@@ -16,12 +16,12 @@ const SUFFIXES: &[&str] = &[
|
||||
"@", "#",
|
||||
];
|
||||
|
||||
/// (char original, substituto) — leet simples, uma troca por vez, não
|
||||
/// combinada, senão a combinatória explode rápido demais.
|
||||
/// `(source_char, leet_replacement)` single-substitution pairs.
|
||||
///
|
||||
const LEET_PAIRS: &[(char, char)] = &[('a', '@'), ('e', '3'), ('i', '1'), ('o', '0'), ('s', '$')];
|
||||
|
||||
/// Gera as variantes de `word` (incluindo a palavra original) que respeitam
|
||||
/// o comprimento válido de WPA (8–63), sem duplicatas.
|
||||
/// Generates deduplicated WPA-valid (8–63 char) mutations of `word` (including `word` itself).
|
||||
///
|
||||
pub fn expand(word: &str) -> Vec<String> {
|
||||
let mut out = Vec::with_capacity(VARIANTS_PER_WORD);
|
||||
let mut push = |s: String| {
|
||||
@@ -52,9 +52,9 @@ pub fn expand(word: &str) -> Vec<String> {
|
||||
out
|
||||
}
|
||||
|
||||
/// Classe de caractere de um token `?x` de máscara (sintaxe hashcat: `?d`
|
||||
/// dígito, `?l` minúscula, `?u` maiúscula, `?s` símbolo comum, `?a` os
|
||||
/// quatro juntos). `??` escapa um `?` literal.
|
||||
/// Character class for a mask token (`?d` digits, `?l` lowercase, `?u` uppercase,
|
||||
/// `?s` symbols, `?a` all printable ASCII, `??` literal `?`).
|
||||
///
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum CharClass {
|
||||
Digit,
|
||||
@@ -83,17 +83,17 @@ impl CharClass {
|
||||
}
|
||||
}
|
||||
|
||||
/// Máscara compilada: uma lista de alfabetos, um por posição. Gera
|
||||
/// candidatos por índice (contagem em base mista) sem materializar a lista
|
||||
/// inteira — essencial, já que `?d?d?d?d?d?d?d?d` sozinho são 100 milhões.
|
||||
/// Compiled brute-force mask (one alphabet per character position), supporting
|
||||
/// O(1) mixed-radix candidate generation by index.
|
||||
///
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Mask {
|
||||
alphabets: Vec<Vec<char>>,
|
||||
}
|
||||
|
||||
impl Mask {
|
||||
/// Compila uma máscara tipo `wifi?d?d?d?d` (literal "wifi" + 4 dígitos).
|
||||
/// `??` é um `?` literal; `?` seguido de letra desconhecida é erro.
|
||||
/// Compiles a hashcat-style mask pattern such as `"wifi?d?d?d?d"`.
|
||||
/// `??` escapes a literal `?`; unknown `?x` tokens return an error.
|
||||
pub fn parse(pattern: &str) -> Result<Self, String> {
|
||||
let mut alphabets = Vec::new();
|
||||
let mut chars = pattern.chars().peekable();
|
||||
@@ -123,8 +123,8 @@ impl Mask {
|
||||
Ok(Self { alphabets })
|
||||
}
|
||||
|
||||
/// Total de candidatos. `None` se não couber num `u64` (máscara longa
|
||||
/// demais pra ser levada a sério de qualquer forma).
|
||||
/// Total keyspace size, or `None` if it overflows `u64`.
|
||||
///
|
||||
pub fn total(&self) -> Option<u64> {
|
||||
self.alphabets
|
||||
.iter()
|
||||
@@ -139,9 +139,9 @@ impl Mask {
|
||||
self.alphabets.is_empty()
|
||||
}
|
||||
|
||||
/// Candidato de índice `index` (contagem em base mista, como um
|
||||
/// odômetro: a última posição gira mais rápido). `None` se `index` >=
|
||||
/// `total()`.
|
||||
/// Materializes the candidate at `index` (mixed-radix odometer order), or
|
||||
/// `None` if `index >= total()`.
|
||||
///
|
||||
pub fn candidate(&self, mut index: u64) -> Option<String> {
|
||||
let total = self.total()?;
|
||||
if index >= total {
|
||||
@@ -165,8 +165,8 @@ mod tests {
|
||||
#[test]
|
||||
fn expand_respects_min_length() {
|
||||
let variants = expand("senha");
|
||||
// "senha" tem 5 chars; sozinha não é candidata WPA válida (precisa
|
||||
// de 8+), mas com sufixo (ex.: "senha123", 8) sim.
|
||||
// `"senha"` is 5 chars (too short for WPA alone), but `"senha123"` (8 chars) is kept.
|
||||
//
|
||||
assert!(!variants.iter().any(|v| v == "senha"));
|
||||
assert!(variants.contains(&"senha123".to_string()));
|
||||
}
|
||||
@@ -183,7 +183,7 @@ mod tests {
|
||||
assert!(variants.contains(&"Abacaxi1".to_string()));
|
||||
assert!(variants.contains(&"ABACAXI1".to_string()));
|
||||
assert!(variants.contains(&"abacaxi1123".to_string()));
|
||||
// leet troca TODAS as ocorrências de 'a': as três em "abacaxi1".
|
||||
// Leetspeak substitution replaces all occurrences of `'a'` in `"abacaxi1"`.
|
||||
assert!(variants.contains(&"@b@c@xi1".to_string()));
|
||||
}
|
||||
|
||||
@@ -208,8 +208,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn mask_literal_question_mark_and_unknown_class() {
|
||||
// "??" vira um '?' literal; os dois primeiros chars são consumidos
|
||||
// juntos, então "???d" é: '?' literal + "?d" (classe dígito).
|
||||
// `"??"` escapes a literal `'?'`, so `"???d"` parses as literal `'?'` + `?d`.
|
||||
//
|
||||
assert_eq!(
|
||||
Mask::parse("???d").unwrap().candidate(0).as_deref(),
|
||||
Some("?0")
|
||||
|
||||
Reference in new issue
Block a user