O uso mais comum é fazer uma informação secreta
Criptografia

São 4 as áreas que a criptografia cobrem:
Confidencialidade:
Integridade:
Não repudiação:
Autenticação:

Encriptação simétrica é quando a mesma senha é utilizada para encriptar e decriptar

NIST – National Institute of Standards and Technology
RSA (Rivest-Shamir-Adleman)
AES Advanced Encryption Standard
Rijndael – Vincent Rijmen and Joan Daemen
PBKDF2 – password based key derivation function
PKCS – Public Key Cryptographic Standards


Building Secure Applications with
Cryptography in .NET
Course Overview


Introduction

Hashing is commonly used to check the integrity of data and provide an equivalent to a digital fingerprint.
A digital signature is a technique used to validate the authenticity and integrity of a message, software, or digital document.


What Is Cryptography?
Before we proceed to the main content of this course and look at practical
cryptography in .NET, let’s first take a look at some background information about
cryptography itself.
The most common use case for cryptography is that of making some information secret. This is done using a process called encryption.

In this example, we have a message that reads Meet under the clock tower at 12pm. Wear a red rose on your lapel.
Through encryption we want to turn that message into an unreadable form so that it can be sent to a person who wants to read it. To do this, you encrypt the message with a secret key. Only you and the recipient know that key. Once the message has been encrypted, you can send
that message to the recipient. The message they receive will be in a completely unreadable form. Before they can read the message, it will need to be decrypted.
To decrypt the message, you need to run the message with the same algorithm using the secret key that is known to both parties. If they have the same key, then
the contents of the message will be revealed. This is just one example of encryption. The type of encryption described here is called symmetric encryption because the same key is used to both encrypt and decrypt the message, provided both the sender and the receiver have that same key.
Symmetric encryption is powerful, but it does come with its own set of challenges, in that you have to be able to securely share the key with multiple parties, which is easier said than done.
To help mitigate this problem, there’s another type of encryption called asymmetric encryption.

Security Concepts
Cryptography covers many different types of security operation.
There are four main areas that are covered by cryptography
The first: 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.

The second: Data Integratity. In information security, data integrity means maintaining and assuring the accuracy and consistency of data over its entire lifecycle.
This means that the 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.

The third: Nonrepudiation. Non-repudiation is the assurance that someone cannot deny something. Typically, non-repudiation 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.
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 that document, but also, since a digital signature can only be created by one person, to ensure that a person cannot later deny that they have furnished the signature.

The fourth: Authentication. Using a cryptographic system, we can establish the identity of a remote user or system. A typical example is the SSL certificates on a web server, providing proof to a user that they are connected to the correct server.
The identity is not of the user, but the cryptographic key of the user. Having less secure key lowers the trust that we place on the identity.

Cryptographic Random Numbers

Why Are Random Numbers So Important?
Most encryption algorithms require a source of random data to generate their encryption keys. Most computers do not have a hardware-based random number generator available, so programmers have had to resort to software-based techniques to generate random numbers as best they can.

Because these random numbers are generated in software, they are very rarely truly random.
To generate this random data, you need a source of entropy or random inputs. Others will take
events such as hard drive activity or network activity for that source of entropy.
You can also use a hardware device to generate a secure random number. These devices are called hardware security modules.

System.Random and It’s Problems
In .NET, when you need to generate a pseudorandom number, you might use the System.Random class to generate that number. The number generator works by providing a seed value when the object is constructed. For most application scenarios, this is fine, and we’ll get the appearance of randomness when you apply a different seed every time. When you are dealing with security though. System.Random is not sufficient. As a result, is deterministic and predictable. The current implementation of the System.Random class is based on Donald E. Knuth’s subtractive random number generator algorithm taken from his book, The Art of Computer Programming, Volume 2: Seminumerical Algorithms, published by Addison-Wesley.

In his book, he states a subtractive number generator calculates a sequence of random numbers where each number is congruent to the subtraction of the two previous numbers from the sequence.
So we know that System.Random is not useful as a tool for creating cryptographically secure random numbers due to it being deterministic and predictable.

Secure Random Numbers with RNGCryptoServiceProvider Random numbers are very important in cryptography. You need them for generating encryption keys for symmetric algorithms such AES and for writing randomness to hashing functions and key derivation functions. We will use the RNGCryptoServiceProvider class to generate the random numbers that we need for our cryptographic applications. This is a much more secure way of generating these numbers. The tradeoff to these much more secure random numbers is that RNGCryptoServiceProvider is much slower to execute compared to System.Random. This is a small tradeoff though when you want to do random numbers being generated to use these encryption keys.
So let’s now take a look at a demo of how to use RNGCryptoServiceProvider.


Hashing Algorithms

