Skip to main content
added 6 characters in body
Source Link
Maarten Bodewes
  • 94.5k
  • 13
  • 165
  • 319

Neither approach is particularly good because it depends too much on the PBKDF2 function. The PBKDF2 function should always be performed in such a way that the number of iterations (the work factor) is high.

Besides that, PBKDF2 should not be asked for more output than the internal hash function (usually SHA-1, so 160 bits / 20 bytes). Otherwise you give back a part of your advantage back to the attacker (this is an unwanted property of PBKDF2 itself).


You can perform the following on the client:

master = pbkdf2(uip, email, 2000, 256);
hash = hkdf(master, 'hash')
kenc = hkdf(master, 'kenc')
ciphertext = gcm-aes(kenc, message)

then send hash and ciphertext over a TLS encrypted channel to the server (obviously you do not want to leak the hash value to an attacker).

The server should contain a hash over the previously calculated hash value, storedHash = H(hashOrg). It can then do a (secure) compare with the calculated hash value calculatedHash = H(hashGiven) to perform authentication.


Because hash cannot be reversed to the master value (which is pseudo-random, with the strength of the password and the work factor combined), it can also not calculate kenc.

The additional hash on the server just puts a bit of distance between the hash send over the secure channel and the stored value. Otherwise retrieving the database is enough for an attacker to obtain hash and simply send that value to log in.


Note that PBKDF2 is computationally intensive. You can bring that down by choosing really strong passwords. You could also use an asymmetric key pair, pasting in the public or private key value when required.


The biggest issue is that you'd still need to trust the service, especially if you would use encryption in the browser. That is not something that is easily avoided. You can avoid some of this by having your server audited or by creating an open source client application and only put the code into a repository after a thorough review. But at some point the client will still have to trust you, the service provider. There is no known good way around that.

Your client application may implement a great encryption / authentication scheme and send the password together with the authentication code and authenticated ciphertext. Simple as that.

If your users wants encryption that cannot be decrypted by the service, he/she is better off encrypting with their own PGP public key, and pasting the result ASCII armored into some input form.

Neither approach is particularly good because it depends too much on the PBKDF2 function. The PBKDF2 function should always be performed in such a way that the number of iterations (the work factor) is high.

Besides that, PBKDF2 should not be asked for more output than the internal hash function (usually SHA-1, so 160 bits / 20 bytes). Otherwise you give back a part of your advantage back to the attacker (this is an unwanted property of PBKDF2 itself).


You can perform the following on the client:

master = pbkdf2(uip, email, 2000, 256);
hash = hkdf(master, 'hash')
kenc = hkdf(master, 'kenc')
ciphertext = gcm-aes(message)

then send hash and ciphertext over a TLS encrypted channel to the server (obviously you do not want to leak the hash value to an attacker).

The server should contain a hash over the previously calculated hash value, storedHash = H(hashOrg). It can then do a (secure) compare with the calculated hash value calculatedHash = H(hashGiven) to perform authentication.


Because hash cannot be reversed to the master value (which is pseudo-random, with the strength of the password and the work factor combined), it can also not calculate kenc.

The additional hash on the server just puts a bit of distance between the hash send over the secure channel and the stored value. Otherwise retrieving the database is enough for an attacker to obtain hash and simply send that value to log in.


Note that PBKDF2 is computationally intensive. You can bring that down by choosing really strong passwords. You could also use an asymmetric key pair, pasting in the public or private key value when required.


The biggest issue is that you'd still need to trust the service, especially if you would use encryption in the browser. That is not something that is easily avoided. You can avoid some of this by having your server audited or by creating an open source client application and only put the code into a repository after a thorough review. But at some point the client will still have to trust you, the service provider. There is no known good way around that.

Your client application may implement a great encryption / authentication scheme and send the password together with the authentication code and authenticated ciphertext. Simple as that.

If your users wants encryption that cannot be decrypted by the service, he/she is better off encrypting with their own PGP public key, and pasting the result ASCII armored into some input form.

Neither approach is particularly good because it depends too much on the PBKDF2 function. The PBKDF2 function should always be performed in such a way that the number of iterations (the work factor) is high.

Besides that, PBKDF2 should not be asked for more output than the internal hash function (usually SHA-1, so 160 bits / 20 bytes). Otherwise you give back a part of your advantage back to the attacker (this is an unwanted property of PBKDF2 itself).


You can perform the following on the client:

master = pbkdf2(uip, email, 2000, 256);
hash = hkdf(master, 'hash')
kenc = hkdf(master, 'kenc')
ciphertext = gcm-aes(kenc, message)

