RSS-Feed anzeigen

jahlives

Verschlüsseln mit openssl

Bewerten
Wir haben im Forum ja oft die Frage auf welche Weise(n) man Daten verschlüsseln kann. Dazu bietet der DSM ja einerseits die Möglichkeit die Freigaben zu verschlüsseln. Oder man verwendet ein Tool auf dem Client (z.B. Truecrypt oder was ähnliches).

Da auf der DS ja aber ein openssl vorhanden ist, gäbe es auch den Weg Files mittels openssl zu verschlüsseln. Also direkt auf der Konsole. Dazu muss man aber immer relativ lange openssl Kommandos tippen, drum habe ich ein kleines Script geschrieben, das die Ver-und Entschlüsselung übernimmt.

Folgende Voraussetzungen/Dinge solltet ihr beachten:

1) ist ein Bash Script. Setzt also die Bash auf der DS voraus. Wird mit ash oder sh kaum laufen (die Bash gibt es bei ipkg)
2) openssl muss installiert sein (das Script funzt mit der openssl Version der Firmware problemlos)
3) das Script schreibt die verschlüsselte Datei über die Originaldatei. Ihr habt danach also nur noch die verschlüsselte Version der Datei!
4) beim Entschlüsseln wird die Datei temporär entschlüsselt und der Inhalt auf der Konsole angezeigt. Danach wird das temporäre File sofort wieder gelöscht

Wegen 4) macht das Script eigentlich nur bei Textfiles wirklich Sinn. Wenn ihr die Datei wirklich wieder entschlüsselt auf der Platte haben wollt, dann geht das mit dem Script nicht. Dazu müsst ihr das openssl Kommando manuell auf der Konsole absetzen.
Wenn ihr also z.B. das File /root/totalGeheim.txt mit dem Script verschlüsselt habt und es wieder entschlüsselt auf der Platte wollt, dann sähe das openssl Kommando ungefähr so aus
Code:
openssl enc -in /root/TotalGeheim.txt -out /tmp/TotalGeheim.txt -d -md sha1 -blowfish
openssl könnte zwar auch direkt -out /root/TotalGeheim.txt nutzen, davon wird aber im openssl Manual explizit abgeraten. Es ist besser das File erstmal an einen anderen Ort zu Entschlüsseln und dann an den Ursprungsort zu verschieben.
Das einzige was man oben ggf noch anpassen müsste wäre es statt -blowfish einen anderen Algo zu verwenden. Das müsst ihr aber nur dann machen wenn ihr bei der Verschlüsselung mit dem Script explizit einen anderen Algo via -c oder --cipher festgelegt habt. Per default verwendet das Script immer den blowfish.

Die Verwendung des Scriptes ist relativ einfach ;-)
Code:
#Verschlüsseln
/path/script -e -f |--file /path/to/file [-c|--cipher CIPHER] 

#"Entschlüsseln"
/path/script -d -f|--file /path/to/file [-c|--cipher CIPHER]
-e steht für encrypt und muss angegeben werden
-d steht für decrypt und muss angegeben werden
-f resp --file ist selbsterklärend ;-) und muss angegeben werden
-c resp --cipher legt den Algo für die auszuführende Aktion fest. Beim Entschlüsseln muss derselbe verwendet werden wie beim Verschlüsseln! Eine Liste der untersützten Algos ergibt folgendes openssl-Kommando
Code:
openssl ciphers
-c resp --cipher ist aber ein fakultativer Parameter. Wenn er nicht angegeben wird, verwendet das Script den blowfish

Code:
#!/bin/bash
 
#Define vars for commandline args
action=''
file=''
cipher=''
 
#Read args from cli
while (( $# ))
do
 case $1 in
  '-d' | '-e')
   action=$1
   shift
  ;;
  '-f' | '--file')
   shift
   file=$1
   shift
  ;;
  '-c' | '--cipher')
   shift
   cipher=$1
   shift
  ;;
  *)
   echo ""
   echo "Usage: crypto -d|-e -f|--file /path/to/file -c|cipher cipher_to_use"
   echo "-d|-e      :   Action to perform. Decrypt OR Encrypt"
   echo "-f|--file  :   File to perform action on"
   echo "-c|--cipher:   cipher to use for action. See openssl ciphers command for ciphers supported on your system"
   echo ""
   exit
 esac
done
 
#Checks for args given by user
[ -z "$file" ] && echo 'No file given' && exit 1
[[ "x$file" != x  && ! -f "$file" ]] && echo "Given file not found. Check $file" && exit 1
[ -z "$action" ] && echo 'No action given' && exit 1
[ -z "$cipher" ] && echo 'No cipher given  will be used' && cipher='blowfish'
[[ "$cipher" != 'blowfish' && -z "$(openssl ciphers | grep -v 'grep' | grep -i '\-'${cipher}'\-')" ]] && echo "$cipher not found.  will be used" && cipher='blowfish'
 
