rund um MessageDigest

Status
Nicht offen für weitere Antworten.
R

rookie

Gast
Hallo,

wollte eigentlich selber draufkommen 8) aber ich hab so meine Probleme damit. ???:L
Es geht um eine Umsetzung der folgenden in Perl geschriebenen Zeilen nach Java:

Code:
sub setMD5pw{
	my $pw = md5_hex("passwort");
	$pw = md5_hex("$pw.$rnd");
	return($pw);
}

Doc zum Perlmodul: http://aspn.activestate.com/ASPN/docs/ActivePerl/lib/Digest/MD5.html

Sollte ja eigentlich kein Problem sein, allerdings verdenke ich mich immer irgendwo zwischen String, unsigned/signed byte und hex, deswegen sieht mein ATM am besten funktionierendes Stück Javacode wie folgt aus:

Code:
String mypw = "passwort";
byte[] bytepw = mypw.getBytes();
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(bytepw);
byte[] bres = md.digest();
int[] ires = new int[bres.length];
for(int i = 0; i<bres.length; i++) {
	ires[i] = bres[i] + 127;
	System.out.print(Integer.toHexString(ires[i]));
}

Das ist, gelinde gesagt, nicht so der Hit; und weil ich a-b-s-o-l-u-t nicht weiterkomme damit, brauch ich Hilfe oder einen Geistesblitz (auf letzteres warte ich seit ein paar Stunden, deswegen also ersteres).

Hat Kopfschmerzen und hofft geholfen zu werden, Rookie
 
G

Guest

Gast
oki, hatte grad einen Geistesblitz, hat sich also so gut wie erledigt
ires = bres + (bres < 0 ? 256 : 0); :oops: :wink:
 

mic_checker

Top Contributor
rookie hat gesagt.:
Hallo,

wollte eigentlich selber draufkommen 8)

Das ist schon mal gut ;)

Sollte ja eigentlich kein Problem sein, allerdings verdenke ich mich immer irgendwo zwischen String, unsigned/signed byte und hex, deswegen sieht mein ATM am besten funktionierendes Stück Javacode wie folgt aus:

Code:
String mypw = "passwort";

Du solltest Passwörter nicht in Strings speichern. Stattdessen solltest du z.B. auf ein char Array zurückgreifen.

Wo genau besteht jetzt eigentlich dein Problem?
 
R

Rookie

Gast
Wo genau besteht jetzt eigentlich dein Problem?

Mein Problem bestand eigentlich in der umsetzung/umrechnung des byte-arays wegen der kleinen Stolperfalle signed/unsigned, aber ich hab's inzwischen gelöst, danke.

Du solltest Passwörter nicht in Strings speichern. Stattdessen solltest du z.B. auf ein char Array zurückgreifen.

Warum genau bitte?
 

mic_checker

Top Contributor
Weil Strings immutable sind.

Sagen wir du speicherst dein pwd in einem String:

Code:
String my_pwd = "secret password";

Anschließend führst du gewisse Authentifizierungsmechanismen durch .... letztendlich denkst du dir: Nun überschreibe ich das Passwort noch damit es nicht mehr ausgelesen werden kann:

Code:
my_pwd = "foobar";

Nur da Strings unveränderlich sind, heisst das "secret password" nicht gelöscht wurde, sondern irgendwo im Speicher rumliegt....

Deswegen gibts in Swing ja "JPasswordField", wobei man da nicht getText() verwenden sollte, da dies einen String zurückgibt, sondern getPassword(), welches char[] zurückgibt.

Hoffe meine Ausführungen sind wo weit richtig und konnten helfen.

Ansonsten lerne ich gerne dazu und lass mich gerne eines besseren belehren ;)

Siehe auch: http://www.jforum.de/showthread.php?t=1099&page=2
 
R

rookie

Gast
.... letztendlich denkst du dir: Nun überschreibe ich das Passwort noch damit es nicht mehr ausgelesen werden kann

