Lab Overview

Data security has become important as more information is in a digital form. We need security services such as Confidentiality to protect data from unauthorized access. Data authentication is also another important security service, as it provides a method to prove the authenticity of data. In the world of digital communications, in addition to the first two services, data integrity is also essential. The data integrity service is not to protect the data from being tampered with, but it provides a way to prove whether it has been modified. These three services are important; however, other security services are becoming more attractive for the digital world such as anonymity and service availability. This tutorial is used in Cryptography TELECOM 2820/INFSCI 2170.

In this exercise, you will learn how to protect your data using confidentiality, which is commonly called encryption. You will use two different programming languages, C and Java, for encryption. You will also learn how difficult it is to crack an encrypted piece of code. Finally, you will learn how to create your own encryption mode and justify what you did. This tutorial is divided into five sections. The first section describes OpenSSL and the lab requirements. The second section covers using OpenSSL. The third section covers the use of Java Cryptography Extensions. The fourth and fifth sections are user exercises and resources.

OpenSSL: Cryptography Library and SSL/TLS Toolkit

Due to popular web transactions and a need to transmit confidential information, a secure transfer mode was created by Netscape Communications Corporation. They introduced the Secure Socket Layer (SSL) framework for Hypertext Transfer Protocol (HTTP) for securing web transactions on their web browser. As SSL become popular, it was immediately deployed for other web browsers. As the number of web services and users continue to grow the demand for secure transactions dramatically increased. This increase in secure transactions is not only for HTTP, but also for security services that us other protocols on the top of Transmission Control Protocol (TCP). Internet Engineering Task Force (IETF) has established a working group called Transport Layer Security (TLS) in 1996, with the goal to standardize the security protocol for the Transport Layer.

The OpenSSL Project was established to create a software library or toolkit for SSL/TLS. It is a collaborative effort to develop a robust, commercial-grade, fully featured, and Open Source toolkit implementing the SSL v2/v3 and TLS v1 protocols as well as a full-strength general purpose cryptography library. The project is managed by a worldwide community of volunteers that use the Internet to communicate, plan, and develop the OpenSSL toolkit and its related documentation. OpenSSL is based on the excellent SSLeay library developed from Eric A. Young and Tim J. Hudson around 1996. The OpenSSL toolkit is licensed under a dual-license (the OpenSSL license plus the SSLeay license) , which basically means that you are free to get and use it for commercial and non-commercial purposes as long as you fulfill the conditions of both licenses.

In this lab, you will be introduced to some concepts of OpenSSL's application programming interface (API), which will allow you to create your own program to solve a particular crypto problem such as encryption or decryption. To accomplish this you will also learn how to use the crypto library in OpenSSL.

Overview of OpenSSL

OpenSSL includes APIs for SSL/TLS protocol, in addition to several cryptographic algorithms for confidential services based on both secret key and public key cryptography. It also includes hash/MAC mechanisms for message integrity services and digital signature for non-repudiation services. Along with SSL/TLS, a digital certificate is an important part, which you will be able to create using OpenSSL. OpenSSL supports the creation of digital or public key certificates based on thee X.509 standard, the conversion between X.509 and ASN.1 encoding standards, and PEM certificates. The OpenSSL toolkit includes the following components:

• Libssl.a: Implementation of SSLv2, SSLv3, TLSv1 and the required code to support both SSLv2, SSLv3 and TLSv1 in the one server and client.

• libcrypto.a: General encryption and X.509 v1/v3 stuff needed by SSL/TLS but not actually logically part of it. It includes routines for the following:

• openssl: A command line tool that can be used for: creation of RSA, DH and DSA key parameters, creation of X.509 certificates, CSRs and CRLs, calculation of Message Digests Encryption and Decryption with Ciphers SSL/TLS Client and Server Tests, Handling of S/MIME signed or encrypted mail

Lab Requirements

To complete the C portion of this lab you will need a workstation in SIS Lab or a Windows-based machine that already has OpenSSL installed. The SIS workstations already have OpenSSL installed on them, so using them will require less work on your part. If you wish to install OpenSSL on your computer, please read the instructions at http://www.openssl.org.

To complete the Java portion you will need a workstation in SIS Lab or a Windows-based machine that already has the latest Java 2 Standard Edition (J2SE) installed. Again J2SE is already installed on the computers in the SIS lab. If you insist to install java on your computer, please read the instructions at http://java.sun.com/products/jce/downloads/index.html. If you require an overview of Java or C you should visit http://java.sun.com.

.NET Cryptography Overview

Cryptography with C# .NET Framework

The required main namespace for this lab exercise is System.Security.Cryptography, which provides modern cryptographic services such as symmetric and asymmetric encryption, hashing algorithms, and digital signatures. To see all the classes provided by this namespace, see the System.Security.Cryptography topic in the MSDN documentation at http://msdn.microsoft.com/library/.

Symmetric Encryption

In this section, we will learn how to encrypt data using symmetric algorithms. With classes defined under the System.Security.Cryptography Namespace, you can implement DES, RC2, Triple-DES, and Rinndael/AES cryptosystems with the key size and block size attributes described in the table below.

Program Explanation

The class CryptoClass contains two methods, which are Initialize and Encrypt. The Initialize method is used to generate the values of the key and initial vector (IV). The Encrypt method receives a string of plaintext as an argument, and then converts the string into an array of bytes.

In this simple example you will set the values of the key and IV manually. Alternatively, the key and IV can be generated randomly using x_alg.GenerateKey() and x_alg.GenerateIV(), respectively. Since AES is a block cipher, you need to specify the mode of operation and block padding on the Mode and Padding members. The following CipherMode options are available: ECB, CBC, CFB, CTS, OFB PaddingMode: Zeros, PKCS7.

To create or instantiate an encryption algorithm object (i.e., x_alg), use the Create method of the SymmetricAlgorithm class with the argument Rijndael as SymmetricAlgorithm x_alg = SymmetricAlgorithm.Create("Rijndael"); You can use this object to set the key, IV, and all other cipher attributes.

In the first stage of encryption, the class SymmetricAlgorithm uses the ICryptoTransform interface for the cryptographic transformation from plaintext to ciphertext or the reverse for decryption. This interface has to be used with the CryptoStream class, which defines a stream that links data streams to cryptographic transformations. The CryptoStream class requires a target data stream, the transformation to use, and the mode of the stream as the arguments. The target data stream is an instance of the MemoryStream class, which is defined under the System.IO namespace. This class defines a stream that uses memory for backing. In the final stage, the ciphertext is obtained from the memory stream.

Before terminating the program, all sensitive information such as the key, IV, or other random seed values left in the memory should be destroyed. This can be achieved by using the Clear method for the instances of the algorithm implementation class, and the Close method for the Memory Stream or CryptoStream objects. The resources used by ICryptoTransform objects can be released by the Dispose method.

Message Authentication

Hashing Algorithms

An implementation of the hashing algorithm is much simpler than the encryption demonstrated in the previous section on Symmetric Encryption. In this section, you will not have to use the ICryptoTransform, CryptoStream, and MemoryStream objects. The following table lists the hashing algorithms.

Hashing Algorithm

Input block size (bits)

Hash code size (bits)

MD5

512

128

SHA-1

512

160

SHA-256

512

256

SHA-384

1024

384

SHA-512

1024

512

To create an instance of the hashing implementation class HashAlgorithm, you would use HashAlgorithm h_alg = HashAlgorithm.Create("SHA256"); to create the object h_alg, for the SHA-256 algorithm. You can omit the hyphen between SHA and the number 256. For example, you can use either SHA-256 or SHA256 for an argument of the Create method. To compute a hash code, you should use the ComputeHash method of the HashAlgorithm class as: byte[] h_code = h_alg.ComputeHash(byte[] message); This method takes a byte array of a message as an argument, and returns a byte array of a hash code.

Keyed Hashing Algorithms

The hashing algorithms can be made even more secure by using a secret key. The .NET Framework supports two hybrid types of keyed hashing algorithm as follows.

The HMAC-SHA-1 algorithm is a combination of the HMAC and SHA-1 algorithm. The MAC-Triple-DES algorithm uses the Triple-DES to create a block hash code.

The KeyedHashAlgorithm class defines these two algorithms. Thus, an object of the keyed hashing algorithm, h_alg, can be created as KeyedHashAlgorithm h_alg = KeyedHashAlgorithm.Create("HMACSHA1");

The Create method will take a string value, HMACSHA1 for the HMAC-SHA-1 algorithm, and MACTripleDES for the MAC-Triple-DES algorithm. Since you are dealing with keyed hashing algorithms here, how would you set up the key? You can use the same concept as described in the symmetric encryption section to set up the key. Again, both the message and key must be converted to byte arrays before hashing. After setting the key value, you can compute a hash code using the ComputeHash method, similar to what described in the Hashing Algorithms section.

Digital Signatures

The .NET Framework supports two algorithms for digital signature schemes: the RSA signature and the Digital Signature Algorithm (DSA.) The required classes are DSACryptoServiceProvider and RSACryptoServiceProvider for the DSA and RSA implementation, respectively. To create an instance of the DSA algorithm class, dsa, you should use DSACryptoServiceProvider dsa = new DSACryptoServiceProvider(); and the object instantiation of the RSACryptoServiceProvider class is similar.

