I am trying to implement a security system that has the following requirements:
Let me try to give a graphical representation of this:
Client Server
.--------------^-----------. .----------^----------.
f(client-id 1) g(client-id 1)
PASSWORD ----------------> request 1 ----------------> KEY
|| equal || equal
PASSWORD ----------------> request 2 ----------------> KEY
f(client-id 2) g(client-id 2)
Here, f() [g()] are functions that the client [server] applies to the password [request] to obtain the request [key]. These functions may depend on the client-id.
There's two approaches that I have come up with that might do this, but I am hoping for something simpler that requires less traffic and less server load:
"No-brainer": The clients hash the password. The clients and server each use a standard mechanism (like SSL) to secure their connection and send the hash over this connection.
"A little more clever": The server has a fixed private-key coded into it and each client has the public-key coded into it. The clients hash the password, XOR it with their client-id, encrypt the result with RSA/PGP using the public key. The server then decrypts the request using the private key and XORs the result with the client-id to arrive at the password hash.
In both cases, the server ends up with the same secret for the clients: the password hash. The advantage of the second version is that there is no need for the overhead of a full-fledged key exchange and encryption system, since unfortunately I won't be able to rely on SSL in all cases. In fact, it allows me to generate the server secret in a single request without any handshake. The client-id-XOR in the second version are used to prevent replay-attacks, where a third party with a different client-id could otherwise simply send the same encrypted message to the server to generate the same secret. Basically it's a no-overhead way to add a salt.
Now the question:
Since I don't really have any requirements on the server-side secret, not even that the clients can generate this secret locally, is there an even simpler way to do this that doesn't require expensive modular exponentiation of arbitrary-precision numbers like RSA does? I'm thinking of maybe some sort of other trapdoor function for f() and g() above that allows me to achieve the same result.
No takers, I guess... The question is probably too vague...
In any case: For now I've decided to use RSA (i.e. approach 2 from above). It's simple enough to implement and with the right libraries, it's not too expensive to run either.