5
$\begingroup$

I am using 32 byte EC private keys on the client side of a web application. These keys should be securely stored on a server database. The keys should be encrypted (AES) before being sent to the server in javascript. The ciphertext will be given to the client when they have been authenticated with their login credentials. The client would then decrypt the ciphertext to obtain the private key.

Anyone with access to the database ciphertexts should not be able to derive the private keys.

On the face of it, it seems that ECB is actually fine because the private key data is pseudo-random, but ECB is generally not recommended for any purpose. What mode would be appropriate in this situation? CBC tends to be used often for similar purposes from what I can see.

If I used GCM, will the client always be able to authenticate the ciphertext? So if the client-side encrypted a private key with a particular encryption key and only retained the encryption key, the server cannot forge a combination of IV, authentication tag and ciphertext which would be decryptable using the same key?

I'm not sure if such authentication would be useful as already the client has to trust the downloaded client software, but I suppose it could be a matter of "why not?". In that case would there be downsides to using GCM? More data would need to be stored of-course but not a lot.

PBKDF2 is a reasonable method to derive the AES key for a password, am I right? Are there any weaknesses to PBKDF2 or advantages to any other algorithms?

Lastly I've read about the AES key wrapping algorithm, though I do not know much about it and there does not seem to be many open-source implementations.

$\endgroup$
  • 1
    $\begingroup$ 32 byte (or 256-bit) key is approximately equivalent to approx 43 characters randomly chosen from all alpha numeric characters. Even with a very good password-based key derivation function (PBKDF), you can expect the strength of the password to be weak compared to the keys. $\endgroup$ – user4982 Sep 24 '15 at 18:39
7
$\begingroup$

SIV is a mode specially designed for this purpose. SIV-AES would be a good choice, but it has the same issues as AES-wrap; not many implementations. If you use a GCM you should make sure that the IV is unique (if your plaintext is ever not random you would otherwise be in problems).

As for the password based key derivation function: yes, PBKDF2 is good, with a high enough iteration count. For this kind of data though I would really make sure that the pass phrase has enough entropy. You could consider scrypt with a relatively high memory usage and possibly additional key access restrictions / authentication.

$\endgroup$
  • 1
    $\begingroup$ ... or may consider using Argon2. $\endgroup$ – SEJPM Sep 24 '15 at 18:46
  • $\begingroup$ Sure, I think I will use GCM and with scrypt as you suggested, and I'll use a unique IV each time. I'm assuming I can find a good javascript implementation for scrypt. js-scrypt is not asynchronous so there may be risk of it blocking the webpage, so I'm not sure about that one. $\endgroup$ – Matthew Mitchell Sep 24 '15 at 19:34
  • $\begingroup$ Note that I'm not speaking here in favor of using JavaScript encryption, usually that's very hard to get right. I've just explained a bit on the key wrapping that can be done. $\endgroup$ – Maarten Bodewes Sep 24 '15 at 19:38
  • $\begingroup$ I found js-scrypt-async which I could use (I need to check it properly first). Javascript encryption is the only option for what I am doing considering it is a web app. $\endgroup$ – Matthew Mitchell Sep 24 '15 at 20:14
  • $\begingroup$ @MatthewMitchell At least read into the matter and don't just rely on JS crypto. $\endgroup$ – Maarten Bodewes Sep 24 '15 at 20:17
0
$\begingroup$
  1. If you encrypt the private say with a 8-char password, the strength of your solution will be not 32 bytes (256 bits), but merely 8 bytes (32 bits). The comment of "user4982" above is correct. Doing your encryption process more complicated does NOT make it more secure. The strength depends only on the length of the secret. In your case it will be the password for the private key. If you don't send encrypted PK, nobody has a chance to intercept it and so the strength of your solution will remain 32 bytes (256 bits).

  2. Why do you want to keep PRIVATE keys on the server? Why PUBLIC keys are not sufficient? On the server side you will encrypt text with the client's PUBLIC key and send that to the client. The client will decrypt this text with his PRIVATE key. What will you do on the server side with the client's private key?

  3. And if you agree to use public key, you will not need to encrypt it at all. Because public key should be available to anyone.

$\endgroup$
  • $\begingroup$ Key stretching does not apply? Users will be able to backup their private keys, but for convenience it is stored encrypted on the server so they can obtain it with only their login details (and 2FA if on unfamiliar machine). $\endgroup$ – Matthew Mitchell Sep 24 '15 at 23:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.