回音模糊


15

我需要在屏幕上打印一些变量,但是我需要优先混淆前几个字符,我想知道bash中是否有一个echo命令,可以在将其打印到终端时混淆秘密值的前几个字符:

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

Answers:


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-> ***deabc-> ***):

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*

坦率地说,我不喜欢随机遮罩。坚定的肩膀冲浪者会假装喜欢和我闲聊,最终将获得我的秘密。
Emory

当然,显示敏感信息应该小心!我介绍了随机掩码作为固定前缀掩码和可变前缀掩码的替代方法。
Jeff Schaller

4
我也不喜欢固定前缀或可变前缀掩码,但是有了这些前缀,我的秘密“内核”仍然是秘密。使用随机屏蔽,没有“内核”。最终,一切都会对那些患者足够显露。
Emory

7

您可以尝试管道连接到sed。例如,要将字符串的前8个字符替换为星号,可以通过管道传递给sed 's/^......../********/'命令,例如:

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

您还可以定义执行此操作的函数:

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

2
我建议printfecho让您不须解释,如数据\r\n
杰夫·夏勒

@JeffSchaller这是我在SE上发帖的原因之一。好点子。感谢您的反馈。
igal

这也是在这里学到的许多东西之一!乐意传递!
杰夫·谢勒

1
当您可以使用herestring代替时,无需使用管道: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}

要屏蔽除最后三个字符外的所有字符:

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>}进行猛砸
  • ^在这种情况下是反向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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.