Specious spreadsheet security

If not for Chinese, it would’ve worked.

So in Excel, you can set a password for either protecting a particular worksheet, or protecting the entire workbook/spreadsheet. This password is then hashed, and the result is stored within the spreadsheet contents.

Now with the use of Open XML spreadsheets, this means the resulting hash is stored in “plain text” within XML files. Without going into too much detail, here’s the algorithm for the hash as documented in the Open XML SDK 2.0 help docs:

// Function Input:
//    szPassword: NULL-terminated C-style string
//    cchPassword: The number of characters in szPassword (not including the NULL terminator)
WORD GetPasswordHash(const CHAR *szPassword, int cchPassword) {
      WORD wPasswordHash;
      const CHAR *pch;
 
      wPasswordHash = 0;
 
      if (cchPassword > 0)
            {
            pch = &szPassword[cchPassword];
            while (pch-- != szPassword)
                  {
                  wPasswordHash = ((wPasswordHash >> 14) & 0x01) | ((wPasswordHash << 1) & 0x7fff);
                  wPasswordHash ^= *pch;
                  }
            wPasswordHash ^= (0x8000 | ('N' << 8) | 'K');
            }
      
      return(wPasswordHash);
}

This algorithm is wrong. Or at least it doesn't give the resulting hash that Excel produces.

Granted, I didn't really expect the algorithm to be correct. Because from the SDK help:

An example algorithm to hash the user input into the value stored is as follows:

It's an example algorithm, so it may or may not be the one that Excel actually use. However, for the purposes of usability, the password used by users have to be encrypted using Excel's algorithm, so we have to somehow get the resulting hash. Either we get the algorithm itself, or we simulate an algorithm such that the resulting hash matches that of Excel's.

Which is what Kohei Yoshida did. See his modified algorithm. This algorithm worked!

Given that I'm Chinese, I did what's natural: I used Chinese characters as the password.

And the modified algorithm failed. It only worked if the password consisted only of Latin alphabets. I tried Japanese characters. Failed too.

This is why I don't support password protection in SpreadsheetLight. I don't want to give the false impression that the worksheet/workbook encryption works. This is one feature where "partially worked" is unacceptable.

Granted Open XML spreadsheets also support other types of encryption, and you can store the name of the algorithm and salt value you used, and even the number of times the hash algorithm was run.

But.

This is in the context of a spreadsheet library.

What are spreadsheet libraries mostly used for? Automation.

Which means minimal (if at all) human interaction and intervention.

And so the question comes up.

Where do you store the password?

If a human is protecting the worksheet/workbook, she will provide the password herself, and then encrypts it (well Excel does it), and she just remembers the password.

If a spreadsheet library is generating the workbook, and encrypting it, the password has to be gotten from somewhere, right? So it's stored, maybe in a text file, maybe in a database, maybe hardcoded in code, or whatever.

The point being that the password is not held solely by a human being. And a computer hard drive is easier to hack into than a human brain.

And I will prefer not to be a party to facilitating insecure spreadsheet generation. Besides, it's Open XML. The data is supposed to be open and sharable. Password protection seems to be the opposite. Even Microsoft cautions the use of depending just on encrypted Excel files.

We already have social engineering used by devious people to deceive people into giving their passwords over. Storing passwords on a computer seems suicidal because computers have no common sense at all.

As a final word, I'd say using the Open XML SDK can be either verbose, or obscenely painstakingly verbose. Simple tasks need a couple of dozens of lines of code, and complex tasks take at least 2 magnitudes of work to do. For individualistic, compartmentalisable (that's not a word, right?) tasks, you can do it from scratch. Add even a smidgeon of complexity, and you'll find a library more useful. Try mine.

So hot, I was stopped by security

The recent heat wave in Singapore, and the unfortunate H1N1 epidemic reminded me of a story. I’ve only told this to a few people, but here is where you’ll read about the full story.

It was slightly later than the SARS period. People were frightened of getting infected. The basic detection method was the temperature check, so thermometers and heat scans were employed.

I was also looking for a potential job position, and I got an afternoon interview with a company. I arrived early because the location was a bit remote.

Now, it’s a habit of mine. Whenever I know something important is happening later, I stop drinking. Just so I won’t have to go to the bathroom at the most inopportune moments. I don’t know why, it’s just a personal quirk.

So I was walking from the bus stop to the company’s location, under the hot sun, in long sleeves and pants (thankfully no suit and tie needed), and heated, slightly sweaty and parched. It was a wonder I reached the security guardroom of the company not dripping wet from my own sweat.

Now this company had a very high security level. They had a full temperature head scanner. They had this device that scans people, and a heat map shows up on their screens.

Well, it was after the SARS period, so I could understand their security concerns. Someone from the company was waiting for me. He waited by the side while the security guard asked me to stand at a designated spot. Then the guard activated the scanner.

Apparently, my temperature scan looked like a sunset with lavish swathes of reds and oranges, because the guard told me to stand still again while he scanned again. Sensing something wrong, the adrenaline in me surged a little, which didn’t help cool down my body temperature. I held still. I even held my breath. I still failed the temperature scan.

The company liaison, surprised by this unexpected unfolding of events, took me to the inner parts of the guardroom, where the air conditioning was stronger. He also offered me a cup of water from the dispenser. Then he told me to sit and wait for a while first. I got myself a cup of water, drank and accepted his suggestion.

“I’m gonna fail the interview before I even step into the company office, aren’t I?” silently and matter-of-factly entered my thoughts.

After 15 minutes (or half an hour, I didn’t keep track), I stood up, and took the temperature scan again. I placed my feet at the exact position of the designated spot, shifting my shoes to fit the exact outline of the pre-drawn shoe print. My hands were held in a limbo of alternating tenseness and forced relaxation. I looked up as confidently as I could, keeping my breathing steady, taking deep breaths… And the guard scanned.

What took seconds felt like the time passed while running around a 400 metre track 2 times, then jumping into a pool to swim 100 metres and then work out a 6 digit long division. By hand. I was getting ready to dive into that imaginary pool in my mind when the guard said it’s ok. I passed.

The company liaison, obvious relief on his face, took me into the company proper. And the interview itself? Well, it’s not as interesting as the guardroom episode… alright fine, I’ll tell you about it some other time.

Exploits of a mom

Here’s a comic strip I recently read. I can’t remember whose RSS feed I read it from (sorry!), but I Googled, and found the original source (I hope). Here’s the link: http://xkcd.com/327/

Shrunk a little to fit into the width. Click to enlarge.
Exploits of a mom

When I read it, I laughed and laughed. I did LOLs and nearly did an ROTF. So I shared it with my fellow colleagues. As expected, no reply. However, one fellow asked me what the joke was.

So I explained it to him, giggling and excitedly. Now I don’t know whether I’m happy that I explained the joke to him, or that I’m sad because I had to explain the joke to him. Seems like I’ve got some work to do about creating awareness on SQL injection and other security issues…