C:对另一个文件中函数的未定义引用

C:对另一个文件中函数的未定义引用,c,C,我试图调用另一个文件中定义的C函数。我将函数的定义添加到头文件,并将其包含在两个.c文件中,但仍收到一个错误: C:\Users\Hunter\AppData\Local\Temp\ccyqsulH.o: 在函数main'中: C:DES_hash.C:42:对DES'的未定义引用 collect2:ld返回1 退出状态 以下是功能原型定义: /* DES_Utils.h */ #ifndef GUARD_DES_Utils /* prevents errors when including t

我试图调用另一个文件中定义的C函数。我将函数的定义添加到头文件,并将其包含在两个.c文件中,但仍收到一个错误:

C:\Users\Hunter\AppData\Local\Temp\ccyqsulH.o:

在函数
main'中:
C:DES_hash.C:42:对
DES'的未定义引用

collect2:ld返回1 退出状态

以下是功能原型定义:

/* DES_Utils.h */
#ifndef GUARD_DES_Utils /* prevents errors when including twice */
#define GUARD_DES_Utils

#include "DES.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
unsigned long long * DES(unsigned long long, unsigned long long);
....
#endif
下面是我尝试使用它的地方:

/* DES_hash.c */
#include "DES_Utils.h"
int main(int argc, int * argv)
{
    .....
        Ekp_i = DES(P_i ^ C_i, k); //<- line 42
    .....                          //P_i, C_i, and k are all unsigned long longs
}
DES_Utils.h:

/* McMillen_DES_Utils.h
 * This header file holds the functions that do 
 * the majority of the work for my program. I abstracted
 * them from the main C file to avoid excess clutter
 *
 * Hunter McMillen
 * 2/9/2012
 */ 
 #ifndef GUARD_DES_Utils /* prevents errors when including twice */
 #define GUARD_DES_Utils


 #include "DES.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>

 //Definition of shared function !!
 unsigned long long * DES(unsigned long long plaintext, unsigned long long key);

  /* Counts the number of bits it
   * takes to represent an integer a
   */
   int num_bits(unsigned long long a)
   {
      int bitCount = 0;

      while(a > 0)
      {
         bitCount++;
         a = a >> 1; //shift to the right 1 bit
      }

      return bitCount;
   }

   /* Converts from an unsigned long long into an array of 
       integers that form the binary representation of a */
   void ull_to_bin_array(unsigned long long a, int *b, int length)
   {
      int *temp = malloc(length * sizeof(int));

      int i;
      for(i = length - 1; i >= 0; i--)
      {
         temp[i] = (a >> i) & 1; //store the ith bit in temp[i]
      }

      for(i = 0; i < length; i++)
      {
         int tLen = (length - 1) - i; //mapping from temp[i] -> b[i]
         b[i] = temp[tLen]; 
         //store the (length - i)th of temp in b[i], this puts the MSB first
      }
   }

   unsigned long long * bin_string_to_ull(char * bin_string)
   {
    //allocate space for a pointe to an ull
      unsigned long long * out = malloc(sizeof(unsigned long long));
    //interpret bin_string as a 64-bit number
      unsigned long long t = strtoull(bin_string, NULL, 2);

    //copy the address of t into out
      out = &t;

      return out;
   }

    /* prints a one-dimensional array given
       a pointer to it, and its length, and optionally a header */
   void print_array(int *arr, int length, char *msg)
   {
      int i;
      if(msg != NULL) printf("%s: ",msg);
      for(i = 0; i < length; i++)
      {
         printf("%d", arr[i]);
      }
      printf("\n");
   }    

    /**
     * Takes an input of a 4 element character array
     * that represents a half-byte in binary, maps
     * the 4-bit value to the appropriate hex character
     */
   void map_bin_to_hex(char *c)
   {
      char hexMap[] = "0123456789ABCDEF";
      int index = strtoull(c, NULL, 2);
      printf("%c", hexMap[index]);
   }

    /**
     * Takes a 64 element integer array that holds 
     * the binary representation of a 64-bit hex number
     */
   void bin_array_to_hex(int *b, int length)
   {
      int i, j, k;

    //read 4 bits 16 times
      for(i = 0; i < length; i+=4)
      {
         char hexB[5];
         for(k = 0, j = i; j < (i+4); j++, k++)
         {
            hexB[k] = b[j] + '0';
            //printf("h[%d] = %d\n", k, hexB[k]);
         }
         hexB[5] = '\0';
         map_bin_to_hex(hexB);
      }
      printf("\n");
   }

    /**
     * Takes as input an integer array containing the binary 
     * representation of some number N, and converts all the 
     * bits of N to characters then compresses
     * them into a single "string"
     */ 
   char * bin_array_to_string(int *b, int length)
   {
    //allocate space for length characters
      char *string = malloc((length+1) * sizeof(char));

      int i;
      for(i = 0; i < length; i++)
      {
         string[i] = b[i] + '0';
      }
      string[length] = '\0';

      return string;
   }

    /** 
     * This function takes as input the binary representation
     * of a 64-bit integer held in array form, and partitions it 
     * into LEFT and RIGHT halves
     */
   void partition_arrays(int *s, int *l, int *r, int length)
   {
      int pLength = length / 2;
      int i, j;

      for(i = 0; i < pLength; i++)
      {
         l[i] = s[i];
      }

      for(i = pLength, j = 0; i < length - 1; i++, j++)
      {
         r[j] = s[i];
      }
   }

   /**
     * Takes two arrays of equals length and concatenates their 
     * contents using memcpy 
     */
   int * concatenate_arrays(int *a, int *b, int length)
   {    
      int aLen = length * sizeof(int);
      int bLen = length * sizeof(int);      
      //allocate enough space in the new array for both arrays a and b
      int *new = malloc((aLen + bLen) * sizeof(int));

      memcpy(new, a, aLen);
      memcpy(new + length, b, bLen);

      return new;
   }

    /**
     * Given an integer array and a character array, this function
     * converts the character array to an integer then XORs the two arrays
     * contents
     */
   int * xor_arrays(int *a, char *b, int length)
   {
    //alocate enough space in the xor array 
      int *xor = malloc(length * sizeof(int));

      int i;
      for(i = 0; i < length; i++)
      {
         xor[i] = a[i] ^ (b[i] - '0'); 
         //compute xor, subtract '0' to convert from char to int
      }

      return xor;
   }

    /**
     * Same as the above function but for two integer arrays, 
     * their contents are XORed and returned in another array
     */
   int * xor_int_arrays(int *a, int *b, int length)
   {
    //alocate enough space in the xor array 
      int *xor = malloc(length * sizeof(int));

      int i;
      for(i = 0; i < length; i++)
      {
         xor[i] = a[i] ^ b[i]; //compute xor
      }

      return xor;
   }

    /**
     * Given an array and its length, this function will compute 
     * the results of ALL of the SBOXs for this array
     * The result that is returned is an integer array consisting 
     * of the results from the SBOXs
     */
   int * compute_sbox(int *a, int length)
   {
    /* bits needed for each sbox */
      int sbox_length  = length / 8;
    /* holds integer values retrieved from the SBOX */
      int sbox_results[8]; 
      /* two indices for each sbox */
      int *sbox_indices = malloc(sbox_length * sizeof(int));

    /* i counts every 6 bits in the array 
       k processes bits from 0 - 6 in the inner loop
       j is used to copy values properly into the sbox char array
       y indicates what SBOX we are taking a value from */
      int i, k, j, y;

    /* read 6 bits 8 times */
      for(i = 0, y = 0; i < length; i += sbox_length, y++)
      {
         char sbox[7];
        /* grab every 6 elements of the array */
         for(k = 0, j = i; j < (i + sbox_length); k++, j++)
         {
            sbox[k] = a[j] + '0'; //convert to a string
         }
         sbox[7] = '\0'; //append the null terminator

        /* compute the row and column index */
         char rows[3];
         rows[0] = sbox[0];
         rows[1] = sbox[5];
         rows[2] = '\0';

         char cols[5];
         cols[0] = sbox[1];
         cols[1] = sbox[2];
         cols[2] = sbox[3];
         cols[3] = sbox[4];
         cols[4] = '\0';

        /* get indices into the SBOXy+1 */
         int row = strtoull(rows, NULL, 2);
         int col = strtoull(cols, NULL, 2); 

        /* switch over y and get the results from the SBOXs */
         switch(y)
         {
            case 0:
               sbox_results[y] = SBOX_1[row][col];
               break;   
            case 1:
               sbox_results[y] = SBOX_2[row][col];
               break;   
            case 2:
               sbox_results[y] = SBOX_3[row][col];
               break;   
            case 3:
               sbox_results[y] = SBOX_4[row][col];
               break;   
            case 4:
               sbox_results[y] = SBOX_5[row][col];
               break;   
            case 5:
               sbox_results[y] = SBOX_6[row][col];
               break;   
            case 6:
               sbox_results[y] = SBOX_7[row][col];
               break;   
            case 7:
               sbox_results[y] = SBOX_8[row][col];
               break;       
            default:
               break;   
         }
      }

    /* at this point we have processed every 6 bits in the array 
       and retrieved the correct values from the SBOXs, 
       all that remains is to convert the 
       results to arrays and concatenate them */

    /* initialize arrays */
      int SBOX_1_Result[4]; int SBOX_5_Result[4];
      int SBOX_2_Result[4]; int SBOX_6_Result[4];
      int SBOX_3_Result[4]; int SBOX_7_Result[4];
      int SBOX_4_Result[4]; int SBOX_8_Result[4];

    /* fill the arrays */
      ull_to_bin_array(sbox_results[0], SBOX_1_Result, 4);
      ull_to_bin_array(sbox_results[1], SBOX_2_Result, 4);
      ull_to_bin_array(sbox_results[2], SBOX_3_Result, 4);
      ull_to_bin_array(sbox_results[3], SBOX_4_Result, 4);
      ull_to_bin_array(sbox_results[4], SBOX_5_Result, 4);
      ull_to_bin_array(sbox_results[5], SBOX_6_Result, 4);
      ull_to_bin_array(sbox_results[6], SBOX_7_Result, 4);
      ull_to_bin_array(sbox_results[7], SBOX_8_Result, 4);

    /* concatenate the arrays in pairs, since my concatenate function above
       requires equal length inputs */
      int *first_2  = concatenate_arrays(SBOX_1_Result, SBOX_2_Result, 4);
      int *second_2 = concatenate_arrays(SBOX_3_Result, SBOX_4_Result, 4);
      int *third_2  = concatenate_arrays(SBOX_5_Result, SBOX_6_Result, 4);
      int *last_2   = concatenate_arrays(SBOX_7_Result, SBOX_8_Result, 4);

    /* combine the two halves */
      int *first_half = concatenate_arrays(first_2, second_2, 8);
      int *second_half = concatenate_arrays(third_2, last_2, 8);

    /* combine into one full array */
      int *full = concatenate_arrays(first_half, second_half, 16);

      return full;
   }

    /* Reverses the elements in array a
      from index start to end */
   void reverse(int *a, int start, int end)
   {
      int swap;
      while(start < end)
      {
         swap         = a[start];
         a[start++]   = a[--end];
         a[end]       = swap;
      }
   }

    /**
     * Uses a triple-reversal method of left-shifting
     * that is described here: 
     * http://www.cs.bell-labs.com/cm/cs/pearls/s02b.pdf
     * takes as input, a pointer to an array, 
     * the length of that array and the amount
     * to left shift by
     */
   void left_shift(int *a, int aLen, int amt)
   {
    //left shift a by amt using three reversals
      reverse(a, 0, amt);
      reverse(a, amt, aLen);
      reverse(a, 0, aLen);
   }