What Is Hashing?
Hashing is a fundamental primitive used within cryptography.
A cryptographic hash function is an algorithm that takes an arbitrary block of data, passes it through a hashing function, and returns a fixed size block of data, the cryptographic hash value, such that any accidents 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 often called the message digest, or simply the digest.
The ideal cryptographic hash function has four main properties.
First:
– It is easy to compute the hash value for any given message, and then it is infeasible to generate a message that has a given hash. What this means is that you should not be able to pick a particular hash value and create the original message that generates that hash.
Next we have it’s infeasible to modify a message without changing the hash. What this means is if you generate a hash for a particular message, if you change just one bit of the original message and recalculate the hash, the resulting hash should be totally different to the original hash message.
And finally, it should be infeasible to find two different messages with the same hash value. This is also referred to as a hash collision.

A good hash function should guard against being able to generate the same hash code or digest for two different messages. Another way of thinking of a hash function is that of creating a unique fingerprint for a piece of data.
For any data that you pass through a hash function, its digital fingerprint should be unique. If the data changes, even just by one bit, then the fingerprints will be completely different.

There are various different hashing algorithms that you can use, such as MD5 and the Secure Hash family, such as SHA-1, SHA-256, and SHA-512.
Each of the hashing algorithms share a Base Class Library called HashAlgorithm.
A hash function is a one-way function. That means once you have hashed some data, you cannot reverse it back to the original data.
On the flipside to this, encryption is designed to be a two-way operation.

Once you have encrypted some data using a key, you can reverse the operation and decrypt the data by using that same key.
When you hash some data, the hash will be the same every time you perform the operation unless the original data changes in some way.
Even if the data only changes by one bit, the resulting hash code should be completely different. This makes hashing the perfect mechanism for checking the integrity of data.

Hashing is useful when you want to send data across a network to another recipient, and that recipient wants to check whether the data that was sent is intact and has not been tampered with or corrupted.

MD5 and Secure Hash
The two most common hashing methods used are MD5 and the Secure Hash family of hashes, such as SHA-1, SHA-256, and SHA-512.
MD5 was designed by Ron Rivest at the RSA Security Company in 1991 to replace MD4, an earlier hash function.
The MD5 message-digest algorithm is a widely used cryptographic hash function that produces a 128-bit, or 16-byte, hash value, which is typically expressed in text form as referred to by a hexidecimal number, or a Base64 encoded string.
MD5 has been used in a wide number of cryptographic applications and is also commonly used to verify file integrity.
In 1996, a flaw was found in the design of MD5 where it was possible to detect hash collisions where parts of the hash could be the same across multiple messages.
While it was not deemed a fatal weakness at the time, cryptographers began to recommend the use of other algorithms, such as the Secure Hash family.
In 2004, it was shown that MD5 contained further hash collision resistance problems, which means that it is possible to generate an MD5 hash of two sets of data, which could result in the same hash, although this was quite rare. You may still need to use MD5 in your applications if you’re checking the integrity of data coming from a legacy system that makes use of MD5.
So it is still relevant to discuss MD5 in regard to legacy application support. The Secure Hash family is a family of cryptographic hash functions published by The National Institute of Standards and Technology, also known as NIST. The Secure Hash family comes from different variants, including SHA-1, which is a 160-bit hash function, which resembles the earlier MD5 algorithm. This was designed by the National Security Agency to be part of their digital signature algorithm. Cryptographic weaknesses were discovered in SHA-1, and the standard was no longer approved for most cryptographic uses after 2010. Then we have SHA-2, which is a family of two similar hash functions with different block sizes known as SHA-256 and SHA-512. They differ in their word sizes. SHA-256 uses 32-bit words where SHA-512 uses 64-bit words.
These versions of the Secure Hash family were also designed by the National Security Agency. And then we have SHA-3, which is a hash function based on the Keccak cypher, which was chosen in 2012 after a public competition among non-NSA designers. It supports the same hash lengths as SHA-2, and its internal structure differs significantly from the rest of the Secure Hash family. SHA-3 is not currently supported in the .NET family directly, although third-party implementations are available.


Hashed Message Authentication Codes
If you combine a one-way hash function with a secret cryptographic key, you get what is called a hash message authentication code, or HMAC for short.
Like with a hash code, a HMAC is used to verify the integrity of a message. A HMAC also allows you to verify the authenticity of a message because only a person who knows the key can calculate the same hash of that message.
A HMAC can be used with different hashing functions like MD5 or the secure hash family of algorithms. The cryptographic strength of a HMAC depends on the size of the key that is used. And the most common attack against a HMAC is a brute force attack to try and uncover that key. HMACs are substantially less affected by collisions than their underlying hash algorithms, as the addition of the secret key adds entropy to the hashing operation. HMACs are use when you need to check for both integrity and authenticity of a message. For example, consider a scenario in which you are sent a piece of data along with its hash. You can verify the integrity of the message by recomputing the hash of that message and comparing it with a hash that you’ve also received. However, you don’t know for sure if the message and the hash were sent by someone you know or trust. If you use the HMAC, you would recompute the HMAC using a secret key that only you and the sender know, and compare it with the HMAC that you just received. This is the purpose of authentication, which is one of the security pillars that we looked at in the introduction of this course.


