# JPasswordField



## homer65 (7. Jul 2009)

Ich benutze öfters code der folgenden Art:
[Java]
JPasswordField tf1 = new JPasswordField(10);
...
tf1.getText();
[/Java]
Dann heißt es immer tf1.getText() sei deprecated. Was muß man denn stattdessen benutzen, wenn man das Passwort im Klartext bhaben möchte?


----------



## The_S (7. Jul 2009)

getPassword()


----------



## homer65 (7. Jul 2009)

Also wäre jetzt folgendes richtig:
[Java]
JPasswordField tf1 = new JPasswordField(10);
...
char[] pw = tf1.getPassword();
String passwort = new String(pw);
[/Java]
Warum so umständlich? Da hätte man doch auch einfach die getText() Methode behalten können. Oder hatt das einem tieferen Sinn, der sich mir nicht erschließt?


----------



## The_S (7. Jul 2009)

Hat nen tieferen Sinn, der sich dir scheinbar nicht erschließt. Ein String liegt komplett so und sofort auslesbar im Arbeitsspeicher => Sicherheitsrisiko.


----------



## SlaterB (7. Jul 2009)

und das char[] nicht? war das nicht eher was hinsichtlich String-Cache in Java?


----------



## The_S (7. Jul 2009)

Achja, da war was ... müsste man mal schnell recherchieren. Aufjedenfall ist es ein Sicherheitsrisiko.


----------



## Ebenius (7. Jul 2009)

SlaterB hat gesagt.:


> war das nicht eher was hinsichtlich String-Cache in Java?


Meinst Du den String-Literal-Pool? Was hat der mit dem Passwortfeld zu tun?

Ebenius


----------



## SlaterB (7. Jul 2009)

wenn einer das dumm fragt, dann kann ja jemand anders schlau glänzen,
nochmal dumm nachgefragt bringt keinen weiter 

also musste ich selber suchen:
JPasswordField auslesen - coding-board


----------



## Ebenius (7. Jul 2009)

Hat also doch nix mit caching (bzw. dem Literal-Pool) zu tun, sondern damit, dass ich das char-Array nach der Verwendung wieder bereinigen kann, der String aber unverändert darauf warten muss, dass ihn irgendwann der GC erwischt. Also trifft eher The_S' Erklärung zu. Oder hab ich das jetzt falsch verstanden?

Ebenius


----------



## SlaterB (7. Jul 2009)

> der String aber unverändert darauf warten muss, dass ihn irgendwann der GC erwischt.

es erwischt ihn nicht wegen des String-Caches

edit:
jedenfalls potentiell nicht so schnell


----------



## Gast2 (7. Jul 2009)

homer65 hat gesagt.:


> Also wäre jetzt folgendes richtig:
> [Java]
> JPasswordField tf1 = new JPasswordField(10);
> ...
> ...



aber wenn man es so macht hat man doch einen String den man auslesen kann oder?
Oder dann einfach der benutzung das char array und den string auf null setzen??


----------



## SlaterB (7. Jul 2009)

new String() ist das, was hier vermieden werden soll, das wäre also genauso schlimm, korrekt

char[] auf null setzen ist schon recht gut, sollte relativ zügig vom GC gelöscht werden,
noch besser aber die Felder im Array auf 0 setzen, das passiert nun wirklich direkt bei Codeausführung 
und mit einem leeren Array kann bis auf die Länge niemand mehr was anfangen,

String = null; kann potentiell lange Zeit nix bringen, wobei ich persönlich aber das Cachen von Strings in Java nicht im Detail kenne


----------



## Ebenius (7. Jul 2009)

SlaterB hat gesagt.:


> > der String aber unverändert darauf warten muss, dass ihn irgendwann der GC erwischt.
> 
> es erwischt ihn nicht wegen des String-Caches
> 
> ...


Sorry, dass ich das nochmal aufgreife. Was ist "String-caching"? Den Begriff kenne ich nicht und er geht auch nicht aus der Seite oben hervor. Ich kenne den Literal-Pool und mit dem hat's nichts zu tun. Bitte erklär's mir.

Nachtrag: Soweit ich weiß gibt es keine Sonderbehandlung für Strings, außer den Literal-Pool. In diesen werden nur String-Literale und mit String.intern() explizit in den Pool geworfene String-Instanzen gehalten. Der einzige logische Grund, getPassword() zu bevorzugen, ist der, das char-Array nach Verwendung mit _0_en (oder anderen Werten) zu überschreiben. Die char-Array-Referenz auf _null_ zu setzen hat genau die selbe Konsequenz wie die Referenz auf den String auf _null_ zu setzen: Irgendwann räumt der GC auf (ggf. niemals, wenn man die VM entsprechend initialisiert) und dann kann man das Passwort zu jeder Zeit aus dem Speicher lesen.

