Table of Contents
The Story behind the Succinctly Series of Books
Chapter 1 What is Cryptography?
Chapter 2 Cryptographic Random Numbers
Chapter 3 Hashing Algorithms
Chapter 4 Password Storage
Chapter 5 Symmetric Encryption
Chapter 6 Asymmetric Encryption
Chapter 7 Hybrid Approach (RSA+AES)
Chapter 8 Digital Signatures
Closing Notes
Further Reading
Detailed Table of Contents
Introduction
Throughout history, cryptography has been used to confidentially pass messages to different recipients. This has been especially useful in times of war. Up until World War II, with the use of the German enciphering machine Enigma, messages that were encrypted were text-based. With the advent of modern computing, cryptography now tends to operate on raw data and is used to protect our communication channels, email messages, web browsing, financial transactions, and much more. Cryptography is all around us and is, normally, completely transparent to the user. However, just because you can’t see it doesn’t make it any less important. In the modern day, we face threats from cybercrime, terrorists, and our own government snooping on its citizens. Because of these threats, it is very important to understand and apply cryptography in your software solutions.
This book is aimed at .NET developers who want to understand how to use cryptography in their applications. The user is expected to be reasonably experienced as a .NET developer but no prior knowledge of cryptography and encryption is required.
This book is for developers who want to be pragmatic about encrypting data in their applications by using the .NET framework. The examples in this book target writing applications for Windows desktops and servers, which includes technologies such as console applications, Windows Presentation Foundation (WPF), ASP.NET, Windows Communication Foundation (WCF), Windows Forms (WinForms), and anything else that you might use in the enterprise.
Cryptography is an interesting subject and the math behind how a lot of these algorithms work is fascinating. However, as a developer who has to deliver systems, you don’t need that level of knowledge. You just need to know what algorithms are safest to use and how to use them, and that is exactly what this book aims to teach.
The source code examples have been kept as simple as possible to show you how to apply them in your own code. You can treat the code examples in this book (and the source code project that accompanies this book) as a cookbook to which you can refer whenever you need to use any of the cryptography primitives in your own code.
Note: The source code examples from this book can be downloaded from https://bitbucket.org/syncfusiontech/cryptography-in-.net-succinctly.
Chapter 1 What is Cryptography?
Cryptography is the art of protecting information by transforming it (i.e. encrypting it) into an unreadable format called ciphertext. Only those who possess a secret key can decipher (or decrypt) the message into plaintext. Encrypted messages can sometimes be broken by cryptanalysis (also called code breaking) although modern cryptography techniques are virtually unbreakable.
As the Internet and other forms of electronic communication become more prevalent, electronic security is becoming increasingly important. Cryptography is used to protect email messages, credit card information, and corporate data.
There is more to cryptography than just encrypting data, though. There are three main security themes that are covered by cryptography and different cryptography primitives that help you satisfy each concept. These themes are:
Confidentiality
Confidentiality is what you traditionally associate with cryptography. This is where you take a message or some other data and encrypt it to make the original data completely unreadable. There are many different cryptography algorithms that you can use, but this book will cover the main primitives that are in use today, including RSA and Advanced Encryption Standard (AES). We will also cover a couple of primitives (DES and Triple DES) that are not recommended for use in new code but you may have to use them if you are writing code that deals with older legacy systems.
Integrity
In information security, data integrity means maintaining and assuring the accuracy and consistency of data over its entire life cycle. This means that data cannot be modified in an unauthorized or undetected manner. Integrity is violated when a message is actively modified in transit. Systems typically provide message integrity in addition to data confidentiality. We will cover some different cryptography primitives that you can use to help enforce data integrity including hashing algorithms such as MD5, Secure Hash Algorithm (SHA)-1, SHA-256, and SHA-512. We will also cover hash message authentication codes (HMACs) that also use MD5, SHA-1, SHA-256, and SHA-512.
In addition to standard hashing primitives, we will also discuss why it is not a good idea to use hashes to store passwords and discuss an alternative method called a password-based key derivation function.
Nonrepudiation
Nonrepudiation is the assurance that someone cannot deny something. Typically, nonrepudiation refers to the ability to ensure that a party to a contract or a communication cannot deny the authenticity of their signature on a document or the sending of a message that originated with them.
For many years, authorities have sought to make repudiation impossible in some situations. You might send registered mail, for example, so the recipient cannot deny that a letter was delivered. Similarly, a legal document typically requires witnesses to its signing so that the person who signs it cannot deny having done so.
On the Internet, a digital signature is used not only to ensure that a message or document has been electronically signed by the person that purported to sign the document but also, since a digital signature can only be created by one person, to ensure that a person cannot later deny that they furnished the signature.
In this book, we will cover digital signatures that use the RSA cryptographic primitive.
Cryptography in .NET
.NET comes with a rich collection of cryptography objects that you can use to help provide better security in your applications. The cryptography objects in .NET all live within the System.Security.Cryptography namespace.
Chapter 2 Cryptographic Random Numbers
Typically in .NET, when you need to generate a random number or a pseudorandom number, you would use the System.Random object to generate the number. For most scenarios, this is fine and will give the appearance of randomness when you apply a different seed each time. When you are dealing with security though, System.Random is not sufficient as the result of System.Random is very deterministic and predictable.
Random numbers are important in cryptography as you need them for generating encryption keys for symmetric algorithms such as AES, which we will cover in a later chapter, and also for adding entropy into hashing functions and key derivation functions.
Note: Entropy is the measure of uncertainty associated with a random variable. In cryptography, entropy must be supplied by the cipher for injection into the plaintext of a message so as to neutralize the amount of structure that is present in the unsecure plaintext message.
A better approach is to use the RNGCryptoServiceProvider object in the System.Cryptography namespace. RNGCryptoServiceProvider provides much better randomness than System.Random, but it does come at a slight cost as the call into RNGCryptoServiceProvider is much slower. However, this is a necessary trade-off if you require good quality, nondeterministic random numbers for key generation.
The following code demonstrates how to use RNGCryptoServiceProvider.
public static byte[] GenerateRandomNumber(int length)
{
using (var randomNumberGenerator = new RNGCryptoServiceProvider())
{
var randomNumber = new byte[length];
randomNumberGenerator.GetBytes(randomNumber);
return randomNumber;
}
}
Code Listing 1
Once you have constructed the RNGCryptoServiceProvider object, you make a call to GetBytes() by passing in a pre-instanced, fixed-length byte array. If, for example, you wanted to generate a random number to use as a 256-bit key for the AES encryption algorithm, you would create an array that was 32 bytes in length, as 32 bytes multiplied by 8 bits in a byte gives you 256 bits total.
Apart from speed of execution and the nondeterministic nature of RNGCryptoServiceProvider, the other difference between this and System.Random is that RNGCryptoServiceProvider is thread safe and System.Random is not.
Figure 1: Randomly generated numbers using RNGCryptoServiceProvider
In the sample code, we generate 10 sets of 32-byte random numbers by using the RNGCryptoServiceProvider and write the results to the console window. The GenerateRandomNumber method returns a byte array that is the same size as the parameter that you pass into the method. When we output the random number onto the screen, we first convert it to a Base64 string. This is common practice when displaying the results of a cryptographic operation on the screen.
Note: Base64 is a group of similar binary-to-text encoding schemes that represent binary data in an ASCII string format by translating it into a radix-64 representation. The term Base64 originates from a specific MIME content transfer encoding.
for (int i = 0; i < 10; i++)
{
Console.WriteLine("Random Number " + i + " : "
+ Convert.ToBase64String(Random.GenerateRandomNumber(32)));
}
Code Listing 2
If you need to convert from a Base64 encoded string back into a byte array, you call Convert.FromBase64String.
Chapter 3 Hashing Algorithms
Hashing Functions
A cryptographic hash function is an algorithm that takes an arbitrary block of data and returns a fixed-size string, the (cryptographic) hash value, such that any (accidental or intentional) change to the data will change the hash value. The data to be encoded is often called the “message” and the hash value is sometimes called the “message digest” or, simply, the “digest.”
The ideal cryptographic hash function has four main properties:
Another way of thinking of a hash function is that of creating a unique fingerprint of a piece of data. Generating a hash digest of a block of data is easy to do in .NET. There are various algorithms you can use such as MD5, SHA-1, SHA-256, and SHA-512.
Figure 2: Hashing functions versus encryption functions
As illustrated in the preceding diagram, a hash function is a one-way function. That means once you have hashed some data, you cannot reverse
Verlag: BookRix GmbH & Co. KG
Tag der Veröffentlichung: 01.02.2016
ISBN: 978-3-7396-3507-1
Alle Rechte vorbehalten