WebApp Sec mailing list archives

Re: Cryptography and Site Security: Please critique my security idea


From: "Jim McGarvey" <jim.mcgarvey () interblink com>
Date: Thu, 27 Mar 2003 16:14:16 -0800

Hi Robert,

My comments are below in your e-mail.  Hopefully I haven't stated anything
that is glaringly incorrect, but we'll see after others on the list weigh
in.  In general I like your idea, at least from a theoretical standpoint.

-Jim

----- Original Message -----
From: "Robert Paris" <rpjava () hotmail com>
To: <webappsec () securityfocus com>
Sent: Thursday, March 27, 2003 7:05 AM
Subject: Cryptography and Site Security: Please critique my security idea




My company is going to have an application that houses and shares
internal documents through an extranet. There has been a concern by
the network administrators that even with a firewall, someone might
get direct access to the server (housing these documents) whether
through hacking or otherwise. If they did, they'd have access to all
the documents. So I came up with the following solution, which I'd
like some critique on:

1. A symmetric (secret) key ( Key "A" ) is created
2. All files to be managed are encrypted with key "A"

So if I understand correctly, you are going to encrypt every file on the
server with the same symmetric key.  Since you didn't specify, I'll assume
this means you're using a symmetric encryption algorithm, like RC4, with a
standard sized symmetric key, say 128 bits.

You state that you are trying to protect the contents of the files in the
event the server is compromised.  In general I would not advise encrypting
every file with the same symmetric key.  It probably depends on your
encryption algorithm, but most would be quite susceptible to being
compromised if used in this manner.

If an attacker gets into your server and downloads all of the encrypted
files, if he knows or can guess the decrypted contents of any of the files
(say one of the files that happened to be encrypted with your "Key A" was
allyourbase.swf, a large file whose decrypted contents can be easily found
on the Internet), then he is one step closer to being able to decrypt every
other encrypted file he has downloaded.

Take RC4 for example.  The encryption method basically uses your key, "Key
A," to generate a pseudo-random byte stream, which it then XOR's with the
real data to produce encrypted data.  But if "Key A" is the same for every
file, the pseudo-random byte stream is always the same.  So if the attacker
has an unencrypted copy of any of the encrypted files (allyourbase.swf, for
example), he can simply XOR the encrypted and unencrypted versions together,
and he then has the first part of the pseudo-random byte stream (up to the
size of that file, say 800 Kbytes).  Now he can decrypt the first 800 Kbytes
of any encrypted file by XORing the byte stream he now knows with the
encrypted file.  If he is very clever or the encryption algorithm is weak
(or the key is weak), he may even be able to determine what you're using for
"Key A" based on what he now knows.

3. Each user is assigned an asymmetric (public-private key pair)
   key ( Key "B" )
   a. The user is assigned this key pair, but NOT given the key. We
      house the key internally.
4. Key "A" is encrypted separately for each key "B" ( called
   file "1" )
5. User is given file "1"
6. The public key for each user's private key is stored on an internal
   server that is inaccessible from the server and vice versa
7. When the app/web server is started up, the application is in a
   "turned off" state. This is because no public keys have loaded.
   There is one page only that is accessible and it is locked to two
   IPs (both internal). This page allows an authenticated user to
   upload the public keys in to applciation memory. This must happen
   after every restart or the site is unusable.

I think what you're calling a "public key" I usually think of as a "private
key" because that's the one you want to keep a secret.  The key you used to
originally encrypt Key "A" into file "1" doesn't need to be kept secret, so
I would call that one "public."  But of course it works no matter how you
name them.

8. The first time a user ever logs in to the site, they must give
   username, password and upload file "1". This file "1" (after being
   verified through message digest) is then stored in the user's
   cookie. After this, they log in with username and password.

That makes sense.  Two levels of authentication (password and encrypted key)
makes it that much more secure.