Ebenius


----------



## eRaaaa (7. Jul 2009)

Hi,

dann hab ich direkt auch noch eine Frage 
Wie und wo liegt dann das "echte" Passwort, also das, mit dem ich die Benutzereingabe überprüfen möchte? Denn wenn dieses, auch irgendwo als String vorliegt, wäre dies ja dann genauso auch Blödsinn oder?!

Gruß


----------



## Ebenius (7. Jul 2009)

eRaaaa hat gesagt.:


> wenn dieses, auch irgendwo als String vorliegt, wäre dies ja dann genauso auch Blödsinn oder?!


Ja.

Ebenius


----------



## SlaterB (7. Jul 2009)

@Ebenius:
Literal-Pool = Menge von vorhandenen String-Objeken = String-Cache

und auf die Tour sage ich nichts weiter, wenn du Argumente dagegen hast dann erkläre doch deine Sichtweise

--------

@eRaaaa
stimmt,

wie und wo liegt dann das "echte" Passwort vorliegt war bisher noch nicht das Thema,
in Sicherheitsbetonten-Programm sicher nirgendwo sondern nur der Hashwert dazu,


----------



## SlaterB (7. Jul 2009)

also, nochmal neu sortiert: 
String wie char[] werden vom GC gelöscht, wann die Zeit dafür ist, es gibt keinen Cache für die dynamisch zusammengebauten Strings,
der Literal-Pool ist nur für Strings aus dem Quellcode

der GC kann sich Zeit lassen, bei char[] hat man aber die Möglichkeit, das Array selber zu leeren (alles auf 0 setzen)

edit: wie auch in deinem Nachtrag, sag ich doch, erkläre es einfach


----------



## Ebenius (7. Jul 2009)

SlaterB hat gesagt.:


> und auf die Tour sage ich nichts weiter, wenn du Argumente dagegen hast dann erkläre doch deine Sichtweise


:autsch: Bin ich Dir auf den Schlips getreten? Das war nicht meine Absicht! Hast meinen Nachtrag oben noch gelesen?

Der Literal-Pool beinhaltet alle String-Instanzen die im ByteCode als Literal vorkommen. Dafür ist er da. Was ein Literal ist, entscheidet der Compiler. Beispiel: 
	
	
	
	





```
/** das Literal "abc" liegt im Pool */
final String s1 = "abc";

/**
 * das Literal "def" liegt im Pool, die Instanz auf die die Referenz s2
 * verweist liegt nicht im Pool
 */
final String s2 = new String("def");

/**
 * die Literale "a", "b" und "ab" liegen im Pool, da der Compiler die
 * String-Konkatenation von Literalen selbst ausführt
 */
final String s3 = "a" + "b";

/**
 * die Literale "a", "b" und "a1b" liegen im Pool, da auch 1 ein Literal ist
 */
final String s4 = "a" + 1 + "b";
```

Wenn Du aber einen Text in ein JTextComponent-Derivat eingibst, von einer URL lädst, per Random erzeugst, etc., dann handelt es sich nicht um Literale. Deswegen gibt es auch keinen Passworttext im Literal-Pool, es sei denn jemand ruft String.intern() auf dem Passwort-String auf; was natürlich niemand macht.

Ich halte die namentliche Unterscheidung zwischen einem Cache und einem Literal-Pool für sehr wichtig. Cache bedeutet, dass eine gewisse Menge an Information zeitlich oder mengenmäßig begrenzt zur Wiederverwendung vorgehalten wird. Der Literal-Pool enthält alle Literale ab ihrer ersten Verwendung; diese Literale verlassen den Pool nie wieder.

Nachtrag


> wie auch in deinem Nachtrag, sag ich doch, erkläre es einfach


Du bist einfach zu schnell.  Auch dieser Beitrag bezog sich noch auf den Vorgänger. :-D

Ebenius


----------



## SlaterB (7. Jul 2009)

habe ich ja inzwischen verstanden, siehe vorheriges Post,

und die Antwort zeigt nun genau, dass du alles dazu wußtest, viel besser als ich,
da konnte ich schon erahnen zu was deine pseudo-freundlichen 'Bitte erklär's mir.'-Postings führen:
ich erklär nochmal meine falsche Sichtweise genauer und dann kannst du sie noch genauer widerlegen