The default characteristics of a digital signature provided by the .NET framework will be different each time a message is signed, even though the message is not changed. This randomness, in the DSA case, is caused by random numbers generated by the .NET Framework. In the RSA case, the public-private key pair and other performance-enhancement parameters is randomly generated each time a message is signed, thus obtaining different signatures. Unfortunately, how to manually set the key and some random parameters is not documented in the MSDN library. However, this would not be a big problem since having keys generated randomly by a computer instead of assigning these values manually is prefered. For example, in the RSA case, the public-private key pair used in .NET Framework is a set of large numbers with 1024-bit keys.

Signing and Verifying Data

The .NET Framework provides methods for signing and verifying data, which can be seen below.

Algorithm

Action

Method

Return type

DSA

Sign

SignData(byte[ ] data);

byte [ ]

Verify

VerifyData(byte[ ] data, byte[ ] sig);

bool

RSA

Sign

SignData(byte[ ] data, object h_alg);

byte [ ]

Verify

VerifyData(byte[ ] data, object h_alg, byte[ ] sig);

bool

The value sig denotes a byte array of the signature obtained after signing the message data, which is found in the verifyData methods. In RSA scheme, an instance of the hashing algorithm class need to be created fist, and then specified in both the SignData and VerifyData methods, which is denoted by the h_alg. The return type, bool, is a Boolean value, which equals one if the signature is valid, and equals zero otherwise.

Transmitting Cryptographic Parameters Between Applications

The .NET Framework provides methods for exporting and importing public or private parameters stored in the DSAParametersand RSAParametersstructures. You more infirmation on this topic you can look in the MSDN documentation for more details, but you do not need to know about all the members of these structures. As mentioned before, a digital signature created by .NET is random. The DSA signature relies on random numbers. Unfortunately, the MSDN library does not explain a definition of each parameter, and the following notation is not conventional. The public parameters (byte array type) are P, Q, J, G, and Seed, which are of a byte array type. The private parameters are X and Y. All parameters are members of the DSAParameters structure.

For the RSA signature, the public-private key pair is randomly generated, and stored in the RSAParameters structure. The public key members are Modulus and Exponent and the private key is D. How do you import or export these parameters? For example, Alice signs a message, and then transmits her public parameters to Bob so that he can use these parameters to verify the message if it comes from Alice.

There are two ways to achieve this. The first is to use the ExportParameters and ImportParameters methods After the signature has been created, Alice exports her algorithm parameters as DSAParameters para = dsa.ExportParameters(bool); ,where bool denotes a string of Boolean value (i.e., true or false). The argument is false if you want to export only the public parameters, and is true to export both the public and private parameters. These two Boolean cases are used for both the DSA and RSA signatures. After exporting parameters, you can access some parameters, e.g., the byte array P as para.P. The other application (e.g., Bobs) can simply obtain these parameters by using dsa_Bob.ImportParameters(para);

For RSA, the Import and export procedures are the same. You will use the ToXmlString and FromXmlString methods. The .NET framework also provides an alternative, which is more convenient, to transmit algorithm parameters between applications with an XML (Extensible Markup Language) string. Analogous to the ExportParameters method, we can use the ToXmlString(bool) method to create and return an XML string representation of the algorithm parameters, where bool denotes a string of Boolean value as described above. For example, the RSA key pair parameters can be exported as string key_pair = rsa.ToXmlString(bool); ,where rsa is an instance of the RSACryptoServiceProvider class. Similar to the ImportParameters above, these parameters can be obtained by using rsa_Bob.FromXmlString(key_pair);

Exercises

rom the previous sections, you learned about encryption, hashing, and digital signatures for use with C# and the .NET Framework. In this section you will be presented with a number of exercises requiring you to use the knowledge you learned from the previous sections along with a number of questions.

If you are submitting your work, include your name in the header of each program for problem 1 - 7. Each program must be named according to its associated problem, e.g., Problem1.cs. . . Problem7.cs. Zip all the files into one file and upload it onto the class FTP server. You must include printouts of each program and answers to each question.

Problem 1

Encrypt a plaintext with the following options: -AES-CBC mode with PKCS#7 padding mode -128-bit key size and block size.

Problem 2

Write a decryption program to verify your answer in Problem 1.

Hints:

You can add an additional decryption method inside the CryptoClass class.

Create a byte array to save the decrypted message, such as byte[] array1 = new byte[x_cipher_rx.Length];,where x_cipher_rx is the byte array obtained after using FromBase64String to decode the received Base64-encoded ciphertext.

You need to create an instance of MemoryStream initialized with the byte array x_cipher_rx (we no longer use the default constructor of MemoryStream here).

Use the CreateDecryptormethod similar to the CreateEncryptor method in the encryption example, and also use Readinstead of Write here.

Problem 3

Given ciphertext and plaintext use the information provided in Problem 1 except for the key to find the last missing three bytes of the key.