Du scheinst BouncyCastle über die Java-Crypto-API anzusprechen, nicht über seine eigenen Klassen. Deshalb kannst du auch den (auskommentierten) GCMBlockCipher nicht nutzen. Damit das funktioniert, musst du den Provider noch registrieren, sonst findet Java den nicht: [src=java]static{
Security.addProvider(new BouncyCastleProvider());
}[/src]
Eigentlich mache ich das doch direkt im Konstruktor?
Ich habe jetzt einfach mal deine Zeile bei mir eingefügt, sollte dann ja hoffentlich auch klappen.
[src=java]import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.lang3.ArrayUtils;
import org.bouncycastle.crypto.engines.AESFastEngine;
import org.bouncycastle.crypto.io.CipherInputStream;
import org.bouncycastle.crypto.io.CipherOutputStream;
import org.bouncycastle.crypto.io.InvalidCipherTextIOException;
import org.bouncycastle.crypto.modes.GCMBlockCipher;
import org.bouncycastle.crypto.params.AEADParameters;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;
/**
*
* @author
*/
public class MyCryptClass {
private byte[] dataKey;
// private byte[] dataKeyMac;
private byte[] salt;
private byte[] passHash;
private byte[] iv;
// private IvParameterSpec ivSpec;
static {
Security.addProvider(new BouncyCastleProvider());
}
public MyCryptClass() {
// Security.addProvider(new BouncyCastleProvider());
}
public void generateSalt() {
SecureRandom random = new SecureRandom();
byte[] saltBytes = new byte[32]; //32 Bytes = 256 Bits
random.nextBytes(saltBytes);
this.salt = saltBytes;
}
public void generateDataKey() {
SecureRandom random = new SecureRandom();
byte[] keyBytes = new byte[32]; //32 Bytes = 256 Bits
random.nextBytes(keyBytes);
// this.dataKey = new SecretKeySpec(keyBytes, "AES");
this.dataKey = keyBytes;
}
// public SecretKeySpec getDataKey() {
// return this.dataKey;
// }
public byte[] getDataKey() {
return this.dataKey;
}
public byte[] getSalt() {
return this.salt;
}
public byte[] getPasswordHash() {
return this.passHash;
}
public byte[] getIV() {
return this.iv;
}
public void setSalt(byte[] s) {
if (s.length == 32) {
this.salt = s;
} else if (s.length > 32) {
//Der DataKey kann nicht verwendet werden
this.generateSalt();
} else {
SecureRandom random = new SecureRandom();
byte[] randomBytes = new byte[32 - s.length];
random.nextBytes(randomBytes);
this.salt = ArrayUtils.addAll(s, randomBytes);
}
}
public void setDataKey(String dKey) {
// this.dataKey = new SecretKeySpec(dKey.getBytes(), "AES");
if (dKey.getBytes().length == 32) {
this.dataKey = dKey.getBytes();
} else if (dKey.getBytes().length > 32) {
//Der DataKey kann nicht verwendet werden
this.generateDataKey();
} else {
SecureRandom random = new SecureRandom();
byte[] randomBytes = new byte[32 - dKey.getBytes().length];
random.nextBytes(randomBytes);
this.dataKey = ArrayUtils.addAll(dKey.getBytes(), randomBytes);
}
}
public void setPasswort(String pass) {
try {
if (this.salt == null) {
this.generateSalt();
}
MessageDigest md = MessageDigest.getInstance("SHA-256");
// md.update(pass.getBytes() + this.salt);
md.update(ArrayUtils.addAll(pass.getBytes(), this.salt));
this.passHash = md.digest();
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(MyCryptClass.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void generateIV() {
SecureRandom random = new SecureRandom();
byte[] ivBytes = new byte[16]; //16 Bytes = 128 Bits
random.nextBytes(ivBytes);
// this.ivSpec = new IvParameterSpec(ivBytes);
this.iv = ivBytes;
}
public String getPasswordDataToSave() {
String data = "";
byte[] encDataKey = encryptDataKey();
byte[] salt = this.getSalt();
byte[] iv = this.getIV();
byte[] dataBytes = ArrayUtils.addAll(ArrayUtils.addAll(encDataKey, salt), iv);
data = Base64.toBase64String(dataBytes);
return data;
}
public void loadPasswordData(String pd) {
byte[] data = Base64.decode(pd);
byte[] encDataKey = Arrays.copyOfRange(data, 0, data.length - 64);
byte[] salt = Arrays.copyOfRange(data, data.length - 64, data.length - 32);
byte[] iv = Arrays.copyOfRange(data, data.length - 32, data.length);
/* Daten wieder in den Cipher einlesen */
}
private byte[] encryptDataKey() {
byte[] encDataKey = null;
// Initialisieren
GCMBlockCipher cipher = new GCMBlockCipher(new AESFastEngine());
cipher.init(true, new AEADParameters(new KeyParameter(this.passHash), 128, this.iv)); // 128 = Block-Größe (immer 128 für AES)
// Encrypten, bspw mit CipherOutputStream:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream stream = new CipherOutputStream(baos, cipher); // output kann ein beliebiger OutputStream sein, bspw. FileOutputStream
try {
// ... Daten in "stream" schreiben
stream.write(this.dataKey);
stream.close(); // damit sollte die MAC an die Daten angehängt werden
// Verschlüsselte Daten aus dem ByteArray-Stream holen
encDataKey = baos.toByteArray();
// System.out.println("Ciphertext length: "+encrypted.length);
} catch (IOException ex) {
Logger.getLogger(MyCryptClass.class.getName()).log(Level.SEVERE, null, ex);
}
return encDataKey;
}
private byte[] decryptDataKey(byte[] encDataKey) {
byte[] decDataKey = new byte[32];
// Initialisieren
GCMBlockCipher cipher = new GCMBlockCipher(new AESFastEngine());
cipher.init(false, new AEADParameters(new KeyParameter(this.passHash), 128, this.iv));
// dataKey = cipher.doFinal(encDataKey);
try (CipherInputStream stream = new CipherInputStream(new ByteArrayInputStream(encDataKey), cipher)) {
stream.read(decDataKey);
} catch (InvalidCipherTextIOException e) {
System.err.println("Ciphertext was manipulated, MAC check failed!");
decDataKey = null;
} catch (IOException ex) {
Logger.getLogger(MyCryptClass.class.getName()).log(Level.SEVERE, null, ex);
}
return decDataKey;
}[/src]
Das verschlüsseln und entschlüsseln der eigentlichen Daten müsste jetzt noch dazu und dann muss natürlich alles vernünftig aufgerufen werden und die Sichtbarkeiten angepasst werden.
Findet ihr noch grobe Fehler?
Habe ich jetzt die richtigen Klassen importiert?