/*
  Sample file for an attack fixing the rd[] values of the Abacus hash function.
  This can be used to perform theoretical second-preimage and collision attacks.
  
  David A. Wilson, 11 Dec 2008
*/

#include "Abacus_Reference.c"
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

//message length in bytes.  Must be at least 90; a few hundred is ideal.
#define MSGLEN 200

#define DIGESTLENGTH 512

void printState(hashState *state, BitSequence *msg);

int main(){
  int i;
  hashState target, attack;
  BitSequence tgtmsg[MSGLEN], attmsg[MSGLEN], sboxinv[256];

  //initialize target message.  In this case we just use the zero vector.
  for(i=0;i<MSGLEN;i++){
    tgtmsg[i]=0;
  }

  //initialize inverse s-box
  for(i=0;i<256;i++){
    sboxinv[sbox[i]]=i;
  }

  //Process target message up until the end of the message itself (before padding)
  Init(&target, DIGESTLENGTH);
  Update(&target, tgtmsg, MSGLEN * 8);

 
  //process |m|-89 random bytes for the start of the possible second preimage
  Init(&attack, DIGESTLENGTH);
  srand(time(NULL));
  for(i=0;i<MSGLEN-89;i++){
    //rand() isn't very good, but will work for demonstration purposes
    attmsg[i] = (BitSequence)((rand() / ((double)RAND_MAX + 1))*256);
  }
  Update(&attack, attmsg, (MSGLEN-89)*8);

  //construct the last 89 bytes of the message byte by byte.
  for(i=0;i<89;i++){
    /*
      Construct next message byte to generate a byte from the target message's
      rd[] state.  Since the state rotates, the byte we generate during
      this cycle (i-th in this loop, the (89-i)th from the end of the
      message) will end up in position rd[i] after the message has been 
      processed.  So based on the current state we construct it to be equal
      to rd[i] in the target message state.
      We achieve this by focusing only on the resulting rd value and 
      inverting each substep of the absorb phase.
    */
    attmsg[MSGLEN - 89 + i] = 
      attack.rd[0] ^ 
      sboxinv[attack.c4 ^
	      sbox[attack.ra ^ attack.rd[58]] ^ attack.c1 ^
	      gf_mult3[sbox[attack.rb[0] ^ attack.rc[24]] ^ attack.c2] ^
	      gf_mult2[sbox[attack.rc[0] ^ attack.rb[3]]  ^ attack.c3] ^ 
	      sboxinv[target.rd[i]]];

    //process the new byte.
    Update(&attack, attmsg + (MSGLEN-89+i), 8);
  }

  /*
    Print the resulting states.  
    Note that the rd[] arrays are equal for both messages due to the 
    way we crafted the attack message.
   */
  printState(&target, tgtmsg);
  printState(&attack, attmsg);

  return 0;

}

void printState(hashState *state, BitSequence *msg){
  int i;

  printf("Message:  \n");
  for(i=0;i<MSGLEN;i++){
    printf("%02X ", msg[i]);
  }

  printf("\nInternal array state after absorbing message (before final padding):\n");
  printf("ra = %02X\nrb = ", state->ra);
  for(i=0;i<5;i++){
    printf("%02X ", state->rb[i]);
  }
  printf("\nrc = ");
  for(i=0;i<37;i++){
    printf("%02X ", state->rc[i]);
  }
  printf("\nrd = ");
  for(i=0;i<89;i++){
    printf("%02X ", state->rd[i]);
  }
  printf("\n\n");
}

  

