Isn't the IV essentially another "password" needed to decrypt the password? I understand with it you get different encryption strings with the same password and simple text, but it's also just another important piece of data you need to keep track of. Could just use different passwords for similar effect too.
🚀C# Progress Academy - Become a senior C# developer: academy.tutorials.eu/p/csharp-progress-academy
What is the best practice to save the iv and key?
Database, cloud storage,... ?
key vault
Thanks, this is amazing, I was reading Microsoft.learn obsolete methods, but this is clear and useful, definitely I've learnt a lot!
Great tutorial, thank you! :) How about a similar tutorial for RSA, using certificates? - That would be awesome!
Thanks so much for sharing your ideas!
Greets,
Jannick
Really good tutorial, tks!
Can you generate the AES Encryption with Different Key Sizes?
Isn't the IV essentially another "password" needed to decrypt the password? I understand with it you get different encryption strings with the same password and simple text, but it's also just another important piece of data you need to keep track of. Could just use different passwords for similar effect too.
Please provide solution for this
if I have an excel file has a password "123", then I want to open it in c#, so how I do this?
Where can i find the source code?
Here at our article: tutorials.eu/cyber-security-with-csharp/
:)
public static MemoryStream AES_Decrypt(MemoryStream inputStream, string password)
{
// Reset input stream to the beginning
inputStream.Position = 0;
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
// Read the salt (first 32 bytes)
byte[] salt = new byte[32];
int saltBytesRead = inputStream.Read(salt, 0, salt.Length);
if (saltBytesRead != salt.Length)
{
throw new ArgumentException("Invalid input stream: unable to read salt.");
}
Console.WriteLine($"Salt used for decryption: {BitConverter.ToString(salt)}");
// Read the encrypted segment length (next 4 bytes)
byte[] lengthBytes = new byte[4];
int lengthBytesRead = inputStream.Read(lengthBytes, 0, lengthBytes.Length);
if (lengthBytesRead != lengthBytes.Length)
{
throw new ArgumentException("Invalid input stream: unable to read segment length.");
}
int encryptedSegmentLength = BitConverter.ToInt32(lengthBytes, 0);
Console.WriteLine($"Encrypted Segment Length: {encryptedSegmentLength}");
// Derive key and IV from password and salt
var key = new Rfc2898DeriveBytes(passwordBytes, salt, 50000);
var aes = new AesManaged
{
KeySize = 256,
BlockSize = 128,
Padding = PaddingMode.PKCS7
};
aes.Key = key.GetBytes(aes.KeySize / 8);
aes.IV = key.GetBytes(aes.BlockSize / 8);
Console.WriteLine($"Key: {BitConverter.ToString(aes.Key)}");
Console.WriteLine($"IV: {BitConverter.ToString(aes.IV)}");
// Create a CryptoStream for decryption
CryptoStream cryptoStream = null;
MemoryStream decryptedStream = new MemoryStream();
byte[] buffer = new byte[8192]; // 8 KB buffer
int bytesRead;
try
{
// Start decryption
Console.WriteLine("Starting decryption process...");
cryptoStream = new CryptoStream(inputStream, aes.CreateDecryptor(), CryptoStreamMode.Read);
// Read and write data from the CryptoStream to the MemoryStream
while ((bytesRead = cryptoStream.Read(buffer, 0, buffer.Length)) > 0)
{
decryptedStream.Write(buffer, 0, bytesRead);
}
Console.WriteLine("Decryption completed successfully.");
}
catch (CryptographicException ex)
{
Console.WriteLine($"CryptographicException: {ex.Message}");
throw new InvalidOperationException("Decryption failed: Invalid padding or corrupted data.");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
throw;
}
finally
{
// Dispose resources
cryptoStream?.Dispose();
aes.Dispose();
}
// Reset the position of the decrypted stream for further reading
decryptedStream.Position = 0;
return decryptedStream;
}