#endif
/*McMillen_DES_Utils.h
*此头文件包含执行以下操作的函数
*我的计划的大部分工作。我抽象了
*从主C文件中删除它们以避免过多的混乱
*
*亨特·麦克米伦
* 2/9/2012
*/ 
#ifndef GUARD_DES_Utils/*在包含两次时防止错误*/
#定义保护措施
#包括“DES.h”
#包括
#包括
#包括
//共享函数的定义!!
无符号长*DES(无符号长明文,无符号长密钥);
/*计算它的位数
*表示整数a的时间
*/
int num_位(无符号长a)
{
int位计数=0;
而(a>0)
{
位计数++;
a=a>>1;//右移1位
}
返回位计数;
}
/*将无符号long-long转换为
构成二进制表示形式的整数*/
void ull_to_bin_数组(无符号长a,int*b,int-length)
{
int*temp=malloc(长度*sizeof(int));
int i;
对于(i=长度-1;i>=0;i--)
{
temp[i]=(a>>i)&1;//将第i位存储在temp[i]中
}
对于(i=0;ib[i]映射
b[i]=温度[tLen];
//将temp的(长度-i)th存储在b[i]中,这会将MSB放在第一位
}
}
无符号长*二进制字符串到二进制字符串(字符*二进制字符串)
{
//为指向ull的点分配空间
unsigned long*out=malloc(sizeof(unsigned long));
//将bin_字符串解释为64位数字
无符号长t=strtoull(bin_字符串,NULL,2);
//把t的地址抄出来
out=&t;
返回;
}
/*打印给定的一维数组
指向它的指针及其长度,以及可选的标题*/
无效打印数组(int*arr,int-length,char*msg)
{
int i;
如果(msg!=NULL)printf(“%s:”,msg);
对于(i=0;i #ifndef GUARD_DES /* prevents errors when including twice */
 #define GUARD_DES

 #define NUM_ROUNDS 16
 /* 1. Data Encoding Permutations and Definitions */

 /* This macro defines the initial permutation, it will re-order the 
    64-bit message into this bit configuration
     Source: Stallings pg 80
     Note: all indices in this macro are 1 less than the table in Stallings
           because arrays are 0-based in C
  */
#define IP(x)  { x[57], x[49], x[41], x[33], x[25], x[17], x[9], x[1], \
                 x[59], x[51], x[43], x[35], x[27], x[19], x[11], x[3], \
             x[61], x[53], x[45], x[37], x[29], x[21], x[13], x[5], \
             x[63], x[55], x[47], x[39], x[31], x[23], x[15], x[7], \
             x[56], x[48], x[40], x[32], x[24], x[16], x[8],  x[0], \
             x[58], x[50], x[42], x[34], x[26], x[18], x[10], x[2], \
                 x[60], x[52], x[44], x[36], x[28], x[20], x[12], x[4], \
                 x[62], x[54], x[46], x[38], x[30], x[22], x[14], x[6] }

/* This macro defines the final permutation 
   Note: all numbers are off by 1 to support 0-based array indexing*/
#define IP_1(x) {
      x[39],  x[7],   x[47],    x[15],    x[55],   x[23],    x[63],   x[31], \
      x[38],  x[6],   x[46],    x[14],    x[54],   x[22],    x[62],   x[30], \
      x[37],  x[5],   x[45],    x[13],    x[53],   x[21],    x[61],   x[29], \
      x[36],  x[4],   x[44],    x[12],    x[52],   x[20],    x[60],   x[28], \
      x[35],  x[3],   x[43],    x[11],    x[51],   x[19],    x[59],   x[27], \
      x[34],  x[2],   x[42],    x[10],    x[50],   x[18],    x[58],   x[26], \
      x[33],  x[1],   x[41],    x[9],     x[49],   x[17],    x[57],   x[25], \
      x[32], x[0],   x[40],    x[8],     x[48],   x[16],    x[56],   x[24]} 

 /* This macro defines the expansion permutation, it takes an input of 
    32 bits; reorders these bits and reuses some bits in places,
     producing a 48-bit output
     Note: all numbers are off by 1 to support 0-based array indexing */
#define E(x) {   x[31],  x[0],  x[1],  x[2],   x[3],    x[4], \
                 x[3],   x[4],  x[5],  x[6],   x[7],    x[8], \
                 x[7],   x[8],  x[9],  x[10],  x[11],   x[12], \
                 x[11],  x[12], x[13], x[14],  x[15],   x[16], \
                 x[15],  x[16], x[17], x[18],  x[19],   x[20], \
                 x[19],  x[20], x[21], x[22],  x[23],   x[24], \
                 x[23],  x[24], x[25], x[26],  x[27],   x[28], \
                 x[27],  x[28], x[29], x[30],  x[31],   x[0] }

 /* This macro defines the Permutation function P which shuffles a 32 
    bit array 
    Note: all numbers are off by 1 to support 0-based array indexing */
#define P(x) {  x[15],  x[6],   x[19],  x[20], \
                x[28],  x[11],  x[27],  x[16], \
                x[0],   x[14],  x[22],  x[25], \
                x[4],   x[17],  x[30],  x[9], \
                x[1],   x[7],   x[23],  x[13], \
                x[31],  x[26],  x[2],   x[8],  \
                x[18],  x[12],  x[29],  x[5],  \
                x[21],  x[10],  x[3],   x[24]}

 /* These Matrix definitions are for the S boxes */
  #define SBOX_ROWS 4
  #define SBOX_COLS 16

   int SBOX_1[SBOX_ROWS][SBOX_COLS] =  { 
   {14,  4,  13,  1,   2, 15,  11,  8,   3, 10,  6, 12,  5,  9,   0,  7},
   { 0, 15,   7,  4,  14,  2,  13,  1,  10,  6, 12, 11,  9,  5,   3,  8},
   { 4,  1,  14,  8,  13,  6,   2, 11,  15, 12,  9,  7,  3, 10,   5,  0},
   {15, 12,   8,  2,   4,  9,   1,  7,   5, 11,  3, 14,  10, 0,   6, 13}};

   int SBOX_2[SBOX_ROWS][SBOX_COLS] =  {
   {15,  1,   8, 14,   6, 11,   3,  4,   9,  7,   2, 13,  12,  0,   5, 10},
   { 3, 13,   4,  7,  15,  2,   8, 14,  12,  0,   1, 10,   6,  9,  11,  5},
   { 0, 14,   7, 11,  10,  4,  13,  1,   5,  8,  12,  6,   9,  3,   2, 15},
   {13,  8,  10,  1,   3, 15,   4,  2,  11,  6,   7, 12,   0,  5,  14,  9}};

   int SBOX_3[SBOX_ROWS][SBOX_COLS] =  {
   {10,  0,   9, 14,   6,  3,  15,  5,   1, 13,  12,  7,  11,  4,   2,  8},
   {13,  7,   0,  9,   3,  4,   6, 10,   2,  8,   5, 14,  12, 11,  15,  1},
   {13,  6,   4,  9,   8, 15,   3,  0,  11,  1,   2, 12,   5, 10,  14,  7},
   {1,  10,  13,  0,   6,  9,   8,  7,   4, 15,  14,  3,  11,  5,   2, 12}};

   int SBOX_4[SBOX_ROWS][SBOX_COLS] =  {
   { 7, 13,  14,  3,   0,  6,   9, 10,   1,  2,   8,  5,  11, 12,   4, 15},
   {13,  8,  11,  5,   6, 15,   0,  3,   4,  7,   2, 12,   1, 10,  14,  9},
   {10,  6,   9,  0,  12, 11,   7, 13,  15,  1,   3, 14,   5,  2,   8,  4},
   { 3, 15,   0,  6,  10,  1,  13,  8,   9,  4,   5, 11,  12,  7,   2, 14}};

   int SBOX_5[SBOX_ROWS][SBOX_COLS] =  {
   {2,  12,   4,  1,   7, 10,  11,  6,   8,  5,   3,  15,  13,  0,  14,  9},
   {14, 11,   2, 12,   4,  7,  13,  1,   5,  0,  15,  10,   3,  9,   8,  6},
   {4,   2,   1, 11,  10, 13,   7,  8,  15,  9,  12,   5,   6,  3,   0, 14},
   {11,  8,  12,  7,   1, 14,   2, 13,   6, 15,   0,   9,  10,  4,   5,  3}};

   int SBOX_6[SBOX_ROWS][SBOX_COLS] =  {
   {12,  1,  10, 15,   9,  2,   6,  8,   0, 13,   3,  4,  14,  7,   5, 11},
   {10, 15,   4,  2,   7, 12,   9,  5,   6,  1,  13, 14,   0, 11,   3,  8},
   { 9, 14,  15,  5,   2,  8,  12,  3,   7,  0,   4, 10,   1, 13,  11,  6},
   { 4,  3,   2, 12,   9,  5,  15, 10,  11, 14,   1,  7,   6,  0,   8, 13}};

   int SBOX_7[SBOX_ROWS][SBOX_COLS] =  {
   { 4, 11,   2, 14,  15,  0,   8, 13,   3, 12,   9,  7,   5, 10,   6,  1},
   {13,  0,  11,  7,   4,  9,   1, 10,  14,  3,   5, 12,   2, 15,   8,  6},
   { 1,  4,  11, 13,  12,  3,   7, 14,  10, 15,   6,  8,   0,  5,   9,  2},
   { 6, 11,  13,  8,   1,  4,  10,  7,   9,  5,   0, 15,  14,  2,   3, 12}};

   int SBOX_8[SBOX_ROWS][SBOX_COLS] =  {
   {13,  2,   8,  4,   6, 15,  11,  1,  10,  9,   3, 14,   5,  0,  12,  7},
   { 1, 15,  13,  8,  10,  3,   7,  4,  12,  5,   6, 11,   0, 14,   9,  2},
   { 7, 11,   4,  1,   9, 12,  14,  2,   0,  6,  10, 13,  15,  3,   5,  8},
   { 2,  1,  14,  7,   4, 10,   8, 13,  15, 12,   9,  0,   3,  5,   6, 11}};


 /* 2. Subkey Generation Permutations and Definitions*/

 /* This macro defines Permuted Choice#1, it reorders and reduces the input 
     64-bit key to 56 bits, Note: all numbers are off by 
     1 to support 0-based array indexing */