9. After user log-in, file "1" is sent to the server, and opened with
   the proper public key (in memory) and stored in session memory
   only. During this session, if this user wishes to download a
   document, this now decrypted key "A" will be used to decrypt the
   file and send the decrypted stream to the user. The file remains
   encrypted on the server. As well, the in-memory key "A" is used for
   encryption when they upload a file.

This should effectively keep Key "A" from being written to the disk on the
server, and only in memory during an open session, which is good.

10. All communication is HTTPS, 128.

As well, I am considering putting a lifespan on the private/public key
pair that is used to encrypt the symmetric key that is stored (encrypted)
in the user's cookie. What I would do (and I don't have this 100% down)
is, if the lifespan is past, create a new key once (for that old key) and
use that new key to encrypt the symmetric key and save that to their
cookie. So even if they gave the original file to someone (along with
username and pass), it'd no longer be useful. I'm not 100% sure how to
make this work correctly or even if it's a good idea.

I think it's a good idea to expire key pairs.  I don't think you could do it
on the fly with cookies, because you have the public key pairs stored on a
separate server which this server can't access, so you would have no way to
exchange the appropriate information.

I would just re-issue encrypted symmetric keys once every year.  Hand them
out to users, and have a two week period where you upload both the old and
new public keys to the server.  Then destroy the old public keys, and the
old encrypted symmetric keys are forever useless.


Please let me know:
1. What are the weaknesses of this architecture?

I think the potential to break your symmetric encryption that I mentioned
above is a weakness.

2. What performance hits will this cause?

It should be minimal, almost identical to the performance hit of SSL, since
like SSL, your asymmetric encryption is only done on keys, and the bulk of
the encryption is symmetric.  So the performance hit is double that of just
doing SSL, because you are doing both SSL encryption of transferred
files and your own decryption of each transferred file.

3. What are some alternative/better ways to achieve this?

I can't think of any, though I feel this may be overkill unless you are
protecting classified government information... and then you aren't allowed
to build your own encryption without getting it approved by NIST.  I would
hate to be the guy who inherits this system from you when your career takes
you on to bigger and better things.  Chances are the first thing the next
guy will do is blow away the entire system and do something else on his
own... that's always how it seems to go.  So my personal suggestion is to
try to keep things simple if possible, and consider carefully whether the
risk is worth the cost (short term, long term, and ongoing management)
of implementing a system like this.

However I do have one idea for dealing with the encryption weakness I
suspect this system has.  Instead of encrypting every file with the same
symmetric key (generating identical pseudo-random byte streams that could be
determined by an intruder), find some way to vary the symmetric key on a per
file basis.  For example, have a table on the server that has a second
symmetric key unique for each file, then the symmetric key you actually use
to decrypt the file (and originally to encrypt it) is the XOR of your Key
"A" and the not-so-secret key in the table.

This ensures that every pseudo-random byte stream used to encrypt each file
is unique.  So if someone knows the contents of one of the encrypted files,
and uses that information to produce the byte stream used to encrypt the
file, that information can't be used to decrypt other files.  Assuming an
strong encryption algorithm is used.  My experience tells me RC4 would
probably be adequate, but if anyone knows otherwise please let me know.

The table of per-file keys could of course be discovered by an intruder, but
that doesn't matter.  The only reason for doing this is to ensure every
pseudo-random byte stream used to encrypt each file is unique.  Having the
Key "A" XOR'd with the key from the table ensures that the symmetric key is
still secret.

Or instead of a table of files and keys, you might be able to do some sort
of hash of the filename to get a fairly unique key for the same purpose.


Some major concerns/limitations:
1. We must use the browser as the thin client and it may be
IE/Netscape or even something else (as long as cookeis and HTTPS 128
are enabled) on windows, linux, unix, mac/osX.

2. Our users will not be willing to do anything more inconvenient than
that one time uploading of the encrypted key. And if possible to do
less, they'd prefer this. Especially since they'd prefer a way to have
it accessible from any computer not just one with the key (although
I'm not sure I think that's the best idea)



Current thread: