[PATCH] fhem.pl - Veränderung eines Attribut Values durch AttrFn

Begonnen von Markus Bloch, 12 Dezember 2014, 22:09:36

Vorheriges Thema - Nächstes Thema

Markus Bloch

Vielleicht wäre noch eine deletePassword() Sub sinnvoll, damit die Liste nicht mit Leichen vollgepflastert wird.
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

tupol

Soweit wie ich es durchblicke, finde ich es gut. Trennst Du key und password mit "|"? Da wird es Leute geben, die das Zeichen im Passwort oder key benutzen. Besser wäre vielleicht ein \n zum Trennen (also 2-Zeilenweise). Warum nimmst Du eigentlich xor und nicht MD5?

Gruß
tupol

Markus Bloch

Zitat von: tupol am 28 Dezember 2014, 21:00:23
Soweit wie ich es durchblicke, finde ich es gut. Trennst Du key und password mit "|"? Da wird es Leute geben, die das Zeichen im Passwort oder key benutzen. Besser wäre vielleicht ein \n zum Trennen (also 2-Zeilenweise).

Ja, da hast du wohl recht, nunja irgendwie muss man ja key und password zusammen abspeichern. Das ließe sich aber durchaus noch ändern. Ich wollte es vermeiden mit Data::Dumper eine weitere Modulabhängigkeit ins Spiel zu bringen.

Zitat von: tupol am 28 Dezember 2014, 21:00:23
Warum nimmst Du eigentlich xor und nicht MD5?

Nunja, ganz einfach. MD5 ist eine kryptographische Hashfunktion (bzw. eine Einwegverschlüsselung). Man kann sie nicht mehr entschlüsseln. Da man das Passwort aber unter Umständen in Klartextform braucht (z.B. beim FritzBox telnet Login), muss es wieder in originaler Form zur Verfügung stehen. Natürlich steht es dem Modulentwickler/User frei als Passwort einen MD5 Hash zu hinterlegen. Das macht die Sache natürlich nochmal eine Stufe sicherer. Es gibt aber dennoch Fälle in der das Passwort in originaler Form benötigt wird (z.B. um ein One-Time-Password mit der aktuellen Zeit als Komponente zu bilden).
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

Markus Bloch

#48
Hier nochmal ein Update:

Die xor-Funktionen (leicht verbessert, im Falle Digest::MD5 steht nicht zur Verfügung):

######## xor_encode ####################################################
# What    : encrypts a given string with XOR encryption
# Call    : { xor_encode("foo bar", "key") }
# Returns : "5e585816555447"
sub xor_encode($$)
{
    my ($str, $key) = @_;
   
    if(eval "use Digest::MD5;1")
    {
        $key = Digest::MD5::md5_hex(unpack "H*", $key);
        $key .= Digest::MD5::md5_hex($key);
    }

    my $enc_str = '';
    for my $char (split //, $str){
       
        my $encode = chop $key;
     
        $enc_str .= sprintf("%.2x", ord($char) ^ ord($encode ));
        $key = $encode . $key;
    }
   return $enc_str;
}


######## xor_encode ####################################################
# What    : decrypts a given string with XOR encryption
# Call    : { xor_decode("5e585816555447", "key") }
# Returns : "foo bar"
sub xor_decode($$)
{
    my ($str, $key) = @_;
   
    if(eval "use Digest::MD5;1")
    {
        $key = Digest::MD5::md5_hex(unpack "H*", $key);
        $key .= Digest::MD5::md5_hex($key);
    }

    my $dec_str = '';
    for my $char (map { pack('C', hex($_)) } ($str =~ /(..)/g)){
       
        my $decode = chop $key;
       
        $dec_str .= chr(ord($char) ^ ord($decode));
        $key = $decode . $key;
    }
   return $dec_str;
}


Die storePassword() Funktion:

$err = storePassword($index, $password);

sub storePassword($$)
{
  my ($key, $pass) = @_;
  my $passwdFile  = $attr{global}{modpath}."/FHEM/FhemUtils/passwd";
  my %passwdList = ();
 
  $key = $key->{NAME} if(ref($key) eq "HASH" and exists($key->{NAME}));

  return "empty key given" unless(length($key));
 
  if(-R $passwdFile)
  {
    my ($err, @lines) = FileRead($passwdFile);
   
    return "error while reading passwd file - $err" if(defined($err));
   
    foreach (@lines)
    {
        my $line = $_;
       
        $line = xor_decode($line, getUniqueId());
        next unless($line =~ /^.+ <-> .+$/);
     
        my ($tmpKey, $tmpPass) = split(/ <-> /, $line, 2);
        $passwdList{$tmpKey} = $tmpPass;
    }
  }
 
  $passwdList{$key} = $pass;
   
  my @string;
 
  while (my ($key, $value) = each(%passwdList))
  {
    push(@string, xor_encode($key." <-> ".$value, getUniqueId()));
  }
 
  return FileWrite($passwdFile, @string);

}


Die queryPassword() Funktion:

($err, $password) = queryPassword($index);


