I need to turn a password plus salt into a 256 bit hash. The hash is used as a key to encrypt / decrypt a database on an iPhone, so it need never be generated outside the phone. It also need not be moved to a different iPhone. Currently we use a standard hash function with lots of rounds, to make a brute force attack hard.

I would like to involve the iPhone's secure enclave into the process, in the hope to make it more secure. However, functionality is very limited: I can generate an elliptic curve private / public key pair, I can encrypt / decrypt, and I can generate or verify an ECC signature.

My idea to generate a hash is: Generate an ECC private / public key pair; ignore the public key. Take password and salt, then use the ECC key to calculate a signature of the data repeatedly for 100 ms (the number of iterations would be quite low, because the Secure Enclave is slow). Then use some standard cryptographically secure hash function to turn the result into the hash that I need.

PS. Comment said that a signature wouldn't necessarily be unique. I suppose it could be filled with random data, for example. Since all I want is a random looking, but deterministic bit pattern, it might be better to fill the password + salt with deterministic padding and then encrypt. Still not sure if that would be deterministic.

Do you think this is safe?

The biggest question is whether repeatedly calculating a signature loses entropy. It shouldn't, but then what I'm doing is not a typical use case, and the designer of the signature algorithm might be fine with losing 2 bits of entropy every round. The normal use case would still have 254 bit entropy. Do you think this method will generate 2^256 possible keys or fewer?

Another objection is that an attacker might get hold of the public keys and use them somehow to undo signature calculation. Of course just because public keys are called "public", they are not publically known unless someone makes them public.

(If there are no objections, then this method should be quite secure. A reference to the private key is stored in the keychain; to get it an attacker would have to unlock the phone and install an app with a forged or stolen signature from my company. Then they would have to brute force the key on the iPhone, since the private key cannot be removed from the secure enclave, losing the ability to use powerful hardware).

PS. It had never occurred to me, but generating 10 signatures for the string "abcdef", using the same key in the iPhone Secure Enclave, did in fact produce 10 different signatures :-( So whether my idea was good or not, it doesn't work.

  • $\begingroup$ Are you sure the signature computation is deterministic, that is, do you get the same signature every time? Is the available encryption also symmetric or asymmetric-only (or symmetric-only)? $\endgroup$ – SEJPM Aug 12 '17 at 11:03
  • $\begingroup$ Excellent point. Would be awful if the signature contained a time stamp, for example. I don't actually use the encryption at all (all I want is turn a password into a hash using a method that requires the secure enclave). Apple just says "ECC key". $\endgroup$ – gnasher729 Aug 12 '17 at 12:47
  • 2
    $\begingroup$ @gnasher729 The ECDSA signature algorithm requires a random value as part of the signature generation. While there is a way to replace generate it deterministically (derived from the hash of private key and message), it's unlikely that your secure enclave uses that approach. $\endgroup$ – CodesInChaos Aug 12 '17 at 13:12
  • $\begingroup$ You need to be aware that you can bind the key derivation to the device with the help of the secure enclave, but you would have to return the derived key to the app so it can do the DB encryption. You should not use any primitive for different functions (for example if you do not provide a nonce to ECDSA it allows to recalculate the key). So the primitive you desire is actually decryption of a blob which contains your salt for the PBKDF. So if a new password is generated you generate a random salt but not store it directly in the App but run it through encrypt of the secure enclave. $\endgroup$ – eckes Aug 12 '17 at 17:07

You can simply create a database / enclave specific (symmetric) key and encrypt that using Enclave key pair. You can retrieve that wrapped key back by decrypting.

The password-derived key can simply be calculated like you do now.

So all that is left is to combine the keys back to one single key that depends on both. You could simply XOR the keys together for that. Or you could concatenate them and then use a KBKDF (which, in the simplest form, could just be a hash algorithm) to derive a new data key.

You could also concatenate the salt and the unwrapped key together and use that as salt input. Such a combination is called salt-and-pepper, where pepper is the secret part of the input. That way the derived key depends both on the secret and the password.

The derived data key can then be used to protect the database.

Don't forget to add authentication if you don't want the database to get corrupted by an attacker.

|improve this answer|||||
  • $\begingroup$ Sometimes you need to back to your initial requirements. You don't need to change your password hash algorithm using Enclave. You want to have your database protected by both. $\endgroup$ – Maarten Bodewes Aug 12 '17 at 16:13
  • $\begingroup$ Note that I don't know Enclave myself; I'm assuming this is correct by using the info you've presented in the question. $\endgroup$ – Maarten Bodewes Aug 12 '17 at 20:47

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.