Внизу есть код, который я придумал.
Код: Выделить всё
java.io.StreamCorruptedException: invalid stream header: DBA5F4D2
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:863)
at java.io.ObjectInputStream.(ObjectInputStream.java:354)
at myapp.IOUtils.readJavaSerialized(IOUtils.java:1043)
...
< /code>
Любая идея кто -нибудь, почему это не работает? Разве невозможно объединить написание двоичных данных и выходной поток зашифрованного объекта с тем же выходным потоком? Или впоследствии считывать из того же потока ввода? Стронг пароля запрашивается у пользователя перед вызовами этих методов. < /P>
private static final byte ENCRYPTED_FILE_VERSION = 0x01; // safe-guard to allow later adaptation...
private final static String CipherTransformation = "AES/GCM/NoPadding";
private static final int SALT_LENGTH = 16;
private static final int IV_LENGTH = 12;
private static final int KEY_LENGTH = 256;
private static final int PBKDF2_ITERATIONS = 65536;
private static final int GCM_TAG_LENGTH = 128; // in bits
public void encryptAndWrite(String password, Object obj, OutputStream os) throws Exception {
SecureRandom random = new SecureRandom();
// Generate salt and IV
byte[] salt = new byte[SALT_LENGTH];
byte[] iv = new byte[IV_LENGTH];
random.nextBytes(salt);
random.nextBytes(iv);
// Derive AES key:
SecretKey key = deriveKey(password, salt);
// Set up cipher
Cipher cipher = Cipher.getInstance(CipherTransformation);
GCMParameterSpec gcmSpec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);
cipher.init(Cipher.ENCRYPT_MODE, key, gcmSpec);
// Write a file version marker:
os.write(ENCRYPTED_FILE_VERSION);
// Write salt and IV:
os.write(salt);
os.write(iv);
// Encrypt and write serialized data:
try (CipherOutputStream cipherOut = new CipherOutputStream(os, cipher);
ObjectOutputStream oos = new ObjectOutputStream(cipherOut)) {
oos.writeObject(obj);
} // .close() is done implicitly in finally-clause
os.flush();
}
@SuppressWarnings("unchecked")
public Object readAndDecrypt(String password, InputStream is) throws Exception {
// Read and verify the file version marker:
int version = is.read();
if (version != ENCRYPTED_FILE_VERSION) {
throw new IllegalArgumentException("Unsupported encryption version: " + version);
}
// Read salt and IV:
byte[] salt = is.readNBytes(SALT_LENGTH);
byte[] iv = is.readNBytes(IV_LENGTH);
if (salt.length != SALT_LENGTH || iv.length != IV_LENGTH) {
throw new IllegalArgumentException("Stream does not contain valid salt or IV");
}
// Derive AES key
SecretKey key = deriveKey(password, salt);
// Set up cipher:
Cipher cipher = Cipher.getInstance(CipherTransformation);
GCMParameterSpec gcmSpec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);
cipher.init(Cipher.DECRYPT_MODE, key, gcmSpec);
// Decrypt and write data
try (CipherInputStream cipherIn = new CipherInputStream(is, cipher);
ObjectInputStream ois = new ObjectInputStream(cipherIn)) {
return ois.readObject();
} // .close() is done implicitly in finally-clause
}
private static SecretKey deriveKey(String password, byte[] salt) throws Exception {
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, PBKDF2_ITERATIONS, KEY_LENGTH);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
byte[] keyBytes = factory.generateSecret(spec).getEncoded();
return new SecretKeySpec(keyBytes, "AES");
}
Посмотреть ближе к местоположению ошибки в objectInputStream.readObject () Код, очевидно, ожидает волшебный заголовок, состоящий из двух шорт
public interface ObjectStreamConstants {
...
final static short STREAM_MAGIC = (short)0xaced;
final static short STREAM_VERSION = 5;
...
< /code>
как первые два слова (4 байта) в сериализованном потоке объектов. Эти байты, по -видимому, отсутствуют здесь - также при просмотре сгенерированного файла с использованием шестнадцатеричного редактора.>
Подробнее здесь: https://stackoverflow.com/questions/797 ... tputstream