Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

The program takes a PPM image and will either encrypt or decrypt it when supplie

ID: 3750823 • Letter: T

Question

The program takes a PPM image and will either encrypt or decrypt it when supplied with a key. The goal is to fix the program and decrypt the secret PPM image.

Once you’ve fixed compiler errors, you can run the program like this: ./crypto secret.ppm key decrypted.ppm. Use the secret.ppm and key below as the source, key as the crypto key, and decrypted.ppm as the location of the generated image. You will be presented with an option to encrypt or decrypt. Do not encrypt an already encrypted image!

Fix the errors in the three files below so the program runs properly. Then determine what the decrypted image becomes.

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

#include "stdio.h"

#include "stdlib.h"

#include "crypto.h"

int main(int argc, char const *argv[]) {

FILE* image_file = fopen(argv[1], "r");

FILE* key_file    = fopen(argv[2], "r");

FILE* out_image   = fopen(argv[3], "w");

// Read image

header_t header;

  img_t img;

read_header(image_file, header);

read_image(image_file, &img, &header);

// Read secret key

int seed;

read_seed(key_file, *seed);

sp_rand(eed);

printf("Encrypt[1] or Decrypt[2]? ");

int choice;

while(true) {

    scanf("%d",&choice);

    if(choice == 1 || choice == 2) {

      sym_crypt(out_image, &header, &img, choice);

      break;

    } else {

      printf("Please enter 1 or 2 ");

    }

}

/********************/

fclose(image_file);

fclose(key_file);

fclose(out_image);

return 0;

}

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

#include "crypto.h"

int P_RAND_SEED = 1;

void read_header(FILE* in_img, header_t* header) {

header->type = malloc(sizeof(char)*3);

fscanf(in_img, "%s ",     header->type);

fscanf(in_img, "%d %d ", &header->w, &header->h);

fscanf(in_img, "%d ",    &header->cs);

printf("Header: %s %d %d %d ", header->type, header->w, header->h, header->cs);

}

/********************/

/** Fix errors... **/

void read_image(FILE* input, img_t* image, header_t* header) {

int row, col;

image->data = malloc(sizeof(pixel_t*) * header.h);

for(row = 0; row < header->h; row++) {

    image->data[row] = malloc(sizeof(pixel_t) * header->w * 3);

    for(; col < header->w; col++) {

      pixel_t pix

      fscanf(input, "%c%c%c", &pix.r, &pix.g, &pix.b);

      image.data[row][col] = pix;

    }

}

}

void read_seed(FILE* seed_file, int* seed) {

fscanf(seed_file, "%d", seed);

}

/** Fix errors... **/

void sym_crypt(FILE* output, header_t* header, img_t* image, int mode) {

// Write header of PPM to files

fprintf(output, "%s %d %d %d ", header->type, header->w, header->h, header->cs);

/*********************/

// Encrypt or Decrypt!

// fix errors //

int row, col;

switch (mode) {

    case 1:

      printf("Encrypt ", );

      for(row = 0; row < header->h; row++) {

        for(col = 0; col < header->w; col++) {

          int swap_row = p_rand(row*row) % header.h;

          int swap_col = p_rand(col*col) % header->w;

          pixel_t swap = image->data[row][col];

          image->data[row][col] = image->data[swap_row][swap_col];

          image->data[swap_row][swap_col] = swap;

        }

      } break;

    case 2:

      printf("Decrypt ");

      for(row = header->h-1; row >= 0; row--) {

        for(; col >= 0; col--) {

          int swap_row = p_rand(row*row) % header->h;

          int swap_col = p_rand(col*col) % header->w;

          pixel_t swap = image->data[row][col];

          image->data[row][col] = image->data[swap_row][swap_col];

          image->data[swap_row][swap_col] = swap;

        }

      } break;

    default: break;

}

for(row = 0; row < header->h; row++) {

    for(col = 0; col < header->w; col++) {

      pixel_t pix = image->data[row][col];

      fprintf(output, "%c%c%c", pix.r, pix.g, pix.b);

    }

}

/********************/

}

