0

Before I start, I know there are a lot of similar questions on stackoverflow, but the majority of the answers consist of a large section of code with no explanation or help to aid the user.

What I need to do is rather simple, take a string as input from the user, then the password, then encrypt the string with the password and write the cipher text to a file. Then at a later date when the user wants, read the cipher text from the file and decrypt it and present the user with the original plain text. I can handle writing to and from the file, I just need help with the encryption of the string. (Note: I do not want to just encrypt/decrypt the whole file - as it has to contain some unencrypted stuff - just a string in the program)

Also, the 'Initialisation Vector' that is required - can it be the same as the password? Or can it be simply hard coded into the program? Is it even essential for security? If not then does the user have to remember the password and the IV?

Another thing, when the user comes to decrypt and and enters an incorrect password, do the methods in the Rijndael class just raise an error or what?

I am proficient when it comes to C# but I am new to cryptography so if you could step me through any code or answer you post I'd be most grateful.

Thanks

Harvey
  • 319
  • 1
  • 4
  • 8
  • 3
    Harvey have you done any other internet searches..? here is a good article to explain how to [Encrypt & Decrypt using Rijndeal](http://www.superstarcoders.com/blogs/posts/symmetric-encryption-in-c-sharp.aspx) – MethodMan Feb 27 '13 at 16:23
  • 1
    Hi there checkout this article on MSDN covering this topic - there is a lot of code BUT its extremely wll commented (almost line by line) explaining whats going on at each stage - it might not fully answer your question BUT it should give a good insight into the process for you! http://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndaelmanagedtransform(v=vs.80).aspx – Luke Baughan Feb 27 '13 at 16:23

2 Answers2

2

IV's are required for most Rijndael modes, typically you just prepend it to your ciphertext, no need for users to remember.

Since you are using a user typed password to decrypt, you want to use Authenticated Encryption so that your program can safely re-prompt if the wrong password is entered, otherwise your program might not give any indication there was an issue and spit out random text.

I have an example of using AES-CBC with HMAC-SHA256 authentication that I try and keep up to date and reviewed, it in fact has a helper method that handles encrypting with just plaintext and password, and is also well commented:

Modern Examples of Symmetric Authenticated Encryption of a string. C#

Community
  • 1
  • 1
jbtule
  • 31,383
  • 12
  • 95
  • 128
  • 1
    If the ciphertext is long, you may also want to store some extra data (e.g. a MAC of an empty message) to allow mistyped passwords to be detected without having to first process the whole ciphertext. – Ilmari Karonen Feb 27 '13 at 21:48
  • 1
    @IlmariKaronen that is really *not* the way to achieve the goal of detecting a wrong password. The only way to do that is via a MAC or an autheticated encryption mode like CCM or GCM. – Peter Elliott Feb 28 '13 at 13:12
  • @PeterElliott: Would you mind explaining _why_ you think so? The primary purpose of MACing the ciphertext (or using an AE mode) is to protect it against malicious tampering; the fact that using an incorrect key also gives a MAC failure is really just a side effect, and not really a very good way to check password correctness. (For one thing, you can't tell the difference between a wrong password and a corrupted ciphertext that way. For another, you need to process the whole ciphertext to detect the MAC failure.) – Ilmari Karonen Feb 28 '13 at 15:05
  • (continued) A better solution is to verify the key _before_ trying to process any of the actual ciphertext (but after deriving it from the password with a suitable key-stretching KDF like PBKDF2 or scrypt; you should never use the raw password as anything other than input to the KDF). One way to do that is to store a salted hash of the key, or a MAC of a short random message with the key. (My earlier suggestion of using an empty message _is_ somewhat suboptimal _if_ the KDF is not itself salted, which it of course should be; see e.g. http://crypto.stackexchange.com/q/1507/ for more details.) – Ilmari Karonen Feb 28 '13 at 15:12
  • @IlmariKaronen in fairness, it's not really a side effect for encrypt-then-mac or AEAD, they both provide deterministic ways to verify that you have a valid ciphertext, whether the ciphertext is invalid because comes from an adversary, or tampering or is mismatched to your key due to your own mistake is irrelevant in both of these security constructions. – jbtule Feb 28 '13 at 15:22
1

You need to take the following steps:

  1. Calculate a key from the password. You need to generate a random salt of 8 bytes and an iteration count as input for your password based key derivation function (PBKDF) such as PBKDF2;
  2. Encode your string using any encoding such as UTF-8, giving you the plaintext for your cipher;
  3. Create a cipher, such as AES-128 in CBC mode, using PKCS#7 padding;
  4. Create a random IV, this should be the blocksize in bytes (so for AES this would be 16 bytes);
  5. Encrypt your plaintext using the given cipher, giving you the ciphertext;
  6. Store salt, IV and ciphertext - if you require a string, you may use an encoding such as Base64.

PBKDF2 is implemented in Rfc2898DeriveBytes.

Note that this answer only shows how to achieve confidentiality, not integrity or authenticity.

Ilmari Karonen
  • 49,047
  • 9
  • 93
  • 153
Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • Note that, technically, having _both_ a random salt for PBKDF2 and a random IV isn't strictly necessary (but it won't hurt, either). Still, +1. – Ilmari Karonen Feb 27 '13 at 21:41
  • @IlmariKaronen Yeah, I know, but generating enough random data to also extract an IV may require that the whole PBKDF function has to be executed again, which also has its drawbacks. Better to generate a separate IV if you have the space to store it. Thanks for the +1. – Maarten Bodewes Mar 01 '13 at 00:14
  • Actually, my comment above is wrong: what I was trying to say was that, if you use a random salt in PBKDF2 to derive the key, and only use that derived key to encrypt one message, then using a fixed IV should be OK. But _that's not actually true for CBC mode_, although for most other modes it would be. (What you could do, even for CBC mode, however, would be to derive the IV by encrypting a nonce with the raw block cipher, as in NIST SP 800-38A, appendix C. The nonce then only needs to be unique within the scope of each key; and if keys are never reused, it may thus be fixed.) – Ilmari Karonen Mar 01 '13 at 00:45
  • @IlmariKaronen I think if you are *never* reusing the key for encryption then even a zero IV is OK, even for CBC mode. The NIST document talks about the IV being unpredictable, but I presume (incorrectly?) that the standard expects that the key is used multiple times (it does not say). Note that this premise breaks even if you just create a key check value (KCV) for TDEA or AES. – Maarten Bodewes Mar 05 '13 at 23:44
  • Anything wrong with my answer, Harvey? If there is, please let me know by commenting, otherwise hit accept (read the nicely worded FAQ!) – Maarten Bodewes Mar 05 '13 at 23:46
  • I hate downvotes without comment, guys, please indicate a reason when voting down. – Maarten Bodewes May 08 '13 at 22:28
  • You know, looking at your recent rep history, I think you may be getting hit by a serial downvoter or several (or possibly several socks of one person). If the votes don't get reversed automatically, you may want to contact a mod. – Ilmari Karonen May 08 '13 at 23:00
  • @IlmariKaronen yeah, I know and I did. Trouble is that I now don't know if a downvote for a good reason or not. It's a bit of a shame that stackoverflow does not seem to be resistant against these kind of attacks. Then again, maybe that's the only way it can work at all... – Maarten Bodewes May 08 '13 at 23:46