Ver- und Entschlüsselungsproblem

eolith421

Mitglied
Hallo!
Ich versuche derzeit ein Programm zu schreiben welches Daten verschlüsselt in einer DB speichert. In diesem Fall muss ich dann die verschlüsselten Daten auch wieder entschlüsseln können.
Ich habe mir dabei folgendes Konzept überlegt:
Die Anwendung hat einen öffentlichen Schlüssel der als Datei gespeichert wird. Der private Schlüssel wird zusammen mit den verschlüsselten Daten in zwei verschiedenen Tabellen in der Datenbank gespeichert. Nach einigen Recherchen habe ich dann folgenden Code erstellt (der auch fast vollständig funktioniert):
Java:
public class Crypter {
	private KeyPair keyPair;
	private String cryptMode = "RSA";
	private Cipher cipher;
	
	public Crypter() {
		try {
			KeyPair loadedKeyPair = this.LoadKeyPair(cryptMode);
			System.out.println("Loaded Key Pair");
			this.dumpKeyPair(loadedKeyPair);
			
			// Store the the key pair in the variable
			this.keyPair = loadedKeyPair;
			this.cipher = Cipher.getInstance(cryptMode);
			
		} 
		catch(java.io.FileNotFoundException e) {
			try {
				KeyPairGenerator keyGen = KeyPairGenerator.getInstance(cryptMode);

				keyGen.initialize(1024);
				KeyPair generatedKeyPair = keyGen.genKeyPair();

				System.out.println("Generated Key Pair");
				this.dumpKeyPair(generatedKeyPair);
				this.SaveKeyPair(generatedKeyPair);
				
				// Store the the key pair in the variable
				this.keyPair = generatedKeyPair;
			}
			catch (Exception innerE) {
				innerE.printStackTrace();
				return;
			}
		}
		catch (Exception e) {
			e.printStackTrace();
			return;
		}
	}
	
	public String crypt(String data) {
		try {
			cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
			
			ByteArrayOutputStream baosEncryptedData = new ByteArrayOutputStream();
	        CipherOutputStream cos = new CipherOutputStream(baosEncryptedData,
	                cipher);
	 
	        cos.write(data.getBytes("UTF-8"));
	        cos.flush();
	        cos.close();
	 
	        System.out.println("Array: "+baosEncryptedData);
	        String result = new String(baosEncryptedData.toByteArray(),"UTF-8");
	        System.out.println("Encrypted data: "+result );
	        
	        return result;
			
		} catch(InvalidKeyException e){
			e.printStackTrace();
			return null;
		} catch(UnsupportedEncodingException e){
			e.printStackTrace();
			return null;
		} catch(IOException e){
			e.printStackTrace();
			return null;
		}
	}
	
	public String decrypt(String cryptedData){
		try {
			System.out.println("String: "+cryptedData);
		
	        cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
	        CipherInputStream cis = new CipherInputStream(new ByteArrayInputStream(cryptedData.getBytes("UTF-8")), cipher);
	 
	        ByteArrayOutputStream baosDecryptedData = new ByteArrayOutputStream();
	        byte[] buffer = new byte[8192];
	        int len = 0;
	        while((len = cis.read(buffer))> 0){
	            baosDecryptedData.write(buffer,0,len);
	        }
	        baosDecryptedData.flush();
	        cis.close();
	        
	        System.out.println("Array: "+baosDecryptedData);
	        String result = new String(baosDecryptedData.toByteArray(),"UTF-8");
	        System.out.println("Decrypted data: "+result );
	        
	        return result;
			
		} catch(InvalidKeyException e){
			e.printStackTrace();
			return null;
		} catch(UnsupportedEncodingException e){
			e.printStackTrace();
			return null;
		} catch(IOException e){
			e.printStackTrace();
			return null;
		}
	}

	private void dumpKeyPair(KeyPair keyPair) {
		PublicKey pub = keyPair.getPublic();
		System.out.println("Public Key: " + getHexString(pub.getEncoded()));

		PrivateKey priv = keyPair.getPrivate();
		System.out.println("Private Key: " + getHexString(priv.getEncoded()));
	}

	private String getHexString(byte[] b) {
		String result = "";
		for (int i = 0; i < b.length; i++) {
			result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
		}
		return result;
	}

	private void SaveKeyPair(KeyPair keyPair) throws IOException {
		PrivateKey privateKey = keyPair.getPrivate();
		PublicKey publicKey = keyPair.getPublic();

		// Store Public Key.
		X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(
				publicKey.getEncoded());
		FileOutputStream fos = new FileOutputStream("public.key");
		fos.write(x509EncodedKeySpec.getEncoded());
		fos.close();

		// Store Private Key.
		PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(
				privateKey.getEncoded());
		fos = new FileOutputStream("private.key");
		fos.write(pkcs8EncodedKeySpec.getEncoded());
		fos.close();
	}

