Відлуння з притупленням


15

Мені потрібно надрукувати деякі змінні на екрані, але мені потрібно замовчувати перші кілька символів, і мені було цікаво, чи є команда echo в bash, яка може затуманити перші символи секретного значення під час друку на терміналі:

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

Відповіді:


11

Інші відповіді маскують фіксовану кількість символів з самого початку, при цьому суфікс простого тексту може змінюватися по довжині. Альтернативою було б залишити фіксовану кількість символів у простому тексті та змінити довжину частини маскування. Я не знаю, який із них корисніший, але ось інший вибір:

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

Це відбитки **cdeі *********jkl.


Якщо вам подобається, ви також можете змінити nкороткі рядки, щоб переконатися, що більшість рядків маскується. Наприклад, це забезпечить маскування принаймні трьох символів навіть для коротких рядків. (так abcde-> ***deі 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

Одним із варіантів було б змусити себе використовувати функцію замість echo:

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

Тоді ви можете зателефонувати obfuprint 'secretvalue'та отримати ********lue(із заднім рядком). Функція використовує розширення параметрів для пошуку перших восьми символів переданого значення та замінює їх вісьмома зірочками. Якщо вхідне значення коротше восьми символів, всі вони замінюються зірочками. Завдяки ilkkachu за вказівку мого початкового припущення про вісім або більше символьних введень!


Надихнувшись гнучкою маскуючою відповіддю ilkkachu , я подумав, що було б цікаво додати варіант, який випадковим чином замаскує деякий відсоток рядка:

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
}

Це спирається на $RANDOMспеціальну змінну bash ; він просто проходить цикл через кожен символ вводу та вирішує, чи замаскувати цей символ чи надрукувати його. Вибірка зразка:

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

Якщо чесно, я не люблю випадкове маскування. Рішучий плечовий серфер зрештою отримає мої секрети, роблячи вигляд, що любить спілкуватися зі мною.
Еморі

Звичайно, показ конфіденційної інформації слід робити обережно! Я представив випадкове маскування як альтернативу маскуванню з фіксованим префіксом та маскуванням із змінними префіксами.
Джефф Шаллер

4
Я також не шанувальник маскування з фіксованим префіксом або префіксом змінної, але з тими, хто існує "ядро" мого секрету, який залишається таємним. При випадковому маскуванні "ядра" немає. Врешті-решт всім виявиться достатньо пацієнтів.
Еморі

7

Ви можете спробувати виконати трубопроводи sed. Наприклад, щоб замінити перші 8 символів рядка зірочками, ви можете передати sed 's/^......../********/'команду, наприклад:

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

Ви також можете визначити функцію, яка робить це:

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

2
Я хотів би запропонувати printfбільшecho так , що ви не підлягають інтерпретації даних , таких як \rабо\n
Джефф Schaller

@JeffSchaller Це одна з причин, чому я публікую повідомлення в SE. Гарна думка. Дякуємо за відгук.
igal

Це одна з багатьох речей, про які я навчився свого часу і тут! Радий передати це разом!
Джефф Шаллер

1
Не потрібно використовувати трубу, коли замість неї можна використовувати херестинг:sed 's/^......../********/' <<< 'secretvalue'
wjandrea

@roaima Це фактично тимчасовий звичайний файл. Ви можете побачити це, якщо це зробити bash -c 'lsof -d0 -a -p $$ 2>/dev/null' <<< foo.
JoL

7

zshВаріант , який маскує три чверті тексту:

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

Приклад:

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

Щоб замаскувати перші 8 символів:

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

Щоб замаскувати всі, крім останніх 3 символів:

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

Щоб замаскувати випадкову кількість символів:

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

2

Ще один варіант у Bash, якщо ви не заперечуєте проти одного простого, evalви можете зробити це з парою 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}"

Але будьте обережні:

  • виправте вище, як вам потрібно, коли ${#password}менше${chars_to_show}
  • evalможе бути дуже небезпечним для ненадійного введення: тут його можна вважати безпечним, оскільки його вхід надходить лише з безпечних джерел, тобто довжини ${password}та значення${chars_to_show}

0

Ось декілька іграшок Bash-сценаріїв, з якими можна зіграти, які показують, як поєднувати пошук, схожий на регулярні виразки, із підстановкою рядків.

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

Ключові вивезення

  • [a-z 0-9]є повністю дійсним і зручним, як <search>всередині ${_var_name//<search>/<replace>}Bash
  • ^, в цьому контексті - це зворотний або not для регекс-подібних пошуків
  • Вбудовані в основному більш швидкі і часто більш стислі, особливо коли вони вирізають непотрібні трубопроводи

Хоча я розумію , що printfце краще , майже у всіх випадках використання наведений вище код використовує для echoтого, щоб не занадто плутати то , що відбувається.

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.