Thinking Pinoy: BBM vs Leni: Forget Math, Hash Code is the Smoking Gun

May 12, 2016

BBM vs Leni: Forget Math, Hash Code is the Smoking Gun

The PPCRV count began right after voting precincts closed at 05:00 PM of 09 May 2016. BBM led the race by a wide margin for the first couple of hours and BBM supporters were pretty sure that he will never have to look back. In a surprising twist of fate, however, Leni slowly inched closer and finally overtook BBM in the early morning of 10 May 2016.

Robredo’s camp attributes this to votes from her bailiwicks: Bicol, Iloilo, and ARMM [Robredo]. Marcos, on other hand, suspected electoral fraud [CNN].

BBM accused Leni of cheating. Leni accused BBM of bitterness. It was one side’s word against the other... until a PPCRV IT expert blew the whistle. In plain English, let ThinkingPinoy explain the how this allegedly hash code anomaly was discovered and what allegedly happened.

Inday! I need some popcorn.

PPCRV IT expert blows the whistle


Earlier today, a PPCRV IT expert claimed that the COMELEC’s transparency server may have been compromised [Inquirer]. This report was corroborated by another article from the [Manila Standard].

The IT expert backed his claims with four (4) screenshots of commands showing discrepancies in hash code data for files downloaded from Comelec’s transparency server. The screenshots basically contained the same data, and the highest-resolution screenshot is shown below:



To facilitate discussion, ThinkingPinoy re-typed the relevant contents of the screenshot, as shown below:
rodelaniban@Rodels-Macbook-Air:~/results/processing$ cat results_nle2016_05092016_2000.zip.hash
results_nle2016_05092016_2000.zip. Hash(md5sum): 962213f5ecd5348d0f57ac1df0e0e4929.
rodelaniban@Rodels-Macbook-Air: ~/results/processing$ md5 results_nle2016_05092016_2000.zip
MD5 (results_nle2016_05092016_2000.zip): 962213f5ecd5348d0f57ac1df0e0e4929.
rodelaniban@Rodels-Macbook-Air:~/results/processing$ cd results_nle2016_05092016_2000
rodelaniban@Rodels-Macbook-Air:~/results/processing/results_nle2016_05092016_2000$ cat results_nle2016_05092016_2000.hash
results_nle2016_05092016_2000.txt. Hash (md5sum): b5cf93b92c0a7b6f114fc4849337a3ca.
rodelaniban@Rodels-Macbook-Air:~/results/processing/results_nle2016_05092016_2000$ md5 results_nle2016_2000.txt
MD5 (results_nle2016_05092016_2000.txt) = 7370d0daf9a76d026afbdeabad55c2ae
rodelaniban@Rodels-Macbook-Air:~/results/processing/results_nle2016_05092016_2000$
TP will explain why he used varying colors later.

Basic Linux Commands


The commands shown above look daunting for those who are not familiar with Linux code. A closer look, however, shows that the commands are rather simple and relatively easy to understand, even for those with little to no programming knowledge.

To understand the code, let’s talk about a few simple concepts first.

Your computer uses Windows or MacOS. You interact with your computer using the keyboard, the mouse, and a graphical user interface, which is an image-based system of icons and windows.

Comelec-Smartmatic, on the other hand, uses Linux. Comelec guys interact with their computers using the keyboard, the mouse, and a command line, which is basically a text-based system where users input specific text-based commands to achieve a desired outcome. In the context of this article, Comelec-Smartmatic’s Linux command line interface is like the command prompt program in your windows PC.

(L to R) Mac OS, Windows, and Linux

The leaked image above shows several commands, highlighted in blue, entered into Comelec’s system. Each of these commands yields a corresponding response from Comelec’s computers. Let’s take a look at the same commands, which TP paired with a corresponding line number for easier discussion.

LINE 001: rodelaniban@Rodels-Macbook-Air:~/results/processing$ cat results_nle2016_05092016_2000.zip.hash
LINE 002: results_nle2016_05092016_2000.zip. Hash(md5sum): 962213f5ecd5348d0f57ac1df0e0e4929.
LINE 003: rodelaniban@Rodels-Macbook-Air: ~/results/processing$ md5 results_nle2016_05092016_2000.zip
LINE 004: MD5 (results_nle2016_05092016_2000.zip): 962213f5ecd5348d0f57ac1df0e0e4929.
LINE 005: rodelaniban@Rodels-Macbook-Air:~/results/processing$ cd results_nle2016_05092016_2000
LINE 006: rodelaniban@Rodels-Macbook-Air:~/results/processing/results_nle2016_05092016_2000$ cat results_nle2016_05092016_2000.hash
LINE 007: results_nle2016_05092016_2000.txt. Hash (md5sum): b5cf93b92c0a7b6f114fc4849337a3ca.
LINE 008: rodelaniban@Rodels-Macbook-Air:~/results/processing/results_nle2016_05092016_2000$ md5 results_nle2016_2000.txt
LINE 009: MD5 (results_nle2016_05092016_2000.txt) = 7370d0daf9a76d026afbdeabad55c2ae
LINE 010: rodelaniban@Rodels-Macbook-Air:~/results/processing/results_nle2016_05092016_2000$

