2016-10-03 5 views
0

Ich brauche eine Möglichkeit Hashing eines vorhandenen Dateinamens mit einer Passphrase (ASCII-Zeichenfolge), aber in der Lage, es wieder mit der gleichen Passphrase zurück zu stellen.Hashing einer Zeichenfolge mit einer Passphrase in Bash

Ich weiß, dass Chiffren können dies tun - sie verschlüsseln die Zeichenfolge ... Aber ihre Ausgabe Länge basiert auf dem Dateinamen length, die genau das ist, was ich nicht will ... vor allem, weil es manchmal verdoppelt die Dateilänge , aber die ausgegebenen Strings sind nicht immer kompatibel mit dem FS. Ex. "\ n" in einem Dateinamen.

Um klar zu sein, habe ich viel recherchiert und sogar einige Skripte geschrieben, aber alle Lösungen sind entweder langsam oder funktionieren überhaupt nicht für meine Anwendung.

Das Ziel dieses ist eine konstante Länge von Dateinamen zu erhalten, die alle ‚‘ entschlüsselt einmal sein kann, an einem einzigen Passwort verwenden. Ohne zusätzliche Metadaten-ähnliche Dateien erstellen zu müssen.

+2

Wenn es überhaupt reversibel ist, ist es kein verschlüsselter Hash. So arbeiten sie nicht/was sie tun/wofür sie sind. –

+0

@CharlesDuffy Ich weiß das, ich erwähnte, dass Ciphers genau dafür sind. Aber ich brauche einige der Eigenschaften von Hashes - wie konstante Hash-Länge, Geschwindigkeit usw. – areuz

+1

(Nun, ich nehme an, Sie könnten etwas Inhalt mit der Ausgabe eines kryptografischen Hashes speichern - das klingt ein bisschen so was du willst - aber wenn du dein Ziel genauer beschreibst, erhältst du wahrscheinlich einen besseren Vorschlag. –

Antwort

1

Ich bin mit meiner ersten Frage herumgekommen. Es scheint nur eine Lösung für das obige Problem zu geben, und das ist (wie James vorgeschlagen hat) die formatbewahrende Verschlüsselung. Soweit ich das beurteilen kann, gibt es jedoch keine Befehle, die dies tun.

Also habe ich genau das getan, was meine allererste Option war, und das hasht den Dateinamen, setzt den Hash und den Dateinamen in eine einfache Datei (eine Datei pro Verzeichnis) und verschlüsselt diese Datei mit einer Passphrase.

Ich poste meinen Code hier. Obwohl es wahrscheinlich nicht der hübscheste noch der portabelste Code ist, aber es macht den Job und ist (IMO) wirklich einfach.

#!/usr/bin/env bash 

man="Usage: namecrypt [ -h ] [ -e || -d ] [ -F ] [ -D ] [DIRECTORY] [PASSPHRASE]\n 
    -h, --help  display this message 

    -e, --encrypt  encrypt the specified directory 
    -d, --decrypt  decrypt the specified directory 

    -F, --files  include files 
    -D, --dir  include directories 

    [DIRECTORY]  relative or absolute path to a directory/symbolic link 
    [PASSPHRASE]  optional - specify the user passphrase on command line"; 

options=(); 
for Arg in "[email protected]"; do 
    if [ "$Arg" == "-h" ] || [ "$Arg" == "--help" ]; then 
     echo -e "$man"; exit; 
    elif [ "$Arg" == "-e" ] || [ "$Arg" == "--encrypt" ]; then 
     options[0]="E"; 
    elif [ "$Arg" == "-d" ] || [ "$Arg" == "--decrypt" ]; then 
     options[0]="D"; 
    elif [ "$Arg" == "-F" ] || [ "$Arg" == "--files" ]; then 
     options[1]="${options[1]}F"; 
    elif [ "$Arg" == "-D" ] || [ "$Arg" == "--dir" ]; then 
     options[1]="${options[1]}D"; 
    elif [ -d "$Arg" ]; then 
     options[2]="$(realpath "$Arg")"; 
    else  
     options[3]="$Arg";  
    fi; 
done; 

if [ "${options[0]}" == "" ]; then echo "No Mode specified!"; exit 1; fi; 
if [ "${options[1]}" == "" ]; then options[1]="F"; fi; 
if [ "${options[2]}" == "" ]; then echo "No such directory!"; exit 2; fi; 
if [ "${options[3]}" == "" ]; then echo "Enter a passphrase: "; read options[3]; fi; 

shopt -s nullglob dotglob; 

function hashTarget 
{ 
    BASE="$(basename "$1")"; 
    DIR="$(dirname "$1")/"; 

    if [ -a "$1" ]; then 
     oldName="$BASE"; 
     newName=$(echo "$oldName" | md5sum); 
     echo "$oldName||$newName" >> "$DIR.names"; 
     mv "$1" "$DIR$newName"; 
    else echo "Skipping '$1' - No such file or directory!"; 
    fi; 
} 

function dehashTarget 
{ 
    BASE="$(basename "$1")"; 
    DIR="$(dirname "$1")/"; 

    [ -f "$DIR.names.cpt" ] && ccdecrypt -K "${options[3]}" "$DIR.names.cpt"; 

    if [ -f "$DIR.names" ]; then 
     oldName="$BASE"; 
     newName=$(grep "$oldName" "$DIR.names" | awk -F '|' '{print $1}'); 
     [[ ! -z "${newName// }" ]] && mv "$1" "$DIR$newName"; 
    else 
     echo "Skipping '$1' - Hash table not found!"; 
    fi; 
} 

function mapTarget 
{ 
    DIR="$(dirname "$1")/"; 

    for Dir in "$1"/*/; do 
     mapTarget "$Dir"; 
    done; 

    for Item in "$1"/*; do 
     if ([ -f "$Item" ] && [[ "${options[1]}" == *"F"* ]]) || 
      ([ -d "$Item" ] && [[ "${options[1]}" == *"D"* ]]); then 

      if [ "${options[0]}" == "E" ]; then 
       hashTarget "$Item"; 
      else 
       dehashTarget "$Item"; 
      fi; 
     fi; 
    done; 

    [ "${options[0]}" == "D" ] && [ -f "$DIR.names" ] && rm "$DIR.names"; 
    [ "${options[0]}" == "E" ] && [ -f "$DIR.names" ] && ccencrypt -K "${options[3]}" "$DIR.names"; 

} 

mapTarget "${options[2]}"; 

Wahrscheinlich der einzige Grund, warum es so lange dauert, ist, weil ich nicht mit OOP störten, und ich habe auch eine Menge von Schecks und Schritte, um sicherzustellen, dass die meiste Zeit keine Namen verstümmelt bekommen und kann nicht wiederhergestellt werden - Benutzerfehler kann immer noch dazu führen.

Dies ist der Befehl verwendet, um die Hash-Tabelle Dateien zu verschlüsseln: CCrypt

+0

Alle Änderungen oder Kommentare über den Code sind natürlich willkommen. Ich bin nicht wirklich ein geschickter Bash-Programmierer. – areuz

+0

Das ist eine ziemlich gute Lösung! Das habe ich mit dem Aufbau einer Hashtabelle gemeint :-) – mahatmanich

+1

@mahatmanich Danke!Ich habe NUR einen komplett neuen Code hochgeladen, der alte war fehlerhaft und hatte Einschränkungen wie Leerzeichen in Verzeichnisnamen und führte keine spezifischen Fehlerprüfungen durch. – areuz

Verwandte Themen