sub queryPassword($)
{
  my ($key) = @_;
  my $passwdFile  = $attr{global}{modpath}."/FHEM/FhemUtils/passwd";
  my %passwdList = ();
 
  $key = $key->{NAME} if(ref($key) eq "HASH" and exists($key->{NAME}));
   
  return "empty key given" unless(length($key));
 
  my ($err, @lines) = FileRead($passwdFile);

  return "error while reading passwd file - $err" if(defined($err));

  foreach (@lines)
  {
    my $line = $_;
       
    $line = xor_decode($line, getUniqueId());
    next unless($line =~ /^.+ <-> .+$/);
     
    my ($tmpKey, $tmpPass) = split(/ <-> /, $line, 2);
    $passwdList{$tmpKey} = $tmpPass;
  }
 
 
  return (undef, $passwdList{$key}) if(exists($passwdList{$key}));
  return ("no password stored", undef);

}


Beide Funktionen verwenden FileRead/FileWrite, sollten also (meiner Meinung nach) mit configDb kompatibel sein. Als Trennzeichen wird " <-> " verwendet (was eigentlich nicht wirklich in Passwörtern vorkommt), ob das das optimale ist, lässt sich sicher drüber diskutieren. Da die FileRead/FileWrite Funktionen zeilenbasiert die Datei lesen/schreiben möchte ich Index und Passwort auch gerne auf einer Zeile belassen, da es sich so einfacher pro Zeile verschlüsseln lässt und anschließend es auch einfacher ist das ganze zeilenweise einzulesen und zu verarbeiten. Man kann als Index auch $hash übergeben (sofern $hash->{NAME} existiert), dann wird $hash->{NAME} als Index verwendet.

Nachwievor gilt als Vorraussetzung: http://forum.fhem.de/index.php/topic,30528.0.html

Eure Meinung?

Viele Grüße

Markus
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

justme1968

hallo markus,

ich mag die version. habe aber einen vorschlag:

wie wäre es das file nicht zeilenweise bzw. mit separator zu schreiben sondern einen 'echten' hash mit Data::Dumper zu serialisieren und mit eval wieder einzulesen?

das ist bei der zu erwartenden anzahl an einträgen auch resourcen technisch noch lange kein problem und spart alle klimmzüge irgendwelche zeichen zu vermeiden oder zu maskieren.

ich mache das in LightScene und es funktioniert sehr gut.

gruß
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

Markus Bloch

Prinzipiell ja, ich wollte allerdings Modulabhängigkeiten vermeiden.
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

justme1968

Data::Dumper ist ein core modul und sollte immer vorhanden sein. sogar auf der fritzbox. im gegensatz zu JSON das ich sonst vorgeschlagen hätte.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

herrmannj


rudolfkoenig

Siehe http://forum.fhem.de/index.php?topic=30528

Fuer die Verwendung von xor habe ich noch keine Begruendung gesehen, und selbst kommt ich auf keine sinnvolle.

Markus Bloch

Zitat von: rudolfkoenig am 29 Dezember 2014, 09:56:28
Fuer die Verwendung von xor habe ich noch keine Begruendung gesehen, und selbst kommt ich auf keine sinnvolle.

Nunja, es war als weiter Sicherheitsstufe gedacht, damit Passwörter nicht so ohne weiteres im Klartext gespeichert werden (zumindest in den Fällen, in denen das nötig ist). Bei der FritzBox brauche ich das Passwort im Klartext und ich wollte es ungern in Klartextform in einer Datei speichern, wo man es einfach rauslesen kann.
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

rudolfkoenig

Ich teile deine Argumentation nicht, da ich die Anwender nicht in falscher Sicherheit wiegen will. Lieber sieht der Benutzer direkt, dass da Passwoerter sind, und schuetzt die Daten. Ich will dich nicht davon abhalten, selbst auf xor zu setzen, ich will das aber nicht als "offiziell gewuenscht" propagieren.

tupol

Mir wäre die Verschlüsselung ganz recht. Zwar ist sie leicht knackbar aber nur mit Insiderwissen. Außerdem ist fhem bei mir über samba zugänglich und irgendwann kommen auch die Kinder drauf, dort mal nach dem Passwort für die Fritzbox zu forschen. (Kindersicherung :) Durch die Verschlüsselung habe ich wieder ein paar Monate Vorsprung :-)

Markus Bloch

Mein Plan wäre es, das Passwort auch verschlüsselt abzulegen. Sofern es keine einheitliche Methode dafür in FHEM gibt, würde ich die xor-Funktionen modulspezifisch in FB_CALLMONITOR einbauen.
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

tupol

Wie gerade per PN geschrieben:
GANZ WICHTIG. Der Device-Name (Nicht der Modulname)  ;) muss ein dritter Parameter in der Funktion sein. Dann kann kein Entwickler versehentlich die Passwörter anderer Module ändern, weil er den selben Key benutzt und sich nicht richtig eingelesen hat. Das sollte nicht über den key allein passieren sondern über einen weiteren Parameter.

justme1968

das ist nicht wirklich eine gute idee. dann funktioniert rename nicht mehr.

wir reden nicht von einem hoch sicherheits system. wenn du anderen modulen nicht traust hash du ein ganz anderes problem.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968