Echo mit Verschleierung

15

Ich muss einige Variablen auf dem Bildschirm ausgeben, aber ich muss die ersten Zeichen vorzugsweise verschleiern, und ich habe mich gefragt, ob es in bash einen Echobefehl gibt, der die ersten Zeichen eines geheimen Werts beim Drucken auf dem Terminal verschleiern kann:

echo 'secretvalue'
********lue
Xerxes
quelle

Antworten:

11

Die anderen Antworten maskieren von Anfang an eine feste Anzahl von Zeichen, wobei das Klartext-Suffix in der Länge variiert. Eine Alternative wäre, eine feste Anzahl von Zeichen im Klartext zu belassen und die Länge des maskierten Teils zu variieren. Ich weiß nicht, welches nützlicher ist, aber hier ist die andere Wahl:

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

Dies druckt **cdeund *********jkl.


Wenn Sie möchten, können Sie auch nkurze Zeichenfolgen ändern , um sicherzustellen, dass ein Großteil der Zeichenfolge maskiert wird. Dies würde z. B. sicherstellen, dass auch für kurze Zeichenfolgen mindestens drei Zeichen maskiert sind. (so abcde-> ***deund 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"
}
ilkkachu
quelle
13

Eine Möglichkeit wäre, sich zu zwingen, stattdessen eine Funktion zu verwenden echo, wie zum Beispiel:

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

Dann könntest du anrufen obfuprint 'secretvalue'und empfangen ********lue(mit einer nachgestellten Newline). Die Funktion sucht mithilfe der Parametererweiterung nach den ersten acht Zeichen des übergebenen Werts und ersetzt sie durch acht Sternchen. Wenn der eingehende Wert kürzer als acht Zeichen ist, werden sie alle durch Sternchen ersetzt. Vielen Dank an ilkkachu für den Hinweis auf meine anfängliche Annahme von acht oder mehr Zeicheneingaben!


Inspiriert von der flexiblen Maskierungsantwort von ilkkachu fand ich es interessant, eine Variation hinzuzufügen, die zufällig einen bestimmten Prozentsatz der Zeichenfolge maskiert:

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
}

Dies beruht auf der $RANDOMspeziellen Variablen von bash . Es durchläuft einfach jedes Zeichen der Eingabe und entscheidet, ob dieses Zeichen maskiert oder gedruckt werden soll. Beispielausgabe:

$ obfuprintperc 0123456789
0*****6*8*
$ obfuprintperc 0123456789
012***678*
$ obfuprintperc 0123456789
**********
$ obfuprintperc 0123456789
*****56***
$ obfuprintperc 0123456789
0*******8*
Jeff Schaller
quelle
Um ehrlich zu sein, ich mag keine zufällige Maskierung. Ein entschlossener Schultersurfer wird irgendwann meine Geheimnisse erfahren, wenn er vorgibt, mit mir Smalltalk zu führen.
Emory
Das Anzeigen vertraulicher Informationen sollte auf jeden Fall sorgfältig erfolgen! Ich präsentierte die Zufallsmaskierung als Alternative zur festen Präfixmaskierung und zur variablen Präfixmaskierung.
Jeff Schaller
4
Ich bin auch kein Fan von Festpräfix- oder Variablenpräfix-Maskierung, aber bei diesen gibt es einen "Kernel" meines Geheimnisses, der geheim bleibt. Bei zufälliger Maskierung gibt es keinen "Kernel". Irgendwann wird den Patienten alles genug offenbart.
Emory
7

Sie könnten versuchen, Rohrleitungen zu sed. Um beispielsweise die ersten 8 Zeichen einer Zeichenfolge durch Sternchen zu ersetzen, können Sie eine Pipe zu dem sed 's/^......../********/'Befehl ausführen, z.

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

Sie können auch eine Funktion definieren, die dies ausführt:

obsecho () { echo "$1" | sed 's/^......../*********/'; }
igal
quelle
2
Ich schlage printfvorecho , dass Sie keine Daten wie \roder interpretieren müssen\n
Jeff Schaller
@ JeffSchaller Dies ist einer der Gründe, warum ich auf SE poste. Guter Punkt. Danke für die Rückmeldung.
20.
Das ist auch eines der vielen Dinge, die ich in meiner Zeit hier gelernt habe ! Gerne weitergeben!
Jeff Schaller
1
Sie müssen keine Pfeife verwenden, wenn Sie stattdessen einen Herestring verwenden können:sed 's/^......../********/' <<< 'secretvalue'
wjandrea
@roaima Es ist eigentlich eine temporäre reguläre Datei. Sie können es sehen, wenn Sie es tun bash -c 'lsof -d0 -a -p $$ 2>/dev/null' <<< foo.
JoL
7

Eine zshVariante, die drei Viertel des Textes maskiert:

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

Beispiel:

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

So maskieren Sie die ersten 8 Zeichen:

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

So maskieren Sie alle Zeichen außer den letzten drei Zeichen:

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

So maskieren Sie eine zufällige Anzahl von Zeichen:

mask() printf '%s\n' ${(l:$#1::*:)1: RANDOM%$#1}
Stéphane Chazelas
quelle
2

Eine andere Option in Bash, wenn Sie nichts dagegen haben eval, können Sie es mit ein paar tun 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}"

Aber sei vorsichtig:

  • Beheben Sie die oben genannten Probleme, wenn ${#password}weniger als erforderlich ist${chars_to_show}
  • evalkann bei nicht vertrauenswürdigen Eingaben sehr gefährlich sein: Hier kann es als sicher angesehen werden, da seine Eingabe nur aus sicheren Quellen stammt, dh der Länge ${password}und dem Wert von${chars_to_show}
LL3
quelle
0

Hier sind einige Spielzeug- Bash-Skripte zum Spielen, die zeigen, wie man die Suche nach regulären Ausdrücken mit der Ersetzung von Zeichenfolgen kombiniert.

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

Die zentralen Thesen

  • [a-z 0-9]ist absolut gültig und praktisch, als eine <search>Innenseite ${_var_name//<search>/<replace>}für Bash
  • ^In diesem Kontext ist es umgekehrt oder notfür reguläre Suchen
  • Eingebaute Leitungen sind im Allgemeinen schneller und oft präziser, insbesondere wenn nicht benötigte Leitungen herausgeschnitten werden

Während ich das bekommen printfist besser in fast allen Anwendungsfällen die oben genannten Code Verwendungen echo, um nicht übermäßig zu verwirren , was los ist .

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
S0AndS0
quelle