Links und Funktionen
Sprachumschaltung

Navigationspfad
You are here: Home / Teaching / Summer 2017 / Cryptography / Exercises / exercise5_2.c


Inhaltsbereich

exercise5_2.c

C source code icon exercise5_2.c — C source code, 4 KB (4384 bytes)

File contents

#include<stdio.h>
#include<stdbool.h>
#include<stdint.h>


/********************************************************************************
 * Parameters of sp-network
 ********************************************************************************/

const uint8_t sbox[] = {
  0, 1, 2, 0xd, 4, 7, 0xf, 6, 8, 0xc, 0xe, 0xb, 0xa, 9, 3, 5
};

const uint8_t sbox_inv[] = {
  0, 1, 2, 0xe, 4, 0xf, 7, 5, 8, 0xd, 0xc, 0xb, 9, 3, 0xa, 6
};

const uint8_t perm[] = {
  15, 6, 19, 20, 28, 11, 27, 16, 0, 14, 22, 25, 4, 17, 30, 9, 1, 7, 23, 13,
  31, 26, 2, 8, 18, 12, 29, 5, 21, 10, 3, 24
};

const uint8_t perm_inv[] = {
  8, 16, 22, 30, 12, 27, 1, 17, 23, 15, 29, 5, 25, 19, 9, 0, 7, 13, 24, 2,
  3, 28, 10, 18, 31, 11, 21, 6, 4, 26, 14, 20
};


/********************************************************************************
 * Type of word with functions for manipulating words
 ********************************************************************************/

/* Type of input and output words of sp-network. */
typedef uint32_t word_t;


bool bit(word_t x, int i) {
  return (x >> i) & 1;
}

int nibble(word_t x, int i) {
  return (x >> (4 * i)) & 0xf;
}

void set_nibble(word_t *x, int i, uint8_t n) {
  *x &= ~(0xf << (4 * i));  // delete old bits
  *x |= (n & 0xf) << (4 * i); // set new bits
}

void print_word(word_t w) {
  printf("%08x\n", w);
}

word_t from_int32(uint32_t x) {
  return x;
}

word_t zero_word() {
  return from_int32(0);
}

bool equal_words(word_t v, word_t k) {
  return v == k;
}

word_t or_words(word_t v, word_t k) {
  return v | k;
}

word_t and_words(word_t v, word_t k) {
  return v & k;
}

word_t xor_words(word_t v, word_t k) {
  return v ^ k;
}

/********************************************************************************
 * Implementation of encryption
 ********************************************************************************/

/* Apply eight S-Boxes in parallel to the word v */
word_t apply_sboxes(const uint8_t sbox[], word_t v) {
  word_t w = zero_word();
  for (int i = 0; i < 8; i++) {
    set_nibble(&w, i, sbox[nibble(v, i)]);
  }
  return w;
}

/* Apply bit permutation */
word_t apply_perm(const uint8_t perm[], word_t v) {
  word_t w = 0;
  for (int i = 0; i < 32; i++) {
    if (bit(v, i)) {
      w |= (1 << perm[i]);
    }
  }
  return w;
}

/* apply the substitution and permutation of one round */
word_t spround(word_t input) {
  return apply_perm(perm, apply_sboxes(sbox, input));
}

/* invert permutation and substitution of one round */
word_t spround_inv(word_t output) {
  return apply_sboxes(sbox_inv, apply_perm(perm_inv, output));
}

/* full round including key mixing */
word_t full_round(word_t input, word_t subkey) {
  return spround(input ^ subkey);
}


/* full inverted round including key mixing */
word_t full_round_inv(word_t output, word_t key) {
  return spround_inv(output) ^ key;
}


void get_key(int n, word_t input[], word_t output[]) {
  word_t y[n];

  for (int i = 0; i < n; i++) {
    y[i] = apply_perm(perm_inv, spround_inv(output[i]));
  }

  // Go through the eight S-Boxes in the first round.
  for (int b = 0; b < 8; b++) {

    for (uint8_t k2_part_candidate = 0; k2_part_candidate < 16; k2_part_candidate++) {

      uint8_t k1_b[n];
      for (int i = 0; i < n; i++) {
        // actual output of box b for input-output-pair i and key candidate
        uint8_t output_sbox_b = nibble(y[i], b) ^ k2_part_candidate;
        // actual input of box i
        uint8_t input_sbox_b = sbox_inv[output_sbox_b];
        // part of k1 in block b determined from input i and k2_part_candidate
        k1_b[i] = input_sbox_b ^ nibble(input[i], b);
      }

      // The choice of k2_part_candidate is possible if all input-output
      // pairs lead to the same part of k1_b
      bool possible = true;
      for (int i = 1; i < n; i++) {
        possible &= (k1_b[0] == k1_b[i]);
      }

      if (possible) {
        printf("Possible candidate for block %i of key 1: %01x; ", b, k1_b[0]);
        printf("corresponding bit values of k2: %08x (mask %08x)\n",
            apply_perm(perm, 0xf << (4*b)),
            apply_perm(perm, k2_part_candidate << (4*b)));
      }
    }
  }
}

int main() {
  int n = 3;
  word_t input[] = {
    0x40414243,
    0x84838281,
    0x12345678
  };
  word_t output[] = {
    0xf82e5109,
    0x3291021d,
    0xaefcf8c1
  };

  get_key(3, input, output);

}

Document Actions


Funktionsleiste