#define PC_1(x) { x[56], x[48],  x[40],  x[32],  x[24],  x[16],  x[8],  \
                  x[0],  x[57],  x[49],  x[41],  x[33],  x[25],  x[17], \
                  x[9],  x[1],   x[58],  x[50],  x[42],  x[34],  x[26], \
                  x[18], x[10],  x[2],   x[59],  x[51],  x[43],  x[35], \
                  x[62], x[54],  x[46],  x[38],  x[30],  x[22],  x[14], \
                  x[6],  x[61],  x[53],  x[45],  x[37],  x[29],  x[21], \
                  x[13], x[5],   x[60],  x[52],  x[44],  x[36],  x[28], \
              x[20], x[12],  x[4],   x[27],  x[19],  x[11],  x[3]  }

/* This macro defines Permuted Choice#2, it reorders and reduces the input
   56-bit key to 48 bits
    Note: all numbers are off by 1 to support 0-based array indexing */
#define PC_2(x) { x[13],  x[16],  x[10],  x[23],  x[0],   x[4],  \
                  x[2],   x[27],  x[14],  x[5],   x[20],  x[9], \
                  x[22],  x[18],  x[11],  x[3],   x[25],  x[7],  \
                  x[15],  x[6],   x[26],  x[19],  x[12],  x[1],  \
                  x[40],  x[51],  x[30],  x[36],  x[46],  x[54], \
                  x[29],  x[39],  x[50],  x[44],  x[32],  x[47], \
                  x[43],  x[48],  x[38],  x[55],  x[33],  x[52], \
                  x[45],  x[41],  x[49],  x[35],  x[28],  x[31] }

/* This array defines the number of left shifts to perform
   at round i */
   #define NUM_LEFTSHIFTS 16
   int LEFTSHIFT_SCHEDULE[NUM_LEFTSHIFTS] = {1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};
