6

A bit complementary to, but no way the same as, this question.

How to create a password protected file?

Community
  • 1
  • 1
Peter
  • 47,963
  • 46
  • 132
  • 181

2 Answers2

16

encrypt:

private const int SaltSize = 8;

public static void Encrypt( FileInfo targetFile, string password )
{
  var keyGenerator = new Rfc2898DeriveBytes( password, SaltSize );
  var rijndael = Rijndael.Create();

  // BlockSize, KeySize in bit --> divide by 8
  rijndael.IV = keyGenerator.GetBytes( rijndael.BlockSize / 8 );
  rijndael.Key = keyGenerator.GetBytes( rijndael.KeySize / 8 );

  using( var fileStream = targetFile.Create() )
  {
    // write random salt
    fileStream.Write( keyGenerator.Salt, 0, SaltSize );

    using( var cryptoStream = new CryptoStream( fileStream, rijndael.CreateEncryptor(), CryptoStreamMode.Write ) )
    {
      // write data
    }
  }
}

and decrypt:

public static void Decrypt( FileInfo sourceFile, string password )
{
  // read salt
  var fileStream = sourceFile.OpenRead();
  var salt = new byte[SaltSize];
  fileStream.Read( salt, 0, SaltSize );

  // initialize algorithm with salt
  var keyGenerator = new Rfc2898DeriveBytes( password, salt );
  var rijndael = Rijndael.Create();
  rijndael.IV = keyGenerator.GetBytes( rijndael.BlockSize / 8 );
  rijndael.Key = keyGenerator.GetBytes( rijndael.KeySize / 8 );

  // decrypt
  using( var cryptoStream = new CryptoStream( fileStream, rijndael.CreateDecryptor(), CryptoStreamMode.Read ) )
  {
    // read data
  }
}
tanascius
  • 53,078
  • 22
  • 114
  • 136
  • If you use CryptoStream for network communications, you should find a stream cipher. Rijndael is typically used as a block cipher. A stream cipher is optimal for small pieces of data, which is typical on chatty network streams. Stream ciphers can be more secure when compared to block ciphers, especially when the data stream is not blocky. Padding and chaining is required for block ciphers. Stream ciphers can spend downtime calculating more psuedorandom key, and then use very efficient XOR for the actual ondemand encryption/decryption operation. – Kind Contributor Feb 24 '17 at 06:13
  • 1
    When I implement this answer, I get ``System.Security.Cryptography.CryptographicException: Padding is invalid and cannot be removed.`` whenever I supply any password except the correct one. Doesn't that defeat the purpose of a password? *edit* no, that means you have to discover or brute-force the password in order to decrypt it, which is exactly the point of a password. Derp. – Overlord Zurg Oct 25 '18 at 22:57
  • is there option to detect if user input wrong password? – Johny Corbie Nov 14 '19 at 22:23
  • 2
    It would be very useful to have a complete answer, not just some `//write data` and `//read data` incomplete sections. Like having a string "Hello World", encrypting it to a file and reading the encrypted file back into the string. –  Feb 10 '22 at 15:17
2

Use the RijndaelManaged class for encryption and Rfc2898DeriveBytes to generate the key (and IV) for the crypto.

JMD
  • 1,408
  • 11
  • 9