then send hash and ciphertext over a TLS encrypted channel to the server (obviously you do not want to leak the hash value to an attacker).

The server should contain a hash over the previously calculated hash value, storedHash = H(hashOrg). It can then do a (secure) compare with the calculated hash value calculatedHash = H(hashGiven) to perform authentication.


Because hash cannot be reversed to the master value (which is pseudo-random, with the strength of the password and the work factor combined), it can also not calculate kenc.

The additional hash on the server just puts a bit of distance between the hash send over the secure channel and the stored value. Otherwise retrieving the database is enough for an attacker to obtain hash and simply send that value to log in.


Note that PBKDF2 is computationally intensive. You can bring that down by choosing really strong passwords. You could also use an asymmetric key pair, pasting in the public or private key value when required.


The biggest issue is that you'd still need to trust the service, especially if you would use encryption in the browser. That is not something that is easily avoided. You can avoid some of this by having your server audited or by creating an open source client application and only put the code into a repository after a thorough review. But at some point the client will still have to trust you, the service provider. There is no known good way around that.

Your client application may implement a great encryption / authentication scheme and send the password together with the authentication code and authenticated ciphertext. Simple as that.

If your users wants encryption that cannot be decrypted by the service, he/she is better off encrypting with their own PGP public key, and pasting the result ASCII armored into some input form.

deleted 47 characters in body
Source Link
Maarten Bodewes
  • 94.5k
  • 13
  • 165
  • 319

Neither approach is particularly good because it depends too much on the PBKDF2 function. The PBKDF2 function should always be performed in such a way that the number of iterations (the work factor) is high.

Besides that, PBKDF2 should not be asked for more output than the internal hash function (usually SHA-1, so 160 bits / 20 bytes). Otherwise you give back a part of your advantage back to the attacker (this is an unwanted property of PBKDF2 itself).

Finally there is no need for the encryption to be dependent on the password at all.


You can perform the following on the client:

master = pbkdf2(uip, email, 2000, 256);
hash = hkdf(master, 'hash')
kenc = hkdf(master, 'kenc')
ciphertext = gcm-aes(message)

then send authhash and ctciphertext over a TLS encrypted channel to the server (youobviously you do not want to leak the authhash value to an attacker).

The server should contain a hash over the previously calculated authhash value, storedHash = H(authOrghashOrg). It can then do a (secure) compare with the calculated hash value calculatedHash = H(authhashGiven) to perform authentication.


Because authhash cannot be reversed to the master value (which is pseudo-random, with the strength of the password and the work factor combined), it can also not calculate kenc.

The additional hash on the server just puts a bit of distance between the hash send over the secure channel and the stored value. Otherwise retrieving the database is enough for an attacker to obtain authhash and simply send that value to log in.


Note that PBKDF2 is computationally intensive. You can bring that down by choosing really strong passwords. You could also use an asymmetric key pair, pasting in the public or private key value when required.


The biggest issue is that you'd still need to trust the service, especially if you would use encryption in the browser. That is not something that is easily avoided. You can avoid some of this by having your server audited or by creating an open source client application and only put the code into a repository after a thorough review. But at some point the client will still have to trust you, the service provider. There is no known good way around that.

Your client application may implement a great encryption / authentication scheme and send the password together with the authentication code and authenticated ciphertext. Simple as that.

If your users wants encryption that cannot be decrypted by the service, he/she is better off encrypting with their own PGP public key, and pasting the result ASCII armored into some input form.

Neither approach is particularly good because it depends too much on the PBKDF2 function. The PBKDF2 function should always be performed in such a way that the number of iterations (the work factor) is high.

Besides that, PBKDF2 should not be asked for more output than the internal hash function (usually SHA-1, so 160 bits / 20 bytes). Otherwise you give back a part of your advantage back to the attacker (this is an unwanted property of PBKDF2 itself).

Finally there is no need for the encryption to be dependent on the password at all.


You can perform the following on the client:

master = pbkdf2(uip, email, 2000, 256);
hash = hkdf(master, 'hash')
kenc = hkdf(master, 'kenc')
ciphertext = gcm-aes(message)

then send auth and ct over a TLS encrypted channel to the server (you do not want to leak the auth value).

The server should contain a hash over the previously calculated auth value, storedHash = H(authOrg). It can then do a (secure) compare with the calculated hash value calculatedHash(auth) to perform authentication.


Because auth cannot be reversed to the master value (which is pseudo-random, with the strength of the password and the work factor combined), it can also not calculate kenc.

The additional hash on the server just puts a bit of distance between the hash send over the secure channel and the stored value. Otherwise retrieving the database is enough for an attacker to obtain auth and simply send that value to log in.