#endif
/* McMillen_DES_Utils.h
 * This header file holds the functions that do 
 * the majority of the work for my program. I abstracted
 * them from the main C file to avoid excess clutter
 *
 * Hunter McMillen
 * 2/9/2012
 */ 
 #ifndef GUARD_DES_Utils /* prevents errors when including twice */
 #define GUARD_DES_Utils


 #include "DES.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>

 //Definition of shared function !!
 unsigned long long * DES(unsigned long long plaintext, unsigned long long key);

  /* Counts the number of bits it
   * takes to represent an integer a
   */
   int num_bits(unsigned long long a)
   {
      int bitCount = 0;

      while(a > 0)
      {
         bitCount++;
         a = a >> 1; //shift to the right 1 bit
      }

      return bitCount;
   }

   /* Converts from an unsigned long long into an array of 
       integers that form the binary representation of a */
   void ull_to_bin_array(unsigned long long a, int *b, int length)
   {
      int *temp = malloc(length * sizeof(int));

      int i;
      for(i = length - 1; i >= 0; i--)
      {
         temp[i] = (a >> i) & 1; //store the ith bit in temp[i]
      }

      for(i = 0; i < length; i++)
      {
         int tLen = (length - 1) - i; //mapping from temp[i] -> b[i]
         b[i] = temp[tLen]; 
         //store the (length - i)th of temp in b[i], this puts the MSB first
      }
   }

   unsigned long long * bin_string_to_ull(char * bin_string)
   {
    //allocate space for a pointe to an ull
      unsigned long long * out = malloc(sizeof(unsigned long long));
    //interpret bin_string as a 64-bit number
      unsigned long long t = strtoull(bin_string, NULL, 2);

    //copy the address of t into out
      out = &t;

      return out;
   }

    /* prints a one-dimensional array given
       a pointer to it, and its length, and optionally a header */
   void print_array(int *arr, int length, char *msg)
   {
      int i;
      if(msg != NULL) printf("%s: ",msg);
      for(i = 0; i < length; i++)
      {
         printf("%d", arr[i]);
      }
      printf("\n");
   }    

    /**
     * Takes an input of a 4 element character array
     * that represents a half-byte in binary, maps
     * the 4-bit value to the appropriate hex character
     */
   void map_bin_to_hex(char *c)
   {
      char hexMap[] = "0123456789ABCDEF";
      int index = strtoull(c, NULL, 2);
      printf("%c", hexMap[index]);
   }

    /**
     * Takes a 64 element integer array that holds 
     * the binary representation of a 64-bit hex number
     */
   void bin_array_to_hex(int *b, int length)
   {
      int i, j, k;

    //read 4 bits 16 times
      for(i = 0; i < length; i+=4)
      {
         char hexB[5];
         for(k = 0, j = i; j < (i+4); j++, k++)
         {
            hexB[k] = b[j] + '0';
            //printf("h[%d] = %d\n", k, hexB[k]);
         }
         hexB[5] = '\0';
         map_bin_to_hex(hexB);
      }
      printf("\n");
   }

    /**
     * Takes as input an integer array containing the binary 
     * representation of some number N, and converts all the 
     * bits of N to characters then compresses
     * them into a single "string"
     */ 
   char * bin_array_to_string(int *b, int length)
   {
    //allocate space for length characters
      char *string = malloc((length+1) * sizeof(char));

      int i;
      for(i = 0; i < length; i++)
      {
         string[i] = b[i] + '0';
      }
      string[length] = '\0';

      return string;
   }

    /** 
     * This function takes as input the binary representation
     * of a 64-bit integer held in array form, and partitions it 
     * into LEFT and RIGHT halves
     */
   void partition_arrays(int *s, int *l, int *r, int length)
   {
      int pLength = length / 2;
      int i, j;

      for(i = 0; i < pLength; i++)
      {
         l[i] = s[i];
      }

      for(i = pLength, j = 0; i < length - 1; i++, j++)
      {
         r[j] = s[i];
      }
   }

   /**
     * Takes two arrays of equals length and concatenates their 
     * contents using memcpy 
     */
   int * concatenate_arrays(int *a, int *b, int length)
   {    
      int aLen = length * sizeof(int);
      int bLen = length * sizeof(int);      
      //allocate enough space in the new array for both arrays a and b
      int *new = malloc((aLen + bLen) * sizeof(int));

      memcpy(new, a, aLen);
      memcpy(new + length, b, bLen);

      return new;
   }

    /**
     * Given an integer array and a character array, this function
     * converts the character array to an integer then XORs the two arrays
     * contents
     */
   int * xor_arrays(int *a, char *b, int length)
   {
    //alocate enough space in the xor array 
      int *xor = malloc(length * sizeof(int));

      int i;
      for(i = 0; i < length; i++)
      {
         xor[i] = a[i] ^ (b[i] - '0'); 
         //compute xor, subtract '0' to convert from char to int
      }

      return xor;
   }

    /**
     * Same as the above function but for two integer arrays, 
     * their contents are XORed and returned in another array
     */
   int * xor_int_arrays(int *a, int *b, int length)
   {
    //alocate enough space in the xor array 
      int *xor = malloc(length * sizeof(int));

      int i;
      for(i = 0; i < length; i++)
      {
         xor[i] = a[i] ^ b[i]; //compute xor
      }

      return xor;
   }

    /**
     * Given an array and its length, this function will compute 
     * the results of ALL of the SBOXs for this array
     * The result that is returned is an integer array consisting 
     * of the results from the SBOXs
     */
   int * compute_sbox(int *a, int length)
   {
    /* bits needed for each sbox */
      int sbox_length  = length / 8;
    /* holds integer values retrieved from the SBOX */
      int sbox_results[8]; 
      /* two indices for each sbox */
      int *sbox_indices = malloc(sbox_length * sizeof(int));

    /* i counts every 6 bits in the array 
       k processes bits from 0 - 6 in the inner loop
       j is used to copy values properly into the sbox char array
       y indicates what SBOX we are taking a value from */
      int i, k, j, y;

    /* read 6 bits 8 times */
      for(i = 0, y = 0; i < length; i += sbox_length, y++)
      {
         char sbox[7];
        /* grab every 6 elements of the array */
         for(k = 0, j = i; j < (i + sbox_length); k++, j++)
         {
            sbox[k] = a[j] + '0'; //convert to a string
         }
         sbox[7] = '\0'; //append the null terminator

        /* compute the row and column index */
         char rows[3];
         rows[0] = sbox[0];
         rows[1] = sbox[5];
         rows[2] = '\0';

         char cols[5];
         cols[0] = sbox[1];
         cols[1] = sbox[2];
         cols[2] = sbox[3];
         cols[3] = sbox[4];
         cols[4] = '\0';

        /* get indices into the SBOXy+1 */
         int row = strtoull(rows, NULL, 2);
         int col = strtoull(cols, NULL, 2); 

        /* switch over y and get the results from the SBOXs */
         switch(y)
         {
            case 0:
               sbox_results[y] = SBOX_1[row][col];
               break;   
            case 1:
               sbox_results[y] = SBOX_2[row][col];
               break;   
            case 2:
               sbox_results[y] = SBOX_3[row][col];
               break;   
            case 3:
               sbox_results[y] = SBOX_4[row][col];
               break;   
            case 4:
               sbox_results[y] = SBOX_5[row][col];
               break;   
            case 5:
               sbox_results[y] = SBOX_6[row][col];
               break;   
            case 6:
               sbox_results[y] = SBOX_7[row][col];
               break;   
            case 7:
               sbox_results[y] = SBOX_8[row][col];
               break;       
            default:
               break;   
         }
      }

    /* at this point we have processed every 6 bits in the array 
       and retrieved the correct values from the SBOXs, 
       all that remains is to convert the 
       results to arrays and concatenate them */

    /* initialize arrays */
      int SBOX_1_Result[4]; int SBOX_5_Result[4];
      int SBOX_2_Result[4]; int SBOX_6_Result[4];
      int SBOX_3_Result[4]; int SBOX_7_Result[4];
      int SBOX_4_Result[4]; int SBOX_8_Result[4];

    /* fill the arrays */
      ull_to_bin_array(sbox_results[0], SBOX_1_Result, 4);
      ull_to_bin_array(sbox_results[1], SBOX_2_Result, 4);
      ull_to_bin_array(sbox_results[2], SBOX_3_Result, 4);
      ull_to_bin_array(sbox_results[3], SBOX_4_Result, 4);
      ull_to_bin_array(sbox_results[4], SBOX_5_Result, 4);
      ull_to_bin_array(sbox_results[5], SBOX_6_Result, 4);
      ull_to_bin_array(sbox_results[6], SBOX_7_Result, 4);
      ull_to_bin_array(sbox_results[7], SBOX_8_Result, 4);

    /* concatenate the arrays in pairs, since my concatenate function above
       requires equal length inputs */
      int *first_2  = concatenate_arrays(SBOX_1_Result, SBOX_2_Result, 4);
      int *second_2 = concatenate_arrays(SBOX_3_Result, SBOX_4_Result, 4);
      int *third_2  = concatenate_arrays(SBOX_5_Result, SBOX_6_Result, 4);
      int *last_2   = concatenate_arrays(SBOX_7_Result, SBOX_8_Result, 4);

    /* combine the two halves */
      int *first_half = concatenate_arrays(first_2, second_2, 8);
      int *second_half = concatenate_arrays(third_2, last_2, 8);

    /* combine into one full array */
      int *full = concatenate_arrays(first_half, second_half, 16);

      return full;
   }

    /* Reverses the elements in array a
      from index start to end */
   void reverse(int *a, int start, int end)
   {
      int swap;
      while(start < end)
      {
         swap         = a[start];
         a[start++]   = a[--end];
         a[end]       = swap;
      }
   }

    /**
     * Uses a triple-reversal method of left-shifting
     * that is described here: 
     * http://www.cs.bell-labs.com/cm/cs/pearls/s02b.pdf
     * takes as input, a pointer to an array, 
     * the length of that array and the amount
     * to left shift by
     */
   void left_shift(int *a, int aLen, int amt)
   {
    //left shift a by amt using three reversals
      reverse(a, 0, amt);
      reverse(a, amt, aLen);
      reverse(a, 0, aLen);
   }
