|
Chapter 1: Encryption
1 EncryptionKey concepts in this chapter are:
If you read the Introduction, you'll recall that this book is for Visual Basic .NET programmers new to security, not security experts new to Visual Basic .NET. This book unashamedly simplifies concepts and leaves out unnecessary techno-babble with the goal of making security easier to understand and implementwithout sacrificing accuracy. For many programmers, this simplified look at security is all they will ever need, whereas others, after given a taste of security, will want to know more. In a nutshell, this book is not the last word in security; instead, it is the first book you should read on the subject. What is encryption? Before discussing how to implement encryption with Visual Basic .NET, you need to have an understanding of encryption in general. Encryption is about keeping secrets safe by scrambling messages to make them illegible. In encryption terms, the original message is known as plain text, the scrambled message is called cipher text, the process of turning plain text into cipher text is called encryption, and the process of turning cipher text back into plain text is called decryption. Encryption isn't just used in cyberspace or in mysterious government work either. You can find examples of it in everyday activities such as baseball. For example, in the game of baseball, the catcher commonly uses hand signals to suggest to the pitcher the type of ball the pitcher should throw next. Curveballs, sinkers, sliders, and fastballs all have a different hand signal. As long as the batter and others on the opposing team don't understand the catcher's hand signals, their secret is safe. Figure 1-1 shows the process of encryption as it applies to baseball. Figure 1-1 Encrypting and decrypting a secret message Computers allow us to encrypt rich messages in real time, but the underlying principle is the same as in the simple baseball example. For encryption to be effective, the sender and the recipient must be the only parties who know how to encrypt and decrypt the messages. Microsoft Windows and the .NET Framework provide robust algorithms for doing encryption, and we'll use these routines in this chapter. Unless you're an encryption expert, you shouldn't try to write your own encryption algorithm, for exactly the same reason that only aviation engineers should build their own airplanes. It's a common misconception that encryption algorithms and hash functions must be secret to be secure. The encryption algorithms and hash functions used in this book are commonly understood, and the associated source code is distributed freely on the Internet. They are, however, still secure because they are designed to be irreversible (in the case of hash functions) or they require the user to supply a secret key (in the case of encryption algorithms). As long as only the authorized parties know the secret key, the encrypted message is safe from intruders. Encryption helps to ensure three things:
Some cryptography mechanisms are one way; that is, they produce cipher text that can't be decrypted. A good example of a one-way cryptography is a hash. A hash is a very large number (the hashes in this chapter are 160 bits in size) mathematically generated from a plain-text message. Because the hash contains no information about the original message, the original message can't be derived from the hash. "What use is cipher text that can't be decrypted?" you might ask. As you'll see soon, a hash is useful for verifying that someone knows a secret without actually storing the secret. In the examples in this chapter, you'll learn how to create and use a hash for verifying passwords. You'll also learn how to use private key encryption for storing and retrieving information in a database. We'll also begin building a library of easy-to-use encryption functions that you can reuse in your Visual Basic programs.
Practice FilesIf you haven't already installed the practice files, which you can download from the book's Web site at http://www.microsoft.com/mspress/books/6432.aspx, now would be a good time to do so. If you accept the default installation location, the samples will be installed to the folder C:\Microsoft Press\VBNETSec, although you'll be given an opportunity to change the destination folder during the installation process. The practice files are organized by version of Microsoft Visual Basic, chapter, and exercise. The practice files for each chapter give a starting point for the exercises in that chapter. Many chapters also have a finished version of the practice files so that you can see the results of the exercise without actually performing the steps. To locate the practice file for a particular exercise, look for the name of the exercise within the chapter folder. For example, the Visual Basic .NET 2003 versions of the practice files for the following section on using hash digests for encrypting database fields will be in the folder
C:\Microsoft Press\VBNETSEC\VB.NET 2003\CH01_Encryption\ In many of the exercises in this book, you'll modify an employee management system, adding security features to make the program more secure. The employee management system is a sample program that adds, edits, and removes employees for a fictional company. For background on the employee management system, see Appendix A. The system uses a Microsoft Access database named EmployeeDatabase.mdb. The techniques you learn are equally relevant to Microsoft SQL Server, Oracle, DB2, and other databases. You don't need Microsoft Access to use the practice files because the database drivers are installed with Microsoft Visual Studio .NET. In some exercises, we modify the database structure. These exercises are optional. If you don't have Microsoft Access installed, don't worry: the practice files have been designed to work with the database whether or not you make the changes to the database structure .
Hash DigestsAs we mentioned earlier in this chapter, a hash is a type of one-way cryptography. Some people refer to hashing as encryption; others feel it's not strictly encryption because the hash cannot be unencrypted. A hash is a very large number, generated by scrambling and condensing the letters of a string. In this chapter, you'll use the SHA-1 algorithm. SHA-1 is an acronym for Secure Hashing Algorithm. The "-1" refers to revision 1, which was developed in 1994. SHA-1 takes a string as input and returns a 160-bit (20-byte) number. Because a string is being condensed into a fixed-size number, the result is called a hash digest, where digest indicates a shortened size, similar to Reader's Digest condensed books. Hash digests are considered to be one-way cryptography because it's impossible to derive the original string from the hash. A hash digest is like a person's fingerprint. A fingerprint uniquely identifies an individual without revealing anything about that personyou can't determine someone's eye color, height, or gender from a fingerprint. Figure 1-2 shows the SHA-1 hash digests for various strings. Notice that even very similar strings have quite different hash digests.Figure 1-2 SHA-1 hash digests It's common, as shown in Figure 1-2, to display a hash as a base-64 encoded 28-character string. This is easier to read than a 48-digit (160-bit) number. Hash digests are useful for verifying that someone knows a password, without actually storing the password. Storing passwords unencrypted in the database opens two security holes:
Because the password is used solely for authenticating the user, there's no reason to store the password in the database. Instead, a hash digest of the password can be stored. When the user logs on to the system, a hash digest from the password she types in is created and compared with the hash digest stored in the database. If an intruder somehow gained access to the password table, he wouldn't be able to use the hash digest to log on to the system because he would need to know the unencrypted password, which isn't stored anywhere. In the following exercise, you'll change the employee management system to validate logons using hash digests instead of passwords.1 Create a hash digest function In this exercise, you'll write a function that returns SHA-1 hash digests. You'll then use this function to create hash digests for all the passwords in EmployeeDatabase.mdb and store the hash digests in a field named PasswordHash. This field is already in the database, but it's currently unpopulated. The passwords are currently stored unencrypted in the Password field.
Namespace Hash This function is all that is needed to create a hash. It converts a string to an array of bytes and then creates a SHA-1 hash. The result is returned as a 28-character string.
Sub Main()
Verify passwords using a hash digest Now you will modify the employee management system to verify passwords with the hash digests you just created.
Private m_Password As String and change it to
Private m_PasswordHash As String
Me.m_Password = CStr(dr("Password"))and change it to
Me.m_PasswordHash = CStr(dr("PasswordHash"))
If strPassword = Me.m_Password AndAlso Me.m_IsValidUser Then and change it to read
If Hash.CreateHash(strPassword) = Me.m_PasswordHash _
Dim strPassword As String = Me.txtPassword.Text to
Dim strPassword As String = Hash.CreateHash(Me.txtPassword.Text)
strSQL = _ and change it to
strSQL = _ "INSERT INTO Employee ( UserName, [PasswordHash], Fullname ) " & _
Private Key EncryptionWhile hash digests are useful for one-way encryption, when you need to decrypt the encrypted information, you need to use two-way encryption. The most common two way-encryption technique is key-based encryption. A key is simply a unique string that you pass together with a plain-text message to an encryption algorithm, which returns the message encrypted as cipher text. The cipher text bears no resemblance to the original message. To decrypt the cipher text, you again pass the key with the cipher text to a decryption algorithm, which returns the original plain-text message.The most common type of key-based encryption is private key encryption, also called symmetric, traditional, shared-secret, secret-key, or conventional encryption. (Encryption is one of those areas in computing in which many names mean the same thing.) Private key encryption relies on the sender and recipient both knowing the key. This implies that potential intruders do not know the key and have no way to obtain the key. Private key encryption is good for communicating information over the Internet or for storing sensitive information in a database, registry, or file. Figure 1-3 shows private key encryption in action. Figure 1-3 Private key encryption Now you'll add functions for applying private key encryption to the security library you created in the preceding exercise, and you'll use private key encryption to store and retrieve bank account information in the database. The type of encryption you'll use is Triple-DESDES is an acronym for Data Encryption Standard. Triple refers to how the encryption worksfirst the plain text is encrypted; this encrypted result is encrypted again; and finally, the encrypted-encrypted plain-text message is encrypted once more, resulting in the plain-text message being encrypted three times and earning the moniker Triple-DES. You get three encryptions for the price of one, and the result is a robust 192-bit encryption. Encrypt the BankAccount field with a private key The employee management system stores bank account information for the purpose of depositing the salaries of employees directly into their bank accounts. Currently this information is being stored as plain text. In this exercise, you'll add private key encryption and decryption functions to your security library, and you'll use these functions to encrypt the BankAccount field.
Namespace PrivateKey You can use these two functions in your code to encrypt and decrypt messages. The key is named strKey24 because it must be 24 characters long.
EncryptField("Password", "PasswordHash")to read
EncryptField("BankAccount", "BankAccountEncrypted")
strCipherText = HashCreateHash(strPlainText) and change it to the following:
strCipherText = PrivateKey.Encrypt(strPlainText, _
Store and retrieve account information using encryption Next you'll change the employee management system to store and retrieve the bank account number using private key encryption.
Public G_PRIVATEKEY As String = "111222333444555666777888" This is the global variable you'll use to store the private key.
Private m_BankAccount As String Change it to
Private m_BankAccountEncrypted As String
Return m_BankAccount to
Return PrivateKey.Decrypt(m_BankAccountEncrypted, G_PRIVATEKEY)
m_BankAccount = Value to
m_BankAccountEncrypted = PrivateKey.Encrypt(Value, G_PRIVATEKEY)
Me.m_BankAccount = CStr(dr("BankAccount"))to
Me.m_BankAccountEncrypted = CStr(dr("BankAccountEncrypted"))
Dim strSQL As String = "UPDATE Employee SET " & _ to
Dim strSQL As String = "UPDATE Employee SET " & _
Keeping Private Keys SafeThe Triple-DES encryption algorithm we use accepts a 24-character string for a key. The 24 characters are treated as a passphrase that is used to derive a 192-bit byte array, which is then used as the actual key. This is known as 192-bit encryption. The number of bits in the key determines the total combination of possible keysfor example, a 192-bit key has 6.3 × 1057 possible values. A common method intruders use to try to crack encryption is a brute force attack, which means trying every different key combination available until they find the key that works. The more bits in the key, the longer it takes for a brute force attack to find the key. An intruder using the latest hardware would take a long time to crack a 192-bit keysupposing the intruder can try 1,000,000,000,000 keys a second, it would take about 200,000,000,000,000,000,000,000,000,000,000,000,000 years to try every combination. Even if the intruder got lucky, and found the key after trying only 0.0000000001% of the available combinations, the task would still take trillions of years.Another method intruders use for cracking encryption is to find where the key is stored and then simply read the key. How can you store the key to protect against this? The least secure method is to store the key unencrypted in a file or in the registry accessible to everyone, since if an intruder gains access to your machine, all he needs is notepad.exe to read the file or RegEdit.exe to read the registry. Hard-coding the key in the application (as the employee management system currently does) is also not a good idea since if an intruder gets a copy of your application, he could easily use a de-compiler or debugger to find the key. A better method is to encrypt the key and store it in a file that is protected by the file system so that only authorized users of the system can read it. This immediately raises the questions of where to store the key you use to encrypt the private key? Windows helps with this by providing methods for encrypting and decrypting sensitive data by using logon credentials as a key. When using these methods, there are several things to be aware of:
While these techniques are great for storing private keys, they can be used for any sensitive information such as connection strings and credit card information . Encrypt the private key In this exercise, you will encrypt the private key and store it in the application directory. You will also change the employee management system to retrieve the private key from the encrypted file.
'Insert code below...
Public G_PRIVATEKEY As String = "1122334455667788" and change it to
Public G_PRIVATEKEY As String = Settings.LoadEncrypted("EMSKey")
One final note on private keys: In your own applications, you should create a private key that is more complicated than the 111222333444555666777888 used in this exampleprivate keys should be a random string of characters, numbers, and punctuation.
Public Key EncryptionPublic key encryption (also called asymmetric encryption) has an important difference from private key encryption. Public key encryption uses two different keys: one key for encryption and another key for decryption. Why don't they simply call this two-key encryption and call private key encryption one-key encryption? While it is well known that security experts like to invent jargon to justify their high consultancy fees, there is also a logical reason for this naming, which lies in the way the two types of encryption are used.While private key encryption assumes that both the encrypting and decrypting parties already know the private key, public key encryption provides a method to securely issue a key to someone and have that individual send you information that only you can decrypt. It works like this: Our system creates a public/private key pair. We send the public key to someone who uses it to encrypt a message. She sends the encrypted message to us, and we decrypt the message with the private key. (Note: The private key is not the same as the key used in private key encryption.) Even if an intruder gains possession of the public key, he cannot use it to decrypt the encrypted message because only the private key can decrypt the message, and this is never given away. In contrast with private key encryption, the keys used in public key encryption are more than simple strings. The key is actually a structure with eight fields: two of the fields are used for encrypting with the public key, and six are used for decrypting with the private key. The public key is obtained by extraction from the private key, which is why the private key can be used for both encryption and decryption. Figure 1-4 shows how public key encryption and decryption work, using the example of a system requesting a credit card number from a user. Figure 1-4 Public key encryption and decryption Public key encryption is slower than private key encryption and cannot process large amounts of data. The RSA algorithm (RSA refers to the initials of the people who developed it: Ron Rivest, Adi Shamir, and Leonard Adleman) can encrypt a message of only 116 bytes (58 unicode characters). A common use for public key encryption is for securely passing a private key, which is then used for encrypting and decrypting other information. Add public key encryption to the security library In this exercise, you will add public key encryption functions to your security library.
Namespace PublicKey
Hiding Unnecessary InformationNow that you have encrypted the passwords and bank account information, you should do two more encryption-related things to further secure the employee management system: remove the unencrypted password field and the unencrypted bank account field from the Employees table, and protect the password entry field in the logon screen.Remove the Password and BankAccount fields The unencrypted Password and BankAccount fields are no longer needed in the EmployeeDatabase.mdb database. In this exercise, you will remove these two fields from the database.
Hide the password entry field If someone is looking over your shoulder while you're logging on to the employee management system, that person might be able to read your password as you type it. Windows Forms has the capability of hiding the password as you type it. The following exercise describes the steps necessary to hide the password.
After you complete these steps, the password entry field will appear as a series of asterisks instead of text, as shown here:
Encryption in the Real WorldAt the end of most chapters in this book, you'll find a section like this one that explores where you might use techniques learned in the chapter in your own real-world projects. Encryption has a number of uses but two main purposes:
SummaryIn this chapter, we jumped right into encryption and created a library of functions for creating hash digests as well as for encryption and decryption using private and public keys, all with a single line of Visual Basic code. In addition, we started securing the employee management system with minimal impact on usability and programming time. This illustrates an important point: if security is complicated to implement or use, people won't implement or use it. The purpose of this and future chapters is to show you techniques that are simple to bolt onto your existing applications and that have minimal impact on usability.
1 Validating against hashes is a good mechanism to use for an application that opens a database directly. For a client-server application or a Web application, this mechanism does not protect against "spoofing" the server componentwhere an intruder who knows the hashes constructs a fake client application that submits the hash to the server. However, if an intruder gains access to the list of passwords, they can do less damage if the passwords are hashed. 2 Be aware that this is not a guarantee against tamperingan intruder could modify the file and then create a hash of the modified file.
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||