From the set of command lines shown above, a command in line 001 yields a response shown in line 002, a command in line 003 yields a response shown in line 004, and so on.

Three Linux commands were used in the screenshot: CAT, CD, and MD5.

  • The “CAT” command displays the contents of a given file.
  • The “CD” command allows a user to “change directories” or “enter” a zip (compressed) file.
  • The “MD5” command allows the generation of the hash code of a given file.

Hash Codes as Digital Fingerprints


Comelec or not Comelec, every computer program on earth has two versions:

  • a source code that’s readable by humans
  • a compiled or executable program that’s readable by computers

The source code is a sequence of programming code typed by a computer programmer. It is then converted into a machine-readable form known as the executable. The "converter" is pretty much the same in all cases. That is, the final executable is entirely dependent on the source code.

This is the same reason why Comelec-Smartmatic source codes are reviewed before they are converted into executable programs [CNN].

Each source code, when compiled, is subjected to the MD5 command. MD5 is a special command that generates a hash code, which serves as the digital fingerprint of the executable. The hash code is the assurance that whatever has been tested will be the same for the machines that will be used for the elections [Rappler].


Before the May 9 elections, all tested-and-approved source codes and their corresponding executables are subjected to the MD5 command, thus generating hash codes for each of the approved programs. This allows the us to ensure that the programs used during vote-counting works exactly the way they should.

How? If someone changes even a single line of code, the resulting hash code would be different. That’s why it’s called a digital fingerprint.

More on that later.

COMELEC’s Database Design


Let's take another look at the re-typed leaked screenshot:

LINE 001: rodelaniban@Rodels-Macbook-Air:~/results/processing$ cat results_nle2016_05092016_2000.zip.hash 
LINE 002: results_nle2016_05092016_2000.zip. Hash(md5sum): 962213f5ecd5348d0f57ac1df0e0e4929. 
LINE 003: rodelaniban@Rodels-Macbook-Air: ~/results/processing$ md5 results_nle2016_05092016_2000.zip
LINE 004: MD5 (results_nle2016_05092016_2000.zip): 962213f5ecd5348d0f57ac1df0e0e4929.
LINE 005: rodelaniban@Rodels-Macbook-Air:~/results/processing$ cd results_nle2016_05092016_2000
LINE 006: rodelaniban@Rodels-Macbook-Air:~/results/processing/results_nle2016_05092016_2000$ cat results_nle2016_05092016_2000.hash 
LINE 007: results_nle2016_05092016_2000.txt. Hash (md5sum): b5cf93b92c0a7b6f114fc4849337a3ca.
LINE 008: rodelaniban@Rodels-Macbook-Air:~/results/processing/results_nle2016_05092016_2000$ md5 results_nle2016_2000.txt
LINE 009: MD5 (results_nle2016_05092016_2000.txt) = 7370d0daf9a76d026afbdeabad55c2ae
LINE 010: rodelaniban@Rodels-Macbook-Air:~/results/processing/results_nle2016_05092016_2000$
You probably see the character string “results_nle2016_05092016_2000” used several times. This is actually very descriptive:
  • results_ refers to Results
  • nle2016_ refers to National and Local Elections 2016
  • 05092016_ refers to 09 May 2016
  • 2000_ refers to 2000 hrs (military time) or 8:00 PM
In short, “results_nle2016_05092016_2000” refers to the “Results of the 2016 National and Local Elections as of 09 May 2016, 2000 hrs”.

Each file retrieved by the PPCRV from the Comelec database (called the Comelec Transparency Server for added drama) comes with a paired hash file. The hash file (with file extension “.hash”) provides the expected hash code – or the digital fingerprint – of the file.

For example, SAMPLE.zip always has a paired SAMPLE.zip.hash.
  • SAMPLE.zip.hash contains a hash code in the form of a hexadecimal number, say, 0abcdef1, which is the expected hash code.
  • If I process SAMPLE.zip (the original file) using a hash code generator, the resulting hash should also be 0abcdef1. That's what we need to ensure integrity.
  • However, if the generated hash code is different from the expected hash code, then may imply the use of an unauthorized source code OR the contents of that ZIP file were changed, i.e. electoral fraud may be happening.
So the logical question to ask is:

Were there instances of non-matching hash codes discovered during the PPCRV quick count?

The Screenshot

Now, it’s time to explain what the command lines in the screenshot mean.

Let’s take a look at the first two lines:
LINE 001: rodelaniban@Rodels-Macbook-Air:~/results/processing$ cat results_nle2016_05092016_2000.zip.hash
LINE 002: results_nle2016_05092016_2000.zip. Hash(md5sum): 962213f5ecd5348d0f57ac1df0e0e4929.
The text in red doesn’t really matter right now: it’s just the name of the computer being used. What’s important is the orange text plus the blue text that comes right after it.