Secure Password Storage

How Not to Store Passwords
When you’re developing a system that needs to authenticate a user and set up passwords, you need to store those passwords somewhere that the user can come back later to log in.
Generally, this might be a SQL or a NoSQL database. There are various techniques you can use to encode the password, but the biggest mistake that you can make is storing passwords as clear text in your database.
To do so counteracts the very benefits of having passwords in the first place, which is to authenticate and grant access to a system using the password known only by the user. Once a system needs to be able to verify a password, that system should never need to know what the actual password is. A big risk here is that if your database is ever compromised and the password tables are stolen, the attacker doesn’t have to do much hard work to gain access to your customers’ accounts. They just log in with the username and the passwords that were stolen from your database. This could have catastrophic consequences for your business.
Encryption is a two-way process .You can create using a key and then decrypt with same key. This is called symmetric encryption. This mechanism could be used to store passwords, and it’s certainly much better than storing passwords in the clear. But this approach comes with its own set of problems and challenges. If the password tables are compromised as before with our example of passwords being stored in the clear, the attacker will have access to a full table full of encrypted passwords. They might be thinking this is good because they can’t see the actual passwords. Well, yes, it is. But you also have to manage the encryption keys used to store those passwords. Where do you store those keys? What happens if the key has been stolen? Do you then have to decrypt and re-encrypt all of your passwords with a new key? While the passwords themselves are encrypted so that it cannot be read, the overhead of managing the keys is actually quite a big headache. Instead of encrypting the passwords, hashing passwords has also been a common technique, where you take a password, hash it with something like SHA-256, and then store that hash in the database.

As we discussed earlier in the course, hashing is a one-way function, so you shouldn’t be able to reverse engineer the password back from the original hash.

Whilst hashing the password with an algorithm like SHA-1 or SHA-256 seems like a much better solution, it does have some shortcomings.
Hashing a password is susceptible to two different attacks, that is, a brute force attack or a dictionary or rainbow table attack.
A brute force dictionary attack is where the attacker will try a different combinations of passwords until they get one that matches the password hash.
This is easier if the attacker has already compromised your hash password tables from your database.
To try and make passwords stronger, people tend to try adding in different characters, like turning vowels into numbers in the hope that this will make their password stronger. But it really doesn’t make that much difference to anyone doing a brute force attack. It may sound like a lot of work to try and break a password this way, but with the advent of modern processors and graphics processing units, it’s possible for an attacker to try billions of passwords every second. It’s only a matter of time until they get the correct password. Unfortunately, people still tend to pick weak passwords based on names and other simple words, so a brute force approach like this is remarkably effective.

An alternative attack from a brute force attack is that of a rainbow table. A rainbow table contains a large dictionary of precomputed hashes for different passwords.
These tables are used to determine the original plain text of a password from already precomputed password hashes. Rainbow tables can be many gigabytes in size, and they greatly speed up attacks to recover the original value of a password. A better approach is to increase the entropy of the password being attacked by making the password harder to recover. Entropy, in this case, is a measure of a password strength and how easy it is to guess. If you extend the password of additional random letters and numbers, then this is much harder to get an attack by either using a brute force attack, a dictionary attack, or a rainbow table attack. This type of storage mechanism can be done by adding a salt onto the password before hashing. The salt can be generated as a random number and then appended to the password before hashing. By adding a salt, you’re making the password a lot more complex, and this makes a brute force or rainbow table attack much harder. To check if a password is correct, we need the salt, so it’s usually stored in the database along with the hash. An attacker won’t know in advance what the salt would be, so they can’t precompute a lookup table.
Each time you hash a new password, you should use a new salt value. This means that if two users have the same password, because the salts are different each time, the hashed password would look completely different, even though the passwords are the same.