Note that PBKDF2 is computationally intensive. You can bring that down by choosing really strong passwords. You could also use an asymmetric key pair, pasting in the public or private key value when required.


The biggest issue is that you'd still need to trust the service, especially if you would use encryption in the browser. That is not something that is easily avoided. You can avoid some of this by having your server audited or by creating an open source client application and only put the code into a repository after a thorough review. But at some point the client will still have to trust you, the service provider. There is no known good way around that.

Your client application may implement a great encryption / authentication scheme and send the password together with the authentication code and authenticated ciphertext. Simple as that.

If your users wants encryption that cannot be decrypted by the service, he/she is better off encrypting with their own PGP public key, and pasting the result ASCII armored into some input form.

Neither approach is particularly good because it depends too much on the PBKDF2 function. The PBKDF2 function should always be performed in such a way that the number of iterations (the work factor) is high.

Besides that, PBKDF2 should not be asked for more output than the internal hash function (usually SHA-1, so 160 bits / 20 bytes). Otherwise you give back a part of your advantage back to the attacker (this is an unwanted property of PBKDF2 itself).


You can perform the following on the client:

master = pbkdf2(uip, email, 2000, 256);
hash = hkdf(master, 'hash')
kenc = hkdf(master, 'kenc')
ciphertext = gcm-aes(message)

then send hash and ciphertext over a TLS encrypted channel to the server (obviously you do not want to leak the hash value to an attacker).

The server should contain a hash over the previously calculated hash value, storedHash = H(hashOrg). It can then do a (secure) compare with the calculated hash value calculatedHash = H(hashGiven) to perform authentication.


Because hash cannot be reversed to the master value (which is pseudo-random, with the strength of the password and the work factor combined), it can also not calculate kenc.

The additional hash on the server just puts a bit of distance between the hash send over the secure channel and the stored value. Otherwise retrieving the database is enough for an attacker to obtain hash and simply send that value to log in.


Note that PBKDF2 is computationally intensive. You can bring that down by choosing really strong passwords. You could also use an asymmetric key pair, pasting in the public or private key value when required.


The biggest issue is that you'd still need to trust the service, especially if you would use encryption in the browser. That is not something that is easily avoided. You can avoid some of this by having your server audited or by creating an open source client application and only put the code into a repository after a thorough review. But at some point the client will still have to trust you, the service provider. There is no known good way around that.

Your client application may implement a great encryption / authentication scheme and send the password together with the authentication code and authenticated ciphertext. Simple as that.

If your users wants encryption that cannot be decrypted by the service, he/she is better off encrypting with their own PGP public key, and pasting the result ASCII armored into some input form.

Source Link
Maarten Bodewes
  • 94.5k
  • 13
  • 165
  • 319

Neither approach is particularly good because it depends too much on the PBKDF2 function. The PBKDF2 function should always be performed in such a way that the number of iterations (the work factor) is high.

Besides that, PBKDF2 should not be asked for more output than the internal hash function (usually SHA-1, so 160 bits / 20 bytes). Otherwise you give back a part of your advantage back to the attacker (this is an unwanted property of PBKDF2 itself).

Finally there is no need for the encryption to be dependent on the password at all.


You can perform the following on the client:

master = pbkdf2(uip, email, 2000, 256);
hash = hkdf(master, 'hash')
kenc = hkdf(master, 'kenc')
ciphertext = gcm-aes(message)

then send auth and ct over a TLS encrypted channel to the server (you do not want to leak the auth value).

The server should contain a hash over the previously calculated auth value, storedHash = H(authOrg). It can then do a (secure) compare with the calculated hash value calculatedHash(auth) to perform authentication.


Because auth cannot be reversed to the master value (which is pseudo-random, with the strength of the password and the work factor combined), it can also not calculate kenc.

The additional hash on the server just puts a bit of distance between the hash send over the secure channel and the stored value. Otherwise retrieving the database is enough for an attacker to obtain auth and simply send that value to log in.


Note that PBKDF2 is computationally intensive. You can bring that down by choosing really strong passwords. You could also use an asymmetric key pair, pasting in the public or private key value when required.


The biggest issue is that you'd still need to trust the service, especially if you would use encryption in the browser. That is not something that is easily avoided. You can avoid some of this by having your server audited or by creating an open source client application and only put the code into a repository after a thorough review. But at some point the client will still have to trust you, the service provider. There is no known good way around that.

Your client application may implement a great encryption / authentication scheme and send the password together with the authentication code and authenticated ciphertext. Simple as that.

If your users wants encryption that cannot be decrypted by the service, he/she is better off encrypting with their own PGP public key, and pasting the result ASCII armored into some input form.