4.8 Java Code to Encrypt and Decrypt a Sample Client Random

The following Java code illustrates how to encrypt and decrypt with RSA.

 import java.math.BigInteger;
  
 public class RdpRsaEncrypt
 {
     //
     // Print out the contents of a byte array in hexadecimal.
     //
     private static void PrintBytes(
         byte[] bytes
         )
     {
         int cBytes = bytes.length;
         int iByte = 0;
  
         for (;;) {
             for (int i = 0; i < 8; i++) {
                 String hex = Integer.toHexString(bytes[iByte++] & 0xff);
                 if (hex.length() == 1) {
                     hex = "0" + hex;
                 }
  
                 System.out.print("0x" + hex + " ");
                 if (iByte >= cBytes) {
                     System.out.println();
                     return;
                 }
             }
             System.out.println();
         }
     }
  
     //
     // Reverse the order of the values in a byte array.
     //
     public static void ReverseByteArray(
         byte[] array
         )
     {
         int i, j;
         byte temp;
  
         for (i = 0, j = array.length - 1; i < j; i++, j--) {
             temp = array[i];
             array[i] = array[j];
             array[j] = temp;
         }        
     }
  
     //
     // Use RSA to encrypt data.
     //
     public static byte[] RsaEncrypt(
         byte[] modulusBytes,
         byte[] exponentBytes,
         byte[] dataBytes
         )
     {
         //
         // Reverse the passed in byte arrays and then use these to 
         // create the BigIntegers for the RSA computation.
         //
         ReverseByteArray(modulusBytes);
         ReverseByteArray(exponentBytes);
         ReverseByteArray(dataBytes);
  
         BigInteger modulus = new BigInteger(
             1, 
             modulusBytes
             );
         BigInteger exponent = new BigInteger(
             1, 
             exponentBytes
             );
         BigInteger data = new BigInteger(
             1, 
             dataBytes
             );
  
         //
         // Perform RSA encryption: 
         // ciphertext = plaintext^exponent % modulus.
         //
         BigInteger cipherText = data.modPow(
             exponent, 
             modulus
             );
  
         //
         // Reverse the generated ciphertext.
         //
         byte[] cipherTextBytes = cipherText.toByteArray();
         ReverseByteArray(cipherTextBytes);
  
         //
         // Undo the reversal of the passed in byte arrays.
         //
         ReverseByteArray(modulusBytes);
         ReverseByteArray(exponentBytes);
         ReverseByteArray(dataBytes);
  
         return cipherTextBytes;
     }
    
     //
     // Use RSA to decrypt data.
     //
     public static byte[] RsaDecrypt(
         byte[] modulusBytes,
         byte[] privateExponentBytes,
         byte[] encryptedDataBytes
         )
     {
         //
         // Reverse the passed in byte arrays and then use these to 
         // create the BigIntegers for the RSA computation.
         //
         ReverseByteArray(modulusBytes);
         ReverseByteArray(privateExponentBytes);
         ReverseByteArray(encryptedDataBytes);
  
         BigInteger modulus = new BigInteger(
             1, 
             modulusBytes
             );
         BigInteger privateExponent = new BigInteger(
             1, 
             privateExponentBytes
             );
         BigInteger encryptedData = new BigInteger(
             1, 
             encryptedDataBytes
             );
  
         //
         // Perform RSA encryption: 
         // plaintext = ciphertext^privateExponent % modulus.
         //
         BigInteger decryptedData = encryptedData.modPow(
             privateExponent, 
             modulus
             );
  
         //
         // Reverse the generated plaintext.
         //
         byte[] decryptedDataBytes = decryptedData.toByteArray();
         ReverseByteArray(decryptedDataBytes);
  
         //
         // Undo the reversal of the passed in byte arrays.
         //
         ReverseByteArray(modulusBytes);
         ReverseByteArray(privateExponentBytes);
         ReverseByteArray(encryptedDataBytes);
  
         return decryptedDataBytes;
     }
  
     //
     // Main routine.
     //
     public static void main(
         String[] args
         )
     {
         //
         // Modulus bytes obtained straight from the wire in the 
         // proprietary certificate (in little endian format). 
         // This is for a 512-bit key set.
         //
         byte[] modulusBytes = 
         {        
             (byte) 0x37, (byte) 0xa8, (byte) 0x70, (byte) 0xfe, 
             (byte) 0x9a, (byte) 0xb9, (byte) 0xa8, (byte) 0x54,
             (byte) 0xcb, (byte) 0x98, (byte) 0x79, (byte) 0x44, 
             (byte) 0x7a, (byte) 0xb9, (byte) 0xeb, (byte) 0x38,
             (byte) 0x06, (byte) 0xea, (byte) 0x26, (byte) 0xa1, 
             (byte) 0x47, (byte) 0xea, (byte) 0x19, (byte) 0x70,
             (byte) 0x5d, (byte) 0xf3, (byte) 0x52, (byte) 0x88, 
             (byte) 0x70, (byte) 0x21, (byte) 0xb5, (byte) 0x9e,
             (byte) 0x50, (byte) 0xb4, (byte) 0xe1, (byte) 0xf5, 
             (byte) 0x1a, (byte) 0xd8, (byte) 0x2d, (byte) 0x51,
             (byte) 0x4d, (byte) 0x1a, (byte) 0xad, (byte) 0x79, 
             (byte) 0x7c, (byte) 0x89, (byte) 0x46, (byte) 0xb0,
             (byte) 0xcc, (byte) 0x66, (byte) 0x74, (byte) 0x02, 
             (byte) 0xd8, (byte) 0x28, (byte) 0x5d, (byte) 0x9d,
             (byte) 0xd7, (byte) 0xca, (byte) 0xfc, (byte) 0x60, 
             (byte) 0x0f, (byte) 0x38, (byte) 0xf9, (byte) 0xb3
         };
  
         //
         // Exponent bytes (in little endian order) obtained straight 
         // from the wire (in the proprietary certificate).
         //
         byte[] exponentBytes = 
         {        
             (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x00
         };
  
         //
         // Private exponent of the private key generated by the 
         // server (in little endian format).
         //
         byte[] privateExponentBytes = 
         {
             (byte) 0xc1, (byte) 0x07, (byte) 0xe7, (byte) 0xd4, 
             (byte) 0xd3, (byte) 0x38, (byte) 0x8d, (byte) 0x36,
             (byte) 0xf5, (byte) 0x9e, (byte) 0x8b, (byte) 0x96, 
             (byte) 0x0d, (byte) 0x55, (byte) 0x65, (byte) 0x08,
             (byte) 0x28, (byte) 0x25, (byte) 0xa3, (byte) 0x2e, 
             (byte) 0xc7, (byte) 0x68, (byte) 0xd6, (byte) 0x44,
             (byte) 0x85, (byte) 0x2d, (byte) 0x32, (byte) 0xf6, 
             (byte) 0x72, (byte) 0xa8, (byte) 0x9b, (byte) 0xba,
             (byte) 0x5e, (byte) 0x82, (byte) 0x82, (byte) 0xf0, 
             (byte) 0x5c, (byte) 0x0c, (byte) 0xeb, (byte) 0x6b,
             (byte) 0x12, (byte) 0x6a, (byte) 0xa7, (byte) 0x45, 
             (byte) 0x15, (byte) 0xce, (byte) 0x41, (byte) 0xe0,
             (byte) 0x03, (byte) 0xe5, (byte) 0xe6, (byte) 0x6d, 
             (byte) 0xdf, (byte) 0xfd, (byte) 0x58, (byte) 0x61,
             (byte) 0x0b, (byte) 0x07, (byte) 0xa4, (byte) 0x7b, 
             (byte) 0xb3, (byte) 0xf3, (byte) 0x71, (byte) 0x94
         };
  
         //
         // Sample 32-byte client random.
         //
         byte[] clientRandomBytes = 
         {
             (byte) 0xff, (byte) 0xee, (byte) 0x00, (byte) 0x00, 
             (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
             (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 
             (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
             (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 
             (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
             (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 
             (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xff
         };
  
         System.out.println("Client random:");
         PrintBytes(clientRandomBytes);
  
         //
         // Perform encryption.
         //
         byte[] encryptedClientRandomBytes = RsaEncrypt(
             modulusBytes,
             exponentBytes,
             clientRandomBytes
             );        
  
         System.out.println("Encrypted client random:");
         PrintBytes(encryptedClientRandomBytes);
  
         //
         // Perform decryption.
         //
         byte[] decryptedClientRandomBytes = RsaDecrypt(
             modulusBytes,
             privateExponentBytes,
             encryptedClientRandomBytes
             );        
  
         System.out.println("Decrypted client random:");
         PrintBytes(decryptedClientRandomBytes);
     }
 };