#Generate "random" string for temp filename
filename=$(basename $file)
filename=$(echo $filename | md5sum | awk '{print $1}')
filename=".${filename:4:16}"
 
case $action in
 '-e')
  openssl enc -in $file -out /tmp/$filename $action -md sha1 -${cipher}
  [ $? -eq 0 ] && mv /tmp/$filename $file && exit 0
  echo 'Fehler' && rm /tmp/$filename > /dev/null 2>&1 && exit 1
  ;;
 '-d')
  openssl enc -in $file -out /tmp/$filename $action -md sha1 -${cipher}
  [ $? -eq 0 ] && cat /tmp/$filename && rm /tmp/$filename && echo "" && exit 0
  echo 'Fehler' && rm /tmp/$filename > /dev/null 2>&1 && exit 1
  ;;
esac
TODO:
* Option die Files auch mit dem Script wieder entschlüsselt an den Urspungsplatz zu schreiben
* Verifizierung der entschlüsselten Daten mittels Filehash

crypto.zip

Aktualisiert: 04.01.2012 um 19:44 von jahlives

Kategorien
etc ppt

Kommentare

  1. Avatar von jahlives
    Aktuellste Version mit beiden TODOs erledigt :-)
    Mittels -df wird das File entschlüsselt und an den Ursprungsort geschrieben. Für die Verifizierung mittels hash wird beim Verschlüsseln der Hash des unverschlüsselten Inhalts in ein File /path/to/file.ext.hash geschrieben und nach dem Entschlüsseln verglichen.
    Code:
    #!/bin/bash
    
    #Define vars for commandline args
    action=''
    file=''
    cipher=''
    
    #Read args from cli
    while (( $# ))
    do
     case $1 in
      '-d' | '-e' | '-df' )
       action=$1
       shift
      ;;
      '-f' | '--file')
       shift
       file=$1
       shift
      ;;
      '--digest')
       shift
       digest=$1
       shift
      ;;
      '-c' | '--cipher')
       shift
       cipher=$1
       shift
      ;;
      *)
       echo ""
       echo "Usage: crypto -d|-e|-df -f|--file /path/to/file [-c|--cipher cipher_to_use]"
       echo "-d|-e|-df  :   Action to perform. Decrypt OR Encrypt OR Decrypt Force. Last command copies the decrypted file back to its origin in the filesystem"
       echo "-f|--file  :   File to perform action on"
       echo "-c|--cipher:   cipher to use for action. See openssl ciphers command for ciphers supported on your system"
       echo ""
       exit
     esac
    done
    
    #Checks for args given by user
    [ -z "$file" ] && echo 'FATAL_ERROR: No file given' && exit 1
    [[ "x$file" != x  && ! -f "$file" ]] && echo "FATAL_ERROR: Given file not found. Check $file" && exit 1
    [ -z "$action" ] && echo 'FATAL_ERROR: No action given' && exit 1
    [ -z "$cipher" ] && echo 'INFO: No cipher given  will be used' && cipher='blowfish'
    [[ "$cipher" != 'blowfish' && -z "$(openssl ciphers | grep -v 'grep' | grep -i '\-'${cipher}'\-')" ]] && echo "INFO: $cipher not found.  will be used" && cipher='blowfish'
    [ -z $digest ] && echo 'INFO: No digest given.  will be used instead' && digest='sha256'
    #Generate "random" string for temp filename
    filename=$(basename $file)
    filename=$(echo $filename | md5sum | awk '{print $1}')
    filename=".${filename:4:16}"
    
    case $action in
     '-e')
      openssl dgst -${digest} -out "${file}.hash" $file
      openssl enc -in $file -out /tmp/$filename $action -md ${digest} -${cipher} 2>/dev/null
      [ $? -eq 0 ] && mv /tmp/$filename $file && exit 0
      echo 'FATAL_ERROR: File could not be encrypted. Check your parameters!' && rm /tmp/$filename > /dev/null 2>&1 && exit 1
      ;;
     '-d')
      openssl enc -in $file -out /tmp/$filename $action -md ${digest} -${cipher} 2>/dev/null
      [ $? -ne 0 ] && echo "FATAL_ERROR: Wrong password and/or wrong algorithm provided and/or $file is not encrypted at all!" && rm /tmp/$filename > /dev/null 2>&1 && exit 1
      [ "$(openssl dgst -$digest /tmp/$filename | awk -F'= ' '{print $2}')" = "$(cat ${file}.hash | awk -F'= ' '{print $2}')" ]
      if [ $? -ne 0 ] ; then
       echo "WARNING: File decrypted but filehashes do NOT match. File is possibly compromised!!"
      else
       echo "INFO: File decrypted and filehashes DO match"
      fi
      [ -f /tmp/$filename ] && cat /tmp/$filename && rm /tmp/$filename > /dev/null 2>&1 && exit 0
     ;;
     '-df')
      openssl enc -in $file -out /tmp/$filename -d -md ${digest} -${cipher} 2>/dev/null
      [ $? -ne 0 ] && echo "FATAL_ERROR: Wrong password and/or wrong algorithm provided and/or $file is not encrypted at all!" && rm /tmp/$filename > /dev/null 2>&1 && exit 1
      [ "$(openssl dgst -$digest /tmp/$filename | awk -F'= ' '{print $2}')" = "$(cat ${file}.hash | awk -F'= ' '{print $2}')" ]
      if [ $? -ne 0 ] ; then
       echo "WARNING: File decrypted but filehashes do NOT match. File is possibly compromised!!"
      else
       echo "INFO: File decrypted and filehashes DO match"
      fi
      [ -f /tmp/$filename ] && mv /tmp/$filename $file > /dev/null 2>&1 && exit 0
     ;;
    esac
  2. Avatar von itari
    zwei Bemerkungen:

    (1) ich würde den 'for' statt des 'while' nehmen ... weil man das Scannen von Aufrufargumenten eigentlich immer per for erledigt (deswegen gibt es ja auch die for-Variante ohne 'in')

    (2) alle Shell-Variablen (auch $1) gehören in doppelte Anführungszeichen, weil ja immer die Gefahr besteht, dass sie 'leer' sind und damit könnte die Syntax daneben gehen; nebenbei empfehlen die Gründungsväter, die GROSSSCHREIBUNG der SHELL-Variablen, der Übersichtlichkeit halber

    Itari
  3. Avatar von jahlives
    @itari
    danke für die Tipps. Hast du gerade einen konkreten Fall gesehen wo ich ohne " und " in ein Problem mit einer Prüfung reinlaufen könnte? Hatte eigentlich gedacht ich würde das überall abfangen :-)
    Das mit der Grossschreibung habe ich auch schon irgendwo gelesen, nur muss ich mich dann immer Fragen: Ist es jetzt eine VAR oder eine Konstante? Mich verwirrt das eher als dass es mir hilft ;-)
    Ich fand den Weg via while schlicht eingängiger für mich.

    Werde deine Tipps aber auf jeden Fall mal versuchen in den Code einzuarbeiten. Habe eh noch einen kleinen Fehler, den ich noch beheben muss (nichts gravierendes nur eine doppelte Fehlermeldung in bestimmten Fällen)

    Sonst findest du kann man das Script leben lassen?

    Gruss

    tobi
  4. Avatar von itari
    ... wenn du an Dateinamen mit Leerstellen denkst, musst noch nacharbeiten ...

    Itari
  5. Avatar von jahlives
    Zitat Zitat von itari
    ... wenn du an Dateinamen mit Leerstellen denkst, musst noch nacharbeiten ...

    Itari
    @itari
    danke daran denk ich nie, weil ich bei mir tunlichst auf Sonder- und Leerzeichen in Pfaden/Dateien verzicht :-)
  6. Avatar von jahlives
    Sodele habe itaris Tipps teilweise mal umgesetzt ;-)
    Den mit dem for für die Argumente habe ich aber ned verstanden, drum habe ich das mit dem while gelassen wie es ist. Die Vars sollten jetzt durchgängig gross geschrieben sein. Auch die Sache mit möglichen Leerzeichen in den Filenamen sollte behoben sein. Wobei ich persönlich trotzdem empfehlen würde immer auf Leer- und Sonderzeichen in Dateinamen zu verzichten ;-)

    Wenn jemand noch was sieht einfach immer her damit :-)

    Das zip mit dem aktuellsten Code habe ich im ersten Post angehängt

    Code:
    #!/bin/bash
    
    #Define vars for commandline args
    ACTION=''
    FILE=''
    CIPHER=''
    
    #Read args from cli
    while (( $# ))
    do
     case "$1" in
      'dec-write' | 'enc' | 'dec-disp' | 'dec' )
       ACTION="$1"
       shift
      ;;
      '-f' | '--file')
       shift
       FILE="$1"
       shift
      ;;
      '-d' | '--digest')
       shift
       DIGEST="$1"
       shift
      ;;
      '-c' | '--cipher')
       shift
       CIPHER="$1"
       shift
      ;;
      *)
       echo ""
       echo "Usage: crypt.sh  dec-write|dec-disp|enc -f|--file /path/to/FILE [-d|--digest digest_to_use] [-c|--cipher cipher_to_use]"
       echo "Order of arguments is not important!"
       echo "enc        : encrypts a file"
       echo "dec-disp   : decrypts a file to a temp file, display its unencrypted content and deletes the temp file"
       echo "dec-write  : decrypts a file and copy the unencrypted file back to its origin in the filesystem"
       echo "-f|--file  : file to perform ACTION on"
       echo "-c|--cipher: cipher to use for ACTION. See  command for ciphers supported on your system"
       echo "-d|--digest: digest to use for hashing the password and creating/verifying a checksum of the of the unencrypted content"
       echo ""
       exit
     esac
    done
    
    #Checks for args given by user
    [ -z "$FILE" ] && echo 'FATAL_ERROR: No FILE given' && exit 1
    [[ "x$FILE" != x  && ! -f "$FILE" ]] && echo "FATAL_ERROR: Given FILE not found. Check $FILE" && exit 1
    [ -z "$ACTION" ] && echo 'FATAL_ERROR: No ACTION given' && exit 1
    [ -z "$CIPHER" ] && echo 'INFO: No CIPHER given  will be used' && CIPHER='blowfish'
    [[ "$CIPHER" != 'blowfish' && -z "$(openssl ciphers | grep -v 'grep' | grep -i '\-'${CIPHER}'\-')" ]] && echo "INFO: $CIPHER not found.  will be used" && CIPHER='blowfish'
    [ -z "$DIGEST" ] && echo 'INFO: No digest given.  will be used instead' && DIGEST='sha256'
    
    if [ -n "$DIGEST" ] ; then
     case $DIGEST in
      md|md5|sha1|sha256|sha224|sha512|md4)
     ;;
     *)
      echo 'INFO: No or a non-valid DIGEST given  will be used' && DIGEST='sha1'
     ;;
     esac
    fi
    #Generate "random" string for temp FILENAME
    FILENAME=$(basename "$FILE")
    FILENAME=$(echo "$FILENAME" | md5sum | awk '{print $1}')
    FILENAME=".${FILENAME:4:16}"
    
    case $ACTION in
     'enc')
      openssl dgst -${DIGEST} -out "${FILE}.hash" "$FILE" > /dev/null 2>&1
      openssl enc -in "$FILE" -out "/tmp/$FILENAME" -e -md "${DIGEST}" -"${CIPHER}" > /dev/null 2>&1
      [ $? -eq 0 ] && mv "/tmp/$FILENAME" "$FILE" && exit 0
      echo 'FATAL_ERROR: File could not be encrypted. Check your parameters!' && rm "/tmp/$FILENAME" > /dev/null 2>&1 && exit 1
      ;;
     'dec-disp' | 'dec')
      openssl enc -in "$FILE" -out "/tmp/$FILENAME" -d -md "${DIGEST}" -"${CIPHER}" > /dev/null 2>&1
      [ $? -ne 0 ] && echo "FATAL_ERROR: Wrong password and/or wrong algorithm provided and/or $FILE is not encrypted at all!" && exit 1
      [ "$(openssl dgst -$DIGEST /tmp/$FILENAME 2>/dev/null | awk -F'= ' '{print $2}')" = "$(cat ${FILE}.hash | awk -F'= ' '{print $2}')" ]
      if [ $? -ne 0 ] ; then
       echo "WARNING: File decrypted but hashes do NOT match. File is possibly compromised!!"
      else
       echo "INFO: File decrypted and hashes DO match"
      fi
      [ -f "/tmp/$FILENAME" ] && cat "/tmp/$FILENAME" && rm "/tmp/$FILENAME" > /dev/null 2>&1 && exit 0
     ;;
     'dec-write')
      openssl enc -in "$FILE" -out "/tmp/$FILENAME" -d -md "${DIGEST}" -"${CIPHER}" 2>/dev/null
      [ $? -ne 0 ] && echo "FATAL_ERROR: Wrong password and/or wrong algorithm provided and/or $FILE is not encrypted at all!" && exit 1
      [ "$(openssl dgst -$DIGEST /tmp/$FILENAME 2>/dev/null | awk -F'= ' '{print $2}')" = "$(cat ${FILE}.hash | awk -F'= ' '{print $2}')" ]
      if [ $? -ne 0 ] ; then
       echo "WARNING: File decrypted but hashes do NOT match. File is possibly compromised!!"
      else
       echo "INFO: File decrypted and hashes DO match"
      fi
      [ -f "/tmp/$FILENAME" ] && mv "/tmp/$FILENAME" "$FILE" > /dev/null 2>&1 && exit 0
     ;;
    esac
  7. Avatar von >dev/null
    Coole Sache funzt einwandfrei. Super !