diff --git a/Encrypter Tests/EncrypterTests.cs b/Encrypter Tests/EncrypterTests.cs
index ddad93c..d73ff9b 100644
--- a/Encrypter Tests/EncrypterTests.cs
+++ b/Encrypter Tests/EncrypterTests.cs
@@ -279,6 +279,93 @@ namespace Encrypter_Tests
}
}
+ [Test]
+ public async Task TestChangedPasswordBehaviourStreaming()
+ {
+ var tempFileInput = Path.GetTempFileName();
+ var tempFileEncryptedPrevious = Path.GetTempFileName();
+ var tempFileReEncrypted = Path.GetTempFileName();
+ var tempFileDecrypted = Path.GetTempFileName();
+
+ try
+ {
+ var message = "This is a test with umlauts äüö.";
+ await File.WriteAllTextAsync(tempFileInput, message);
+
+ var passwordPrevious = "test password";
+ var passwordNext = "better password";
+ var iterations = 1_000;
+
+ await using (var outputStream = File.OpenWrite(tempFileEncryptedPrevious))
+ {
+ await using var inputStream = File.OpenRead(tempFileInput);
+ await CryptoProcessor.Encrypt(inputStream, outputStream, passwordPrevious, iterations);
+ }
+
+ await using (var outputStream = File.OpenWrite(tempFileReEncrypted))
+ {
+ await using var inputStream = File.OpenRead(tempFileEncryptedPrevious);
+ await CryptoProcessor.ChangePassword(inputStream, outputStream, passwordPrevious, passwordNext, iterations);
+ }
+
+ Assert.That(await File.ReadAllBytesAsync(tempFileEncryptedPrevious), Is.Not.EqualTo(await File.ReadAllBytesAsync(tempFileReEncrypted)));
+
+ await using (var outputStream = File.OpenWrite(tempFileDecrypted))
+ {
+ await using var inputStream = File.OpenRead(tempFileReEncrypted);
+ await CryptoProcessor.Decrypt(inputStream, outputStream, passwordNext, iterations);
+ }
+
+ Assert.That(await File.ReadAllTextAsync(tempFileDecrypted), Is.EqualTo(message));
+
+ try
+ {
+ await using var tempBuffer = new MemoryStream();
+ await using var inputStream = File.OpenRead(tempFileReEncrypted);
+ await CryptoProcessor.Decrypt(inputStream, tempBuffer, passwordPrevious, iterations);
+ Assert.Fail("Should not be reached!");
+ }
+ catch (CryptographicException e)
+ {
+ Assert.That(true);
+ }
+ }
+ finally
+ {
+ try
+ {
+ File.Delete(tempFileInput);
+ }
+ catch
+ {
+ }
+
+ try
+ {
+ File.Delete(tempFileDecrypted);
+ }
+ catch
+ {
+ }
+
+ try
+ {
+ File.Delete(tempFileEncryptedPrevious);
+ }
+ catch
+ {
+ }
+
+ try
+ {
+ File.Delete(tempFileReEncrypted);
+ }
+ catch
+ {
+ }
+ }
+ }
+
[Test]
public async Task TestSimpleStream()
{
diff --git a/Encrypter/CryptoProcessor.cs b/Encrypter/CryptoProcessor.cs
index a9c9fb7..28c9645 100644
--- a/Encrypter/CryptoProcessor.cs
+++ b/Encrypter/CryptoProcessor.cs
@@ -374,5 +374,44 @@ namespace Encrypter
// Encrypt the data with the new settings:
return await CryptoProcessor.Encrypt(decryptedData, newPassword, iterations);
}
+
+ ///
+ /// Changes the password of the encryption. In order to re-encrypt the stream, a temporary file
+ /// gets used. When the returned task is finished, the re-encryption is done as well.
+ ///
+ /// With the previous password encrypted data.
+ /// The re-encrypted data.
+ /// The previous password.
+ /// The new password.
+ /// The used iterations.
+ public static async Task ChangePassword(Stream encryptedInput, Stream reEncryptedOutput, string previousPassword, string newPassword, int iterations = ITERATIONS_YEAR_2020)
+ {
+ var tempFileCache = Path.GetTempFileName();
+
+ try
+ {
+ await using (var tempCacheStream = File.OpenWrite(tempFileCache))
+ {
+ // Decrypt the data with the previous settings:
+ await Decrypt(encryptedInput, tempCacheStream, previousPassword, iterations);
+ }
+
+ await using (var tempCacheStream = File.OpenRead(tempFileCache))
+ {
+ // Encrypt the data with the new settings:
+ await Encrypt(tempCacheStream, reEncryptedOutput, newPassword, iterations);
+ }
+ }
+ finally
+ {
+ try
+ {
+ File.Delete(tempFileCache);
+ }
+ catch
+ {
+ }
+ }
+ }
}
}
diff --git a/Encrypter/Encrypter.xml b/Encrypter/Encrypter.xml
index aaf394e..ee1f9ca 100644
--- a/Encrypter/Encrypter.xml
+++ b/Encrypter/Encrypter.xml
@@ -96,6 +96,17 @@
The used iterations.
The re-encrypted data.
+
+
+ Changes the password of the encryption. In order to re-encrypt the stream, a temporary file
+ gets used. When the returned task is finished, the re-encryption is done as well.
+
+ With the previous password encrypted data.
+ The re-encrypted data.
+ The previous password.
+ The new password.
+ The used iterations.
+
Encrypts this string by means of AES. The result gets base64 encoded.