shared secret alternative to DSA
Paul Crowley
paul at ciphergoth.org
Sat Jun 4 00:43:32 PDT 2005
Brad Fitzpatrick wrote:
> As requested, I'm appointing you security dictator over the OpenID spec.
Wow, thanks! I promise to be a benevolent dictator; see the ubiquitous
posters showing me gazing into the future with benificent vision.
I'm pushing quite hard for the shared secret based protocol here, but
I'm not wedded to it - I'm actually more concerned about the lifespan
stuff and other concerns raised in parts two and three, all of which is
necessary no matter which way this goes. However everyone seems to be
happy to agree on those changes, so I think this is the only one that
remains to be decided.
> DEFINITIONS:
I want to modify these somewhat. All the modifications make life easier
for server implementors and make no difference to consumers
The only rule in the specification is that (1) you must get a fresh (ie
never-before-issued by this server) secret ID every time you ask for
one, and (2) the map between the set of secret IDs ever issued and the
secrets they map to must be indistinguishable from random. The rest is
just an implementation recommendation.
I'd recommend something more like this:
secret_handle ::= latest-secret-time(<time>) "-" <public-nonce>
secret_value(handle) ::=
HMAC_SHA1_Hex(server-secret(<time(handle)>), <public-nonce(handle)>)
secret_expiry(handle) ::= server-secret-expiry(<time(handle)>)
In other words, the "time" field in the handle is more of a "server
secret reference". OK, so this means you're effectively telling the
world how often you regenerate your server secret, but that's no harm
really.
I've replaced <public-random> with <public-nonce>, because there's no
requirement that this field be random either. It can be an incrementing
counter if you like; this gives away how many IDs you've been asked for
that day, but again there's little harm in that. You can put a prefix
on it indicating which server from your server farm generated it, so
each server has its own pool of IDs and they can't step on each other's
toes.
Finally, HMAC-SHA1 takes two values, a key and a string, so I've
modified it to show that.
> consumer -> idserver:
> openid.mode=generate_secret
> (perhaps also the consumer site's trust_root, so the returned secret handle/value
> are tied to one trust_root in case the value is intercepted)
No need. You can't use this secret to try and spoof other consumers,
because those other consumers don't know this secret.
> idserver -> consumer:
>
> secret_handle = 1117855428-random_string_19283746
> secret_expiry = 86400
> secret_value = 2e47994eec0b1fa16ac62180005fa5651f5e0e14
I'd rather handle the expiry stuff slightly differently, but that's
nothing to do with the shared secret so I'll save it for another post.
> openid.mode = id_res
> openid.assert_identity = http://bradfitz.com/
> secret_handle = 1117855428-random_string_19283746
> hmac_sha1 = HMACSHA1( secret_value(secret_handle) + plain )
> = HMACSHA1( "2e47994eec0b1fa16ac62180005fa5651f5e0e14" +
> "yyyy-mm-ddThh:mm:ssZ assert_identity http://bradfitz.com/ http://return.to.com");
> Is that about right?
Yup, except that again, HMAC-SHA1 is two-valued, so replace + with , there.
Again this is nothing to do with shared secret, but I wonder what the
pros and cons are of making the server explicitly include information
like secret_handle and openid.assert_identity in the reply, over making
the client encode it in the return_to URL however they like?
> -- DSA isn't /that/ hard. We already have Perl, Java, and PHP
> implementations.
Sure. But the dependencies are quite a bind, and you really can't
escape them - rolling your own DSA implementation is really out of the
question, because even if you're prepared to put up with the very poor
performance that a naive bignum-based implementation would give you,
rolling an ASN.1 parser and parsing out the public key is quite painful
enough by itself. I've been looking through the list archives and
there's been quite a bit of discussion of how to meet them - and one
person reacted quite positively to this proposal when I first put it
forward because of them.
> CON: consumers /must/ cache the secret_handle -> secret_value, at least
> for 30 seconds or so. at least with DSA mode, a completely stateless
> design was possible and caching just helped: it wasn't required.
A completely stateless design is still possible, but you need to be
cunning about it. You have to have a consumer secret, then encrypt/MAC
the HMAC-SHA1 secret with the consumer secret, and include that in the
return_to URL.
However, if this turns out to be a big pain, it would be possible for
identity servers to do more to support consumers that really can't store
any state at all; a simple variant on this protocol would allow for
something more like your original idea of a callback from consumer to
server on each identification, which is what the stateless consumers
have to do anyway.
> What pros/cons and counter arguments am I missing?
The big PRO argument that doesn't get a mention here is performance.
People who take a lot of SSL connections spend real money on SSL
accelerators to do the public key math in reasonable time. HMAC-SHA1 is
a thousand times faster. It makes it possible to host the world's most
popular OpenID server on an old Pentium under the stairs. A three
millisecond calculation is a noticeable burden; a two microsecond
HMAC-SHA1 one really isn't.
One other PRO is that we only really need to send the first 64 bits or
so of the HMAC-SHA1 output, so the resulting signature is about a fifth
of the length of a DSA signature. But that's probably not a big
consideration for most applications.
> CON: secret value goes from idserver to consumer in the clear.
This seems to be everyone's main stopping point.
In one post you mentioned that sending secrets in the clear "looks bad".
But to my eyes, sending public keys unauthenticated looks worse.
Either can make it look as if the security of the protocol isn't very
well considered, if we don't justify them explicitly. Both are
justified only by our assumption that actually, doing bad things to core
internet connections is quite difficult. Both are solved if SSL is used.
> -- Diffie-Hellman /could/ be used for secret exchange, maybe.
If I really can't convince people here that it's no worse to send the
MAC secret in the clear, then let's move to an HMAC-SHA1 + DH protocol.
That will address people's concerns, while still preserving the
performance advantages, and avoiding the implementation complexity of
DSA. But to be honest I'm still far from convinced. If you think
there's a real risk your consumer connection to the ID server will be
snooped, you should be just as worried about the risk it'll be tampered
with, and in that case the only thing that will save you is SSL.
--
__
\/ o\ Paul Crowley, paul at ciphergoth.org
/\__/ http://www.ciphergoth.org/
More information about the yadis
mailing list