shared secret alternative to DSA
Brad Fitzpatrick
brad at danga.com
Fri Jun 3 21:08:23 PDT 2005
Paul,
As requested, I'm appointing you security dictator over the OpenID spec.
You've shown that you're reasonably flexible towards practicality
(accepting the phishing problems as out of scope) and you've impressed me
a lot in the past.
So, to kick-start the DSA vs. shared secret debate, let me paste here my
notes on how I'd see a shared secret approach working, based on what
you've described and LiveJournal's LJ::get_secret(). Let me know if I
have anything wrong and/or if the general strategy is right.
DEFINITIONS:
time ::= current time (w3c or unixtime, id-server's choice)
latest-secret-time(t) ::= floor(t / 86400) * 86400 -- if rotating daily
public-random ::= random string, generated once per secret asked
server-secret(t) ::= the server-only secret generated at time t, where t exists in
set of all possible values of latest-secret-time. value
is some random string. if server-secret(t) doesn't already exist,
it's created and stored.
secret_handle ::= <time> "-" <public-random>
(consumer shouldn't parse: should be treated as opaque ASCII string
with bounded length of perhaps 100 characters)
secret_value(handle) ::= HMAC_SHA1_hex( <public-random(handle)> + server-secret(latest-secret-time(<time(handle)>)) )
(also bounded length opaque ASCII string)
FLOW:
** Getting a secret (once per day/week/month, depending on expirys)
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)
idserver -> consumer:
secret_handle = 1117855428-random_string_19283746
secret_expiry = 86400
secret_value = 2e47994eec0b1fa16ac62180005fa5651f5e0e14
** Checking identity
consumer redirect -> UA -> idserver:
openid.mode = checkid_immediate
openid.is_identity = http://bradfitz.com/
openid.return_to = http://return.to.com
openid.secret_handle = 1117855428-random_string_19283746
idserver redirect -> UA -> consumer:
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?
Pros and cons:
PRO: easier for implentors. SHA1 more available than DSA. (the whole
reason I'm even considering this instead of DSA)
|
+-> Counter arguments:
-- DSA isn't /that/ hard. We already have Perl, Java, and PHP
implementations.
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.
CON: secret value goes from idserver to consumer in the clear.
|
+-> Counter arguments:
-- identity server can choose to run on SSL if they care
-- it's very difficult to sniff core internet connections,
as opposed to ease of sniffing user-agent's connections (Wifi, Etc)
-- Diffie-Hellman /could/ be used for secret exchange, maybe.
What pros/cons and counter arguments am I missing?
- Brad
More information about the yadis
mailing list