# KeyGenerator not available:



## Ulathar (2. Sep 2011)

Hallo,

ich versuche gerade einen String (ein Passwort) zu verschlüsseln, um es "halbwegs sicher" in einer Datei speichern zu können. Halbwegs sicher bedeutet dabei dass es nicht mehr auf den ersten Blick lesbar sein soll.

Da ich sowas zum ersten mal mache, hangel ich mich am Oracle Beispiel entlang und verfolge dabei diesen Ansatz: 


```
KeyGenerator kgen = KeyGenerator.getInstance("SHA");
kgen.init(128); // 192 and 256 bits may not be available

// Generate the secret key specs.
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();

SecretKeySpec skeySpec = new SecretKeySpec(raw, "SHA");

// Instantiate the cipher
Cipher cipher = Cipher.getInstance("SHA");

cipher.init(Cipher.ENCRYPT_MODE, skeySpec);

byte[] encrypted = cipher.doFinal(message.getBytes());
System.out.println("encrypted string: " + asHex(encrypted));

cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] original = cipher.doFinal(encrypted);
String originalString = new String(original);
System.out.println("Original string: " + originalString + " " + asHex(original)); 
[/Java]

Ich erhalte jedoch, ganz egal was ich als Algorithmus auswähle immer direkt in Zeile 1 folgende Exception:

[code]java.security.NoSuchAlgorithmException: SHA KeyGenerator not available
```

Habe schon AES, DSA, SHA, SHA-512 und weiß nich was noch probiert, immer mit dem selben Ergebnis... Jemand ne Idee wo mein Fehler liegt?


----------



## nillehammer (2. Sep 2011)

Ich hab auch grad mit Deinem Code rumgespielt. Mit dem selben Ergebnis. Ich kann Dir dafür also keine Lösung anbieten, aber eine sehr einfach zu benutzende Alternative. Und zwar Codec von Apache Commons (Codec - Home). Dort gibt es die Klasse DigestUtils (DigestUtils (Commons Codec 1.4 API)). Damit wird Deine Anforderung zum Einzeiler, z.B.

```
// MD5
final String pwMd5 = DigestUtils.md5Hex("geheim");

// Oder doch lieber sha256
final String pwSha256 = DigestUtils.sha256Hex("geheim");
```


----------



## bERt0r (2. Sep 2011)

Naja, MessageDigest ist eine einweg Hash-Funktion. Ich schätze aber mal, dass du das passwort dann auch wieder aus der Datei auslesen willst, also wird MessageDigest hier nicht zum Ziel führen.

Hast du diese Algorithmus-Strings schon probiert?
Standard Algorithm Name Documentation


----------



## nillehammer (2. Sep 2011)

bERt0r hat gesagt.:
			
		

> Naja, MessageDigest ist eine einweg Hash-Funktion. Ich schätze aber mal, dass du das passwort dann auch wieder aus der Datei auslesen willst, also wird MessageDigest hier nicht zum Ziel führen.


Das Gegenteil ist Richtig. Der übliche Weg bei Passwortverschlüsselung ist nämlich Einwegverschlüsselung. Man speichert den Digest des Passworts. Wenn der Nutzer dann später ein Passwort eingibt, wird von dieser Eingabe ebenfalls der Digest gebildet und mit der gespeicherten Version verglichen. Sind diese gleich, war das eingegebene Passwort korrekt.


----------



## TheRealSpikee (2. Sep 2011)

FAIL

Natürlich kannst du mit SHA nicht "verschlüsseln" weil SHA ein HASH-Algorythmus ist.

Der von dir gepostete Code sollte aber mit AES problemlos funktionieren.


Wobei mein vor-poster recht hat : das Passwort in der Regel gehashed *hashen hat hier nichts mit verschlüsselen zu tun* und bei abfrage nur der Hash geprüft. Das nennt man Challenge-Response. Dabei ist es nicht das Ziel das Geheimnis selbst offen zu legen sondern lediglich zu beweisen das man das Geheimnis kennt.


----------



## bERt0r (2. Sep 2011)

HmacSHA1 HmacSHA256 HmacSHA384 HmacSHA512 	Keys generator for use with the various flavors of the HmacSHA algorithms. 

Hier gleich von Fail zu reden find ich ein bisschen hart.

@nillehammer: Hast schon recht, aber was der TO damit anstellen will können doch weder du noch ich wissen :bae:.


----------



## Ulathar (2. Sep 2011)

TheRealSpikee hat gesagt.:


