5.12.  Exercise: Encryption

[ fromfile: encryption-exercise.xml id: encryption-exercise ]

  1. In Example 5.16 we declared but did not implement three operators for the Point3 class. Add implementations for these three operators and add tests to the client code.

  2. In this exercise, you reuse the random() function from the <cstdlib> (Appendix B, "Standard Headers").

    random() generates a pseudo-random integer in the range from 0 to RAND_MAX (commonly set to 2147483647).

    Write a function

     int myRand(int min, int max); 

    that returns a pseudo-random int in the range from min to max - 1.

  3. Write the function

    QVector<int> randomPerm(int n, unsigned key); 

    that uses the myRand() function (seeded with key) to produce a permutation of the numbers 0, ... n.

  4. Encryption and privacy are becoming increasingly important. One way to think of encryption is that you start with a string of text that you pass to one or more transforming functions. The result of these transformations is a string of encrypted text that you can then transmit or store more safely. The recipient of the encrypted string then applies the inverses of the transforming functions to the string of encrypted text (i.e., decrypts it) and obtains a copy of the original string. The sender of the encrypted string must share some information with the recipient that permits the string to be decrypted (i.e., a key). The following exercises explore a few simple designs for the transforming functions. These exercises all exploit the fact that the sequence of values returned by random() is completely determined by the initial value (seed) and is, therefore, repeatable.

    1. Write the function

       QString shift(const QString& text, unsigned key) ; 

      shift() uses the parameter key to set the random function's seed by calling srandom(). For each character ch in the given string, text, produce a shifted character by adding the next pseudo-random int to the code for ch. The shifted character is then put in the corresponding place in the new string. When all the characters of text have been processed, shift() returns the new string.

      When you add a random int to the code for a character you must do the addition "mod n" where n is the number of characters in the underlying character set that is being used. For this exercise, you can assume that you are working with the ASCII character set, which has 128 characters.

    2. The next function to write is

       QString unshift(const QString& cryptext, unsigned key); 

      This function reverses the process described in the previous exercise.

    3. Write code to test your shift() and unshift() functions.

    4. Another approach to encryption (which can be combined with the approach described above) is to permute (change the order of) the characters of the given string. Write the function

       QString permute(const QString& text, unsigned key); 

      that uses the randomPerm() function to generate a permutation of the characters of the original string, text.

    5. Write the function

       QString unpermute(const QString& scrtext, unsigned key); 

      that reverses the action of the permute() function described above.

    6. Write code to test your permute() and unpermute() functions.

    7. Write code to test shift() and permute() being applied to the same string, followed by unpermute() and unshift().

  5. Implement a Crypto class that encapsulates the functions from the preceding exercises. You can use the UML diagram in Figure 5.4 to get you started.

    Figure 5.4.  Crypto Class

    Crypto Class

    m_OpSequence is a QString consisting of the characters 'p' and 's' that represent permute() and shift(). The encrypt() function applies those functions to the given string in the order that they appear in the m_OpSequence string.

    Example 5.21 contains some code to test your class.

    Example 5.21. src/functions/crypto-client.cpp

    #include <QTextStream>
    #include "crypto.h"
    
    int main()  {
       QTextStream cout(stdout);
       QString str1 ("asdfghjkl;QWERTYUIOP{}}|123456&*()_+zxcvnm,,, ./?"), 
               str2;
       cout << "Original string: " << str1 << endl;
       cout << "length: " << str1.length() << endl;
       QString seqstr("pspsp");
       ushort key(12579);
       Crypto crypt(key, seqstr);
       str2 = crypt.encrypt(str1);
       cout << "Encrypted string: " << str2 << endl;
       cout << "Recovered string: " << crypt.decrypt(str2) << endl;
    }
    
    
    

The topic of encryption is visited again in Section 17.1.4 which introduces a Qt class that does cryptographic hashing.