joa soweit hab ich schon mitgedacht(gelesen): Das geht nicht. :noe:
ein char[] kann ich also überschreiben ohne daß der alte Inhalt irgendwo im Speicher rumgammelt?

Das ganze wird, BTW, eine Konsolenanwendung (vlt irgendwann mal mit GUI) aber erstmal muß ich ja 'laufen' lernen :). getPassword() merk ich mir aber schonmal, danke.
 

mic_checker

Top Contributor
rookie hat gesagt.:
.... letztendlich denkst du dir: Nun überschreibe ich das Passwort noch damit es nicht mehr ausgelesen werden kann

joa soweit hab ich schon mitgedacht(gelesen): Das geht nicht. :noe:
ein char[] kann ich also überschreiben ohne daß der alte Inhalt irgendwo im Speicher rumgammelt?

Mit dem Beitrag wollte ich ja gerade ausdrücken das es nicht geht - da der String mit dem Passwort dann immer noch irgendwo rumliegt....

Das ganze wird, BTW, eine Konsolenanwendung (vlt irgendwann mal mit GUI) aber erstmal muß ich ja 'laufen' lernen :). getPassword() merk ich mir aber schonmal, danke.
Also wenn du das später mit GUI machst, dann solltest du wie gesagt JPasswordField nutzen, bei Konsole darauf achten das es halt nicht als String sondern char[] gespeichert wird, das kannst du immer noch überschreiben etc.
 
R

rookie

Gast
Es ist vollbracht! Aber es funktioniert nicht. Also das Programm schon (scheinbar), aber der Server akzeptiert mich nicht. :autsch:

Da die Werte die gleichen sind wie bei dem z.Z. laufenden Perlcode denk ich liegts an der Verbindung die ich versuche aufzubauen. Aber ich bin ja ein blutiger Anfänger und hab keinen Plan, bitte werft mal ein Blick drauf

Code:
class Wrap {
	
	public static byte[] tobyte(String arg) {
		return(arg.getBytes());
	}
	
	public static byte[] tobyte(int[] arg) {
		byte[] barg = new byte[arg.length];
		for(int i = 0; i < barg.length; i++) {
			barg[i] = (byte)arg[i];
		}
		return(barg);
	}
	
	public static int[] toint(String arg) {
		byte[] barg = arg.getBytes();
		int[] iarg = new int[barg.length];
		for(int i = 0; i < iarg.length; i++) {
			iarg[i] = barg[i] + (barg[i] < 0 ? 256 : 0);
		}
		return(iarg);
	}
	
	public static int[] toint(byte[] arg) {
		int[] iarg = new int[arg.length];
		for(int i = 0; i < iarg.length; i++) {
			iarg[i] = arg[i] + (arg[i] < 0 ? 256 : 0);
		}
		return(iarg);
	}
}

class Update {
	
	public static void updateip()
	throws IOException, NoSuchAlgorithmException {
		int[] salt = new int[10];
		Socket sock = new Socket("UPDATE.DYNDOMAIN", 3495);
		InputStream in = sock.getInputStream();
		for(int i = 0; i < salt.length; i++) {
			salt[i] = in.read();
		}
		int[] userid = userid(salt);
		OutputStream out = sock.getOutputStream();
		for(int i = 0; i < userid.length; i++) {
			out.write(userid[i]);
		}
	}
	
	public static String hexdig(byte[] arg)
	throws NoSuchAlgorithmException {
		String hexdig = "";
		MessageDigest md = MessageDigest.getInstance("MD5");
		md.update(arg);
		arg = md.digest();
		int[] iarg = Wrap.toint(arg);
		for(int i = 0; i < iarg.length; i++) {
			if(iarg[i] <= 0xF) {
				hexdig += "0" + Integer.toHexString(iarg[i]);
			}
			else{
				hexdig += Integer.toHexString(iarg[i]);
			}
		}
		return(hexdig);
	}
	
