いくつかの変数を画面に出力する必要がありますが、最初の数文字を難読化する必要があります。ターミナルに出力するときに、秘密の値の最初の文字を難読化できるbashのエコーコマンドがあったかどうか疑問に思いました。
echo 'secretvalue'
********lue
他の回答は、最初から固定量の文字をマスクし、プレーンテキストのサフィックスは長さが異なります。別の方法としては、プレーンテキストに一定量の文字を残し、マスクされた部分の長さを変えることです。どちらがより便利かはわかりませんが、他の選択肢は次のとおりです。
#!/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"
}
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*
sed
へのパイプを試すことができます。たとえば、文字列の最初の8文字をアスタリスクに置き換えるには、sed 's/^......../********/'
コマンドにパイプ処理します。たとえば、次のようにします。
$ echo 'secretvalue' | sed 's/^......../********/'
********lue
これを行う関数を定義することもできます。
obsecho () { echo "$1" | sed 's/^......../*********/'; }
テキストの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}
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}
の値からのみであるため、安全と見なすことができます。ここにいくつかの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
です。私は
printf
がbetterであることを理解していますが、ほとんどすべてのユースケースで上記のコードは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