Added upgrade method to increase the number of iterations
This commit is contained in:
parent
ed83878039
commit
8b117c5e6c
@ -128,5 +128,41 @@ namespace Encrypter_Tests
|
|||||||
var decryptedMessage = await encryptedData.Decrypt(password);
|
var decryptedMessage = await encryptedData.Decrypt(password);
|
||||||
Assert.That(decryptedMessage, Is.EqualTo(message));
|
Assert.That(decryptedMessage, Is.EqualTo(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task TestUpgradedIterationsBehaviour()
|
||||||
|
{
|
||||||
|
var message = "This is a test with umlauts äüö.";
|
||||||
|
var password = "test password";
|
||||||
|
var previousIterations = 1_000;
|
||||||
|
var upgradedIterations = 1_000_000;
|
||||||
|
|
||||||
|
var previousEncryptedData = await CryptoProcessor.EncryptString(message, password, previousIterations);
|
||||||
|
var reEncryptedData = await CryptoProcessor.UpgradeIterations(previousEncryptedData, password, previousIterations, upgradedIterations);
|
||||||
|
Assert.That(previousEncryptedData, Is.Not.EqualTo(reEncryptedData));
|
||||||
|
|
||||||
|
var decryptedMessage = await CryptoProcessor.DecryptString(reEncryptedData, password, upgradedIterations);
|
||||||
|
Assert.That(decryptedMessage, Is.EqualTo(message));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var decryptedMessage2 = await CryptoProcessor.DecryptString(reEncryptedData, password, previousIterations);
|
||||||
|
Assert.Fail("Should not be reached!");
|
||||||
|
}
|
||||||
|
catch (CryptographicException e)
|
||||||
|
{
|
||||||
|
Assert.That(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var decryptedMessage2 = await CryptoProcessor.DecryptString(previousEncryptedData, password, upgradedIterations);
|
||||||
|
Assert.Fail("Should not be reached!");
|
||||||
|
}
|
||||||
|
catch (CryptographicException e)
|
||||||
|
{
|
||||||
|
Assert.That(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,10 @@ namespace Encrypter
|
|||||||
{
|
{
|
||||||
public static class CryptoProcessor
|
public static class CryptoProcessor
|
||||||
{
|
{
|
||||||
private const int ITERATIONS = 6_000_000;
|
/// <summary>
|
||||||
|
/// The number of iterations for the year 2020.
|
||||||
|
/// </summary>
|
||||||
|
public const int ITERATIONS_YEAR_2020 = 6_000_000;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Encrypts a string by means of AES. The result gets base64 encoded.
|
/// Encrypts a string by means of AES. The result gets base64 encoded.
|
||||||
@ -20,8 +23,9 @@ namespace Encrypter
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="data">The UTF8 encoded string to encrypt.</param>
|
/// <param name="data">The UTF8 encoded string to encrypt.</param>
|
||||||
/// <param name="password">The password. Must consists of 6 chars or more.</param>
|
/// <param name="password">The password. Must consists of 6 chars or more.</param>
|
||||||
|
/// <param name="iterations">The number of iterations to derive the key. Should not be adjusted. The default is secure for the current time.</param>
|
||||||
/// <returns>The base64 encoded and encrypted string. The string is ASCII encoding.</returns>
|
/// <returns>The base64 encoded and encrypted string. The string is ASCII encoding.</returns>
|
||||||
public static async Task<string> EncryptString(string data, string password)
|
public static async Task<string> EncryptString(string data, string password, int iterations = ITERATIONS_YEAR_2020)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(password) || password.Length < 6)
|
if (string.IsNullOrWhiteSpace(password) || password.Length < 6)
|
||||||
throw new CryptographicException("The password was empty or shorter than 6 characters.");
|
throw new CryptographicException("The password was empty or shorter than 6 characters.");
|
||||||
@ -39,7 +43,7 @@ namespace Encrypter
|
|||||||
// The following operations take several seconds. Thus, using a task:
|
// The following operations take several seconds. Thus, using a task:
|
||||||
await Task.Run(() =>
|
await Task.Run(() =>
|
||||||
{
|
{
|
||||||
using var keyVectorObj = new Rfc2898DeriveBytes(password, saltBytes, ITERATIONS, HashAlgorithmName.SHA512);
|
using var keyVectorObj = new Rfc2898DeriveBytes(password, saltBytes, iterations, HashAlgorithmName.SHA512);
|
||||||
key = keyVectorObj.GetBytes(32); // the max valid key length = 256 bit = 32 bytes
|
key = keyVectorObj.GetBytes(32); // the max valid key length = 256 bit = 32 bytes
|
||||||
iv = keyVectorObj.GetBytes(16); // the only valid block size = 128 bit = 16 bytes
|
iv = keyVectorObj.GetBytes(16); // the only valid block size = 128 bit = 16 bytes
|
||||||
});
|
});
|
||||||
@ -93,8 +97,9 @@ namespace Encrypter
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="base64EncodedAndEncryptedData">The base64 encoded and AES encrypted string. This string must be ASCII encoded.</param>
|
/// <param name="base64EncodedAndEncryptedData">The base64 encoded and AES encrypted string. This string must be ASCII encoded.</param>
|
||||||
/// <param name="password">The password. Must consists of 6 chars or more.</param>
|
/// <param name="password">The password. Must consists of 6 chars or more.</param>
|
||||||
|
/// <param name="iterations">The number of iterations to derive the key. Should not be adjusted. The default is secure for the current time.</param>
|
||||||
/// <returns>The decrypted UTF8 encoded string.</returns>
|
/// <returns>The decrypted UTF8 encoded string.</returns>
|
||||||
public static async Task<string> DecryptString(string base64EncodedAndEncryptedData, string password)
|
public static async Task<string> DecryptString(string base64EncodedAndEncryptedData, string password, int iterations = ITERATIONS_YEAR_2020)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(password) || password.Length < 6)
|
if (string.IsNullOrWhiteSpace(password) || password.Length < 6)
|
||||||
throw new CryptographicException("The password was empty or shorter than 6 characters.");
|
throw new CryptographicException("The password was empty or shorter than 6 characters.");
|
||||||
@ -121,7 +126,7 @@ namespace Encrypter
|
|||||||
// The following operations take several seconds. Thus, using a task:
|
// The following operations take several seconds. Thus, using a task:
|
||||||
await Task.Run(() =>
|
await Task.Run(() =>
|
||||||
{
|
{
|
||||||
using var keyVectorObj = new Rfc2898DeriveBytes(password, saltBytes, ITERATIONS, HashAlgorithmName.SHA512);
|
using var keyVectorObj = new Rfc2898DeriveBytes(password, saltBytes, iterations, HashAlgorithmName.SHA512);
|
||||||
key = keyVectorObj.GetBytes(32); // the max valid key length = 256 bit = 32 bytes
|
key = keyVectorObj.GetBytes(32); // the max valid key length = 256 bit = 32 bytes
|
||||||
iv = keyVectorObj.GetBytes(16); // the only valid block size = 128 bit = 16 bytes
|
iv = keyVectorObj.GetBytes(16); // the only valid block size = 128 bit = 16 bytes
|
||||||
});
|
});
|
||||||
@ -154,5 +159,22 @@ namespace Encrypter
|
|||||||
// it does not create another copy of the data. ToArray would create another copy of the data!
|
// it does not create another copy of the data. ToArray would create another copy of the data!
|
||||||
return Encoding.UTF8.GetString(decryptedData.GetBuffer()[..(int)decryptedData.Length]);
|
return Encoding.UTF8.GetString(decryptedData.GetBuffer()[..(int)decryptedData.Length]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Upgrades the encryption regarding the used iterations for the key.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="encryptedDataBeforeUpgrade">The encrypted data with the previous settings.</param>
|
||||||
|
/// <param name="password">The password.</param>
|
||||||
|
/// <param name="previousIterations">The previous number of iterations.</param>
|
||||||
|
/// <param name="upgradedIterations">The upgraded number of iterations.</param>
|
||||||
|
/// <returns>The re-encrypted data.</returns>
|
||||||
|
public static async Task<string> UpgradeIterations(string encryptedDataBeforeUpgrade, string password, int previousIterations, int upgradedIterations)
|
||||||
|
{
|
||||||
|
// Decrypt the data with the previous settings:
|
||||||
|
var decryptedData = await CryptoProcessor.DecryptString(encryptedDataBeforeUpgrade, password, previousIterations);
|
||||||
|
|
||||||
|
// Encrypt the data with the new settings:
|
||||||
|
return await CryptoProcessor.EncryptString(decryptedData, password, upgradedIterations);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,12 @@
|
|||||||
<name>Encrypter</name>
|
<name>Encrypter</name>
|
||||||
</assembly>
|
</assembly>
|
||||||
<members>
|
<members>
|
||||||
<member name="M:Encrypter.CryptoProcessor.EncryptString(System.String,System.String)">
|
<member name="F:Encrypter.CryptoProcessor.ITERATIONS_YEAR_2020">
|
||||||
|
<summary>
|
||||||
|
The number of iterations for the year 2020.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="M:Encrypter.CryptoProcessor.EncryptString(System.String,System.String,System.Int32)">
|
||||||
<summary>
|
<summary>
|
||||||
Encrypts a string by means of AES. The result gets base64 encoded.
|
Encrypts a string by means of AES. The result gets base64 encoded.
|
||||||
Due to the necessary millions of SHA512 iterations, the methods runs at least several seconds in the year 2020 (approx. 5-7s).
|
Due to the necessary millions of SHA512 iterations, the methods runs at least several seconds in the year 2020 (approx. 5-7s).
|
||||||
@ -14,9 +19,10 @@
|
|||||||
</summary>
|
</summary>
|
||||||
<param name="data">The UTF8 encoded string to encrypt.</param>
|
<param name="data">The UTF8 encoded string to encrypt.</param>
|
||||||
<param name="password">The password. Must consists of 6 chars or more.</param>
|
<param name="password">The password. Must consists of 6 chars or more.</param>
|
||||||
|
<param name="iterations">The number of iterations to derive the key. Should not be adjusted. The default is secure for the current time.</param>
|
||||||
<returns>The base64 encoded and encrypted string. The string is ASCII encoding.</returns>
|
<returns>The base64 encoded and encrypted string. The string is ASCII encoding.</returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:Encrypter.CryptoProcessor.DecryptString(System.String,System.String)">
|
<member name="M:Encrypter.CryptoProcessor.DecryptString(System.String,System.String,System.Int32)">
|
||||||
<summary>
|
<summary>
|
||||||
Decrypts an base64 encoded and encrypted string. Due to the necessary millions of SHA512 iterations,
|
Decrypts an base64 encoded and encrypted string. Due to the necessary millions of SHA512 iterations,
|
||||||
the methods runs at least several seconds in the year 2020 (approx. 5-7s).
|
the methods runs at least several seconds in the year 2020 (approx. 5-7s).
|
||||||
@ -26,8 +32,19 @@
|
|||||||
</summary>
|
</summary>
|
||||||
<param name="base64EncodedAndEncryptedData">The base64 encoded and AES encrypted string. This string must be ASCII encoded.</param>
|
<param name="base64EncodedAndEncryptedData">The base64 encoded and AES encrypted string. This string must be ASCII encoded.</param>
|
||||||
<param name="password">The password. Must consists of 6 chars or more.</param>
|
<param name="password">The password. Must consists of 6 chars or more.</param>
|
||||||
|
<param name="iterations">The number of iterations to derive the key. Should not be adjusted. The default is secure for the current time.</param>
|
||||||
<returns>The decrypted UTF8 encoded string.</returns>
|
<returns>The decrypted UTF8 encoded string.</returns>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="M:Encrypter.CryptoProcessor.UpgradeIterations(System.String,System.String,System.Int32,System.Int32)">
|
||||||
|
<summary>
|
||||||
|
Upgrades the encryption regarding the used iterations for the key.
|
||||||
|
</summary>
|
||||||
|
<param name="encryptedDataBeforeUpgrade">The encrypted data with the previous settings.</param>
|
||||||
|
<param name="password">The password.</param>
|
||||||
|
<param name="previousIterations">The previous number of iterations.</param>
|
||||||
|
<param name="upgradedIterations">The upgraded number of iterations.</param>
|
||||||
|
<returns>The re-encrypted data.</returns>
|
||||||
|
</member>
|
||||||
<member name="M:Encrypter.Extensions.Encrypt(System.String,System.String)">
|
<member name="M:Encrypter.Extensions.Encrypt(System.String,System.String)">
|
||||||
<summary>
|
<summary>
|
||||||
Encrypts this string by means of AES. The result gets base64 encoded.
|
Encrypts this string by means of AES. The result gets base64 encoded.
|
||||||
|
Loading…
Reference in New Issue
Block a user