Generating Unique Keys

Trevor Perrin trevp at trevp.net
Tue Jan 28 21:37:21 CET 2003


> 
> If you have a way of getting a unique integer (say an increasing
> sequence), a very simple way to turn it into an unguessable token is:
> 
>    import sha
> 
>    # make some secret string that's part of your server configuration
>    # do NOT reveal it to attackers ;-)
>    secret_prefix = "some fixed secret string--swordfish orangutan zorkmid"
> 
>    # and then to make a token
>    token = sha.new(secret_prefix + str(unique_integer)).hexdigest()

I think that's a little iffy - SHA1 has a "length extension" property,
where if you know h(m) for some message m that's a multiple of the
block length (64 bytes in this case) you can compute h(m+x) (i.e. m
with x appended).  So if one of your unique integers was a prefix of
another, and your secret_prefix was the right size, you'd be in
trouble.  It would be better to use hmac-sha1 with the secret_prefix
as the key.  And it would be better to generate the secret_prefix as a
good random number on system startup, not bake it into a
configuration.

As for getting a good random number on different platforms, Peter
Gutmann's cryptlib (http://www.cs.auckland.ac.nz/~pgut001/cryptlib/)
does an excellent job of this, it has systems-specific code for
windows, unix, mac, and others, and uses a randomness pool of his own
design (written up in
http://www.cs.auckland.ac.nz/~pgut001/pubs/usenix98.pdf) postprocessed
through an X9.17 generator for FIPS compliance.  I don't know what all
that means, but I think it's good :-).

Anyways, I've got a python wrapper for cryptlib (in alpha state) at
http://trevp.net.  Once I test it on some more systems, and maybe
implement some of the pythonic cipher interfaces, I'll announce it to
the list.

But as an example of using it to get a random key and then just
running AES in OFB mode to get a sequence of random 16-byte blocks:

>>> from cl32 import *   # load the shared library
>>> from array import *
>>> cryptInit()
>>> c = cryptCreateContext(CRYPT_UNUSED, CRYPT_ALGO_AES)
>>> c.CTXINFO_MODE = CRYPT_MODE_OFB
>>> cryptGenerateKey(c)
>>> a = array('b', '\0' * 16)
>>> cryptEncrypt(c, a) # get first value
>>> doSomethingWith(a)
>>> cryptEncrypt(c, a) @ get second value
>>> cryptEncrypt(c, a) @ get third value, etc..

Trevor




More information about the Python-list mailing list