	public static int[] userid(int[] salt)
	throws NoSuchAlgorithmException {
		int[] pw = Wrap.toint(hexdig(Wrap.tobyte("DYNPW")));
		int[] user = Wrap.toint("DYNNAME");
		int[] domain = Wrap.toint("DYNDOMAIN");
		int[] hpw = new int[pw.length + salt.length + 1];
		for(int i = 0; i < pw.length; i++) {
			hpw[i] = pw[i];
		}
		hpw[pw.length] = Wrap.toint(".")[0];
		for(int i = pw.length + 1; i < hpw.length; i++) {
			hpw[i] = salt[i - pw.length -1 ];
		}
		int[] hashpw = Wrap.toint(hexdig(Wrap.tobyte(hpw)));
		
		int[] uid = new int[user.length + hashpw.length + domain.length + 4];
		
		for(int i = 0; i < user.length; i++) {
			uid[i] = user[i];
		}		
		uid[user.length] = Wrap.toint(":")[0];		
		for(int i = user.length + 1; i < user.length + hashpw.length + 1; i++) {
			uid[i] = hashpw[i - user.length - 1];
		}		
		uid[user.length + hashpw.length + 1] = Wrap.toint(":")[0];		
		for(int i = user.length + hashpw.length + 2;
		i < user.length + hashpw.length + domain.length + 2; i++) {
			uid[i] = domain[i - user.length - hashpw.length - 2];
		}	
		uid[user.length + hashpw.length + domain.length + 2] = Wrap.toint(":")[0];		
		uid[uid.length-1] = 0;
		for(int i = 0; i < uid.length; i++) {
			System.out.println(uid[i]);
		}
		return(uid);		
	}
}

Der nächste Schritt scheint mir eine Serverseite zu programmieren damit ich prüfen kann was da ankommt, wobei ich an dieser Stelle evtl. den selben Fehler mache wie hier und niemals draufkommen werde.
@mic_checker: Sobald das Programm macht was es soll kümmere ich mich um die Feinheiten wie PW in char[], versprochen! :D

Hab jedenfalls festgestellt daß Perl einem viel Arbeit abnimmt. :wink:
 

mic_checker

Top Contributor
Vielleicht könnte für dich die Berechnung des Hashwertes über Streams interessant sein ?

Schau dir dazu mal DigestInputStream / DigestOutputStream an.

Ansonsten werd ich mal versuchen den Code durchzuschauen ;)

Code:
   public static int[] toint(String arg) {
      byte[] barg = arg.getBytes();
      int[] iarg = new int[barg.length];
      for(int i = 0; i < iarg.length; i++) {
         iarg[i] = barg[i] + (barg[i] < 0 ? 256 : 0);
      }
      return(iarg);
   }
   
   public static int[] toint(byte[] arg) {
      int[] iarg = new int[arg.length];
      for(int i = 0; i < iarg.length; i++) {
         iarg[i] = arg[i] + (arg[i] < 0 ? 256 : 0);
      }
      return(iarg);
   }

In der ersten der beiden Methoden könntest du der Einfachheithalber nach dem byte Array die zweite Methode aufrufen...erspart dir paar Zeilen Code.

Muss mich selbst nochma in das Thema reinarbeiten...
 
G

Guest

Gast
Vielleicht könnte für dich die Berechnung des Hashwertes über Streams interessant sein ?

Schau dir dazu mal DigestInputStream / DigestOutputStream an.

Damit hab ich schon ein wenig rumprobiert, aber das will mir gleich gar nicht gelingen, irgendwie.


In der ersten der beiden Methoden könntest du der Einfachheithalber nach dem byte Array die zweite Methode aufrufen...erspart dir paar Zeilen Code.

So gesehen, hm ja, wär ich nie drauf gekommen :oops:
Es lebe strg+c, strg+v :D

Ansonsten werd ich mal versuchen den Code durchzuschauen
Vielen Dank! (und viel Glück beim int[] uid..)
 

mic_checker

Top Contributor
rookie hat gesagt.:
Damit hab ich schon ein wenig rumprobiert, aber das will mir gleich gar nicht gelingen, irgendwie.

