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

2
  • 3
    Harvey have you done any other internet searches..? here is a good article to explain how to Encrypt & Decrypt using Rijndeal Commented Feb 27, 2013 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! msdn.microsoft.com/en-us/library/… Commented Feb 27, 2013 at 16:23

2 Answers 2

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#

Sign up to request clarification or add additional context in comments.

5 Comments

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.
@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.
@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.)
(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. crypto.stackexchange.com/q/1507 for more details.)
@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.
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.

8 Comments

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.
@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.
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.)
@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.
Anything wrong with my answer, Harvey? If there is, please let me know by commenting, otherwise hit accept (read the nicely worded FAQ!)
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.