# Passwort verschlüsseln



## internet (9. Jun 2010)

Hallo,
ich habe folgendes Problem:

ich habe eine Anwendung geschrieben.
Datenbank ist MySql.

Bisher wird das Passwort eines Users unverschlüsselt in die Datenbank geschrieben.
Nun möchte ich gerne eine Methode schreiben, die mir das Passwort verschlüsselt.
Und ich dieses verschlüsselte Passwort dann in die Datenbank schreibe.

Zudem benötige ich dann auch eine Methode, die das Passwort wieder umwandelt (beim einloggen zB)

Gibt es hierfür irgendwelche vorgefertigten Methoden?
MfG


----------



## Tomate_Salat (9. Jun 2010)

internet hat gesagt.:


> die mir das Passwort verschlüsselt.
> Und ich dieses verschlüsselte Passwort dann in die Datenbank schreibe.



[c]INSERT INTO users (user,pass) VALUES ('foo',md5('bar'))[/c]

oder MD5 in Java nachschreiben. Unter google findest du fertige algorythmen dazu



internet hat gesagt.:


> Zudem benötige ich dann auch eine Methode, die das Passwort wieder umwandelt (beim einloggen zB)



Falscher weg: verschlüssel das Passwort beim Login auch als MD5 und prüfe diese 32-Stelligen Zeichenketten gegeneinander

*Anmerkung*
[c]SELECT md5( "hallo" )[/c] => bekommst du den md5-code von "hallo". Würde aber zum gegenprüfen lieber den MD5-code im Java erstellen.

*Anmerkung2*
Ja EikeB hat meins schön ergänzt. Natürlich prüfst du das am geschicktesten im 
[c]SELECT * from user WHERE user = md5('foo')[/c]
zu SHA1 kann ich nix sagen. Ich Benutze hierfür gerne md5

MFG

Tomate_Salat


----------



## Foermchen82 (9. Jun 2010)

Das Passwort jetzt verschlüsselt in die DB zu schreiben ist schon mal Prima!!

Ein Passwort verschlüsselt in die DB zu schreiben und dann wieder entschlüsseln zu wollen ist auch nicht ganz so toll. Denn die Anwendung sollte eigentlich nie die Möglichkeit haben dir dein PW zu entschlüsseln. Das ist immer ein Sicherheitsleck.
Besser ist folgender Ansatz:

Bilde aus deinem PW einen Hash, den du in die DB schreibst. Die Eingabe des Users wandelst du dann auch in einen Hash um und vergleichst die beiden Hashs. Somit bekommst du einen Verschlüsselte Prüfmöglichkeit.


----------



## Gast2 (9. Jun 2010)

Hi,
du könntest das Passwort als SHA1 Hash abspeichern. Da bietet dir MySQL schon fertige Methoden an.


```
"INSERT INTO users (user, pw) VALUES ('username', SHA1('meingeheimespasswort'));"
```
(hoffe die Syntax passt)

Wenn du jetzt beim einloggen prüfen willst ob das pw korrekt ist erstellt du wieder einen SHA1 Hash und vergleichst diesen mit dem in der DB.


```
"SELECT user FROM users WHERE pw = SHA1('meingeheimespasswort');"
```

Hoffe das hilft dir weiter.

EDIT: zu langsam...


----------



## Blakh (9. Jun 2010)

Als Alternative zum SQL von meinen  Vorpostern hier mal ein Beispiel mit dem SHA-256 Algorithmus zum Bilden eines Hashs in JAVA. Natürlich gibt es da noch mehr Algorithmen die MessageDigest unterstützt. 


```
import java.security.MessageDigest;

MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(passwort);
byte[] hash = md.digest()
```


----------



## Niki (9. Jun 2010)

Hier der Code für MD5 Verschlüsselung:

//EDIT da hab ich noch was vergessen

```
private static final char[] hexChars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    public static String digest(String s) throws NoSuchAlgorithmException{
      MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] b = md.digest(s.toUpperCase().getBytes());
        
        return hexStringFromBytes(b);
    }

    private static String hexStringFromBytes(byte[] b) {
        String hex = "";
        int msb;
        int lsb = 0;
        int i;

        // MSB maps to idx 0

        for (i = 0; i < b.length; i++) {

            msb = ((int) b[i] & 0x000000FF) / 16;

            lsb = ((int) b[i] & 0x000000FF) % 16;
            hex = hex + hexChars[msb] + hexChars[lsb];
        }
        return (hex);
    }
```


----------



## Tomate_Salat (9. Jun 2010)

@Niki: Wenn er es im Select prüft, braucht er das nicht einmal


----------



## Niki (9. Jun 2010)

stimmt schon, aber schaden tut der code ja auch nicht


----------



## internet (9. Jun 2010)

ist SHA 2 nicht deutlich besser?


----------



## Gast2 (9. Jun 2010)

Das war auch nur als Beispiel gedacht. MySQL sollte auch den Befehl SHA2() kennen, kannst du dann einfach ersetzen


----------



## Tomate_Salat (9. Jun 2010)