void sp_rand(unsigned int seed) {

P_RAND_SEED = seed;

}

/********************/

unsigned int p_rand(unsigned int init) {

return (P_RAND_SEED*init) % INT_MAX;

}

/********************/

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

#ifndef CRYPTO_H

#define CRYPTO_H value

#include "stdio.h"

#include "stdlib.h"

#include "limits.h"

#include "stdbool.h"

extern int P_RAND_SEED;

typedef struct header_t {

char* type;

int w, h, cs;

} header_t;

typedef struct pixel_t {

unsigned char r,g,b;

} pixel_t;

typedef struct img_t {

pixel_t** data;

} img_t;

void read_header(FILE* in_img, header_t* header);

void read_image(FILE* in_img, img_t* image, header_t* header);

void read_seed(FILE* seed_file, int* seed);

void sym_crypt(FILE* out_img, header_t* header, img_t* image, int mode);

// random number generator //

void sp_rand(unsigned int seed);

unsigned int p_rand(unsigned int init);

#endif

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx

key: 22695477

secret.ppm

Explanation / Answer

Firstly we corrected errors out of each file. The main idea is to look into the Function declarations or prototypes present in the corresponding header file and follow/conform to that. I have added the comments where the errors were present as well as reason for the error.

Hope this helps. Code follows:

crypto.h

* No errors here *

#ifndef CRYPTO_H
#define CRYPTO_H value
#include "stdio.h"
#include "stdlib.h"
#include "limits.h"
#include "stdbool.h"

extern int P_RAND_SEED;

typedef struct header_t {
   char* type;
   int w, h, cs;
} header_t;

typedef struct pixel_t {
   unsigned char r,g,b;
} pixel_t;

typedef struct img_t {
   pixel_t** data;
} img_t;

void read_header(FILE* in_img, header_t* header);
void read_image(FILE* in_img, img_t* image, header_t* header);
void read_seed(FILE* seed_file, int* seed);
void sym_crypt(FILE* out_img, header_t* header, img_t* image, int mode);

// random number generator //
void sp_rand(unsigned int seed);
unsigned int p_rand(unsigned int init);

#endif

main.c

#include "stdio.h"
#include "stdlib.h"
#include "crypto.h"

int main(int argc, char const *argv[]) {

   FILE* image_file = fopen(argv[1], "r");
   FILE* key_file = fopen(argv[2], "r");
   FILE* out_image = fopen(argv[3], "w");

   // Read image
   header_t header;
   img_t img;
  
   /*
   * Error 1:
   * read_header(image_file, header);
   *
   * According to read_header declaration, 2nd argument
   * should be a pointer to header_t i.e. header_t *
   *
   * void read_header(FILE* in_img, header_t* header);
   *
   * But here value was being passed in place of address
   * leading to incompatible type error
   * Fix is to pass the address of variable
   */
   read_header(image_file, &header);
   read_image(image_file, &img, &header);

   // Read secret key
   int seed;

   /*
   * Error 2:
   * read_seed(key_file, *seed);
   *
   * Prototype for read_seed
   *
   * void read_seed(FILE* seed_file, int* seed);
   *
   * 'seed' variable is of int type and not a pointer type
   * thus we see error here, this is fixed by passing address
   * of seed variable.
   */
   read_seed(key_file, &seed);

   /*
   * Error 3:
   * sp_rand(eed);
   *
   * This is just a simple typing (aka typo) error
   * it should be 'seed' rather than 'eed'
   */
   sp_rand(seed);
  
   printf("Encrypt[1] or Decrypt[2]? ");
  
   int choice;
   while(true) {
   scanf("%d",&choice);
   if(choice == 1 || choice == 2) {
       sym_crypt(out_image, &header, &img, choice);
       break;
   } else {
       printf("Please enter 1 or 2 ");
   }
   }

   /********************/
   fclose(image_file);
   fclose(key_file);
   fclose(out_image);
  
   return 0;
}

