Následující perl
skript používá buď Digest::MD5
nebo Digest::SHA
modul pro transformaci MAC adresy na hash pomocí tajné soli. Viz manuálové stránky modulů pro více podrobností o nich. Stojí za zmínku, že Digest::SHA má na výběr několik dalších algoritmů.
Kód je napsán tak, aby usnadnil výběr jiného hashovacího algoritmu – jeden odkomentujte a ostatní okomentujte, abyste si vybrali ten, který vám nejlépe vyhovuje. BTW, výstup z _base64
verze funkcí je o něco kratší než _hex
funkce, ale vypadají spíše jako šum linky.
Zjednodušil jsem váš zadaný regulární výraz (neviděl jsem, že by bylo třeba hledat pozadí). Možná to budete muset trochu vyladit, abyste pracovali se svými vstupními daty...neposkytli jste žádný vzorek, takže jsem to jen hádal.
#!/usr/bin/perl
# choose one of the following digest modules:
use Digest::MD5 qw(md5_hex md5_base64);
#use Digest::SHA qw(sha256_hex sha256_base64);
use strict;
my $salt='secret salt phrase';
# store seen MAC addresses in a hash so we only have to calculate the digest
# for them once. This speed optimisation is only useful if the input file
# is large AND any given MAC address may be seen many times.
my %macs=();
while(<>) {
if (m/clientMac:\s*([A-Z0-9]{12})/i) {
my $mac = $1;
if (!defined($macs{$mac})) {
# choose one of the following digest conversions:
#my $uuid = sha256_hex($mac . $salt);
#my $uuid = sha256_base64($mac . $salt);
my $uuid = md5_hex($mac . $salt);
#my $uuid = md5_base64($mac . $salt);
$macs{$mac} = $uuid;
};
s/(clientMac:\s*)$mac/$1$macs{$mac}/gio;
};
print;
};
Jak je požadováno v komentáři, zde je příklad, jak provést takovou substituci pomocí sed
. Použili jste značku /linux, takže by mělo být bezpečné používat GNU sed
s jeho e
příznak pro s
příkaz:
sed -E 'h;s/.*clientMac":\s"([A-Z0-9]{12}).*/echo secretKey\1|md5sum/e;T
G;s/(.*)\s*-\n(.*clientMac":\s")[A-Z0-9]{12}(.*)/\2\1\3/' logfile
Vysvětlení:
h
příkaz uloží řádek do prostoru hold, takže jej můžeme obnovit po zpackání řádku (-;s/.*clientMac":\s"([A-Z0-9]{12}).*/echo secretKey\1|md5sum/e
odpovídá celému řádku a skutečnou MAC vloží do()
k opětovnému použití při výměně. Nahrazení tvoří příkaz, který se má provést:echo
ing MCA spolu se "solí" a potrubím domd5sum
.e
příznak dělásed
spusťte to v shellu a výsledek vložte znovu do vyrovnávací pamětiT
větví na konec skriptu, pokud nebyla provedena žádná náhrada. Toto je tisk řádků bez neupravené MAC. Následující řádky se provedou pouze v případě, že byla provedena výměnaG
připojí původní řádek z vyrovnávací paměti, takže nyní mámemd5sum
výstup, nový řádek a původní řádek ve vyrovnávací pamětis/(.*)\s*-\n(.*clientMac":\s")[A-Z0-9]{12}(.*)/\2\1\3/
zachytí MD5 v prvním páru()
, řádek před MAC ve druhém a zbytek řádku za MAC ve třetím, tedy\2\1\3
nahradí MAC za MD5
Jako alternativní přístup jsem někdy používal jednoduchá čísla řádků jako hodnotu zmatku. Díky tomu je výstup kompaktnější a čitelnější.
Také awk
je dobrý nástroj, když potřebujete provádět "chytré" operace s textovým souborem, který má čitelnější jazyk než sed
. "Chytrá" operace, kterou je v tomto případě třeba provést, je vyhnout se opětovnému spuštění algoritmu zmatku, když je jakákoli MAC adresa nalezena více než jednou. To může značně urychlit operace, pokud máte tisíce řádků odkazujících na malý počet MAC adres.
V praxi zvažte následující skript, který také zpracovává možné více MAC adres vyskytujících se na libovolném řádku, identifikuje a nahrazuje každý výskyt a na konci pak vytiskne mapovací tabulku:
awk -v pat='clientMac"\\s*"[[:xdigit:]]{12}' -v table='sort -k 1,1n | column -t' -- '
$0 ~ pat {
for (i=1; i <= NF; i++)
if (match($i, pat)) {
if (!($i in cache))
cache[$i]=NR "." i
$i = "MAC:" cache[$i]
}
}
1
END {
print "---Table: "FILENAME"\nnum MAC" | table
for (mac in cache)
print cache[mac], mac | table
}
' file.log
Tabulku na konci lze snadno oddělit od hlavního výstupu dodatečným editačním krokem nebo pouhým vytvořením příkazového řetězce v -v table=
argument přesměruje svůj výstup do souboru, jako v -v table='sort -k 1,1n | column -t > table'
. Lze jej také zcela odstranit pouhým odstraněním celého END{ … }
blokovat.
Jako varianta použití skutečného šifrovacího stroje k výpočtu hodnot zmatku, a tedy bez mapovací tabulky na konci:
awk -v pat='clientMac"\\s*"[[:xdigit:]]{12}' -v crypter='openssl enc -aes-256-cbc -a -pass file:mypassfile' -- '
$0 ~ pat {
for (i=1; i <= NF; i++)
if (match($i, pat)) {
addr = cache[$i]
if (addr == "") {
"echo '\''" $i "'\'' | " crypter | getline addr
cache[$i] = addr
}
$i = "MAC:" addr
}
}
1
' file.log
Zde jsem použil openssl
jako šifrovací stroj vybere svůj aes-256-cbc
šifra (také s výstupem zakódovaným v base64, aby byl textově přívětivý) a přečtení šifrovacího tajemství ze souboru s názvem mypassfile
.
Řetězce zašifrované symetrickou šifrou (jako aes-256-cbc
) lze dešifrovat pomocí znalosti použitého tajemství (obsah mypassfile
, které si chcete nechat pro sebe), proto je lze obrátit. Také od openssl
standardně používá náhodnou sůl, každý běh produkuje různé hodnoty pro stejný vstup. Nepoužívá se sůl (volba -nosalt
) by bylo openssl
produkují stejnou hodnotu pro každý běh, takže jsou méně bezpečné, ale na druhou stranu by produkovaly kratší texty a přitom byly stále zašifrovány.
Totéž awk
skript by fungoval pro jiné externí příkazy místo openssl
pouhým nahrazením příkazu v -v crypter=
argument na awk
, pokud externí příkaz, který zvolíte, může přijímat vstup ze stdin a tisknout výstup na stdout.
Řetězce hašované pomocí algoritmů jako MD5 nebo SHA jsou místo toho pouze jednosměrné (tj. nelze je obrátit) a vždy produkují stejnou hodnotu pro stejný vstup, proto byste je chtěli „osolit“, aby vypočítané hodnoty produkované ve výstupu nelze pouze prohledávat přes všechny možné MAC adresy. Můžete přidat náhodnou "sůl" jako v následujícím mírně upraveném skriptu:
awk -v pat='clientMac"\\s*"[[:xdigit:]]{12}' -v crypter='sha256sum' -- '
$0 ~ pat {
for (i=1; i <= NF; i++)
if (match($i, pat)) {
addr = cache[$i]
if (addr == "") {
"(dd if=/dev/random bs=16 count=1 2>/dev/null; echo '\''" $i "'\'') | " crypter | getline addr
cache[$i] = addr
}
$i = "MAC:" addr
}
}
1
' file.log
Tento druhý skript používá 16-bajtovou (pseudo-)náhodnou hodnotu jako „sůl“, takže při každém spuštění se stejnými daty vytváří jinou hash hodnotu.