Passwort in XML wegschreiben

Status
Nicht offen für weitere Antworten.

till123

Bekanntes Mitglied
Hallo,

ich habe momentan ein kleines Problem.
Bis Dato habe ich PWs immer uncodiert in einer XML-Datei weggeschrieben.

Nun codiere ich das PW mittels RSA und das PW sieht dann wie folgt aus:
<passWord>lI(sº%Ó‹ˆÊMäg∞Íÿ^&T±ÇΩ&ª&êúAÄP^îåBÑ’x›»¨∆Åv6d≤°±5¿˜πÙ°ØjO¨z»Ò&‘9§Qpÿ3áv◊2õn√¯B¶&ÀqÆzãwXóõ‡s–wz9°Å^Ìq¬Y≈BtóY+Âu[_|k</passWord>

Das Wegschreiben funktioniert also.

Wenn ich die XML-Datei nun einlesen möchte, dann bekomme ich folgenden Fehler:

[Fatal Error] :8:21: Character reference "&#xf" is an invalid XML character.
com.thoughtworks.xstream.io.StreamException: : Character reference "&#xf" is an invalid XML character.
at com.thoughtworks.xstream.io.xml.DomDriver.createReader(DomDriver.java:86)
at com.thoughtworks.xstream.io.xml.DomDriver.createReader(DomDriver.java:66)
at com.thoughtworks.xstream.XStream.fromXML(XStream.java:861)


Habt ihr eine Idee?

Danke.
 

Campino

Top Contributor
Ich denke mal, RSA produziert irgendwo einen Wert, der vom XML- Reader als Steuerzeichen interpretiert wird, z.B. ein "<" oder ein ">".
 

till123

Bekanntes Mitglied
Habe mal nachgeschaut und nichts entsprechendes gefunden.

Und müsste ich da nicht auch schon Probleme beim Wegschreiben bekommen?

NEU:
Habe doch ein & gefunden. Ist soweit ich weiss auch ein Steuerzeichen.

Wie kann ich das denn verhindern? Eine Idee?
(Ich müsste der Verschlüsselung eine Blacklist von Zeichen mitteilen, die sie nicht verwenden darf - aber wie?)

Hier mal die Verschlüsselung:
Code:
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;

import javax.crypto.Cipher;

public class Crypt {

	private  String ALGORITHM = "RSA";
	PrivateKey privKey;
	PublicKey pubKey;
	
   public Crypt()
   {
	   try {
	   KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALGORITHM);
       keyPairGen.initialize(1024); // 1024 maximale Schluesselbreite
       KeyPair keyPair = keyPairGen.generateKeyPair();
       this.privKey = keyPair.getPrivate();
       this.pubKey = keyPair.getPublic();
	   }
	   catch (Exception e) {
		   
	   }
	   
   }
	
   private byte[] encrypt(byte[] plain) throws Exception {
      Cipher cipher = Cipher.getInstance(ALGORITHM);
      cipher.init(Cipher.ENCRYPT_MODE, pubKey);
      // verschluesseln
      return cipher.doFinal(plain);
   }

   private byte[] decrypt(byte[] chiffr)
         throws Exception {
      Cipher cipher = Cipher.getInstance(ALGORITHM);
      cipher.init(Cipher.DECRYPT_MODE, privKey);
      // Entschlusseln
      return cipher.doFinal(chiffr);
   }
   
   public String encryptPassword(String decodedPassword)
   {
	   try {
		     // Es werden die Bytes vom Text benötigt
	         byte[] bytes = decodedPassword.getBytes();

	         byte[] encrypt = encrypt(bytes);
	         
	         return (new String(encrypt));
	         
	      } catch (Exception e) {
	         return null;
	      }
	   } 
   
   public String decodePassword(String encodedPassword)
   {
	   try {
		   

	         // Es werden die Bytes vom Text benötigt
	         byte[] bytes = encodedPassword.getBytes();

	         //byte[] encrypt = encrypt(bytes);
	         byte[] decrypt = decrypt(bytes);
	         
	         return (new String(decrypt));
	         
	      } catch (Exception e) {
	         return null;
	      }
	   } 
   
   }
Oder ich müsste den Key in einer anderen Datei speichern. Gibt es einen guten Ersatz?
(Ansonsten müsste ich die Datei über Java serialisieren lassen. Dann ist das PW auch nicht ersichtlich)[/code]
 

kleiner_held

Top Contributor
Die Frage ist wie das XML geschrieben wird.
So ziemlich jedes XML Framework das ich kenne, maskiert die XML Steuerzeichen automatisch wenn man Methode wie element.setText(myText); verwendet.
Wenn man natuerlich komplett per Hand schreibt, so ala fileWriter.write("<myTag>"+myText+"</myTag>"); dann kommt ein invalides XML Dokument raus.
 

Murray

Top Contributor
Etwas ausführlicher:

Das Problem besteht darin, dass die verschlüsselten Daten keine Textdaten sind, sondern Binärdaten (eben ein Byte-Array). Wenn man die als Textdaten interpretiert (was hier passiert, denn eine XML-Datei ist nun mal eine Textdatei), dann muss das schiefgehen, weil das Byte-Array alle möglichen Zeichen enthalten kann - u.a. auch solche, die in XML besondere Bedeutung haben.

Würde es jetzt darum gehen, lediglich die für das Parsen von Tags und Entities reservierten Zeichen <,>,& zu behandeln, dann würde eine CDATA-Section reichen (die ist gedacht dafür, Textabschnitte, die reservierte Zeichen enthalten, so in der XML-Datei zu verpacken, dass der Parser diesen Bereich später nicht weiter analysiert, sondern 1:1 im DOM belässt).

Mit beliebigen Binärdaten (wie in diesem Fall) bleiben dann aber zwei Probleme:
1. Mit den hier verwendeten Konstrukten
Code:
return (new String(encrypt));
bzw.
Code:
return (new String(decrypt));
wird bei der Umwandlung von Binärdaten zu (Unicode-)Strings das Default-Encoding der Plattform verwendet. Wenn das Programm jetzt auf verschiedenen Rechnern bzw. VMs läuft, dann muss dieses Default-Encoding nicht notwendigerweise das gleiche sein, so dass u.U. das Ergebnis nicht der ursprüngliche String ist.

2. Die Binärdaten könnten - als Text interpretiert - durchaus die Sequenz "]]" enthalten - und die markiert das Ende einer CDATA-Section; damit wäre das XML wieder nicht mehr well-formed.

Deshalb wäre hier Base-64-Encoding die bessere Wahl: dabei spielt das Encoding keine Rolle mehr, und das Ergebnis enthält garantiert keine Sonderzeichen mehr, die in XML gesondert behandelt werden. Daher ist es auch nicht notwendig (allerdings auch nicht schädlich), die base-64-encodeten Daten nochmal in eine CDATA-Section zu verpacken.
 

till123

Bekanntes Mitglied
Hättest du denn mal einen guten Link für die Base-64-Encoding unter Java?
(Am Besten mit einem Bsp.)

Super. Danke für eure Hilfe.
 

Murray

Top Contributor
Ach ja, das Beispiel (weder übersetzt noch getestet):

Code:
import org.apache.commons.codec.binary.Base64;

...

final String charset = "utf-8";
final String str = "abc123äöüÄÖÜß";

System.out.println( "data:    '" + str + "'");

byte[] rawBytes =  str.getBytes( charset);

Base64 b64 = new Base64();

byte encBytes =  b64.encode( str);

String encStr = new String( encBytes, charset); //--- da encBytes keine Sonderzeichen mehr enthält, 
                                                                //-- ist die Angabe des Charsets nicht unbedingt erforderlich


System.out.println( "encoded: '" + encStr + "'");

byte[] decBytes = b64.decode( encStr.getBytes( charset)); //--- oder einfacher; b64.decode( encBytes)

String decStr = new String( decBytes, charset); //--- hier ist das Charset notwendig

System.out.println( "decoded: '" + decStr + "'");

//EDIT: Typo
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Oben