Echo z zaciemnieniem


15

Muszę wydrukować niektóre zmienne na ekranie, ale muszę preferencyjnie zaciemnić kilka pierwszych znaków i zastanawiałem się, czy w poleceniu nie było polecenia echa, które może zaciemnić pierwsze znaki tajnej wartości podczas drukowania na terminalu:

echo 'secretvalue'
********lue

Odpowiedzi:


11

Inne odpowiedzi maskują stałą liczbę znaków od samego początku, przy czym przyrostek tekstu jawnego ma różną długość. Alternatywą byłoby pozostawienie stałej liczby znaków w postaci zwykłego tekstu i zmiana długości zamaskowanej części. Nie wiem, który z nich jest bardziej przydatny, ale oto inny wybór:

#!/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

To drukuje **cdei *********jkl.


Jeśli chcesz, możesz również zmodyfikować nkrótkie łańcuchy, aby mieć pewność, że większość łańcucha zostanie zamaskowana. Np. Zapewniłoby to maskowanie co najmniej trzech znaków nawet dla krótkich ciągów znaków. (więc abcde-> ***dei 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"
}

13

Jedną z opcji byłoby zmuszenie się do korzystania z funkcji zamiast echo, takich jak:

obfuprint() {
  if [ "${#1}" -ge 8 ]
  then
    printf '%s\n' "${1/????????/********}"
  else
    printf '%s\n' "${1//?/*}"
  fi
}

Następnie możesz dzwonić obfuprint 'secretvalue'i odbierać ********lue(z końcowym znakiem nowej linii). Funkcja korzysta z rozszerzania parametrów w celu wyszukiwania pierwszych ośmiu znaków przekazywanej wartości i zastępuje je osiem gwiazdkami. Jeśli przychodząca wartość jest krótsza niż osiem znaków, wszystkie są zastępowane gwiazdkami. Dzięki ilkkachu za zwrócenie uwagi na moje początkowe założenie ośmiu lub więcej znaków!


Zainspirowany elastyczną odpowiedzią maskowania ilkkachu , pomyślałem, że byłoby interesujące dodać odmianę, która losowo maskuje pewien procent łańcucha:

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
}

Zależy to od $RANDOMspecjalnej zmiennej bash ; po prostu zapętla każdy znak wejścia i decyduje, czy maskować ten znak, czy go wydrukować. Przykładowe dane wyjściowe:

$ obfuprintperc 0123456789
0*****6*8*
$ obfuprintperc 0123456789
012***678*
$ obfuprintperc 0123456789
**********
$ obfuprintperc 0123456789
*****56***
$ obfuprintperc 0123456789
0*******8*

Szczerze mówiąc, nie lubię przypadkowego maskowania. Zdecydowany surfer w końcu pozna moje sekrety, udając, że lubi ze mną rozmawiać.
emory

Z pewnością wyświetlanie poufnych informacji powinno odbywać się ostrożnie! Przedstawiłem maskowanie losowe jako alternatywę dla maskowania o stałym prefiksie i maskowania o zmiennym prefiksie.
Jeff Schaller

4
Nie jestem też fanem maskowania o stałym lub przedrostku, ale z tymi istnieje „jądro” mojego sekretu, które pozostaje tajne. Przy losowym maskowaniu nie ma „jądra”. W końcu wszystko zostanie wystarczająco ujawnione tym pacjentom.
emory

7

Możesz spróbować wykonać potok do sed. Na przykład, aby zastąpić pierwsze 8 znaków ciągu gwiazdkami, możesz potokować do sed 's/^......../********/'polecenia, np .:

$ echo 'secretvalue' | sed 's/^......../********/'
********lue

Możesz także zdefiniować funkcję, która to robi:

obsecho () { echo "$1" | sed 's/^......../*********/'; }

2
Sugeruję printfsięecho tak, że nie jesteś przedmiotem interpretacji danych, takich jak \rlub\n
Jeff Schaller

@JeffSchaller Jest to jeden z powodów, dla których publikuję posty na SE. Słuszna uwaga. Dziękujemy za opinię.
igal

To także jedna z wielu rzeczy , których nauczyłem się tutaj! Chętnie to przekażę!
Jeff Schaller

1
Zamiast tego nie trzeba używać rury, jeśli można użyć sznurka:sed 's/^......../********/' <<< 'secretvalue'
wjandrea,

@roaima To właściwie tymczasowy zwykły plik. Możesz to zobaczyć, jeśli tak bash -c 'lsof -d0 -a -p $$ 2>/dev/null' <<< foo.
JoL

7

zshWariant, że maski trzy czwarte tekstu:

mask() printf '%s\n' ${(l:$#1::*:)1:$#1*3/4}

Przykład:

$ mask secretvalue
********lue
$ mask 12345678
******78
$ mask 1234
***4

Aby zamaskować pierwsze 8 znaków:

mask() printf '%s\n' ${(l:$#1::*:)1:8}

Aby zamaskować wszystkie oprócz ostatnich 3 znaków:

mask() printf '%s\n' ${(l:$#1::*:)1: -3}

Aby zamaskować losową liczbę znaków:

mask() printf '%s\n' ${(l:$#1::*:)1: RANDOM%$#1}

2

Kolejna opcja w Bash, jeśli nie przeszkadza ci jedna prosta eval, możesz to zrobić za pomocą kilku 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}"

Ale bądź ostrożny:

  • napraw powyższe, jak potrzebujesz, gdy ${#password}jest mniej niż${chars_to_show}
  • evalmoże być bardzo niebezpieczny przy niezaufanym wejściu: tutaj można go uznać za bezpieczny, ponieważ jego wkład pochodzi tylko z bezpiecznych źródeł, tj. długości ${password}i wartości${chars_to_show}

0

Oto niektóre zabawkowe skrypty Bash do zabawy z tym pokazem, jak połączyć wyszukiwanie podobne do wyrażenia regularnego z podstawieniem łańcucha.

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

Kluczowe dania na wynos

  • [a-z 0-9]jest całkowicie ważny i przydatny, jako część <search>wewnętrzna ${_var_name//<search>/<replace>}dla Bash
  • ^, w tym kontekście jest odwrotnością lub notdla wyszukiwań wyrażeń regularnych
  • Wbudowane są generalnie szybsze i często bardziej zwięzłe, szczególnie gdy odcina niepotrzebne przewody

Chociaż rozumiem, że printfjest to lepsze w prawie wszystkich przypadkach użycia, powyższy kod używa echo, aby nie nadmiernie mylić tego, co się dzieje.

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.