Risposte:
Le altre risposte mascherano una quantità fissa di caratteri dall'inizio, con il suffisso in chiaro che varia in lunghezza. Un'alternativa sarebbe quella di lasciare un numero fisso di caratteri in testo normale e di variare la lunghezza della parte mascherata. Non so quale sia più utile, ma ecco l'altra scelta:
#!/bin/bash
mask() {
local n=3 # number of chars to leave
local a="${1:0:${#1}-n}" # take all but the last n chars
local b="${1:${#1}-n}" # take the final n chars
printf "%s%s\n" "${a//?/*}" "$b" # substitute a with asterisks
}
mask abcde
mask abcdefghijkl
Questo stampa **cde
e *********jkl
.
Se lo desideri, puoi anche modificare le n
stringhe brevi per assicurarti che la maggior parte della stringa venga mascherata. Ad esempio, questo assicurerebbe che almeno tre caratteri siano mascherati anche per stringhe brevi. (quindi abcde
-> ***de
e abc
-> ***
):
mask() {
local n=3
[[ ${#1} -le 5 ]] && n=$(( ${#1} - 3 ))
local a="${1:0:${#1}-n}"
local b="${1:${#1}-n}"
printf "%s%s\n" "${a//?/*}" "$b"
}
Un'opzione sarebbe quella di forzarti a usare una funzione invece di echo
, come ad esempio:
obfuprint() {
if [ "${#1}" -ge 8 ]
then
printf '%s\n' "${1/????????/********}"
else
printf '%s\n' "${1//?/*}"
fi
}
Quindi è possibile chiamare obfuprint 'secretvalue'
e ricevere ********lue
(con una nuova riga finale). La funzione utilizza l'espansione dei parametri per cercare i primi otto caratteri del valore passato e li sostituisce con otto asterischi. Se il valore in ingresso è inferiore a otto caratteri, vengono tutti sostituiti con asterischi. Grazie a ilkkachu per aver sottolineato la mia ipotesi iniziale di input di otto o più caratteri!
Ispirato dalla risposta flessibile al mascheramento di ilkkachu , ho pensato che sarebbe stato interessante aggiungere una variazione che maschera casualmente una percentuale della stringa:
obfuprintperc () {
local perc=75 ## percent to obfuscate
local i=0
for((i=0; i < ${#1}; i++))
do
if [ $(( $RANDOM % 100 )) -lt "$perc" ]
then
printf '%s' '*'
else
printf '%s' "${1:i:1}"
fi
done
echo
}
Questo si basa sulla $RANDOM
variabile speciale di bash ; scorre semplicemente attraverso ogni carattere dell'input e decide se mascherarlo o stamparlo. Uscita campione:
$ obfuprintperc 0123456789
0*****6*8*
$ obfuprintperc 0123456789
012***678*
$ obfuprintperc 0123456789
**********
$ obfuprintperc 0123456789
*****56***
$ obfuprintperc 0123456789
0*******8*
Potresti provare a eseguire il piping a sed
. Ad esempio, per sostituire i primi 8 caratteri di una stringa con asterischi, è possibile reindirizzare al sed 's/^......../********/'
comando, ad esempio:
$ echo 'secretvalue' | sed 's/^......../********/'
********lue
Puoi anche definire una funzione che faccia questo:
obsecho () { echo "$1" | sed 's/^......../*********/'; }
printf
sopraecho
in modo che non sei soggetto a interpretare i dati come ad esempio \r
o\n
sed 's/^......../********/' <<< 'secretvalue'
bash -c 'lsof -d0 -a -p $$ 2>/dev/null' <<< foo
.
Una zsh
variante che maschera i tre quarti del testo:
mask() printf '%s\n' ${(l:$#1::*:)1:$#1*3/4}
Esempio:
$ mask secretvalue
********lue
$ mask 12345678
******78
$ mask 1234
***4
Per mascherare i primi 8 caratteri:
mask() printf '%s\n' ${(l:$#1::*:)1:8}
Per mascherare tutti tranne gli ultimi 3 caratteri:
mask() printf '%s\n' ${(l:$#1::*:)1: -3}
Per mascherare un numero casuale di caratteri:
mask() printf '%s\n' ${(l:$#1::*:)1: RANDOM%$#1}
Un'altra opzione in Bash, se non ti dispiace una semplice eval
puoi farlo con un paio di printf
:
# example data
password=secretvalue
chars_to_show=3
# the real thing
eval "printf '*%.0s' {1..$((${#password} - chars_to_show))}"
printf '%s\n' "${password: -chars_to_show}"
Ma fa attenzione:
${#password}
è inferiore a${chars_to_show}
eval
può essere molto pericoloso con input non attendibili: qui può essere considerato sicuro perché il suo input proviene solo da fonti sicure, ovvero la lunghezza ${password}
e il valore di${chars_to_show}
Ecco alcuni script Bash giocattolo con cui giocare che mostrano come combinare la ricerca simile a regex con la sostituzione di stringhe.
strip_str.sh
#!/usr/bin/env bash
_str="${1}"
_filter="${2:-'apl'}"
echo "${_str//[${_filter}]/}"
strip_str.sh 'apple-foo bar'
# -> e-foo br
strip_str.sh 'apple-foo bar' 'a'
# -> pple-foo br
privatize_str.sh
#!/usr/bin/env bash
_str="${1}"
_filter="${2:-'apl'}"
_replace="${3:-'*'}"
echo "${_str//[${_filter}]/${_replace}}"
privatize_str.sh 'apple-foo bar'
# -> ****e-foo b*r
restricted_str.sh
#!/usr/bin/env bash
_str="${1}"
_valid="${2:-'a-z'}"
_replace="${3:-''}"
echo "${_str//[^${_valid}]/${_replace}}"
restricted_str.sh 'apple-foo bar'
# -> applefoobar
Key takeaway
[a-z 0-9]
è totalmente valido e utile, come a <search>
all'interno ${_var_name//<search>/<replace>}
di Bash^
, in questo contesto, è il contrario o not
per ricerche simili a regexMentre ottengo che
printf
è meglio in quasi tutti i casi d'uso, il codice sopra riportato utilizza inecho
modo da non confondere eccessivamente quello che sta succedendo.
obfuscate_str.sh
#!/usr/bin/env bash
_str="${1}"
_start="${2:-6}"
_header="$(for i in {1..${_start}}; do echo -n '*'; done)"
echo "${_header}${_str:${_start}}"
obfuscate_str.sh 'apple-foo bar' 3
# -> ***le-foo bar