I want to save some user-generated data with some signature of the user that generated it (let's say that the user has to fill some forms with some data and I want him to sign the written data).
The DB backend is "insecure". It is possible to tamper the data (many persons have access to the machine, perhaps it's "in the cloud"), but there is and a strong sequential continuous backup where it is very difficult to tamper with the already written data (something similar to a secured sequential log) (perhaps a digest of the log is shipped continuously to a secure server, or the sequential log is kept in another cloud totally separate from the first one, or if it only has to save some hashes, even a random machine can do it).
What I want to be able to do is make very difficult for third parties that have read/write access to the DB machine and read access to the server machine to add/modify records created by the user. For the deletion I'll do this: the program doesn't do any real update/delete operation. Every update/delete simply add a new version of the data and marks the old as "old". The hash of all the data is continuously saved on the tamper proof backup. This will even protect me from updates to old data. The only thing it won't protect me is against adding new data through spoofing an existing user.
I will use https to secure transmission (with certificates bought from some SSL cert authority).
I don't want to use client-side SSL certificates because they are difficult to use for the user (if the user changes computer he has to reinstall the certificate, if the user forgets he has a certificate in a computer it's possible to steal it...)
The solution I thought was to use ECDsa, generate a public/private keypair from the user password (plus some other data) and then the client signs the user's data client-side. The public/private key generation happens client side. When the user is created and the password is chosen, the client generates the public/private keypair and tells the server the generated public key. The user only needs to remember its password.
Clearly the weak point of this is that someone could add a new public key of the user on the server and sign something with the new public key, but it would be quite easy to spot this, because there would be a new public key. Something more clever would be to change an old public key and then resign everything the user signed with that new key, so it would be impossible to show if the data was tampered, but for this there is the tamper-proof log.
Another weak point would be from the user side: someone could install a keylogger and steal the password, but this is a problem of all the "standard" password schemes (for this I'll add a TOTP authentication, see at the end)
Password recovery would be handled "manually" (a super-user would have to confirm the identity of the user and then sign the change of the password with the super-user's key)
Now let's make it a little more complex: the private key is generated from the PBKDF2 of a salt unique for each user (sent by the server) plus the user's password. Sadly to make the software compatible with cell phones I will need to keep the iterations of PBKDF2 low (mmmh... On my old Optimus W, 1000 iterations require 8 seconds, while with the S3 it's nearly instantaneous... But 1000 iterations isn't very strong) (perhaps I could use Scrypt instead of PBKDF2... It should be more resistant to GPU attacks)
So in the end it would be:
User inserts username and password and press a button. The client asks the server for the salt, for the number of iterations of the hashing function and for the time of the day (this to stop attacks based on reusing the same signature), then calculates the hash of the password by using PBKDF2/Scrypt, regenerates the ECC private key, signs the message (that contains the operation requested and the time of the day received by the server) and sends the signature. The server must remember what challenges he has given and what have been replied (and so are "exhausted").
After this I could add a two step verification (using the algorithm used by Google Authenticator, for example). The key of this would be shared between user and server. The one-time password could be inserted in the various messages signed by the client. The server could save the calculated time of the TOTP so that it would be easy to verify at a later time.
So the question is: is everything ok? Is there a pre-made solution that does everything? Is there an hole in my reasoning?