# Sicheres Login-System für App implementieren



## Minilulatsch (13. Jun 2016)

Hallo liebe Community,

ich bin aktuell eine Android-App am programmieren, genauer gesagt eine Client-Server-Anwendung. Dabei sollen sich die Nutzer über zuvor angelegte Konten beim Server anmelden können. Das ganze soll natürlich sicher ablaufen, da ich allerdings doch eher ein Anfänger bin, hätte ich einige grundsätzliche Fragen, wie man ein solches Login-System implementieren soll, damit die Zugangsdaten auch wirklich sicher ausgetauscht und gespeichert werden.

Also, angenommen die Client-App baut über TCP eine Verbindung zum Server auf. Nun meldet sich ein Nutzer mit seinem Nutzernamen und Passwort an, beides wird verschlüsselt zwischen Client und Server ausgetauscht. Zum Verschlüsseln hatte ich gedacht RSA zu benutzen. Also wird z.b das Passwort mit dem Public RSA-Key verschlüsselt und übertragen. Das verschlüsselte Passwort wird nun am Server entschlüsselt, gehasht und dann mit dem gespeicherten Hash des Nutzers in der Datenbanken verglichen. Stimmen sie überein, wird der Nutzer eingeloggt. Mein Problem liegt jetzt bei Folgendem: Ein Angreifer im Netzwerk könnte die Übertragung des Verschlüsselten Passworts ja mitlesen. Nun könnte er mit einer selbst erstellen Dritt-App das verschlüsselte Passwort ja direkt an den Server senden, ohne es vorher nochmal mit dem Public RSA-Key zu verschlüsseln. Der Server würde das verschlüsselte Passwort wieder bearbeiten und akzeptieren. Im Endeffekt würde das ja heißen, dass das verschlüsselte Passwort mit einer Dritt-App genau so benutzt werden könnte, wie das Klartext-Passwort bei der eigentlichen App, wobei die Sicherheit durch die Verschlüsselung hinfällig wäre. Hab ich einen Denkfehler bei dieser Vorgehensweise, sodass das Problem gar nicht besteht? Und wenn nicht, wie müsste eine Implementierung gestaltet sein, damit der Login, auch wenn er von dritten mitgelesen wird, nicht reproduziert werden kann.

Ich hoffe, dass Ihr für mich ein bisschen Licht ins dunkle bringen könnt.

LG Minilulatsch


----------



## Thallius (13. Jun 2016)

Die Frage ist warum du das Rad neu erfinden willst. Das was du suchst gibt es fertig und nennt sich HTTPS.
Weiterhin solltest du niemals das Passwort übers Netz schicken auch nicht verschlüsselt, sondern immer nur den Hash des Passwortes.

Gruß

Claus


----------



## mrBrown (13. Jun 2016)

Thallius hat gesagt.:


> Weiterhin solltest du niemals das Passwort übers Netz schicken auch nicht verschlüsselt, sondern immer nur den Hash des Passwortes.



Was in 99% der Fälle genauso sicher/unsicher ist


----------



## Thallius (14. Jun 2016)

mrBrown hat gesagt.:


> Was in 99% der Fälle genauso sicher/unsicher ist



Jein, wenn Password vershlüsselt verschickt wird und irgendjemand entschlüsselt es, weil sich der Programmierer dumm angestellt hat, dann kann dieser ja nicht nur auf dieser Seite meinen Account benutzen sondern alle auf denen ich das gleiche Passwort benutze. Mit dem Hash kann er auf anderen Seiten nichts anfangen.

Gruß

Claus


----------



## Minilulatsch (14. Jun 2016)

Erstmal danke für eure Antworten. Es ist natürlich wenn man das Rad auch benutzt, das schon erfunden wurde^^. Aber gerade als Anfänger hab ich Interesse daran zu wissen, wie man das Konzept für sowas bei Bedarf selber gestalten könnte. Aber ich hab mir dann jetzt doch mal ein bisschen was zu SSL in Java angeguckt und werde mal versuchen daraus was vernünftiges zu basteln. Danke für eure Hilfe!

LG Minilulatsch


----------



## Bitfehler (15. Jun 2016)

Nach Möglichkeit sollte die Verbindung explizit über TLS1.2 erfolgen.
Mit Hilfe eines Salts könnte man noch die Entropie erhöhen.


----------



## Tobse (16. Jun 2016)

Thallius hat gesagt.:


> Jein, wenn Password vershlüsselt verschickt wird und irgendjemand entschlüsselt es, weil sich der Programmierer dumm angestellt hat, dann kann dieser ja nicht nur auf dieser Seite meinen Account benutzen sondern alle auf denen ich das gleiche Passwort benutze. Mit dem Hash kann er auf anderen Seiten nichts anfangen.
> 
> Gruß
> 
> Claus


Da stimme ich dir zu. Wenn es hier aber um Security Best-Practices geht, dann doch bitte eine Challenge-Response über HTTPS. Und wenn man fancy drauf ist kann man mit dem ersten Login auch einen Geräte-Spezifisches Keypair beim Server registrieren; alle weiter Authentifizierung läuft dann über das in TLS eingebaute Client-Certificate. Letzteres ist aber für die meisten Fälle ein ziemlicher overkill....

@TE:
Ein Challenge-Response funktioniert folgendermaßen:

```
# User gibt Username und Passwort in das Login-Formular ein und klickt "Login"
Client -> Server: Ich möchte mich gerne mit dem Account XY anmelden.
Server -> Client: Ok. Hier ist ein Challenge-Code ABCD
Client -> Server: HMAC(HASH(eingegebenesPasswort), ABCD)
# Server prüft ob HMAC(HASH(richtigesPasswort), ABCD) identisch ist mit dem gesendeten Passwort; je nach Ergebnis... u.s.w.
```

Wichtig ist hierbei, dass der Server auch nur den Hash des Passworts speichert (siehe Argument von Claus im Fall dass dein Server gehackt wird). Und es ist wichtig, dass der Challenge-Code *für jeden Login *neu und zufällig generiert wird (siehe dazu *java.security.SecureRandom*; _auf keinen Fall Math.random() oder java.math.Random benutzen!_)


----------

