Home

Electronic Vote Miscounting

Submit comment
"I am committed to helping Ohio deliver
its electoral votes to the president next year"

-- Walden W. O'Dell (CEO of Diebold, Inc)


The Obfuscated V Contest

In October 2004, inspired by the Obfuscated C code contest and the electronic voting debate, Daniel Horn proposed and ran the Obfuscated Voting Contest. The aim of the contest was to produce a vote counter written in C which appeared correct but did the wrong thing when counting votes.

The contest had two divisions: a "date" division and a "no date" division. The winner of the "no date" division was the program which appeared most correct when inspected but would produce incorrect results when run. The winner of the "date" division was the program which appeared most correct on inspection and produced the correct result before the election but an incorrect result on the day of the election.

Furthermore, the programs were scored out of ten and the scoring was based on "creativity, code believability and lastly count accuracy". The winning program was an entry by Paul A. Parkanzky which on election day gave all of the votes of one candidate to another. However, this sort of a fraudulent program would be very obvious if used during an election.

The following is a modified version of Parkanzky's program which is much stealthier. On election day, it skews the votes by "delivering" all votes cast for a few hours to a particular candidate.

/* 
 * Author: Cameron Skinner (cam at cs.auckland.ac.nz)
 * Author: Jasvir Nagra    (jas at cs.auckland.ac.nz)
 *
 * This program is a modified version of an original program by 
 * Paul A. Parkanzky (firstname.lastname@gmail.com) which was
 * submitted to the Obfuscated V contest.  Our aim is to produce an
 * entry that comes closest to scoring a perfect 10 on the Obfuscated
 * V scoring scale.
 * 
 * Works with gcc3.2 on x86 SuSE, gcc3.3 on x86 Gentoo and gcc3.2 on x86 Redhat.
 * Does not work with gcc2.95 on x86 NetBSD or sparc FreeBSD. 
 * I haven't tried it on any other combinations.
 *
 * On Nov 1 the votes are counted correctly. On Nov 2 the total is
 * correct, but SOME of the votes cast for other candidates is instead
 * "delivered" to one particular candidate.  In fact, all votes cast
 * between 10am and 1pm on Nov 2 go to one candidate.  This gives a
 * much more believable overall election although significantly
 * advantages one candidate.
 *
 */
#include<stdio.h>
#include<ctype.h>
#include<time.h>

void printResults(unsigned int *);
void paperTrail(char *);
char *getDay();
char *getTime();

unsigned char BUSH = 0;
unsigned char KERRY = 1;
unsigned char NADER = 2;
unsigned char OTHER = 3;

int main() {
  unsigned int Tally[4] = {0};

  unsigned int Input;
  unsigned char Vote;

  char LogMesg[32] = {0};
  while ((Input=getchar())!=EOF) {

    // For every vote, establish who the voter voted for
    if (!isspace(Input)){
      switch (Input) {
      case 'B':
        Vote = BUSH;
        break;
      case 'K':
        Vote = KERRY;
        break;
      case 'N':
        Vote = NADER;
        break;
      default:
        Vote = OTHER;
        break;
      }
    }

    // Log the time and day the vote was cast
    char* time = getTime();
    char* day = getDay();
    sprintf (LogMesg,"DATE: November %s TIME: %s VOTE: %c \n", day, time,Input);
    paperTrail(LogMesg);

    // Count the vote
    Tally[Vote]++;
  }
  
  // Print out the results
  printResults(Tally);
  return 0;
}

/*
 * This gets a day string for the paper trail log message.
 * ("first","second","third" or "ith")
 */
char *getDay() {
        char *retVal;
        time_t now_time;
        struct tm *now;

        now_time = time(NULL);
        now = localtime(&now_time);

        if (now->tm_mday == 1) {
                retVal = "first";
        } else if (now->tm_mday == 2) { 
                retVal = "second";      
        } else if (now->tm_mday  == 3) {
                retVal = "third";
        } else {
                retVal = (char *)malloc(7);
                sprintf(retVal,"%ith",now->tm_mday);
        }

        return retVal;
}

/*
 * This gets the time at which the vote was cast
 * in 12-hour format (eg. "10:48", "12:02")
 */
char *getTime() {
  char *retVal;
  time_t now_time;
  int hour;
  int min;
  struct tm *now;
  
  now_time = time(NULL);
  now = localtime(&now_time);
  hour = now->tm_hour;
  hour = hour > 12 ? hour - 12 : hour;
  min = now->tm_min;

  retVal = (char *)malloc(7);
  sprintf(retVal,"%i:%02i",hour, min);
  
  return retVal;
}

/*
 * Print the results.
 */
void printResults(unsigned int *Tally) {
  printf( "Kerry: %d\n", Tally[KERRY] );
  printf( "Bush: %d\n",  Tally[BUSH]  );
  printf( "Nader: %d\n", Tally[NADER] );
  printf( "Other: %d\n", Tally[OTHER] );
}

/*
 * This will print a log of the vote to a paper receipt when 
 * the supporting hardware is added.
 */
void paperTrail(char *mesg) {
        /* Log to paper trail for extra legitimacy! */
}
	    


© 2001-2005 Jasvir Nagra <jas@cs.auckland.ac.nz>
First authored: January 02, 2005
Last modified: Fri Jan 21 16:31:45 NZDT 2005