code:     private CipherText convertToCipherText(byte[] cipherTextSerializedBytes)
          throws EncryptionException
      {
          try {
          	assert cipherTextSerializedBytes != null : "cipherTextSerializedBytes cannot be null.";
          	assert cipherTextSerializedBytes.length > 0 : "cipherTextSerializedBytes must be > 0 in length.";
              ByteArrayInputStream bais = new ByteArrayInputStream(cipherTextSerializedBytes);
              int kdfInfo = readInt(bais);
              debug("kdfInfo: " + kdfInfo);
              int kdfPrf = (kdfInfo >>> 28);
              debug("kdfPrf: " + kdfPrf);
              assert kdfPrf >= 0 && kdfPrf <= 15 : "kdfPrf == " + kdfPrf + " must be between 0 and 15.";
              int kdfVers = ( kdfInfo & 0x07ffffff);
              assert kdfVers > 0 && kdfVers <= 99991231 : "KDF Version (" + kdfVers + ") out of range."; // Really should be >= 20110203 (earliest).
              debug("convertToCipherText: kdfPrf = " + kdfPrf + ", kdfVers = " + kdfVers);
              if ( kdfVers != CipherText.cipherTextVersion ) {
                  // NOTE: In future, support backward compatibility via this mechanism. When we do this
              	//		 we will have to compare as longs and watch out for sign extension of kdfInfo
              	//		 since it may have the sign bit set.  Then we will do different things depending
              	//		 on what KDF version we encounter.  However, as for now, since this is
                  //       is first ESAPI 2.0 GA version, there nothing to be backward compatible with.
              	//		 (We did not promise backward compatibility for earlier release candidates.)
              	//		 Thus any version mismatch at this point is an error.
                  throw new InvalidClassException("This serialized byte stream not compatible " +
                              "with loaded CipherText class. Version read = " + kdfInfo +
                              "; version from loaded CipherText class = " + CipherText.cipherTextVersion);
              }
              long timestamp = readLong(bais);
              debug("convertToCipherText: timestamp = " + new Date(timestamp));
              short strSize = readShort(bais);
              debug("convertToCipherText: length of cipherXform = " + strSize);
              String cipherXform = readString(bais, strSize);
              debug("convertToCipherText: cipherXform = " + cipherXform);
              String[] parts = cipherXform.split("/");
              assert parts.length == 3 : "Malformed cipher transformation";
              String cipherMode = parts[1];
              if ( ! CryptoHelper.isAllowedCipherMode(cipherMode) ) {
                  String msg = "Cipher mode " + cipherMode + " is not an allowed cipher mode";
                  throw new EncryptionException(msg, msg);
              }
              short keySize = readShort(bais);
              debug("convertToCipherText: keySize = " + keySize);
              short blockSize = readShort(bais);
              debug("convertToCipherText: blockSize = " + blockSize);
              short ivLen = readShort(bais);
              debug("convertToCipherText: ivLen = " + ivLen);
              byte[] iv = null;
              if ( ivLen > 0 ) {
                  iv = new byte[ivLen];
                  bais.read(iv, 0, iv.length);
              }
              int ciphertextLen = readInt(bais);
              debug("convertToCipherText: ciphertextLen = " + ciphertextLen);
              assert ciphertextLen > 0 : "convertToCipherText: Invalid cipher text length";
              byte[] rawCiphertext = new byte[ciphertextLen];
              bais.read(rawCiphertext, 0, rawCiphertext.length);
              short macLen = readShort(bais);
              debug("convertToCipherText: macLen = " + macLen);
              byte[] mac = null;
              if ( macLen > 0 ) {
                  mac = new byte[macLen];
                  bais.read(mac, 0, mac.length);
              }
  
              CipherSpec cipherSpec = new CipherSpec(cipherXform, keySize);
              cipherSpec.setBlockSize(blockSize);
              cipherSpec.setIV(iv);
              debug("convertToCipherText: CipherSpec: " + cipherSpec);
              CipherText ct = new CipherText(cipherSpec);
              assert (ivLen > 0 && ct.requiresIV()) :
                      "convertToCipherText: Mismatch between IV length and cipher mode.";
              ct.setCiphertext(rawCiphertext);
                // Set this *AFTER* setting raw ciphertext because setCiphertext()
                // method also sets encryption time.
              ct.setEncryptionTimestamp(timestamp);
              if ( macLen > 0 ) {
                  ct.storeSeparateMAC(mac);
              }
              return ct;
          } catch(EncryptionException ex) {
              throw new EncryptionException("Cannot deserialize byte array into CipherText object",
                                            "Cannot deserialize byte array into CipherText object",
                                            ex);
          } catch (IOException e) {
              throw new EncryptionException("Cannot deserialize byte array into CipherText object",
                      "Cannot deserialize byte array into CipherText object", e);
          }
      }
      
  