	private KeyPair LoadKeyPair(String algorithm)
			throws IOException, NoSuchAlgorithmException,
			InvalidKeySpecException {
		// Read Public Key.
		File filePublicKey = new File("public.key");
		FileInputStream fis = new FileInputStream("public.key");
		byte[] encodedPublicKey = new byte[(int) filePublicKey.length()];
		fis.read(encodedPublicKey);
		fis.close();

		// Read Private Key.
		File filePrivateKey = new File("private.key");
		fis = new FileInputStream("private.key");
		byte[] encodedPrivateKey = new byte[(int) filePrivateKey.length()];
		fis.read(encodedPrivateKey);
		fis.close();

		// Generate KeyPair.
		KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
		X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(
				encodedPublicKey);
		PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);

		PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(
				encodedPrivateKey);
		PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);

		return new KeyPair(publicKey, privateKey);
	}
}

Mein Problem ist nun, dass ich zwar ohne Probleme einen String verschlüsseln kann, aber bei der Entschlüsselung hackt es, hier bekomme ich keine Ergebnis zurück.
Daher meine Fragen:
- Funktioniert das überhaupt, dass ich den verschlüsselten Text als String zurückgebe bzw. kann ein String überhaupt genutzt werden um verschlüsselte Daten zu "speichern". Ich habe den Eindruck, dass bei der Konvertierung von ByteArray in String bzw. von String zu ByteArray etwas verloren geht und daher die Entschlüsselungsmethode nicht funktioniert. Wenn das so ist, als was speichere ich einen ByteArrayOutputStream in einer Tabelle?

Danke für eure Hilfe!
Florian
 

Andi_CH

Top Contributor
Ganz allgemein gesagt wird ein chiffrierter String wohl kaum wieder ein String sondern ein Array of Byte sein. Ob das gut geht kann ich nicht schlüssig beantworten.

Du sagst es kommen keine Strings zurück - was liefert denn der sysout in decrypt?
Was hast du mit dem Debugger herausgefunden?
 
S

SlaterB

Gast
JDBC kennt Blobs

alternativ die Bytes auf bessere Weise in einem String speichern, Base64-Encoding oder notfalls ganz manuell jeden Zahlwert eines bytes einzeln komplett mit Komma,
String st = Arrays.toString(array);

die Höhe des Aufwands kann man versuchen zu optimieren, aber man sollte gesicherte, nachprüfbare Richtigkeit ganz oben anstellen,
 
Zuletzt bearbeitet von einem Moderator:

eolith421

Mitglied
Hallo!
Danke für die rasche Antwort!
Grundsätzlich schaut der String wenn ich ihn ausgebe in beiden Methoden gleich aus. Das Problem ist, dass die Größe/Länge des ByteArrayOutputStream vor der Umwandlung in String unterschiedlich ist, als jener ByteArrayOutputStream nach der Rückkonvertierung von String in ByteArrayOutputStream. Daher vermute ich, dass das so nicht funktionieren wird. Ich versuche derzeit die verschlüsselten Daten als Blob zu speichern.

Liebe Grüße,
Florian
 

Andi_CH

Top Contributor
Versuche doch einmal die Daten zu ver- und entschlüsseln ohne die dazwischen zu speichern - dann hast du den Test ob die Chiffrierung richtig implementiert ist.

Dann ob du wirklich dieselben Daten aus der DB zurückliest wie du reinschreibst (bei BLOB vermute ich aber hier keine Probleme - Strings wären da kritischer)
 
G

Gast2

Gast
Hallo!
Danke für die rasche Antwort!
Grundsätzlich schaut der String wenn ich ihn ausgebe in beiden Methoden gleich aus. Das Problem ist, dass die Größe/Länge des ByteArrayOutputStream vor der Umwandlung in String unterschiedlich ist, als jener ByteArrayOutputStream nach der Rückkonvertierung von String in ByteArrayOutputStream. Daher vermute ich, dass das so nicht funktionieren wird. Ich versuche derzeit die verschlüsselten Daten als Blob zu speichern.

Liebe Grüße,
Florian

Wenn du dir einen Gefallen tun möchtest: Encodier die verschlüsselten Daten in Base64 bevor du sie in die DB speicherst. BLOBs funktionieren zwar auch, aber hast du dir schon mal einen BLOB im query Browser angesehn? Oder wenn du die Datenbank dumpst und neuimportierst? Base64 Strings sind wesentlich leichter zu handhaben und zu debuggen.
 

HoaX

Top Contributor
Wenn du dir einen Gefallen tun möchtest: Encodier die verschlüsselten Daten in Base64 bevor du sie in die DB speicherst. BLOBs funktionieren zwar auch, aber hast du dir schon mal einen BLOB im query Browser angesehn? Oder wenn du die Datenbank dumpst und neuimportierst? Base64 Strings sind wesentlich leichter zu handhaben und zu debuggen.

Will ich so nicht unterscheiben, wer weiß wie groß die Daten sind? Base64 braucht mehr Speicherplatz und wenn man einen String speichert, dann wird dieser anders von der DB behandelt als ein BLOB. Bei Postgresql wird z.B. ein BLOB automatisch in kleine Teile zerlegt.
 

Neue Themen


Oben