ist nicht bös gemeint, nur unnötiges Vorgehen welches mich immer total nervt


----------



## Gast2 (7. Jul 2009)

Ebenius hat gesagt.:


> :autsch: Bin ich Dir auf den Schlips getreten? Das war nicht meine Absicht! Hast meinen Nachtrag oben noch gelesen?
> 
> Der Literal-Pool beinhaltet alle String-Instanzen die im ByteCode als Literal vorkommen. Dafür ist er da. Was ein Literal ist, entscheidet der Compiler. Beispiel:
> 
> ...



also wenn ich das char array in ein String objekt umwandel und nach der Verwendung gleich einen anderen wert gebe... dann müsse es doch auch gehen oder?

```
String password = String.valueOf(char[] pas);
        use(password);
        password = "Pech gehabt";
```

klar das char array trotzdem mit 0ern überschreiben...


----------



## SlaterB (7. Jul 2009)

Obejktneuzuweisung bewirkt nicht, dass der GC das alte löscht


----------



## Gast2 (7. Jul 2009)

SlaterB hat gesagt.:


> Obejktneuzuweisung bewirkt nicht, dass der GC das alte löscht



Okay gut zu wissen...
ja aber ich versteh grad nicht was ich mit einzelnen char anfangen kann?


----------



## SlaterB (7. Jul 2009)

z.B.


```
String per MD5 hashen - gulli:board[/url]
klappt auch mit char[], den Hash kann man eher im Speicher verteilen, läßt sich hoffentlich nicht zurückrechnen

oder wenn das andere Passwort als Klartext-char[] vorliegt, dann eben direkt vergleichen,
aus einer Datei könnte man Daten ohne String als char einlesen,
wobei man dann spitzfindig evtl wieder wenig Kontrolle über interne Caches der Reader-Klassen hat,
was bei JDBC/ Hibernate möglich ist, wäre noch zu prüfen
```


----------



## Gast2 (7. Jul 2009)

Also so in etwas?Mal auf die schnelle =)


```
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.security.*;

import javax.swing.JFrame;
import javax.swing.JPasswordField;

public class MD5Test extends JFrame {

    private JPasswordField field;

    public MD5Test() {
        super();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        field = new JPasswordField(30);
        field.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                try {
                    printHash(field.getPassword().toString());
                } catch (NoSuchAlgorithmException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }

            }

        });
        add(field);
        setSize(100, 50);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    private void printHash(String s) throws NoSuchAlgorithmException {
        MessageDigest md5 = MessageDigest.getInstance("MD5");
        md5.reset();

        md5.update(s.getBytes());
        byte[] result = md5.digest();

        /* Ausgabe */
        StringBuffer hexString = new StringBuffer();
        for (int i = 0; i < result.length; i++) {
            hexString.append(Integer.toHexString(0xFF & result[i]));
        }
        System.out.println(hexString.toString());
    }

    public static void main(String[] args) {
        new MD5Test();
    }

}
```


----------



## SlaterB (7. Jul 2009)

gib das mal in der Konsole aus:
field.getPassword().toString()

aber du wirst schon noch nen Weg finden, die chars aus dem char[] zu übertragen
oder sie in ein byte[] umzuwandeln für   MessageDigest,
was da genau zu machen ist, kann ich nicht sagen, der Grundgedanke ist jedenfalls:
aus dem char[] einen Hashwert berechnen


----------



## Ebenius (7. Jul 2009)

SlaterB hat gesagt.:


> ich erklär nochmal meine falsche Sichtweise genauer und dann kannst du sie noch genauer widerlegen


Ne, so war's nicht gemeint. Ich hatte tatsächlich befürchtet, es gibt irgendwas in der Java-6-VM was aus irgendeinem Grund klüger ist und sich String-Cache nennt. Tut mir leid.

Ebenius


----------



## Ebenius (7. Jul 2009)

Umwandeln in byte[]-Array sollte so ganz schnuckelig gehen: 
	
	
	
	





```
char[] cArray = null;
final CharBuffer cBuffer = CharBuffer.wrap(cArray);
final ByteBuffer bBuffer = Charset.forName("UTF-16").encode(cBuffer);
final byte[] bArray = bBuffer.array();
Arrays.fill(cArray, '\u0000');

// ... hier den Digest ermitteln

Arrays.fill(bArray, 0);
```
Ebenius


----------



## Gast2 (7. Jul 2009)

Okay thx...


----------