Password Based Key Derivation Functions
The problem with hashing and storing a password, even with salt, is as processes get faster over the years, we run the risk of what we currently think of secure passwords being compromised because the processes can perform a brute force attack and a rainbow table attack much faster. What we need is a solution that allows us to still hash our passwords with a salt, but it helps us guard against advancements in Moore’s law. The solution here is use what is called a password based key derivation function, or a PBKDF2, as it is also known. A PBKDF2 is part of the RSA Public Key Cryptographic Standards series, otherwise known as PKCS #5 v2.0. The part of a base key derivation function is also part of the Internet Engineering Taskforce’s RFC2898 specification. All of this terminology makes this process sound a little scary and hard to use, but in reality, apart from the intimidating name, this method of hashing passwords is actually very easy to use in .NET. A password based key derivation function takes a password, a salt to an additional entropy to the password, and a number of iterations value. The number of iterations value repeats a hashing operation over the password multiple times to produce a derived key for the password that can then be stored in the database. By repeating the hashing process over the password multiple times, you are algorithmically slowing down the hashing process, which makes brute forcing against attacks of the password much, much harder to do. This means that fewer password brute force attempts can be done at once. As processes get faster over time, you can increase the number of iterations used to create the new password hash, which means password based key derivation functions can scale with Moore’s law. A good default to start with a number of iterations is around 100,000. This means when you call the password based key derivation function, the password will be hashed 100,000 times before it’s returned to you. You need to pick a number of iterations that gives you suitable security versus performance for your system. For example, if you’re using a password based key derivation function as part of the user authentication with your system, then it’s the additional delay encountered for the chosen number of iteration cycles acceptable. For example, if you log into an ecommerce website, you may notice that sometimes, once you’ve hit return after entering your password, there might be a delay for a couple of seconds. The chances are that there is a password based key derivation function, or something similar, happening behind the scenes to rehash your password. You need to pick a number of iterations, which introduces a delay as acceptable to your needs.
Ideally, this number of iterations factor needs to be changed and preferably doubled at least every two years. You can manage this as part of your standard password updating process. If you force your staff or customers to update their passwords every x months, then you can design your system from a specific point in time when a new password is hashed and stored to use the larger number of iterations. By also adding the salts to your derivation function, you further reduce the ability of a rainbow table to be used to recover the original password. The salt should be unique for each password. As we discussed previously, the salt is not a secret value, so it can be stored in the database along with your hash password. A good minimum length for your salt is at least 64-bit, or 8-bytes. The .NET class that we’re going to use to perform the key derivation function is called Rfc2898DeriveBytes. When constructing this object, you pass in the data to be hashed as a byte array. The salt is a byte array and the number of iterations you want the algorithm to perform. The salt in our code demo is generated using the RNGCryptoServiceProvider class as previously discussed in the module on secure random number generation. The salt doesn’t have to be kept secret and can be stored alongside the hash password, and a salt’s purposes to give added entropy to the password being hashed. So let’s go and look at a demo.

 

****************Feito até aqui acima**************

Password Based Key Derivation Functions Demo
In the following code demo we’ll use the RFC2898DeriveBytes class in .NET to hash a password to a different number of iterations. We’ll also use a Stopwatch
object to time how long these different variations take.
So let’s get started. In the Solution file for the example code, I want you to, again, go into Solution folder 2 called Hashing.
And in here I have a project called PBKDF2. So if we open this up, we have a two files in here. So first of all, let’s look at PBKDF2.cs.

