samadhiweb

smalltalk programming for the web



A Simple Secret-Splitting Password Store

11 August 2013

Online examples of SQL database APIs tend to go like this:

spec := DBConnectionSpec new
  key: 'mysql'; 
  host: 'localhost'; port: 3306; 
  user: 'testuser'; password: 'testpass';
  yourself.	

And this:

settings := DBXConnectionSettings
  host: 'localhost'
  port: '3306'
  database: 'sodbxtest'
  userName: 'sodbxtest'
  userPassword: 'sodbxtest'.

Perhaps fine for pedagogical material, and I do the same during development. However, I don't want that for production - hardcoding a database (or any) password in application code simply offends my sensibilities.

Secret splitting divides a message into a number of pieces. In the simplest scheme, all the pieces are required to reconstruct the message. To split the message into, say, 5 pieces, generate 4 random strings, each of the same length as the message, then XOR the message and the random strings together. Save the random strings and the final XOR output. To reconstruct the message, XOR the 5 pieces of saved data.

I've written a package called SpsSplitPasswordStore that implements the simple secret splitting scheme described above. The motivation is to avoid both hardcoding the database password in application code and saving the password in clear text in a file.

The following saves a password:

SpsSplitPasswordStore split: 'testpass' into: 5 andWriteTo: 'sps1.dat'

The file 'sps1.dat' doesn't particularly look like it contains a password. (Yes, security through obscurity, I know.)

% strings sps1.dat
FUEL
FLGlobalClassCluster
OrderedCollection
ByteArray
FLPositive8SmallIntegerCluster
FLByteObjectCluster
E\E?
FLSimpleCollectionCluster

% od -X -N 64 sps1.dat 
0000000          4c455546        00001300        00090000        00000000
0000020          14040000        6c474c46        6c61626f        73616c43
0000040          756c4373        72657473        02000000        64724f11
0000060          64657265        6c6c6f43        69746365        42096e6f
0000100

This code reconstructs the password:

SpsSplitPasswordStore readFrom: 'sps1.dat'

Thus the database connection preparation code becomes like this:

spec := DBConnectionSpec new
  key: 'mysql'; 
  host: 'localhost'; port: 3306; 
  user: 'testuser'; 
  password: (SpsSplitPasswordStore readFrom: 'sps1.dat');
  yourself.	

The security claim I make for SpsSplitPasswordStore is that it is more secure than hardcoding your database username/password pair in your application code.

While convenience usually trumps security in the real world, in this case, SpsSplitPasswordStore also makes it more convenient to change the application's database password without requiring changes to the application.

Edit: Available at http://ss3.gemtalksystems.com/ss/SpsSplitPasswordStore.html.