Wenn du willst kann ich mal ein Beispiel rauskramen, müsste irgendwo hier noch eins haben - hab vor ewigen Zeiten mal so ein mini-tool gemacht zur MD5 Checksummenberechnung....

So gesehen, hm ja, wär ich nie drauf gekommen :oops:
Es lebe strg+c, strg+v :D

Hehe, naja musst du selber wissen ;)
 

rookie

Mitglied
Wenn du willst kann ich mal ein Beispiel rauskramen, müsste irgendwo hier noch eins haben - hab vor ewigen Zeiten mal so ein mini-tool gemacht zur MD5 Checksummenberechnung....

DigestOutputStream in einem anderen Kontext zu sehen ist bestimmt hilfreich, also wenn es keine allzu großen Mühen bereitet würdest Du mich damit ein Stück weit klüger (und glücklicher) machen.

Was mir ATM auch viel weiterhülfe wäre eine kurze Prüfung des OutputStream-Teils, ob ich da eventuell Werte verfälsche ohne es zu merken...

MfG Rookie
 

mic_checker

Top Contributor
Ich habe jetzt in meinen alten Sources nur etwas zu DigestInputStream gefunden.Poste es trotzdem mal. Da das aber noch zu Zeiten war wo ich eher "einfach drauf los programmiert" hab, ist das ganze mit Vorsicht zu genießen ;)

Code:
import java.io.*;
import java.security.*;

public class MD5Streams {
	private MessageDigest md5;
	private byte[] digest;
	
	public MD5Streams(String name) {
		try {
			md5 = MessageDigest.getInstance("MD5");
			do_load(name);
		} catch(NoSuchAlgorithmException ea) {
			ea.printStackTrace();
		}	
	}
	
	public static void main(String[] args) {
		if(args.length > 0) {
			MD5Streams md5 = new MD5Streams(args[0]);
		}			
	}
	
	public String toHexString(byte b) {
   	int value = (b & 0x7F) + (b < 0 ? 128 : 0);
    	String ret = (value < 16 ? "0" : "");
    	ret += Integer.toHexString(value).toUpperCase();
    	return ret;
  	}
		
	public void do_load(String name) {
		try {
			FileInputStream is = new FileInputStream(name);
			DigestInputStream mdis = new DigestInputStream(is,md5);
				
			byte[] buf = new byte[1024];
				
			while(mdis.read(buf) > 0)
				;
			
			digest = md5.digest();
		
			is.close();
		
		   for (int i = 0; i < digest.length; ++i) 
        		System.out.print(toHexString(digest[i]));		   
		 }catch(FileNotFoundException e) {
			 e.printStackTrace();
		 }
		 catch(IOException e) {
			 e.printStackTrace();
		 }
	}
}
 

rookie

Mitglied
Hmm, ist ATM für diese Sache nicht hilfreich, aber trotzdem interessant und allgemein hilfreich. Und jetzt kommt 'ne Hammer-noob-Frage:

Was macht das (b & 0x7F) in:
Code:
int value = (b & 0x7F) + (b < 0 ? 128 : 0);
¿
 

mic_checker

Top Contributor
Erstmal zu :

Code:
b & 0x7F

Hier wird eine bitweise UND-Verknüpfung durchgeführt.

0110 0110
&0111 1111
-------------
0110 0110

Diese Verknüpfung macht sich erst bei negativen Zahlen bemerkbar, z.B. bei "-36":

1101 1100
&0111 1111
-------------
0101 1100 = 92

Nun zum zweiten Teil der Anweisung:

Code:
b < 0 ? 128 : 0

Du kennst den ternären Operator? Falls nicht:
http://www.java-forum.org/de/viewtopic.php?t=11550&highlight=operator

Ganz kurz: Wenn b < 0 , dann liefert der Ausdruck 128, ansonsten 0.
 
Status
Nicht offen für weitere Antworten.

Ähnliche Java Themen

Neue Themen


Oben