Now in here, I have a public static method called GenerateSalt. Now what this is doing is, it’s generating a 32-byte random number, so that’s a 256-bit random number in total.
Now this is what we’re going to use to generate our salt. So this code is pretty much identical to what we’ve seen earlier in the course, and it returns a byte array which contains our 32 bytes of random data.
Now the actual code for performing the password-based key derivation function hash is incredibly simple.
It’s just a few lines of code. So let’s look for it. So we have a method, a public static method, called HashPassword. Now this method takes a byte array, which is the password we want to be hashed.
So again, if your password is a string, we need to convert it to a byte array first. It takes a byte array containing our salt, and it also contains a numberOfRounds, which is our number of iterations, so that’s how many times we want the password to be hashed.
Now to use this, it’s very simple. So we have a class called Rfc2898DeriveBytes.
Now this is a bit of a strange name for a class, so if you’re quite familiar with RFC specifications numbers, then this makes complete sense. It’s RFC2898, which is a specification for a password-based key derivation function.
Now if you’ve never come across that specification before, which I hadn’t when I started learning this stuff, this class is very easy to just easily gloss over in the MSDN documentation because it’s a bit of a strange name, so you don’t really think much of it.
But actually, this is incredibly powerful, and as a tool for hashing passwords, it is incredibly fundamental and easy to use, which is fantastic. So what we do is, we construct an instance of Rfc2898DeriveBytes, and we pass in our data to be hashed, we pass in our salt, and pass in numberOfRounds.
Then to generate the hash we call GetBytes on our rfc2898 object. Now you’ll notice that we pass in 20.
So we’re saying we want it to generate and retrieve 20 bytes. The reason for this is because Rfc2898DeriveBytes internally uses SHA1 as its hashing algorithm.
Now SHA1 only gives you a 20-byte hash, so there’s no point requesting any more than that. It’s just 20 bytes that we want.
But at the point when we get that 20-byte array back, if you passed in, say, 100,000 into your numberOfRounds, that SHA1 operation’s going to be called 100,000 times before you get those 20 bytes back.
So let’s look at Program.cs, which is our example. So what I have here is, I’m going to be hashing a password, so I’ve got a password here called VeryComplexPassword.
Also a very terrible password, but is fine for illustration purposes. Now I have a little helper method here that we’ll look at in a second.
I’m going to hash its password multiple times, but I’m going to start off with 100 iterations, then 1000, then 10,000, 50,000, 100,000, 200,000, then half a million.
What we’re going to do, as you can see here is, we’re going to set a Stopwatch, and that Stopwatch is going to time how long it takes each of those password-based key derivation functions to execute.
So what we should see is, as the number of iteration counts goes up, it’s slower to retrieve the password.
So let’s just step into this and take a look at what’s going on. So we’re going to step into our HashPassword helper method here, and we start the Stopwatch.
Now, the Stopwatch aspect at the moment is kind of pointless because I’m trapped in the debugger so the times are going to be all over the place, so we will rerun it.
And what I’ve done is I’ve stepped over our HashPassword method in the PBKDF2 object, and you can see we’ve retrieved a 20-byte password back.
We step into that individually, so we here we’re creating our salt, and then I’ve constructed the Rfc2898DeriveBytes object, I’ve passed in our password to be hashed, the salt, and the numberOfRounds.
In this case, it’s 50,000. And then I call GetBytes(20), and that’s going to have done 50,000 SHA1 hashes before it gives us the password back.
And what I’m going to do is, I’m going to stop running this because we’re dependent on the stopwatch. Being trapped into the debugger has completely thrown all the timings off.
So let’s remove the breakpoint and then just let it run. Okay, so we’ve got some interesting timings here.
So the very first iteration was 100. Now it’s given us 103ms, but it’s probably because .NET was doing some precompiling behind the scenes, so let’s ignore that one and start with the next one, which is 1000 iterations.
So that operation took 2ms to calculate, Then the next one, which is 10,000 iterations, took 6ms; 50,000 iterations took 53ms; 100,000 seemed to be a bit faster and it took 49ms, for some reason; 200,000 iterations took 125ms; half a million took 362ms.
So generally, apart from a few little edge cases there, you can see the actual process of increasing the integration counter slowed down the hashing process, which is exactly what you want.
So now I’m running this currently on a fairly powerful 6 core machine, so it didn’t take too long to run those iterations.
But if you imagine setting your iteration count to a million or 2 million or 5 million, then you can see that this is going to quite drastically start slowing down that iteration process.
So in this case, 362ms in computing terms is an eternity. Now, just before we end this demo, I just want to make you aware of some other code.
So If we look in the HashPassword project up here, as I’ve said, using a PBKDF2 is kind of the preferred technique to use if you can. But what I’ve done in here, just for illustration purposes, I have done an example of doing a standard salted hash.
So if we go into hash.cs, we can see we’ve got a GenerateSalt method here, which, again, provides us a 32-byte random number.
And then I have a method here called HashPasswordWithSalt. Now what’s happening here is, I’m taking a password to be hashed as a byte array. I’m taking the salt.
I create a SHA256 object where I call the static Create method on the SHA256 object, just like we looked at in the last module.
And then I call ComputeHash. But you can see what I’m doing here is, I’m calling a little helper method here called Combine, and I’m passing in two byte arrays.
The first one is our password to be hashed, and the second one is the salt. And what this is doing is, it’s creating one byte array with both of those two arrays combined.
So what that effectively means, if you imagine they weren’t byte arrays, and that they were strings, I’ve effectively just combined the two strings together.
But in this instance, I’ve got two byte arrays, and I just copied them together. So if we look at the example code for this, and it’s very simple. We have a VeryComplexPassword here. I create a salt or generate a salt, and then what I do is I call my HashPasswordWithSalt.
I convert the password into a byte array. I also pass in the salt, and that returns the salted password for us.
So I’m not going to step through that in any detail, but I will just quickly run it just so you can see the output. So we’ve got the password, which is VeryComplexPassword.
We have the salt, which I’ve converted to Base64 string and put on the screen. And what we do is, we got that complex password and the salt, combine them together, and then hash those as one unit, which gave us our Hashed Password that you can see on the screen there.
So whilst a passwordbased key derivation function is a preferred way of doing this in .NET, I’ve just thought it’d be interesting to include the salted hash version just for your general information.

