コード例 #1
0
ファイル: stealthpng.c プロジェクト: jackcogdill/stealthpng
void encode(char *msg, char *img, char *out_filename) {
	unsigned char *data, *enc_data, *final_data;
	char *filename = 0;
	int len, plen, final_len;

	FILE *fp = fopen(msg, "rb");
	// Not saving the last null byte (in legal C strings) in either case
	// because all the chars are going into the image
	if (!fp) {
		len = strlen(msg);
		data = malloc(len);
		memcpy(data, msg, len);
	}
	else {
		filename = basename(msg);
		int fplen = strlen(filename)+1; // 1 for the colon
		char fprefix[fplen];
		sprintf(fprefix, "%s:", filename);

		// Read the file to data
		fseek(fp, 0, SEEK_END);
		int file_len = ftell(fp);
		len = fplen + file_len;
		rewind(fp);

		data = malloc(len);

		// all chars are 1 byte
		int read_size = fread(data, 1, file_len, fp);
		if (file_len != read_size)
			Error("Error reading file");

		// Prepend filename with colons (filenames can't have colons)
		// Filename gets encrypted too
		memmove(data+fplen, data, file_len);
		memcpy(data, fprefix, fplen);
	}
	fclose(fp);

	// Encrypt the data
	enc_data = aes_encrypt(&en, data, &len);
	// len gets updated here ^ to the new len of the encrypted data
	free(data); // Don't need this anymore

	plen = digits(len)+1;
	char prefix[plen];
	sprintf(prefix, filename ? "%d>" : "%d<", len);
	// The different symbols are to differentiate between file data and plaintext

	final_len = plen + len;
	int padding = 3 - (final_len % 3); // Data needs to be divisible by 3 before being put
		// into the image
	int padded_len = final_len + padding;
	final_data = malloc(padded_len);
	memcpy(final_data, enc_data, len);
	free(enc_data); // All we need now is the final data

	// Prepend the encrypted data with the prefix of how long
	// it is so we know where to stop when decoding
	memmove(final_data+plen, final_data, len);
	memcpy(final_data, prefix, plen);
	// Last, add the padding of null bytes to make it divisible by 3
	// Note: this will get removed in the end because
	// we keep the size not including the padding. We need to have it divisibile by 3 because
	// if we have 2 bits left of data, we need to store it in 1 whole pixel, which holds
	// 6 possible bits of information
	for (int i = final_len; i < padded_len; i++)
		final_data[i] = '\0';

	// Checking if possible
	read_png_file(img);
	int space = (width * height) * (3.0f / 4.0f);
	if (padded_len > space) { // Make sure there is enough space in the image for the data
		puts("Not enough space in image.");
		char *rspace;
		rspace = byteconvert(padded_len);
		printf("Data size: %s\n", rspace);
		free(rspace);

		rspace = byteconvert(space);
		printf("Space available: %s\n", rspace);
		free(rspace);

		exit(1);
	}


	// Loop through all the data, 3 bytes at a time,
	// putting every 3 bytes into groups of 4 pixels
	// (8 bits for 3 bytes is 24 total bits, 6 bits for each of
	// 4 pixels (matching of total 24))
	int pixel_loc = 0;
	int x, y;
	png_byte* pixel;
	for (int i = 0; i < padded_len; i += 3, pixel_loc += 4) {
		// next group of pixels every loop, so add 4 each time

		// Loop for each color component and for each byte of data
		// (3 of each)
		// Each byte has 8 bits, 2 of each go into each of the 4 pixels
		for (int j = 0; j < 3; j++, pixel_loc -= 4) {
			// reset to continue looping through the same pixels every time by doing -= 4

			// Loop for each of 4 pixels to put the data into
			for (int p = 0; p < 4; p++, pixel_loc++) {
				x = pixel_loc % width, y = pixel_loc / width;
				pixel = &(row_pointers[y][x*3]);

				// j for color component
				// Replace last 2 bits with zeros
				pixel[j] &= ~3;

				int sh = p * 2;
				// Add 2 bits of data at a time
				pixel[j] |= ((int)final_data[i + j] & (3 << sh)) >> sh;
				// & 3 gets only the last 2 bits of the data (1 byte) because
				// 3 is 00000011 in binary,
				// 3 << 2 is 00001100, 3 << 4 is 00110000, etc
			}
		}
	}
	// Save the image with the data inside it
	// (use output filename if specified, otherwsie just "new-image.png")
	if (out_filename)
		write_png_file(out_filename);
	else
		write_png_file("new-image.png");


	free(final_data); // Done with this
}
コード例 #2
0
ファイル: stealthpng.c プロジェクト: jackcogdill/stealthpng
int main(int argc, char **argv) {
	// Argument parsing
	char usage[256];
	char *pgrm = argv[0];
	sprintf(usage, "\
Usage: %s -e [message/file] [image]\n\
       %s -d [image]\n\
       %s -s [image(s)]\
", pgrm, pgrm, pgrm);

	if (argc == 1)
		Error(usage);

	char *options = "\n\
Options:\n\
  -h  Show this help message and exit\n\
  -e  Encode data into image\n\
  -d  Decode data from image\n\
  -s  Space available in image(s) (the higher the\n\
      resolution, the more space available)\n\
  -o  When encoding, use this filename for the\n\
      new image\
";
	char *e_arg = 0,
	     *d_arg = 0,
	     *s_arg = 0,
	     *o_arg = 0;
	int c;
	opterr = 0;

	while ((c = getopt(argc, argv, "hd:e:s:o:")) != -1) {
		switch(c) {
			case 'h':
				puts(usage);
				puts(options);
				return 0;
				break;
			case 'e':
				e_arg = optarg;
				break;
			case 'd':
				d_arg = optarg;
				break;
			case 's':
				s_arg = optarg;
				break;
			case 'o':
				o_arg = optarg;
				break;
			case '?':
				break;
			default:
				Error(usage);
		}
	}

	char (*last_args)[256] = malloc(256 * sizeof(*last_args));
	int index = s_arg ? 1 : 0;
	if (optind < argc) {
		while (optind < argc)
			sprintf(last_args[index++], "%s", argv[optind++]);
	}
	if (s_arg)
		sprintf(last_args[0], "%s", s_arg);

	if (e_arg || d_arg) {
		if (e_arg && !index)
			Error(usage);

		// Prompt for password
		char *pass = getpass("Password for encoding:");
		if (strcmp(pass, "") == 0)
			Error("No password entered.");

		// Prepare encryption and decryption:
		// The salt paramter is used as a salt in the derivation:
		// it should point to an 8 byte buffer or NULL if no salt is used.
		unsigned char salt[] = {1, 2, 3, 4, 5, 6, 7, 8};

		unsigned char *key_data = (unsigned char *) pass;
		int key_data_len = strlen(pass);

		// Gen key and iv. init the cipher ctx object
		if (aes_init(key_data, key_data_len, salt, &en, &de))
			Error("Error initializing AES cipher");
	}
	// Encode
	if (e_arg)
		encode(e_arg, last_args[0], o_arg);

	// Decode
	else if (d_arg)
		decode(d_arg);

	// Print space in image(s)
	else if (s_arg) {
		puts("Space available in image(s):");
		for (int i = 0; i < index; i++) {
			read_png_file(last_args[i]);
			int space = (width * height) * (3.0f / 4.0f);
			space -= 256+ AES_BLOCK_SIZE +12; // 256 for filename
			char *rspace = byteconvert(space);
			printf("%s: %s\n", basename(last_args[i]), rspace);
			free(rspace);
		}
	}
	else
		Error(usage);
	if (opterr)
		return 1;

	// Cleanup
	free(last_args);
	aes_clean();
	png_clean();

	return 0;
}
コード例 #3
0
ファイル: compute_value.c プロジェクト: jhunkeler/reftools
/* Perform interpolation, if necessary, to derive the final
 output value for this obsmode from the appropriate row. 
 */
