Эхо с запутыванием


15

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

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
}

Это зависит от BASH в $RANDOMспециальной переменной; он просто перебирает каждый символ ввода и решает, замаскировать ли этот символ или распечатать его. Пример вывода:

$ 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
Jeff Schaller

@JeffSchaller Это одна из причин, почему я пишу на SE. Хорошая точка зрения. Спасибо за ответ.
Игаль

Это одна из многих вещей, которые я изучил здесь, в свое время! Рад передать это!
Джефф Шаллер

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.