Summary
In this module, we’ve talked exclusively about securely storing passwords. We started off by discussing how it is a very bad idea to store passwords in the clear in your database.
If your password tables were ever stolen by an attacker, then they’ll very easily be able to gain access into your systems.
We then looked at encrypting passwords as an alternative. Whilst this is a better solution, it does come with its own set of challenges, and you have to deal with the management and the storage of the cryptographic keys, be they symmetric or asymmetric.
We also discussed how encryptions are a two-way operation where an encrypted password could be decrypted, but you should never actually need to be asked to
decrypt a password.
This led on to a discussion of using hash functions like SHA256 to encode your passwords. Unlike encryption, which is a two-way operation, hashing is a one-way operation only, meaning you shouldn’t be able to divide the original password from the hash.
Straight hashing of passwords does open you up to two types of attack, though. The first type of attack is a brute force dictionary attack, where an attacker we use a large dictionary of words and various combinations and substitutions to try and recreate a hash password.
Once I get a matching hash, this means a part of it’s been filled. The second type of attack is a rainbow table attack where an attacker uses a large database of pre-computed hashes to work out the password that created the hash.
We then discussed a better version of password hashing that adds a random salt value to the password before its hash to add entropy onto that password. This salt value should be unique for each password hashed. This means that if two users have
the same password, because I used a different salt, the hash password would look totally different. The hash value doesn’t have to be kept secret, so it’s okay to
store along with the hash password in the database. We then took the salted hash concept one step further by introducing a password-based key derivation
function. This is very similar to the salted hash, except that it incorporates a third element, which is a number of iterations value. This number of iterations value
is designed to make the hashing process algorithmically slower. This is required as current modern processes and GPUs can process tens of billions of operations
per second. So as hardware scales with Moore’s Law, it means passwords will be easier to brute force over time. By making the hashing operation algorithmically slower, this limits the amount of passwords that can be checked in a fixed period of time.

Symmetric Encryption
Overview
Welcome back to my course, Building Secure Applications with Cryptography in .NET. In this module, we’re going to talk about symmetric encryption. We’re first going to talk about what symmetric encryption is. Then we’ll briefly talk about the DES and Triple DES algorithms. These are not recommended for use in new systems, but it is useful to know about them when you need to work on an older legacy system. Next, we’ll talk about the Advanced Encryption Standard, which is a preferred encryption algorithm to use these days. Primarily, we’ll be working with a mode called cipher block chaining. Next, we’ll talk about two new AES encryption modes called GCM and CCM, and these were introduced into .NET with the .NET Core 3.0 release. If you’re building a new system, then GCM and CCM are the modes that you might want to look at. Finally, we’ll look at a way of storing AES keys using a class called ProtectedData. So let’s get started by looking at what symmetric encryption actually is.

What Is Symmetric Encryption?
Symmetric encryption is a two-way encryption process that uses the same key for both encryption and the decryption of your message.
In the diagram you can see on the screen, you can see we have plain text of our original data represented on the left, which is then encrypted with a key to produce an encrypted cipher text.
Then that data is decrypted using the same key to uncover the original data or plain text.
Therefore, this process is referred to as symmetric encryption, as we’re using the same key for both encryption and decryption.

When using a secure algorithm, symmetric key encryption is extremely secure. One of the most widely used symmetric key encryption systems is the US government designated Advanced Encryption Standard.
One of the drawbacks of public key encryption systems like RSA, which we’ll explore in the next module, is they need relatively complicated mathematics to work, making them computationally intensive and quite slow. Encrypting and decrypting a symmetric key algorithm is more algorithmic and, therefore, more performant and fast on a computer.
The biggest problem with symmetric key encryption is you need to have a way to get the key to a party you are sharing data with. Encryption keys aren’t simple strings of text like passwords.
They’re essentially blocks of random data. As such, you need to have a safe way to get the key to another party. There are ways to use the power of symmetric encryption with a good key sharing scheme, which we’ll look at later in this course when we explore hybrid encryption.
When somebody gets their hands on a symmetric key, they can decrypt everything encrypted with that key. When you’re using symmetric encryption for two-way communications, this means that both sides of the conversation can get compromised. With asymmetric public key encryption schemes like RSA, someone that gets your private key can decrypt messages sent to you, but they can’t decrypt messages that are sent to another party since that is encrypted with a completely different key pair.


