web-dev-qa-db-ja.com

難読化を伴うエコー

いくつかの変数を画面に出力する必要がありますが、最初の数文字を難読化する必要があります。ターミナルに出力するときに、秘密の値の最初の文字を難読化できるbashのエコーコマンドがあったかどうか疑問に思いました。

echo 'secretvalue'
********lue
15
xerxes

他の回答は、最初から固定量の文字をマスクし、プレーンテキストのサフィックスは長さが異なります。別の方法としては、プレーンテキストに一定量の文字を残し、マスクされた部分の長さを変えることです。どちらがより便利かはわかりませんが、他の選択肢は次のとおりです。

#!/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を変更して、文字列の大部分が確実にマスクされるようにすることもできます。例えば。これにより、短い文字列でも少なくとも3つの文字が確実にマスクされます。 (そう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"
}
11
ilkkachu

1つのオプションは、echoの代わりに次のような関数を使用することを強制することです。

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

次に、obfuprint 'secretvalue'を呼び出して********lueを受け取ることができます(末尾の改行付き)。この関数は、パラメーター展開を使用して、渡された値の最初の8文字を検索し、それらを8つのアスタリスクに置き換えます。入力値が8文字より短い場合、すべてアスタリスクに置き換えられます。 ilkkach のおかげで、8文字以上の文字入力の最初の仮定を指摘してくれました。


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*
13
Jeff Schaller

sedへのパイプを試すことができます。たとえば、文字列の最初の8文字をアスタリスクに置き換えるには、sed 's/^......../********/'コマンドにパイプ処理します。たとえば、次のようにします。

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

これを行う関数を定義することもできます。

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

テキストの4分の3をマスクする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}
7

Bashのもう1つのオプションは、単純なevalを1つでも構わない場合は、いくつかの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}の値からのみであるため、安全と見なすことができます。
2
LL3

ここにいくつかのtoyで遊ぶ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]は完全に有効であり、Bashの<search>内の${_var_name//<search>/<replace>}として便利です。
  • このコンテキスト内での^は逆であり、正規表現のような検索の場合はnotです。
  • ビルトインは一般的に高速であり、多くの場合、特に不要な配管を切り取るときにより簡潔になります

私はprintfbetterであることを理解していますが、ほとんどすべてのユースケースで上記のコードは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
0
S0AndS0