Use of less than secure random numbers for 'a' during an SRP proof of password

With Secure Remote Password protocol SRP6a random numbers are used for s, a and b. Where s is the salt registered with the user, a and b are random one time ephemeral keys of the user and host respectively. What would be the risk of letting some clients (old webbrowsers which don't have the WebCryptoAPI secure random numbers) perform a password proof using a which is less random than a good secure source. Lets say that they use the web browsers insecure Math.random and that is seeded with a timestamp.

Superficially if a was simply a nonce, not even a weak random, then an attacker can gain very little. With each login attempt a unique B is sent by the server which can always use secure random numbers. This random B is used with the nonce a to create a new S, then from that a new M1 and M2 proof of a new shared key.

Or is it the case that a being less than a high quality secure random would compromise the security of either the client or the server.

(Edit: Note that sending a from the server opens you up to a server sending a crafted a, s and B to attack the password using a dictionary lookup of M1 to give the password so that is not something that anyone should consider doing. The question is about whether a needs to be truly random not a question about suggested sources of secure random numbers for a)

Look at where $a$ is used in the protocol:

1. The user calculates the public $A = g^a$ using it.
2. The user computes the session key as $K = H(S)$, with $S = (B - kg^x) ^ {a + ux}$.

An attacker should never find out $S$, because even if the session key $K$ leaks due to e.g. a flawed encryption algorithm, she would only know the hashed value. So knowing or even controlling $a$ will not help the attacker find the password hash $x$ and log in to a server with an arbitrary $B$.

Now suppose the attacker posed as a server. If she could choose or observe identical $a$ values, she could send a $B$ captured from an earlier exchange with a real server. That way she could force the user to repeatedly use the same session key. Depending on what the session key is used for, that could allow her to crack it or the encryption it's used for. So $a$ should always be unique.

So, as far as I can tell, uniqueness is the only requirement for $a$. I would still be hesitant to use something like Math.random, because an attacker could control the seed (e.g. MITM on NTP), which results in duplicates. If you are sure the timestamp is secure, then you could just use a hash of it instead of going through Math.random.

• that explains well why it is better to try to use an a coming from the browser than to try to send randoms from the server. i am actually using isaac.js which is the isaac generator seeded by Math.random but i can edit that and take the time and stretch that out to be the 255 byte seed with something like PBKDF2. i then warm up isaac by advancing it by for some milliseconds driven by each key strokes of the users to get further diffusion. – simbo1905 Jun 12 '14 at 13:32
• @simbo1905: Stretching and KDFs will likely not help you here. They only matter if knowing $a$ helps the attacker, which I don't think is the case. They will not make uniqueness more likely. A hash of whatever entropy you can gather would work just as well as a more complex solution. – otus Jun 12 '14 at 14:02
• thanks for the good advice. modern browsers have WebCryptoAPI secure random which is good entropy. That could be buggy so I will hash that value, plus the user login, plus a timestamp. If the user is being forced to reenter their password by a bad server the user will give up long before there is any repeated a. Any observer will see what looks like random a regardless of the random engine used or faults with it. Two different users with the same faulty browser giving the same false random number logging in at the same time will send different values due to using username in the hash. – simbo1905 Jun 13 '14 at 14:33

It seems like a better solution would be to have the server that is providing the Javascript file, also provide a random seed. The Javascript can then use that random seed (and anything other maybe-random bits it can scrounge up, such as the output from Math.random()) to see a cryptographic PRNG, and then use the output of that crypto-PRNG for generating s, a, b. After all, the server who sends you the Javascript has to be trusted anyway, so you might as well trust it to give you some random numbers, too.

See https://security.stackexchange.com/a/34425/971 for more on this.

• In the case of an attacker only capable of passive attacks (e.g. eavesdropped who can decrypt your SSL session), that still leaves the question whether $a$ being known-but-random is enough for the security of SRP. I think it is, but I'm not 100%. – otus Jun 12 '14 at 9:28
• actually @otus points out that if you are a bad server and you can keep on sending the same a to the server and the same B then you could attack the users password. this implies that sending randoms for the server is a bad idea if the browser has good randoms or even 'not repeating' pseudo randoms. – simbo1905 Jun 12 '14 at 12:56