wieso sollte SHA 2 den deutlich besser sein? Oo. Ich weis nicht welche besser ist, aber ich bezweifle, dass es da einen deutlichen Unterschied gibt.


----------



## internet (9. Jun 2010)

was ist denn allgemein besser:

das über die Datenbank überprüfen und ein insert darüber zu machen?

Oder eben eine Methode in JAVA zu schreiben?


----------



## internet (9. Jun 2010)

Tomate_Salat hat gesagt.:


> wieso sollte SHA 2 den deutlich besser sein? Oo. Ich weis nicht welche besser ist, aber ich bezweifle, dass es da einen deutlichen Unterschied gibt.



MD5 ist nicht annähernd so sicher wie SHA2


----------



## Blakh (9. Jun 2010)

Hm ... ich bin kein Experte darin, aber ich denke, dass ist Geschmackssache. Wenn du das per insert machst, hat der Datenbankserver die Last, wenn du es per Methode machst, dann der Client.


----------



## Janus (9. Jun 2010)

Es sollte immer der Client verschlüsseln, um zu verhindern, dass das Kennwort als Klartext übertragen wird.


----------



## internet (9. Jun 2010)

habe hier eine Methode gefunden:
passt das so?
Warum ein String-Array als Parameter?



```
import java.security.*;
 
public class cryptotest {
    public static void main(String[] args) throws NoSuchAlgorithmException {
        MessageDigest md;
        String message = "password";
        try {
            md= MessageDigest.getInstance("SHA-512");
 
            md.update(message.getBytes());
            byte[] mb = md.digest();
            String out = "";
            for (int i = 0; i < mb.length; i++) {
                byte temp = mb[i];
                String s = Integer.toHexString(new Byte(temp));
                while (s.length() < 2) {
                    s = "0" + s;
                }
                s = s.substring(s.length() - 2);
                out += s;
            }
            System.out.println(out.length());
            System.out.println("CRYPTO: " + out);
 
        } catch (NoSuchAlgorithmException e) {
            System.out.println("ERROR: " + e.getMessage());
        }
    }
}
```


----------



## Gast2 (9. Jun 2010)

Weils die main-Methode ist


----------



## internet (9. Jun 2010)

achso ok, 
wie sähe es ohne der Main - Methode aus?


----------



## Niki (9. Jun 2010)

ungetestet:

```
public static String digest(String message) throws NoSuchAlgorithmException {
        MessageDigest md;
        String out = "";
      
            md= MessageDigest.getInstance("SHA-512");
 
            md.update(message.getBytes());
            byte[] mb = md.digest();
            
            for (int i = 0; i < mb.length; i++) {
                byte temp = mb[i];
                String s = Integer.toHexString(new Byte(temp));
                while (s.length() < 2) {
                    s = "0" + s;
                }
                s = s.substring(s.length() - 2);
                out += s;
            }          
 
        
        return out;
}
```


----------



## internet (9. Jun 2010)

prima!
Klappt.
Eine Frage noch:
muss die Methode UNBEDINGT static sein?
Da ich die Methode in einer anderen Bean aufrufe, als in der die Funktion ist.


----------



## Niki (9. Jun 2010)

nein muss sie nicht sein. die methode hat halt keinen Bezug zu einem Objekt. Daher static.


----------



## Blakh (9. Jun 2010)

Janus hat gesagt.:


> Es sollte immer der Client verschlüsseln, um zu verhindern, dass das Kennwort als Klartext übertragen wird.



Oh Gott, stimmt .... hab ich ganz vergessen. Es ist also die Methodenvariante vorzuziehen .


----------



## Wortraum (10. Jun 2010)

Tomate_Salat hat gesagt.:


> wieso sollte SHA 2 den deutlich besser sein? Oo. Ich weis nicht welche besser ist, aber ich bezweifle, dass es da einen deutlichen Unterschied gibt.


Auf Anhieb fallen mir drei Gründe ein:
1) SHA2 kann größere Datenmengen verarbeiten.
2) SHA2 kann Streuwerte in vier verschiedenen Längen erzeugen.
3) Von SHA2 wird nicht abgeraten, und es gibt noch keine bekannte Möglichkeit, die Kollisionsberechnung so weit zu vereinfachen, daß sie für die Praxis bereits am Horizont zu erkennen ist.

Solang man nur den Streuwert speichert, egal ob nun MD5, SHA1 oder SHA2, ist es aber sowieso egal, da kann man auch Klartext nehmen. Gegen Angriffe mittels Regenbogentabellen ist mindestens noch Salz oder eine ordentlich Anzahl Iterationen notwendig. Außerdem möchte man eigentlich nicht, daß gleiche Kennwörter zweier Benutzer sofort am gleichen Streuwert erkennbar sind.

Also das Kennwort nehmen, ein wenig salzen mit Benutzername oder, besser noch, einer zufälligen Zeichenkette, das ganze hübsch durch SHA2 jagen, je nach Belieben auch 5000 mal, und dann ab damit in die Datenbank.


----------