double ComputeValue(PhtRow *tabrow, PhotPar *obs) {
  /* Parameters:
   PhtRow  *tabrow:    values read from matching row of table
   char   *obsmode:    full obsmode string from header 
   
   obsmode string needs to contain values of parameterized values 
   appropriate for this observation.
   */
  
  double value;
  int parnum;
  int n,p, nx, ndim;
  double *out;
  double *obsindx; /* index of each obsmode par value in tabrow->parvals */ 
  double *obsvals; /* value for each obsmode par in the same order as tabrow */
  
  int *ndpos;
  int **bounds; /* [ndim,2] array for bounds around obsvals values */
  double resvals[2]; /* Values from tabrow->results for interpolation */
  double resindx[2]; /* 1-D indices into tabrow->results for bounding positions*/
  int posindx;      /* N dimensional array of indices for a position */
  int indx,pdim,ppos,xdim,xpos;
  int tabparlen;
  /* 
   intermediate products used in iterating over dims 
   */
  int iter, x;
  int dimpow,iterpow;
  double *ndposd;
  int b0,b1,pindx;
  int deltadim;            /* index of varying dimension */
  double bindx[2],bvals[2]; /* indices into results array for bounding values */
  double rinterp;          /* placeholder for interpolated result */
  BoundingPoint **points;   /* array of bounding points defining the area of interpolation */
  
  /* Define functions called in this functions */ 
  double linterp(double *, int, double *, double);
  void byteconvert(int, int *, int);
  int computedeltadim(BoundingPoint *, BoundingPoint *);  
  long computeindex(int *, double *, int);  
  void computebounds(double *, int, double, int *, int*);  
  int strneq_ic(char *, char*, int);
  BoundingPoint **InitBoundingPointArray(int, int);
  void FreeBoundingPointArray(BoundingPoint **, int);
  
  /* Initialize variables and allocate memory */  
  value = 0.0;
  ndim = tabrow->parnum;
  if (ndim == 0) {
    /* No parameterized values, so simply return value
     stored in 1-element array results */
    return(tabrow->results[0]);
  } 
  dimpow = pow(2,ndim);
  
  obsindx = (double *)calloc(ndim, sizeof(double));
  obsvals = (double *)calloc(ndim, sizeof(double)); /* Final answer */
  ndpos = (int *)calloc(ndim, sizeof(int));
  ndposd = (double *)calloc(ndim, sizeof(double));
  bounds = (int **) calloc(ndim, sizeof(int *));
  for (p=0;p<ndim;p++) bounds[p] = (int *) calloc(2, sizeof(int));    
  
  /* We have parameterized values, so linear interpolation 
   will be needed in all dimensions to get correct value.
   Start by getting the floating-point indices for each 
   parameterized value
   */
  /* 
   Start by matching up the obsmode parameters with those in the table row 
   These are the values along each dimension of the interpolation
   */
  for (p=0;p<ndim;p++){
    tabparlen = strlen(tabrow->parnames[p]);
    for(n=0;n<obs->npar;n++){
      if (strneq_ic(tabrow->parnames[p],obs->parnames[n],tabparlen)){
        obsvals[p] = obs->parvalues[n];
        break;
      }
    }
    
    if (obsvals[p] == 0.0) {
      printf("ERROR: No obsmode value found for %s\n",tabrow->parnames[p]);
      
      free(obsindx);
      free(obsvals);
      free(ndpos);
      free(ndposd);
      for (p=0;p<ndim;p++) free(bounds[p]);
      free(bounds);
      
      return ('\0');
    }
    
    /* check whether we're going beyond the data in the table (extrapolation) */
    /* if we are, return -9999 */
    nx = tabrow->nelem[p+1];
    
    if ((obsvals[p] < tabrow->parvals[p][0]) ||
        (obsvals[p] > tabrow->parvals[p][nx-1])) {
      printf("WARNING: Parameter value %s%f is outside table data bounds.\n",
             tabrow->parnames[p],obsvals[p]);
      
      free(obsindx);
      free(obsvals);
      free(ndpos);
      free(ndposd);
      for (p=0;p<ndim;p++) free(bounds[p]);
      free(bounds);
      
      return -9999.0;
    }
  }
  
  /* Set up array of BoundingPoint objects to keep track of information needed
   for the interpolation 
   */
  points = InitBoundingPointArray(dimpow,ndim);
  
  /* Now find the index of the obsmode parameterized value
   into each parameterized value array
   Equivalent to getting positions in each dimension (x,y,...).
   */
  for (p=0;p<ndim;p++){    
    nx = tabrow->nelem[p+1];
    
    out = (double *) calloc(nx, sizeof(double));
    
    for (n=0; n<nx;n++) out[n] = n;
    
    value = linterp(tabrow->parvals[p], nx, out, obsvals[p]);    
    if (value == -99) {
      free(obsindx);
      free(obsvals);
      free(ndpos);
      free(ndposd);
      for (p=0;p<ndim;p++) free(bounds[p]);
      free(bounds);
      free(out);
      return('\0');
    }
    
    obsindx[p] = value;  /* Index into dimension p */
    computebounds(out, nx, (double)floor(value), &b0, &b1);
    
    bounds[p][0] = b0;
    bounds[p][1] = b1;
    /* Free memory so we can use this array for the next variable*/
    free(out);
  } /* End loop over each parameterized value */
  
  /* 
   Loop over each axis and perform interpolation to find final result
   
   For each axis, interpolate between all pairs of positions along the same axis
   An example with 3 parameters/dimensions for a point with array index (2.2, 4.7, 1.3):
   Iteration 1: for all z and y positions , interpolate between pairs in x
   (2,4,1)vs(3,4,1), (2,5,1)vs(3,5,1), (2,4,2)vs(3,4,2), and (2,5,2)vs(3,5,2)
   Iteration 2: for all z positions, interpolate between pairs from iteration 1 in y
   (2.2, 4,1)vs(2.2, 5, 1) and (2.2, 4, 2)vs(2.2, 5, 2)
   Iteration 3: interpolate between pairs from iteration 2 in z
   (2.2, 4.7, 1) vs (2.2, 4.7, 2) ==> final answer
   */
  for (iter=ndim; iter >0; iter--) {
    iterpow = pow(2,iter);
    for (p=0;p < iterpow;p++){
      pdim = floor(p/2);
      ppos = p%2;
      if (iter == ndim) {
        /* Initialize all intermediate products and perform first 
         set of interpolations over the first dimension 
         */
        /* Create a bitmask for each dimension for each position */
        byteconvert(p,ndpos,ndim);
        for (n=0;n<ndim;n++) {
          pindx = bounds[n][ndpos[n]];
          points[pdim][ppos].index[n] = (double)pindx;
          points[pdim][ppos].pos[n] = tabrow->parvals[n][pindx];
        }
        
        /* Determine values from tables which correspond to 
         bounding positions to be interpolated */
        indx = computeindex(tabrow->nelem, points[pdim][ppos].index, ndim);
        points[pdim][ppos].value = tabrow->results[indx];
        
      } /* End if(iter==ndim) */ 
      
      if (ppos == 1) {
        /* Determine which axis is varying, so we know which 
         input value from the obsmode string 
         we need to use for the interpolation */
        deltadim = computedeltadim(&points[pdim][0],&points[pdim][1]);
        if (deltadim < 0 || deltadim >= ndim) {
          printf("ERROR: Deltadim out of range: %i\n",deltadim);
          free(obsindx);
          free(obsvals);
          free (ndpos);
          free (ndposd);
          for (p=0;p<ndim;p++)free(bounds[p]);
          free(bounds);
          
          return('\0');
        }
        bindx[0] = points[pdim][0].pos[deltadim];
        bindx[1] = points[pdim][1].pos[deltadim];
        bvals[0] = points[pdim][0].value;
        bvals[1] = points[pdim][1].value;
        
        /*Perform interpolation now and record the results */
        rinterp = linterp(bindx, 2, bvals,obsvals[deltadim]);
        
        /* 
         Update intermediate arrays with results in 
         preparation for the next iteration 
         */
        if (rinterp == -99) return('\0');
        /* Determine where the result of this interpolation should go */
        x = floor((p-1)/2);
        xdim = floor(x/2);
        xpos = x%2;
        /* update bpos and bindx for iteration over next dimension
         */
        points[xdim][xpos].value = rinterp;
        for (n=0;n<ndim;n++) {
          points[xdim][xpos].index[n] = points[pdim][0].index[n];
          points[xdim][xpos].pos[n] = points[pdim][0].pos[n];
        }
        points[xdim][xpos].index[deltadim] = obsindx[deltadim];
        points[xdim][xpos].pos[deltadim] = obsvals[deltadim];
        
      } /* Finished with this pair of positions (end if(ppos==1)) */
      
    } /* End loop over p, data stored for interpolation in changing dimension */
    
  } /* End loop over axes(iterations), iter, for interpolation */
  
  /* Record result */
  value = points[0][0].value;
  
  /* clean up memory allocated within this function */
  free(obsindx);
  free(obsvals);
  free (ndpos);
  free (ndposd);
  for (p=0;p<tabrow->parnum;p++)free(bounds[p]);
  free(bounds);
  
  FreeBoundingPointArray(points,dimpow);
  return (value);
}