Using Encryption in .NET

Ciphers & Key Strength

Ciphers

A cipher is a cryptographic algorithm that transforms a plain text input into an encrypted output using a secret key. The output of a cipher is called "cipher text". There are two basic types of ciphers, block ciphers and stream ciphers. A block cipher transforms fixed-size plain text blocks into fixed-size cipher text blocks. A stream cipher doesn't actually encrypt the plain text. Instead, a stream cipher transforms plain text into cipher text by generating what is know as a key stream and then XORing the key stream bytes with the plain text bytes to yield the cipher text. All of the ciphers provided in the FCL are block ciphers. However, by using what is known as a cipher mode, a block cipher can be caused to behave as a stream cipher. We will discuss cipher modes later in this article, though we will not specifically discuss streaming modes.

Key Strength

Have you ever seen advertisements of "128-bit Encryption" or similar? How about the IE About dialog, which states (on my computer) "Cipher Strength: 128-bit"? What does this mean and why does it matter? Usually, when you hear about Cipher Strength or Encryption Strength, what is referred to is the length of the key used by the underlying cipher. This length is important, but it does not tell the whole story.

Though there are many possible attacks against a cipher, the simplest attack is what is known as a "brute force" attack. The brute force attack simply tries all possible key values to decrypt one or more blocks of data until a sensible value is achieved. Since the plain text is highly non-random, it will be obvious to the attacker when the correct key has been chosen. This process is simplified when the attacker actually knows what the plain text is. This is more likely than you might think. Most communications protocols, for example, have standard session headers, message headers, etc, so it's not terribly difficult for the attacker to figure out what these blocks of data contain, but I digress.

In order to demonstrate the value of a long key, let's reduce the problem ad ridiculum. Let's say that you are using an 8-bit key. In this case, the attacker only has to perform a maximum of 256 guesses before he knows the key. In reality, though, he'll only have to perform less than half that many steps before his chances of success begin to exceed 50%. In the case of a 40-bit key, the attacker will have to perform a maximum of just over a trillion steps, but in reality, about 500 billion would give him a good chance of success. This is completely feasible given time and the power of modern processing. Even 64-bit keys are now being considered weak, and 128-bit is pretty much the standard today. Let's keep one thing in mind, though; 56-bit keys were considered safe 20 years ago or even less. Why are they not safe today? Well, it's because of the rapid advance of processing technology, a process that is likely to continue for the foreseeable future. When we build systems today that implement encryption, we need to consider how long our system will be in place and take into consideration what the technology will look like well into the future.

Though the length of the key is important, there are also other considerations. It is equally important to consider how the key is selected. Many systems derive keys from sources such as passwords. The problem with this is that, though the resultant key is long, the source is usually much shorter and highly non-random. Users simply cannot and/or will not remember good passwords. Suppose we derive a 128-bit key from a 6 character password. In this case, how random is the key? That's right; it is only as random as the source from which it is derived. Since we must assume that the attacker knows our key-derivation algorithm, he really only needs to attack our 6-character password, a problem that is much easier to solve than attacking the full 128 bits of the key. Don't use a password-derived key to encrypt data. If you must use a password, your only acceptable option is to require a long password that contains at least as many bits of entropy as the key length. Entropy essentially means unpredictability or randomness, and there are public formulas available for calculating the entropy of a string password.  You'll want to implement such an algorithm to verify the strength of the user's password in any system that uses passwords to derive keys in order to ensure a strong key.

Another key source is a Pseudo Random Number Generator (PRNG). Randomness is difficult to achieve using a computer, because the operation of a computer is very predictable and highly non-random. Don't try to roll your own PRNG. Instead, rely on the built in technology provided by the RNGCryptoServiceProvider class to generate random bytes. The underlying implementation of this PRNG is what is used by the GenerateKey method of the FCL ciphers, as we will discuss later.

You might also like...

Comments

About the author

Steve Johnson United States

Steve is a senior developer and consultant for 3t Systems, Inc. in Denver, CO, where he spends his days doing architecture, training, and "in-the-trenches" development. Steve began programming W...

Interested in writing for us? Find out more.

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“The difference between theory and practice is smaller in theory than in practice.”