DES and Triple DES
In a new system, you never want to use DES or Triple DES.
There’s so much older legacy systems may still maintain data that is encrypted with it.
The Data Encryption Standard, or DES, as it is known, was developed in the early 1970s at IBM. And later, in 1977, the algorithm was submitted to the National Bureau of Standards to be approved as Federal Information Processing Standard 46, otherwise known as FIPS 46.
With consultation of the National Security Agency, the National Bureau of Standards accepted a slightly modified version of DES, which became the FIPS 46 standard.
The data is encrypted in DES using 64-bit blocks where the input data to be encrypted is split into 64-bits or 8-byte chunks, which are encrypted using a 56-bit symmetric key to provide confidentiality and privacy.
The original DES cipher key size of 56-bits was generally sufficient when the algorithm was designed, but the availability of increasing computational power made brute force attacks more feasible.
There are several projects to try and break the DES standard. The most well-known is the DES challenge project. DESCHALL, short for DES challenge, was the first group to publicly break a message, which used the Data Encryption Standard, becoming the $10,000 winner of the first set of DES challenges proposed by the RSA security company in 1997.
It was established by a group of computer scientists led by Rocke Verser, assisted by Justin Dolske and Matt Curtin and involved thousands of volunteers who ran software in the background on their own machines connected by the internet.
They announced their success on June 18th, only 96 days after the challenge was announced on January 28th.
Once DES had been compromised, there was a race to find something more secure.

The answer to that was a modified algorithm called Triple DES, which, as the name suggests, encrypts data three times using DES. The first variation uses three separate 56-bit keys.
The data is first encrypted with key 1, then key 2, and then finally key 3. To decrypt the data, the operation is carried out in the reverse direction.
First, you decrypt with key 3, then key 2, and then finally, key 1.
The second variation only uses two keys. To encrypt the data, you encrypt with key 1, then key 2, and then finally, again, with key 1. And then, again, to decrypt it, you
go in the reverse direction with key 1, then key 2, and then finally key 1.


DES, Triple DES, and AES, will show a common programming interface and that they derive from the symmetric algorithm base class.


Advanced Encryption Standard (AES)
AES, which stands for the advanced encryption standard. The AES is the latest encryption standard adopted by NIST in 2001 for the symmetric encryption of messages.
The AES algorithm was selected as part of a contest to find a replacement for the data encryption standard.
The AES, which is also referenced as Rijndael, which is its original name, is a specifications for encryption of electronic data established by the United States National Institute of Standards and Technology, otherwise known as NIST.
The Rijndael Cipher was developed by two Belgian cryptographers, Joan Daemen and Vincent Rijmen, who submitted a proposal to NIST during the AES competition selection process.
Rijndael is a family of ciphers with different key and block sizes.
The AES NIST selected three members of the Rijndael family, each with a block size of 128 bits with 3 different key lengths, 128, 192, and 256-bit keys.
AES has been adopted by the US government, it’s now used worldwide.
Like with DES, the algorithm described by AES is a symmetric key algorithm meaning the same key is used for both encrypting and the encryption of the data.
In the United States, AES was announced by NIST as the standard FIPS 197 on November 26, 2001. The announcement followed a 5-year standardization process in which 15 competing designs represented and evaluated before the Rijndael Cipher was selected as the most suitable.
AES became effective as a federal government standard on May 26, 2002 after approval by the US Secretary of Commerce.
AES is available in many different encryption packages and is the first publicly accessible and open cipher
approved by the National Security Agency for top secret information when using an NSA approved cryptographic module.
Aqui colar o diagrama do AES
The encryption process is split into several intuitive rounds. Once I have finished, there is a final round that is performed.
These are performed on what is called a block where a block represents a small piece of data that you want to encrypt.
You don’t need to encrypt all your data at once, it is split down into smaller pieces and these smaller pieces are what are called the blocks.
The number of times each round is repeated, its dependence on the key size. So 10 rounds of repetition is used for 128-bit keys, 12 rounds of repetition is used for 192-bit keys, and finally, 14 rounds of repetition is used for 256-bit keys.
Each round consists of several processing steps, each containing four similar, but different stages, including one that
depends on the encryption key itself.
A set of reverse rounds will apply to transform Ciphertext back into the original plain text using the same encryption key.
Round keys are derived for each round from the cipher key using a key schedule.
AES requires a separate 128-bit round key block for each round, plus one extra. So how secure is the advanced encryption standard? Governments or businesses place a great deal of faith in the belief that AES is so secure that its security key could never be broken. Also, the key infusion encryption determines a practical feasibility of performing a brute force attack with longer keys exponentially more difficult to crack than shorter ones.
A brute force attack involves systematically checking all possible key combinations until the correct key is found and there is one way to attack when it is not possible to take advantage of other weaknesses in an encryption system.