> FAIL
> 
> Natürlich kannst du mit SHA nicht "verschlüsseln" weil SHA ein HASH-Algorythmus ist.







> Habe schon AES, DSA, SHA, SHA-512 und weiß nich was noch probiert, immer mit dem selben Ergebnis... Jemand ne Idee wo mein Fehler liegt?



Es ist nicht so, als hätt ich die anderen Algos nicht schon probiert, wie ich oben erwähnt habe. Er scheint rein garnix davon zu fressen.

@Anderen Vorposter:
Danke für die Vorschläge.
Ja ich will/muss das codiert gespeicherte Passwort zu einem späteren Zeitpunkt auch wieder aus der Datei auslesen und in seinen originalzustand zurückversetzen.
Es muss auch nicht mal komplex verschlüsselt werden, es sollte nur nicht mehr im Klartext in der Datei stehen.


Edit:
@bERt0r

Was ich damit machen will: 
User A sitzt an PC X wo mein Programm läuft. User A loggt sich auf eine Datenbank mit meinem Programm ein und will die Login-Daten speichern.
User A geht nach Hause und User B sitzt an PC X und benutzt ebenfalls mein Programm.
Jetzt will ich nicht, dass user B binnen 1 Sekunde das Passwort von User A im Klartext in der db.ini (welche die Login-Daten speichert) auslesen kann.
Dann könnt ich bei der DB gleich als password password setzen .


hier noch mal die komplette exception mit der "AES" variante:


```
java.security.NoSuchAlgorithmException: AES KeyGenerator not available
	at javax.crypto.KeyGenerator.<init>(DashoA13*..)
	at javax.crypto.KeyGenerator.getInstance(DashoA13*..)
	at tools.StringTools.encodeString(StringTools.java:135)
	at gui.Connector.login(Connector.java:176)
	at gui.Connector.access$0(Connector.java:175)
	at gui.Connector$1.actionPerformed(Connector.java:150)
	at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
	at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
	at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
	at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
	at java.awt.Component.processMouseEvent(Component.java:6267)
	at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
	at java.awt.Component.processEvent(Component.java:6032)
	at java.awt.Container.processEvent(Container.java:2041)
	at java.awt.Component.dispatchEventImpl(Component.java:4630)
	at java.awt.Container.dispatchEventImpl(Container.java:2099)
	at java.awt.Component.dispatchEvent(Component.java:4460)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4577)
	at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238)
	at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
	at java.awt.Container.dispatchEventImpl(Container.java:2085)
	at java.awt.Window.dispatchEventImpl(Window.java:2478)
	at java.awt.Component.dispatchEvent(Component.java:4460)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
```


Die Zeile "at tools.StringTools.encodeString(StringTools.java:135)"
ist dabei folgende:


```
KeyGenerator kgen = KeyGenerator.getInstance("AES");
```

Aber das hatte ich ja oben schon gepostet... Ich verwende btw Java 1.6_u24 (64 Bit).

Das Oracle Tutorial das ich oben erwähnte is btw hier:
Using AES with Java Technology


----------



## bERt0r (2. Sep 2011)

Aus meinem Link:

```
The following algorithm names can be specified when requesting an instance of KeyGenerator.

Alg. Name 	Description
AES 		Key generator for use with the AES algorithm.
ARCFOUR 	Key generator for use with the ARCFOUR (RC4) algorithm.
Blowfish 	Key generator for use with the Blowfish algorithm.
DES 		Key generator for use with the DES algorithm.
DESede 		Key generator for use with the DESede (triple-DES) algorithm.
HmacMD5 	Key generator for use with the HmacMD5 algorithm.
HmacSHA1 HmacSHA256 HmacSHA384 HmacSHA512 	Keys generator for use with the various flavors of the HmacSHA algorithms.
RC2 		Key generator for use with the RC2 algorithm.
```

Diese Strings hast du wirklich schon alle durchprobiert?


----------



## Ulathar (2. Sep 2011)

jap, resultieren alle in der selben Fehlermeldung.
Deshalb frag ich ja hier .


----------



## Andi_CH (2. Sep 2011)

Ich würde mal nachschauen ob javax auch korrekt installiert ist.


```
import java.security.NoSuchAlgorithmException;
import javax.crypto.KeyGenerator;

public class Test {

	public static void check(String algo) {
		try {
			KeyGenerator kgen = KeyGenerator.getInstance(algo);
			System.out.println("OK Mit algo = " + algo);
		} catch (NoSuchAlgorithmException e) {
			System.out.println("Exception mit algo = " + algo);
		}
	}
	public static void main(String[] args) {
		check("AES");
		check("ARCFOUR");
		check("Blowfish");
		check("SHA");
		check("blabla");
	}
}
/*
 * Output:
 * OK Mit algo = AES
 * OK Mit algo = ARCFOUR
 * OK Mit algo = Blowfish
 * Exception mit algo = SHA
 * Exception mit algo = blabla
 */
```

