Educause Security Discussion mailing list archives
Re: Storing encryption strings - best practice?
From: Alan Amesbury <amesbury () OITSEC UMN EDU>
Date: Tue, 7 Mar 2006 16:53:32 -0600
Mercer, Susan wrote: [snip - overview of application]
The encryption algorithm requires a string to "seed" it. That string is used to encrypt the data to store it, and also to unencrypt it to display it (SSN only...passwords are 1-way encrypted). Our question is: where should we store this string?
I'm not sure I understand what you mean by "seed." The term, used in the context of "seeding" a random number generator (which is then used for cryptographic operations) usually isn't stored; typically it's made up on-the-fly through the hashing of data from high entropy sources (network and disk interrupts, keystrokes, and other system events). The random number generator is then used to do things like pick session keys, salts for password hashes, etc. If you actually mean "key," then I highly recommend that you don't store it anywhere on the system, if at all possible. However, since you don't list that as a choice:
Our choices are: * In a configuration file (least secure should someone get access to the machine)
I'd say this is probably the best option available. In theory you're not storing the configuration with the data being encrypted.
* In the code itself (more secure...but could be reverse-engineered if someone wanted it)
This is by far the *worst* option. If it's compiled into your code, then it's impossible to change if it ever becomes compromised. This sort of thing has been played out many, many times over; you really DO NOT want to do this.
* In the database (somewhat secure...but could be accessed if someone gets access to the database)
I strongly dislike this because it's generally considered bad crypto discipline to store your key with the data it protects. In penetration tests and forensic analysis I've used this sort of thing to great advantage against my opponents.
We are also thinking about obfuscation...putting it somewhere with a filename/tablename/fieldname that seems quite innocuous and somewhere you would never think to look for this type of information.
Obfuscation can't hurt, but you should consider it the *least* effective method of protecting your data. I'm not sure if you've realized this or not, but simply hashing your SSNs isn't going to slow down their recovery much, should your database get stolen (or otherwise accessed by an attacker). Assuming you're hashing the SSNs, you still need to keep in mind that, without a salt, it's (probably) going to be trivial to brute-force the hash. Consider this brief attack analysis. An attacker will already know this information: * Not all numbers need to be tried (see http://www.socialsecurity.gov/employer/stateweb.htm for list of valid three-digit prefixes) * An SSN consists of nine digits. * The format of an SSN is usually represented as nnnnnnnnn or nnn-nn-nnnn. The worst-case scenario is that an attacker will simply try *all* possibilities, i.e., all possible nine digit numbers in the two commonly used formats shown above, or two billion possibilities (10^9*2). OpenSSL's built-in benchmark ('openssl speed md5') says my workstation can do a bit over 2M MD5s in a bit under three seconds, or two billion in a bit under an hour (benchmark output below). While variants on the MD5 hash exist that make use of salts (e.g., the one used in FreeBSD, Linux, and others for hashing passwords), the narrowly defined search space of the database still makes brute-force attacks against SSNs pretty easy. The same machine, when running John the Ripper (a common, well-known, and *fast* password cracker), is capable of only around 7000 hashes/sec. However, that's still fast enough to brute-force two billion possibilities in under four days. Anyway, that's a couple things to keep in mind when choosing defenses to delay/deter attack..... -- Alan Amesbury University of Minnesota % openssl speed md5 To get the most accurate results, try to run this program when this computer is idle. Doing md5 for 3s on 16 size blocks: 2066350 md5's in 2.96s Doing md5 for 3s on 64 size blocks: 2021046 md5's in 2.99s Doing md5 for 3s on 256 size blocks: 1376448 md5's in 2.97s Doing md5 for 3s on 1024 size blocks: 692847 md5's in 2.98s Doing md5 for 3s on 8192 size blocks: 114744 md5's in 2.99s OpenSSL 0.9.7e-p1 25 Oct 2004 built on: Tue Feb 14 14:16:27 CST 2006 options:bn(64,32) md2(int) rc4(idx,int) des(ptr,risc1,16,long) aes(partial) blowfish(idx) compiler: cc available timing options: USE_TOD HZ=128 [sysconf value] timing function used: getrusage The 'numbers' are in 1000s of bytes per second processed. type 16 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes md5 11165.57k 43275.12k 118555.95k 237761.90k 314750.92k
Current thread:
- Storing encryption strings - best practice? Mercer, Susan (Mar 07)
- <Possible follow-ups>
- Re: Storing encryption strings - best practice? Graham Toal (Mar 07)
- Re: Storing encryption strings - best practice? David Gillett (Mar 07)
- Re: Storing encryption strings - best practice? Joel Rosenblatt (Mar 07)
- Re: Storing encryption strings - best practice? Alan Amesbury (Mar 07)
- Re: Storing encryption strings - best practice? Jeremy Hansen at 065 (Mar 07)