Eco con offuscamento


15

Ho bisogno di stampare alcune variabili sullo schermo, ma devo offuscare in modo privilegiato i primi caratteri e mi chiedevo se in bash esistesse un comando echo che può offuscare i primi caratteri di un valore segreto mentre lo stampa sul terminale:

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

Risposte:


11

Le altre risposte mascherano una quantità fissa di caratteri dall'inizio, con il suffisso in chiaro che varia in lunghezza. Un'alternativa sarebbe quella di lasciare un numero fisso di caratteri in testo normale e di variare la lunghezza della parte mascherata. Non so quale sia più utile, ma ecco l'altra scelta:

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

Questo stampa **cdee *********jkl.


Se lo desideri, puoi anche modificare le nstringhe brevi per assicurarti che la maggior parte della stringa venga mascherata. Ad esempio, questo assicurerebbe che almeno tre caratteri siano mascherati anche per stringhe brevi. (quindi abcde-> ***dee 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

Un'opzione sarebbe quella di forzarti a usare una funzione invece di echo, come ad esempio:

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

Quindi è possibile chiamare obfuprint 'secretvalue'e ricevere ********lue(con una nuova riga finale). La funzione utilizza l'espansione dei parametri per cercare i primi otto caratteri del valore passato e li sostituisce con otto asterischi. Se il valore in ingresso è inferiore a otto caratteri, vengono tutti sostituiti con asterischi. Grazie a ilkkachu per aver sottolineato la mia ipotesi iniziale di input di otto o più caratteri!


Ispirato dalla risposta flessibile al mascheramento di ilkkachu , ho pensato che sarebbe stato interessante aggiungere una variazione che maschera casualmente una percentuale della stringa:

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
}

Questo si basa sulla $RANDOMvariabile speciale di bash ; scorre semplicemente attraverso ogni carattere dell'input e decide se mascherarlo o stamparlo. Uscita campione:

$ obfuprintperc 0123456789
0*****6*8*
$ obfuprintperc 0123456789
012***678*
$ obfuprintperc 0123456789
**********
$ obfuprintperc 0123456789
*****56***
$ obfuprintperc 0123456789
0*******8*

Ad essere sincero, non mi piace il mascheramento casuale. Un determinato surfista di spalla alla fine otterrà i miei segreti facendo finta di amare parlare con me.
emory

Certamente, la visualizzazione di informazioni sensibili dovrebbe essere fatta con attenzione! Ho presentato il mascheramento casuale come alternativa al mascheramento a prefisso fisso e mascheramento a prefisso variabile.
Jeff Schaller

4
Non sono nemmeno un fan del mascheramento a prefisso fisso o a prefisso variabile, ma con quelli esiste un "kernel" del mio segreto che rimane segreto. Con il mascheramento casuale, non esiste un "kernel". Alla fine tutto sarà rivelato a quei pazienti abbastanza.
emory

7

Potresti provare a eseguire il piping a sed. Ad esempio, per sostituire i primi 8 caratteri di una stringa con asterischi, è possibile reindirizzare al sed 's/^......../********/'comando, ad esempio:

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

Puoi anche definire una funzione che faccia questo:

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

2
Io suggerirei di printfsopraecho in modo che non sei soggetto a interpretare i dati come ad esempio \ro\n
Jeff Schaller

@JeffSchaller Questo è uno dei motivi per cui inserisco su SE. Buon punto. Grazie per il feedback.
igal,

È anche una delle tante cose che ho imparato nel mio tempo qui! Felice di passarlo!
Jeff Schaller

1
Non è necessario utilizzare una pipe quando è possibile utilizzare un herestring invece:sed 's/^......../********/' <<< 'secretvalue'
wjandrea

@roaima In realtà è un file regolare temporaneo. Puoi vederlo se lo fai bash -c 'lsof -d0 -a -p $$ 2>/dev/null' <<< foo.
JoL

7

Una zshvariante che maschera i tre quarti del testo:

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

Esempio:

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

Per mascherare i primi 8 caratteri:

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

Per mascherare tutti tranne gli ultimi 3 caratteri:

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

Per mascherare un numero casuale di caratteri:

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

2

Un'altra opzione in Bash, se non ti dispiace una semplice evalpuoi farlo con un paio di 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}"

Ma fa attenzione:

  • aggiustare quanto sopra quando è necessario quando ${#password}è inferiore a${chars_to_show}
  • evalpuò essere molto pericoloso con input non attendibili: qui può essere considerato sicuro perché il suo input proviene solo da fonti sicure, ovvero la lunghezza ${password}e il valore di${chars_to_show}

0

Ecco alcuni script Bash giocattolo con cui giocare che mostrano come combinare la ricerca simile a regex con la sostituzione di stringhe.

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

Key takeaway

  • [a-z 0-9] è totalmente valido e utile, come a <search> all'interno ${_var_name//<search>/<replace>}di Bash
  • ^, in questo contesto, è il contrario o notper ricerche simili a regex
  • Gli incorporamenti sono generalmente più veloci e spesso sono più concisi, soprattutto quando tagliano le tubazioni non necessarie

Mentre ottengo che printfè meglio in quasi tutti i casi d'uso, il codice sopra riportato utilizza in echomodo da non confondere eccessivamente quello che sta succedendo.

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.