#endif
 #include "DES.h"
 #include "DES_Utils.h"

 /* Global Definintions */
   char *keys[16]; //array of keys for all 16 rounds

 /* This function takes as input the initial 64-bit key
  * It generates all 16 subkeys for rounds
  * 1 - 16 and stores them in the global keys[] array
  */
   void generate_subkeys(int key[])
   {
      /* uses the macro permutation defined in
      McMillen_DES.h to permute the initial key into
      a 56-bit key */
      int PC1_Key[] = PC_1(key);

      //split the permuted PC_1 key into two halves 
      //C and D using pointer arithmetic
      int *C0 = PC1_Key;
      int *D0 = PC1_Key + 28;
      int i;
      for(i = 0; i < NUM_ROUNDS; i++)
      {
         /* left shift C0 and DO by the amount 
            indicated in the left shift schedule defined in McMillen_DES.h */
         left_shift(C0, 28, LEFTSHIFT_SCHEDULE[i]);
         left_shift(D0, 28, LEFTSHIFT_SCHEDULE[i]);

         /* merge the shifted Ci and Di together, 
            where i is the round number */
         int *temp = concatenate_arrays(C0, D0, 28);

        /* pass temp to the Permuted Choice 2 macro, 
           which will reduce it from 56-bits
           to 48-bits and generate Ki, the key for round i */
         int Ki[] = PC_2(temp);

        /* compress the binary array into a string for storage */
         char *keyi = bin_array_to_string(Ki, 48);

        /* store the string key for round i */
         keys[i] = keyi;
      }    
   }

    /** 
     * This functions handles the encryption functionality
     * of the DES algorithm.
     */
   void encrypt(int plaintext[])
   {
    /* permute the plaintext message with the IP */
      int permuted_pt[] = IP(plaintext);

    /* partition the permuted plaintext into two halves using pointers */
      int *Li = permuted_pt;
      int *Ri = permuted_pt + 32;

      int i;
      for(i = 0; i < NUM_ROUNDS; i++) 
      {
         /* pass Ri into the Expansion permutation to 
            expand it from 32 to 48 bits */
         int e_Ri[] = E(Ri);

         /* XOR the expanded Ri and Ki, the key for this round i */
         int *xorKeyi_Ri = xor_arrays(e_Ri, keys[i], 48);

         /* parses the row and column indices from the xor'd key and E(Ri)
         then gets the value at that position in SBOXi and concatenates
        the results together */
         int *sbox = compute_sbox(xorKeyi_Ri, 48);

        /* apply the permutation P to the result from the SBOXs */
         int permuted_sbox[] = P(sbox);

        /* use a temp variable to store Ri, update Ri, 
               then assign the old Ri to Li */
         int *temp = Ri;
         Ri = xor_int_arrays(Li, permuted_sbox, 32); 
         /* Ri = L(i-1) XOR f(R(i-1), Ki) */
         Li = temp; /* Li = R(i-1) */
      }

    /* swap the two halves so Ri comes first */
      int *encrypted = concatenate_arrays(Ri, Li, 32);
    /* apply the final permutation */
      int fp[] = IP_1(encrypted);
    /* print the hex result of the final permutation to the console */
      bin_array_to_hex(fp, 64);
   }

   /**
     * Encrypts a 64-plaintext value using a 64-bit key
     * held as unsigned long long values
     */
   unsigned long long * DES(unsigned long long plaintext, 
                            unsigned long long key)
   {
      /* initialize arrays with 64 positions that will hold the 
         binary representation of the key and plaintext, 
         initialized to all 0's */
      int key_arr[64] = { 0 };
      int pt_arr[64]  = { 0 };

      /* fill the arrays with the binary representations
         of the plaintext and the key */
      ull_to_bin_array(key, key_arr, 64);
      ull_to_bin_array(plaintext, pt_arr, 64);

      /* generate subkeys for all 16 rounds */
      generate_subkeys(key_arr);

      /* encrypt the plaintext, this function will display the hex results */
      encrypt(pt_arr);
   }
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "DES_Utils.h"

   char * strToHex(const char * input);

   int main(int argc, int * argv)
   {
    /* initialize they key and IV (C sub 0)*/
      unsigned long long k   = strtoull("0123456789ABCDEF", NULL, 16);
      unsigned long long C_i = strtoull("00FF11EE22DD33CC", NULL, 16); 
      unsigned long long P_i;
      unsigned long long * Ekp_i;

      char buffer[9]; //holds 8 characters read from  the file (i.e. 64-bits)
      char * plaintext;
      FILE *f;

      if (f = fopen("input2.txt", "rb"))
      {
         while( fread(buffer, 8, 1, f) != 0)
         {
            buffer[8] = '\0';

            /* convert the ascii string input into a 64-bit hex string */
            plaintext = strToHex(buffer);
            /* convert the hex string into a 64 bit unsigned long long value */
            P_i = strtoull(plaintext, NULL, 16);

            Ekp_i = DES(P_i ^ C_i, k);
            C_i   = *(Ekp_i);

            printf("%s\n", plaintext);
            printf("%llu\n", P_i);
            printf("%llu\n", C_i);
            printf("%llX\n\n", P_i ^ C_i);
            break;
         }
         fclose(f);
      }
   }

    /**
     * Converts an array with ascii strings in it
     * to its corresponding hex value, this will double
     * the size of the input because one ascii character
     * is two hex bits
     */
   char * strToHex(const char * input)
   {
      char *output = malloc((strlen(input) * 2) + 1);
      char * o = output;

      int i;
      for (i = 0; input[i] != '\0'; o += 2, i++)
      {
         sprintf(o, "%02X", input[i]);
      }

    // don't forget to free output!
      return output;
   }
