AES256v2HeaderData(byte[] data) throws InvalidDataException {
    Validate.notNull(data, "Data cannot be null.");

    // Need the header to be able to determine the length
    if (data.length < AES256v3Ciphertext.HEADER_SIZE) {
      throw new InvalidDataException("Not enough data to read header.");
    }

    int index = 0;
    version = data[index++];

    if (version != AES256v3Ciphertext.EXPECTED_VERSION) {
      throw new InvalidDataException(String.format(
          "Expected version %d but found %d.",
          AES256v3Ciphertext.EXPECTED_VERSION, version));
    }

    options = data[index++];

    // Test for any invalid flags
    if (options != 0x00 && options != AES256v3Ciphertext.FLAG_PASSWORD) {
      throw new InvalidDataException("Unrecognised bit in the options byte.");
    }

    // If the password bit is set, we can expect salt values
    isPasswordBased = ((options & AES256v3Ciphertext.FLAG_PASSWORD) == AES256v3Ciphertext.FLAG_PASSWORD);

    final int minimumLength = (isPasswordBased) ? SIZE_WITH_PASSWORD
        : SIZE_WITHOUT_PASSWORD;

    if (data.length < minimumLength) {
      throw new InvalidDataException(String.format(
          "Data must be a minimum length of %d bytes, but found %d bytes.",
          minimumLength, data.length));
    }

    if (isPasswordBased) {
      encryptionSalt = new byte[AES256v3Ciphertext.ENCRYPTION_SALT_LENGTH];
      System.arraycopy(data, index, encryptionSalt, 0, encryptionSalt.length);
      index += encryptionSalt.length;

      hmacSalt = new byte[AES256v3Ciphertext.HMAC_SALT_LENGTH];
      System.arraycopy(data, index, hmacSalt, 0, hmacSalt.length);
      index += hmacSalt.length;
    } else {
      encryptionSalt = null;
      hmacSalt = null;
    }

    iv = new byte[AES256v3Ciphertext.AES_BLOCK_SIZE];
    System.arraycopy(data, index, iv, 0, iv.length);
    index += iv.length;
  }