crypto.c

#include "crypto.h"

int P_RAND_SEED = 1;

void read_header(FILE* in_img, header_t* header) {

header->type = malloc(sizeof(char)*3);
fscanf(in_img, "%s ", header->type);
fscanf(in_img, "%d %d ", &header->w, &header->h);
fscanf(in_img, "%d ", &header->cs);
printf("Header: %s %d %d %d ", header->type, header->w, header->h, header->cs);
}

/********************/
/** Fix errors... **/
void read_image(FILE* input, img_t* image, header_t* header) {
int row, col;
/*
* Error 1:
* image->data = malloc(sizeof(pixel_t*) * header.h);
*
* As here header variable is a pointer to structure type
* then right way/operator to get the value of h will be
* arrow '->' operator
*/
image->data = malloc(sizeof(pixel_t*) * header->h);
for(row = 0; row < header->h; row++) {
image->data[row] = malloc(sizeof(pixel_t) * header->w * 3);
for(; col < header->w; col++) {
/*
* Error 2:
* pixel_t pix
*
* ';' is missing after the declaration
*/
pixel_t pix;
fscanf(input, "%c%c%c", &pix.r, &pix.g, &pix.b);
/*
* Error 3:
* image.data[row][col] = pix;
*
* image variable is a pointer to structure type
* then right way/operator to get the value of h will be
* arrow '->' operator
*/
image->data[row][col] = pix;
}
}
}

void read_seed(FILE* seed_file, int* seed) {
fscanf(seed_file, "%d", seed);
}

/** Fix errors... **/
void sym_crypt(FILE* output, header_t* header, img_t* image, int mode) {
// Write header of PPM to files
fprintf(output, "%s %d %d %d ", header->type, header->w, header->h, header->cs);

/*********************/
// Encrypt or Decrypt!
// fix errors //
int row, col;
switch (mode) {
case 1:
/*
* Error 4:
*
* printf("Encrypt ", );
*
* This seems to be typo error
* As here printf is expecting some expression after ','
*
* Now, as we don't have any format specifiers, we don't
* need this ','
*/
printf("Encrypt ");
for(row = 0; row < header->h; row++) {
for(col = 0; col < header->w; col++) {
int swap_row = p_rand(row*row) % header->h;
int swap_col = p_rand(col*col) % header->w;
pixel_t swap = image->data[row][col];
image->data[row][col] = image->data[swap_row][swap_col];
image->data[swap_row][swap_col] = swap;
}
} break;
case 2:
printf("Decrypt ");
for(row = header->h-1; row >= 0; row--) {
for(; col >= 0; col--) {
/*
* Error 5:
*
* int swap_row = p_rand(row*row) % header.h;
*
* As here header variable is a pointer to structure type
* then right way/operator to get the value of h will be
* arrow '->' operator
*/
int swap_row = p_rand(row*row) % header->h;
int swap_col = p_rand(col*col) % header->w;
pixel_t swap = image->data[row][col];
image->data[row][col] = image->data[swap_row][swap_col];
image->data[swap_row][swap_col] = swap;
}
} break;
default: break;
}
for(row = 0; row < header->h; row++) {
for(col = 0; col < header->w; col++) {
pixel_t pix = image->data[row][col];
fprintf(output, "%c%c%c", pix.r, pix.g, pix.b);
}
}
/********************/
}
void sp_rand(unsigned int seed) {
P_RAND_SEED = seed;
}
/********************/
unsigned int p_rand(unsigned int init) {
return (P_RAND_SEED*init) % INT_MAX;
}
/********************/

Now, after removing all errors and compiling we ran the code and we see that generated decrypted ppm file is an black image.