Colar a tabela de tempos de ataques para o AES
The table on the screen now shows a possible number of key combinations with respect to a key size.
Highlighted are different key lengths for DES and AES. Notice in the table the exponential increase in possible combinations as the key size increases.
DES is part of a symmetric cryptography algorithm with a key size of 56 bits that has been cracked in the past using a brute force attack. There is an argument that 128-bit symmetric encryption keys are computational secure against a brute force attack. Consider the times to crack in this table compared to key sizes. As shown in this table, even if a supercomputer with today’s standards, it would take 1 billion billion years to crack the 128-bit AES key using a brute force attack. This is more than the age of the universe, which is 13.75 billion years. Of course, we don’t know what the future of computing holds in store for us, but for the moment, AES is a very secure algorithm and it hasn’t been compromised by brute force attacking it. Even though 128-bit key should be more than sufficient, it is common to use a 256-bit key in practice. Let’s watch our code demo for AES we’ll use in a bit. Like when we took a brief look at DES and Triple DES, the AES implementation also inherits from the common abstract base class called SymmetricAlgorithm. This means that once you know how to use one of the algorithms, you know how to use them all as you’ll see in the demo. The
SymmetricAlgorithm class has some common parameters that we need to populate. The first is the CipherMode. Block cipher algorithm such as AES, DES, and triple DES encrypt in data blocks rather than in single bytes at a time. Block ciphers use the same encryption algorithm for each block. Because of this, a block of plain text will always return the same Ciphertext when encrypted with the same key and algorithm.
Because this behavior can be used to crack a cipher, cipher modes introduce that modify the encryption process based on feedback from the earlier block encryptions. The available encryption modes are cipher block chaining, or CBC, Ciphertext feedback, CFB, Ciphertext stealing, CTS, electronic codebook, ECB, or output feedback mode, OFB. In terms of the overall security of the AES algorithm and its mode of operation, with the AesCryptoServiceProvider implementation in .NET, the best default to use here is cipher block chaining.
Since .NET core 3.0, there are 2 new modes that are available called CCM and GCM, but these are not available in the AesCryptoServiceProvider code. While CCM and GCM are not new modes to AES, they have only recently just been added to .NET Core. But for now, we’re going to look at how to use the cipher block chaining mode.
If the project you are working on uses a version of .NET prior to .NET Core 3 and it’s perhaps now a legacy system, then it will most likely be using cipher block chaining with AesCryptoServiceProvider, which is what we’re going to explore first.

Padding specifies what paddings were applied to a message block being encrypted, which is shorter than the full number of bytes needed for a cryptographic operation.
There are different padding schemes included like ANSI X923, ISO 10126, none, PKCS7, or just all zeros.
The default padding in .NET for AES, DES, and Triple DES is PKCS7, and unless you have a good need to change it, you should just go with the defaults, which is what we’re going to do in our demos.
The key property is a byte array that is used to store the encryption key prior to running encrypt and decrypt operations. You can call the RngCryptoServiceProvider object and generate a byte array of the desired key length or you can call the generateKey method on the AesCryptoServiceProvider class.
Internally, the generateKey method uses RNGCryptoServiceProvider to generate its key, either way is fine.

The final property you need to provide when using AesCryptoServiceProvider is the initialization vector, or IV property, and this is a byte array that is used to store an arbitrary number that can be used along with your secret key for data encryption.
This number, also referred to as a nonce or number once, is employed only one time in any encryption session. The use of an initialization vector prevents repetition and encryption making it more difficult for a hacker who is using a dictionary attack to find patterns to break a cipher. The initialization vector for AesCryptoServiceProvider is 16 bytes in length and needs to be shared with the person decrypting the data. The initialization vector is not considered a secret piece of information, but it is required for successful decryption of that data. In versions of .NET prior to .NET Core 3, there are 2 implementations of AES provided.
There is AesManaged and AesCryptoServiceProvider, but which one should you use? They both provide the same functionality in that they both implement the AES encryption specification, but a main difference is that AesManaged is a .NET specific implementation, whereas, AesCryptoServiceProvider uses the underlying cryptographic libraries in Windows, which are FIP certified.
If you want to ensure you are encrypting data with AES by using a compliant implementation, then AesCryptoServiceProvider is the implementation that you’ll want to use, especially if you need to interoperate with systems that are also compliant with FIPS 140-2. This means if you encrypt your data in AesCryptoServiceProvider, then try to decrypt it with another FIPS 140-2 certified platform say in Java, for example, then it is guaranteed to work. AesManaged does not have that guarantee. The code examples in the demo are all based around AesCryptoServiceProvider and not AesManaged, although their usage is very similar apart from their class name. The common language runtime uses a stream-oriented design for cryptography. The core of this design is CryptoStream. Any cryptographic object that implements CryptoStream can be chained together with objects that implement streams. So the streams output from one object can be fed into the input of another object. The intermediate results, the result from the first object, does not need to be stored separately. So let’s now take a look at a demo.

/***************************Parei aqui para revisar essa demo e fazer anotações se necessario******************************************************/
Advanced Encryption Standard (AES) Demo