/* DES_Utils.h */
#include "DES.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef GUARD_DES_Utils /* prevents errors when including twice */
...
In function main': C:DES_hash.c:42: undefined reference to DES'
#ifndef GUARD_DES_Utils /* prevents errors when including twice */
#define GUARD_DES_Utils

//Definition of shared function !!
unsigned long long *DES(unsigned long long, unsigned long long);
void left_shift(int *, int, int);
int *concatenate_arrays(int *, int *, int);
char *bin_array_to_string(int *, int);

int *xor_arrays(int *, char *, int);
int *compute_sbox(int *, int);
int *xor_int_arrays(int *, int *, int);
void bin_array_to_hex(int *, int);

void ull_to_bin_array(unsigned long long, int *, int);

#endif
#define NUM_LEFTSHIFTS 16
int LEFTSHIFT_SCHEDULE[NUM_LEFTSHIFTS] = {1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};
#define SBOX_ROWS 4
#define SBOX_COLS 16
int SBOX_1[SBOX_ROWS][SBOX_COLS] =  { ...
trough
int SBOX_8[SBOX_ROWS][SBOX_COLS] =  { ...
gcc -c -o obj/DES_Hash.o src/DES_Hash.c -Wall -Wextra -pedantic -std=c99 -ggdb
gcc -c -o obj/DES_Utils.o src/DES_Utils.c -Wall -Wextra -pedantic -std=c99 -ggdb
gcc -c -o obj/DES.o src/DES.c -Wall -Wextra -pedantic -std=c99 -ggdb
gcc -o ./bin/DES_Hash ./obj/DES_Hash.o ./obj/DES_Utils.o ./obj/DES.o -Wall -Wextra -pedantic -std=c99 -ggdb
73FB90EEDF18B09A
SIGSEGV
.
├── bin
│   └── DES_Hash
├── obj
│   ├── DES_Hash.o
│   ├── DES.o
│   └── DES_Utils.o
├── src
│   ├── DES.c
│   ├── DES.h
│   ├── DES_Hash.c
│   ├── DES_Utils.c
│   └── DES_Utils.h
└── test
    └── input2.txt
#define BYTE_ULL  (sizeof(unsigned long long))

char buffer[BYTE_ULL + 1];
fread  BYTE_ULL bytes
buffer[BYTE_ULL] = '\0';
==31352== Command: bin/DES_Hash
==31352== 
73FB90EEDF18B09A
74657374696E6720
8387236824869660448
1234
74657374696E63F2

==31352== 
==31352== HEAP SUMMARY:
==31352==     in use at exit: 48,417 bytes in 308 blocks
==31352==   total heap usage: 310 allocs, 2 frees, 48,777 bytes allocated
==31352== 
==31352== LEAK SUMMARY:
==31352==    definitely lost: 47,633 bytes in 292 blocks
==31352==    indirectly lost: 0 bytes in 0 blocks
==31352==      possibly lost: 0 bytes in 0 blocks
==31352==    still reachable: 784 bytes in 16 blocks
==31352==         suppressed: 0 bytes in 0 blocks