Line 001 issued the command cat results_nle2016_05092016_2000.zip.hash, which instructs the computer to show us the contents of that file, which is the “expected hash code”. The computer, in response, tells us that the expected hash code is…

962213f5ecd5348d0f57ac1df0e0e4929

Now, let’s take a look at the next two lines.
LINE 003: rodelaniban@Rodels-Macbook-Air: ~/results/processing$ md5 results_nle2016_05092016_2000.zip


LINE 004:
 MD5 (results_nle2016_05092016_2000.zip): 962213f5ecd5348d0f57ac1df0e0e4929.
Line 003 issued the command md5 results_nle2016_05092016_2000.zip, which tells the computer to generate a hash code for that file on the spot. In response, it returns the hash code...

962213f5ecd5348d0f57ac1df0e0e4929

Hence, the hash codes match for the file “results_nle2016_05092016_2000.zip”. That's what we want.

There’s nothing fishy so far. However, things take a curious turn after TP checked the next several lines.
LINE 005: rodelaniban@Rodels-Macbook-Air:~/results/processing$ cd results_nle2016_05092016_2000
Line 005 instructs the computer to explore "results_nle2016_05092016_2000.zip", allowing us to examine its contents.

Now, let's examine the next two lines.
LINE 006: rodelaniban@Rodels-Macbook-Air:~/results/processing/results_nle2016_05092016_2000$ cat results_nle2016_05092016_2000.hash


LINE 007:
 results_nle2016_05092016_2000.txt. Hash (md5sum): b5cf93b92c0a7b6f114fc4849337a3ca.
Line 006 tells the computer to show the expected hash code for results_nle2016_05092016_2000.txt. This .TXT file is found inside the ZIP file mentioned in Line 001. The computer, in response, told us that the expected hash code is:
b5cf93b92c0a7b6f114fc4849337a3ca
Hence, the next logical step is to generate, on the spot, a hash code for results_nle2016_05092016_2000.txt and see if matches the expected hash code shown above.
LINE 008: rodelaniban@Rodels-Macbook-Air:~/results/processing/results_nle2016_05092016_2000$ md5 results_nle2016_2000.txt

LINE 009:
 MD5 (results_nle2016_05092016_2000.txt) = 7370d0daf9a76d026afbdeabad55c2ae
Line 008 generates the on-the-spot hash code for results_nle2016_05092016_2000.txt, which is:

 7370d0daf9a76d026afbdeabad55c2ae
This is the problem that the IT expert was pointing out. The expected hash code which starts with "b5cf93b..." DOES NOT MATCH the generated hash code that starts with "7370d0...".

Yes, the Comelec Transparency Server seems to have used two different programs: one before 8:00 PM 09 May 2016, and another after that.  An alternative explanation would be that the Comelec Transparency Server's zip files's contents were changed in the middle of the night.

Note, that this discovery need not necessarily imply electoral fraud. However, the fact remains that Comelec-Smartmatic appears to have used two different programs in the middle of counting votes, or that it changed file contents, in the middle of the night.

Yes, differing hash codes do not automatically mean electoral fraud, but they sure do point to it.


One among many instances

The PPCRV IT expert claims to have tested files from 8:30 PM, 9:30 PM, 9:30 PM, all the way to 1:00 AM.

That is, the following files' hash codes do not match their respective expected hash codes:
  • results_nle2016_05092016_2000
  • results_nle2016_05092016_2030
  • results_nle2016_05092016_2130
  • results_nle2016_05092016_2230  
  • results_nle2016_05092016_2330
  • results_nle2016_05102016_0030
  • results_nle2016_05102016_0130 
That is, at around 8:00 PM of 09 May 2016, it appears that Comelec changed its vote-counting program. If not, it may have changed the zip files containing vote-count data.

Of course, the reader may argue that the leaked image could have been fabricated, however, a look at the command lines show the following character string:
rodelaniban@Rodels-Macbook-Air
That is, the computer used appears to belong to a certain Rodel Aniban.

A little googling gives us a March 2016 news article mentioning a person with the same name [SunStar]:

There are many programmers who have seen the source code of the Election Management System (EMS), Vote Counting Machines (VCM),and Consolidation and Canvassing System (CCS), including Rodel Aniban, Kendrick Chan, Wilhansen Li, Pepe Bawagan...
So yes, it appears that the leaked image was taken from an official source.

I hate Bongbong Marcos, but this is what it is.

Hey, Comelec and Smartmatic, you have a serious problem. (TP)

UPDATE 13 May 2016: TP rebuts Comelec's "ñ" alibi in "BBM vs Leni: Comelec-Smartmatic gives Sec. Abaya a run for his money"


Did you like this post? Help ThinkingPinoy.com stay up! Even as little as 50 pesos will be a great help!