Beispiel für eine Exception:

```
java.security.NoSuchAlgorithmException: SHA KeyGenerator not available
	at javax.crypto.KeyGenerator.<init>(DashoA13*..)
	at javax.crypto.KeyGenerator.getInstance(DashoA13*..)
	at com.javaforum.Test.check(Test.java:10)
	at com.javaforum.Test.main(Test.java:21)
```


----------



## TheRealSpikee (2. Sep 2011)

also ich weis zwar nicht genau WAS das problem ist ... fakt ist jedoch das es DEIN problem ist ... denn das hier läuft bei mir sauber durch ...


```
import java.security.*;
import java.security.spec.*;
import java.security.interfaces.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import javax.crypto.interfaces.*;
public class KeyGenTest
{
	public static void main(String[] args) throws Exception { new KeyGenTest(); }
	public KeyGenTest() throws Exception
	{
		String message="TEST";
		
		KeyGenerator kgen = KeyGenerator.getInstance("AES");
		kgen.init(128); // 192 and 256 bits may not be available
		 
		// Generate the secret key specs.
		SecretKey skey = kgen.generateKey();
		byte[] raw = skey.getEncoded();
		 
		SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
		 
		// Instantiate the cipher
		Cipher cipher = Cipher.getInstance("AES");
		 
		cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
		 
		byte[] encrypted = cipher.doFinal(message.getBytes());
		System.out.println("encrypted string: " + asHex(encrypted));
		 
		cipher.init(Cipher.DECRYPT_MODE, skeySpec);
		byte[] original = cipher.doFinal(encrypted);
		String originalString = new String(original);
		System.out.println("Original string: " + originalString + " " + asHex(original));
	}
	public String asHex (byte buf[]) {
      StringBuffer strbuf = new StringBuffer(buf.length * 2);
      int i;

      for (i = 0; i < buf.length; i++) {
       if (((int) buf[i] & 0xff) < 0x10)
	    strbuf.append("0");

       strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
      }

      return strbuf.toString();
     }

}
```

beachte algo : AES

ich würd sagen das hier was mit deinem JDK / JRE nich stimmt


----------



## freez (2. Sep 2011)

Ulathar hat gesagt.:


> Ja ich will/muss das codiert gespeicherte Passwort zu einem späteren Zeitpunkt auch wieder aus der Datei auslesen und in seinen originalzustand zurückversetzen.



Darf ich fragen, warum du das benötigst? Ich kenne wenige, bis gar keine Fälle, wo sowas wirklich benötigt wird. Solange deine Anwendung die Möglichkeit bietet das Passwort SICHER zurückzusetzen, wird der Anwender immer in das System kommen. Und wenn deine Anwendung sauber designt wurde, muss auch kein anderer User den Account eines Users nutzen, um an bestimmte Daten zu kommen.

Normalerweise hinterlegt man das Passwort wie nillehammer es beschrieben hatte. Hash vom Passwort erzeugen und speichern. Beim login das Passwort hashen und die beiden hashes vergleichen. Wenn gleich, dann login.
Ich gehe in der Regel noch einen Schritt weiter ... ich versalze das Passwort vor dem Hashen: 
	
	
	
	





```
String hashedpasswort = hash("irgendeinString-ö83465shhdknstt" + username + passwort);
```
 und speichere dies so. Beim login mache ich das selbe und vergleiche die beiden Hashes.

Siehe auch: Salt (Kryptologie) ? Wikipedia


----------



## Ulathar (2. Sep 2011)

@Andi_CH:
Was ist an deinem vorgeschlagenen Code nun anders als an meinem oben geposteten Test? Die fehlermeldungen für alle Algos sind die selben.

@TheRealSpikee:
ja das meine ich ja die ganze zeit, ich habe keine ahnung wieso es NICHT funktioniert obwohl es funktionieren müsste. Welche SDK version benutzt du denn wenn ich fragen darf? 

@freez:
das ist mir aber nicht möglich, da ich auf die Datenbank keinen Zugriff habe. mein Programm verbindet über JDBC mit einer Datenbank und dazu muss ich das übermittelte Password vorher wieder "rekonstruieren".



EDIT:

Okay es liegt am 64 Bit SDK. Wenn ich es mit x86er JDK ausführe klappt es. Verdammt. Es muss aber mit beiden funktionieren....

Edit 2:
ich sehe gerade, dass mein 32 Bit JDK 1.6.0_u22 ist und mein 64 Bit JDK nur 1.6.0_u20.
Ich update beides mal eben auf u27 und versuchs noch mal, auch wenn ich nicht glaube, dass es daran liegt, sondern eher am 64 Bit JDK generell, weiß da jemand genaueres zu?


----------



## nillehammer (2. Sep 2011)

> @freez:
> das ist mir aber nicht möglich, da ich auf die Datenbank keinen Zugriff habe. mein Programm verbindet über JDBC mit einer Datenbank und dazu muss ich das übermittelte Password vorher wieder "rekonstruieren".


Ahh so langsam komme ich dahinter. Du willst garnicht Nutzerpasswörter verschlüsselt ablegen? Das könntest Du nämlich auch in der Datenbank. Was Dich stört, ist dass in Deinen jdbc-Einstellungen das DB-Passwort im Klartext drinnen steht? Da kann ich nur sagen, lass Dich davon nicht stören. Das ist halt so.



			
				Ulathar hat gesagt.:
			
		

> Okay es liegt am 64 Bit SDK. Wenn ich es mit x86er JDK ausführe klappt es. Verdammt. Es muss aber mit beiden funktionieren....


Stimmt, das benutze ich auch! Verdammt. Aber egal, ich brauche die Funktion ja nicht, sondern hab es gestern nur mal ausprobiert...


----------



## Ulathar (2. Sep 2011)

jau das problem is halt, das bis zu ~20 studenten mein tool benutzen (werden) oft an den selben Rechnern mit der selben Datenbank aber unterschiedlichen Logins (logisch).
Und man kennt ja das problem, dass leute für 100 verschiedene sachen 1 und das selbe PW haben und daher will ich es vermeiden, dass Student A das Passwort von Student B aus der server.ini einfach im klartext auslesen kann.

Sicher, im prinzip könnts mir total wurst sein aber es geht hier ums prinzip .


*Aber die Gute Nachricht ist:*
es lag scheinbar am 1.6.0_u20 64 Bit JDK.
Jetzt mit dem neuesten 1.6.0_u27 64 Bit JDK funktioniert es! (auch mit dem 32 Bit update 27er). Java 7 ist bis auf weiteres keine Option, da die Uni-PCs noch "sehr lange" bei der 1.6er bleiben.

Gnarf ich hoffe unser Admin aner Uni pennt nich und hält java dort auch immer aktuell, sonst hab ich ein Problem .
Danke euch jedenfalls für die Mühen, das Thema is hiermit wohl gegessen. Wieder was gelernt ....


----------



## TheRealSpikee (2. Sep 2011)

@TO
rate doch mal was ich drauf habe ?
natürlich Java7 ... sowohl x86 als auch x64 ... und bei beiden läuft es ohne anstand durch ... die x64 ist sogar um einige millisekunden schneller als die x86 ... kp warum aber ist so

das java7 offiziell zwar als FINAL draußen ist ... aber eigentlich noch nur für dev's und noch nicht für die breite masse ist wissen alle ... aber dennoch sind mitlerweile die meisten bugs aus den RC-versionen behoben wurden und ein upate auf v7 ist ungefährlich ...


----------



## Ulathar (2. Sep 2011)

sag das nicht mir sondern unserem admin . ich habe da keinen einfluss drauf und er meinte zu mir, dass bis auf weiteres Java 7 gemieden wird bis es "ausgereift" ist.

Sehr viele unserer Programme die wir am Institut verwenden basieren auf Java und sind teilweise sehr komplex und wenn da dann wegen der VM was nicht klappt würde das ne menge Zeit und Geld kosten. Aber soweit ich weiß ist das Java autoupdate auf den Rechnern aktiv, also sollte auch 1.6u27 vorhanden sein und ich somit keine Probleme kriegen... Morgen mal abchecken .


----------



## TheRealSpikee (2. Sep 2011)

Hmm .. selbst wenn der jusched laufen sollte heißt das nicht das dadurch automatisch 6u27 drauf ist da der jusched kein System-Dienst mit erhöten rechten sondern lediglich durch autostart ein user-prozess ist und es daher an fehlenden rechten fehlen könnte.

"bis java ausgereift ist" ... da kann dein admin aber noch lange warten ... offiziel werden major-versionen erst mit updates jenseits der 10er marke halbwegs "ausgereift" ...


----------

