Encryption Question

E

eggie5

I have a form where a user can change his password, but I'm confused
on how to prevent this from being transmitted in plain text.

Well, I know how not to transmit it in plain text - use any type of
encryption, but then the problem is, how do I decrypt it on the server
to store it?

If I use some type of key based encryption, the how do I get the key
to the client without it being intercepted, rendering the whole
process useless.

My question is, how can I set up secure password change functionality
on my site?
 
S

shimmyshack

I have a form where a user can change his password, but I'm confused
on how to prevent this from being transmitted in plain text.

Well, I know how not to transmit it in plain text - use any type of
encryption, but then the problem is, how do I decrypt it on the server
to store it?

If I use some type of key based encryption, the how do I get the key
to the client without it being intercepted, rendering the whole
process useless.

My question is, how can I set up secure password change functionality
on my site?

easy answer: SSL
not so easy answer: you will need a javascript implementation of
either
a) (not so good) symmetric enc/decryption algo.
b) (more secure) RSA encryption with decent key bit size, and will
need to encrypt as little as possible, because it is 100x slower than
(a)

Assuming (b)
1. get your public key as a javascript string and send to client,
holding back the private on the server.
2. tell your user "please wait" while you use the freely available
RSA.js to encrypt the password field and copy it to a field called
encrypted-password
3. blank the password field
4. send the form off
5. capture $_POST['encrypted-password'] and decrypt using your private
key on the server side

google for "RSA javascript implmentation"
 
D

David Dorward

I have a form where a user can change his password, but I'm confused
on how to prevent this from being transmitted in plain text.

Run the request over HTTP with SSL (HTTPS) not plain old HTTP.

JavaScript isn't relevant to the issue.
 
S

shimmyshack

I have a form where a user can change his password, but I'm confused
on how to prevent this from being transmitted in plain text.

Well, I know how not to transmit it in plain text - use any type of
encryption, but then the problem is, how do I decrypt it on the server
to store it?

If I use some type of key based encryption, the how do I get the key
to the client without it being intercepted, rendering the whole
process useless.

My question is, how can I set up secure password change functionality
on my site?

of course you do have the problem of how you allow your client to
login securely afterwards!
make sure you never send the password as plain text, use a one time
pad, along with multiple hashing to send an password hash, and
immediately expire the pad/hash on successful login.
Make sure you dont fall into the trap of sending a "password
equivalent" by simply hashing the password once with no one time pad,
using the same hashing algo that the db uses, using a check like

if ( $_POST['hashed_password']==$strHashedPasswordFromDatabase )
{
$auth = 1;
}

which I have seen!! That allows a sniffer to capture the hash on its
way to the server, and just use that each time.
 
E

eggie5

I have a form where a user can change his password, but I'm confused
on how to prevent this from being transmitted in plain text.
Well, I know how not to transmit it in plain text - use any type of
encryption, but then the problem is, how do I decrypt it on the server
to store it?
If I use some type of key based encryption, the how do I get the key
to the client without it being intercepted, rendering the whole
process useless.
My question is, how can I set up secure password change functionality
on my site?

easy answer: SSL
not so easy answer: you will need a javascript implementation of
either
a) (not so good) symmetric enc/decryption algo.
b) (more secure) RSA encryption with decent key bit size, and will
need to encrypt as little as possible, because it is 100x slower than
(a)

Assuming (b)
1. get your public key as a javascript string and send to client,
holding back the private on the server.
2. tell your user "please wait" while you use the freely available
RSA.js to encrypt the password field and copy it to a field called
encrypted-password
3. blank the password field
4. send the form off
5. capture $_POST['encrypted-password'] and decrypt using your private
key on the server side

google for "RSA javascript implmentation"

So the key to getting the new password from the client to the server,
while being able to decrypt it on the server is RSA encryption?
 
S

shimmyshack

easy answer: SSL
not so easy answer: you will need a javascript implementation of
either
a) (not so good) symmetric enc/decryption algo.
b) (more secure) RSA encryption with decent key bit size, and will
need to encrypt as little as possible, because it is 100x slower than
(a)
Assuming (b)
1. get your public key as a javascript string and send to client,
holding back the private on the server.
2. tell your user "please wait" while you use the freely available
RSA.js to encrypt the password field and copy it to a field called
encrypted-password
3. blank the password field
4. send the form off
5. capture $_POST['encrypted-password'] and decrypt using your private
key on the server side
google for "RSA javascript implmentation"

So the key to getting the new password from the client to the server,
while being able to decrypt it on the server is RSA encryption?

yep, this is the same encryption that SSL is based on, you must have a
pair of keys, one of which you hold back and call "private" and one of
which you release to the client as javascript string. You use a js
implentation of RSA to encrypt the password string in browser memory
using the RSA key and then send the encrypted password back to the
server where the other key is waiting. You use php or some such to
load the private server-side key and decrypt the incoming POSTed
encrypted password.
It really does work and is strong if you use a 1024 bit key length -
at least, you should also save you private key password protected, so
that it cannot be easily stolen, and the php script which loads the
key should be the only place where the password is used unprotect the
private key as it is loaded for use in decryption.
 
S

shimmyshack

easy answer: SSL
not so easy answer: you will need a javascript implementation of
either
a) (not so good) symmetric enc/decryption algo.
b) (more secure) RSA encryption with decent key bit size, and will
need to encrypt as little as possible, because it is 100x slower than
(a)
Assuming (b)
1. get your public key as a javascript string and send to client,
holding back the private on the server.
2. tell your user "please wait" while you use the freely available
RSA.js to encrypt the password field and copy it to a field called
encrypted-password
3. blank the password field
4. send the form off
5. capture $_POST['encrypted-password'] and decrypt using your private
key on the server side
google for "RSA javascript implmentation"

So the key to getting the new password from the client to the server,
while being able to decrypt it on the server is RSA encryption?

I suppose it might be worth saying that in order for your SSL or
javascript based method to work in a truly secure fashion, you will
have to take steps to ensure your site is not vulnerable to XSS on any
page, and that it is protected from SQL injection, if these or other
vulnerabilities exist in your app layer, no amount of secure
transportation will help.
(most sites have some form of this I would say, so make sure yours
doesnt!)

For instance, you have a page which takes as one value the URL where
you were passed along in the URL to your "contact me if there was an
error with this page" where it is included in the body somewhere. With
a little modification it is possible to inject a piece of javascript
which calls a payload from another server. This payload rewrites the
page to add two further fields "login" and "password" so you can be
credited with bonus points or whatever for reporting the trouble, the
password is nicked and posting to attacker.com before posting the
correct data on to the right place.

This exact problem exists on an ISPs portal page that shall remain
nameless. I was told that due to "random seeding of our SSL sessions
the attack is not possible".
Lesson XSS gets transported and included into the SSL encrypted HTTP
session, so don;t regard any system as secure until the last remaining
vulnerability has been identified - however you do seem to have
security in mind which is great.

While David is right, SSL is best, in general there is a trade off
between getting creative when there are perfectly good tried and
tested open source security solutions out there already, and being
"satisfied" that just because you use one of them you are secure. In
this case javascript is secure provided you stick to a tight
implementation.
 
B

Bart Van der Donck

David said:
Run the request over HTTP with SSL (HTTPS) not plain old HTTP.
JavaScript isn't relevant to the issue.

A plain javascript solution is possible without need for HTTPS.

http://groups.google.com/group/comp.lang.javascript/msg/096d1191285a15a4

- let user type new password
- encrypt it using javascript (see link above)
- send encrypted string over HTTP and store it
- re-authentication based on same algorithm (handled at server or
client)

The algorithm of the script above corresponds to the default crypt
function on UNIX. This means that the password must be stored as an
encrypted string too - which is certainly recommended, and it seems
that the original poster isn't doing this. A safe password encryption
must always be non-reversible.
 
S

shimmyshack

A plain javascript solution is possible without need for HTTPS.

http://groups.google.com/group/comp.lang.javascript/msg/096d1191285a15a4

- let user type new password
- encrypt it using javascript (see link above)
- send encrypted string over HTTP and store it
- re-authentication based on same algorithm (handled at server or
client)

The algorithm of the script above corresponds to the default crypt
function on UNIX. This means that the password must be stored as an
encrypted string too - which is certainly recommended, and it seems
that the original poster isn't doing this. A safe password encryption
must always be non-reversible.


Bart, you method solves the later stages when the OPs user needs to
authenticate, preventing capture of his newly changed password as the
user does so.
The OP wanted to know how he could /change/ his password. This
requires that the server has no knowledge of the password it is about
to receive and so the encryption must be reversible, which is where
sym. or asym. enc. comes in, however sym. cant be used because this
would require that the key be sent to the user-agent, so it has to be
asym. and there are indeed js implementations of this. No link was
provided though because I felt google would suffice.
 
E

eggie5

A plain javascript solution is possible without need for HTTPS.

http://groups.google.com/group/comp.lang.javascript/msg/096d1191285a15a4

- let user type new password
- encrypt it using javascript (see link above)
- send encrypted string over HTTP and store it
- re-authentication based on same algorithm (handled at server or
client)

The algorithm of the script above corresponds to the default crypt
function on UNIX. This means that the password must be stored as an
encrypted string too - which is certainly recommended, and it seems
that the original poster isn't doing this. A safe password encryption
must always be non-reversible.

Correct, right now, I'm saving the password as plain text on the
server. When the user signs in their password is sha1 hashed by
javascript then sent to the server where the server password is then
sha1 hashed and compared to what the client sent.

So what your proposing is when the user signs up, hash the password as
usual, but save it in that state to the server.

Then when the user signs in, hash their password, send to the server
and then compare? Wouldn't that be sending the same hash to the server
each time, how's the better then just sending plain text? that is
plain text in essence...

Please get back to me
 
S

shimmyshack

Correct, right now, I'm saving the password as plain text on the
server. When the user signs in their password is sha1 hashed by
javascript then sent to the server where the server password is then
sha1 hashed and compared to what the client sent.

So what your proposing is when the user signs up, hash the password as
usual, but save it in that state to the server.

Then when the user signs in, hash their password, send to the server
and then compare? Wouldn't that be sending the same hash to the server
each time, how's the better then just sending plain text? that is
plain text in essence...

Please get back to me

your instinct is spot on, sending the same hash each time would be
what I earlier referred to as a "password equivalent" which is why
that's NOT what Bart is suggesting.
Look at the code he points to, it uses a salt.

Client C requests login page
Server S sends login page, with md5.js and sha1.js - _and_ in hidden
input or wherever, a random salt, server also stores salt in session

C inputs password and presses submit, the javascript md5(p) and
concatenates the salt and then sha1( md5(p) + salt ), blanks the
password field(so the plain text isnt sent) and sends hashed
password_data to server

server knows what salt it sent earlier so S just retrieves the
password from the database which is stored in some hashed form (lets
say as md5), so dbpass = md5(p)


then S knows that if $_POST['password_data'] == sha1(dbpass + salt)
then the user must have typed the good password
Server then immediately deletes the salt from the session, so that a
replay attack cannot occur from a passive sniffer (man-in-the-middle)
reposting the same data.


Notice at no point is the actual password stored, instead it is stored
in the database as md5 hash.
This is so if anyone steals any data they cannot obtain the password,
since md5, like sha1 is irreversible.

Also you dont have to use md5 in database, you could use sha1 in the
database, so now the client just needs to be sent
sha1.js and can do sha1( sha1(p) + salt)
and server checks to see if this is equal to
sha1( $_POST['password_data'] + salt )
This is what I referred to as multiple hashing - using same algo,
which is super fast and in fact you can hash a few times if you wish,
as long as the server and client agree on how many times that was.

What you have to understand is that none of this helps you when
*changing* the password. Because when you change the password the
server has no stored password hash in the database, for this you need
assymetirc (reversible) encryption as dicussed earlier.
 
S

shimmyshack

Correct, right now, I'm saving the password as plain text on the
server. When the user signs in their password is sha1 hashed by
javascript then sent to the server where the server password is then
sha1 hashed and compared to what the client sent.
So what your proposing is when the user signs up, hash the password as
usual, but save it in that state to the server.
Then when the user signs in, hash their password, send to the server
and then compare? Wouldn't that be sending the same hash to the server
each time, how's the better then just sending plain text? that is
plain text in essence...
Please get back to me

your instinct is spot on, sending the same hash each time would be
what I earlier referred to as a "password equivalent" which is why
that's NOT what Bart is suggesting.
Look at the code he points to, it uses a salt.

Client C requests login page
Server S sends login page, with md5.js and sha1.js - _and_ in hidden
input or wherever, a random salt, server also stores salt in session

C inputs password and presses submit, the javascript md5(p) and
concatenates the salt and then sha1( md5(p) + salt ), blanks the
password field(so the plain text isnt sent) and sends hashed
password_data to server

server knows what salt it sent earlier so S just retrieves the
password from the database which is stored in some hashed form (lets
say as md5), so dbpass = md5(p)

then S knows that if $_POST['password_data'] == sha1(dbpass + salt)
then the user must have typed the good password
Server then immediately deletes the salt from the session, so that a
replay attack cannot occur from a passive sniffer (man-in-the-middle)
reposting the same data.

Notice at no point is the actual password stored, instead it is stored
in the database as md5 hash.
This is so if anyone steals any data they cannot obtain the password,
since md5, like sha1 is irreversible.

Also you dont have to use md5 in database, you could use sha1 in the
database, so now the client just needs to be sent
sha1.js and can do sha1( sha1(p) + salt)
and server checks to see if this is equal to
sha1( $_POST['password_data'] + salt )
This is what I referred to as multiple hashing - using same algo,
which is super fast and in fact you can hash a few times if you wish,
as long as the server and client agree on how many times that was.

What you have to understand is that none of this helps you when
*changing* the password. Because when you change the password the
server has no stored password hash in the database, for this you need
assymetirc (reversible) encryption as dicussed earlier.

Just in case you are thinking aha, I can now be secure, nope. If you
do not use SSL, then the man-in-the-middle - who might in fact be a
foxy girl - who is now angry at being thwarted earlier, can simply
sniff the session authentication token that you use to maintain the
logged in status, which gets sent between the server and client on
each request, and simply post *that* to you instead.
This gives her access to the user's account without knowing the
password. You will have a very hard time coding something which
*prevents* this girl piggy-backing on the session.
In fact passive sniffing is theoretically preventable if you send a
one time pad (salt) with every request for private data.
Active sniffing - where girl-in-the-middle receives the server data
and prevents real user from receiving it, and simply intercepts and
captures all traffic from then on, is not preventable without using
asymmetric encryption to encrypt the session cookie IMHO.
 
B

Bart Van der Donck

[...]
Correct, right now, I'm saving the password as plain text on the
server.

You shouldn't do that in a robust authentication model.
When the user signs in their password is sha1 hashed by
javascript then sent to the server where the server password is then
sha1 hashed and compared to what the client sent.

SHA-1 is safe, so the transmission should be protected by this measure
(which is probably why you did it). HTTPS wouldn't add much security
here, though it adds a (perceived!) feeling of safety for the user,
which you might also take into account as a valid argument. Your real
weak point is that the password resides in plaintext on the server.
So what your proposing is when the user signs up, hash the password as
usual, but save it in that state to the server.

Exactly - it adds one level of security. And your server program
doesn't need to be bothered with SHA-1 encryptions all the time, which
might become quite CPU-consuming depending on the circumstances.
Then when the user signs in, hash their password, send to the server
and then compare? Wouldn't that be sending the same hash to the server
each time, how's the better then just sending plain text? that is
plain text in essence...

Normal authentication:

- let user type his password, encrypt it
- do something like: login.asp?EncPW=gH4tGhKLNx
- compare gH4tGhKLNx to stored string to find out if authentication
has succeeded

Changing password:

- let user type the current password and his new requested password,
encrypt both
- do something like: getnewpass.asp?
oldEncPW=gH4tGhKLNx&newEncPW=yHjke4c5Wu
- compare oldEncPW to stored string; if it matches, then delete old
string and store the new one

No server encryption or HTTPS is needed in this scenario; it would not
add any additional security. You could use your favourite (one-way!)
encryption technology from javascript only.

Alternatively, you could send plaintext too. Most authentication
models do this, and it's okay, but only as long as the transmission
takes place over HTTPS. In your case, HTTPS has no real effect because
the password is already SHA-1 encrypted.

Hope this helps,
 
S

shimmyshack

[...]
Correct, right now, I'm saving the password as plain text on the
server.

You shouldn't do that in a robust authentication model.
When the user signs in their password is sha1 hashed by
javascript then sent to the server where the server password is then
sha1 hashed and compared to what the client sent.

SHA-1 is safe, so the transmission should be protected by this measure
(which is probably why you did it). HTTPS wouldn't add much security
here, though it adds a (perceived!) feeling of safety for the user,
which you might also take into account as a valid argument. Your real
weak point is that the password resides in plaintext on the server.
So what your proposing is when the user signs up, hash the password as
usual, but save it in that state to the server.

Exactly - it adds one level of security. And your server program
doesn't need to be bothered with SHA-1 encryptions all the time, which
might become quite CPU-consuming depending on the circumstances.
Then when the user signs in, hash their password, send to the server
and then compare? Wouldn't that be sending the same hash to the server
each time, how's the better then just sending plain text? that is
plain text in essence...

Normal authentication:

- let user type his password, encrypt it
- do something like: login.asp?EncPW=gH4tGhKLNx
- compare gH4tGhKLNx to stored string to find out if authentication
has succeeded

Changing password:

- let user type the current password and his new requested password,
encrypt both
- do something like: getnewpass.asp?
oldEncPW=gH4tGhKLNx&newEncPW=yHjke4c5Wu
- compare oldEncPW to stored string; if it matches, then delete old
string and store the new one


thus the man-in-the-middle would now know the password hash being
stored in the database.

Now he can request to login, and send
sha1( password_hash_he_sniffed + salt)
now despite not knowing the password the attacker gets in from that
point onward.

You cannot securely change a password using irreversible hashes
without asym. enc.
 
B

Bart Van der Donck

Bart said:
[...]
In your case, HTTPS has no real effect because the password
is already SHA-1 encrypted.

Sorry, that was not correct. You need HTTPS anyway in order to crypt
the transmission itself, whether the query string is encrypted or not.
Otherwise one could eavesdrop the URL to get the SHA-1 encrypted
string (not the password), which could be successfully used against
the server.
 
B

Bart Van der Donck

shimmyshack said:
thus the man-in-the-middle would now know the password hash
being stored in the database.

Now he can request to login, and send
sha1( password_hash_he_sniffed + salt)
now despite not knowing the password the attacker gets in
from that point onward.

Yes, HTTPS should be added. See my reply to myself some minutes ago.
For the rest, my model should be secure if one uses a one-way
encryption in javascript, both for the authentication as for the
password change.

Of course, once HTTPS is there, one could send the password in
plaintext as well, and let the server application encrypt it before
storing it (which would be the more traditional authentication
scheme).
 
S

shimmyshack

Yes, HTTPS should be added. See my reply to myself some minutes ago.
For the rest, my model should be secure if one uses a one-way
encryption in javascript, both for the authentication as for the
password change.

Of course, once HTTPS is there, one could send the password in
plaintext as well, and let the server application encrypt it before
storing it (which would be the more traditional authentication
scheme).

I did see your reply, don't worry :)
I am not sure that one way hashing is able to secure a password
change, obviously just because I cannot see your point doesnt mean you
are wrong, but if you can clarify how it is possible to send a hashed
password which the server doesnt already know and store /that/ hash in
a way that cannot be replayed I'd be interested. It would certainly
save some time for me, because I would not surrent use such a scheme
to send a change ;)
matt
 
B

Bart Van der Donck

shimmyshack said:
I am not sure that one way hashing is able to secure a
password change, obviously just because I cannot see
your point doesnt mean you are wrong, but if you can
clarify how it is possible to send a hashed password
which the server doesnt already know and store /that/
hash in a way that cannot be replayed I'd be interested.
It would certainly save some time for me, because I would
not surrent use such a scheme to send a change ;)

One-way encryption from client on beforehand is secure to change the
password on one Conditio, which is that the user must know the
previous (encrypted) password.

E.g. if one posts the following to newpass.php:
oldEncPW=gH4tGhKLNx
newEncPW=yHjke4c5Wu

Then compare the old (stored) string to the sent 'gH4tGhKLNx'. If it
matches, replace it by 'yHjke4c5Wu'. No encryption needed at server
side, and safe if it goes over HTTPS.

(One common alternative that comes to mind is to use a cookie where
the old password is stored, so the user doesn't need to retype it when
he requests to change it.)
 
R

Richard Cornford

Bart Van der Donck wrote:
One-way encryption from client on beforehand is secure
to change the password on one Conditio, which is that
the user must know the previous (encrypted) password.

E.g. if one posts the following to newpass.php:
oldEncPW=gH4tGhKLNx
newEncPW=yHjke4c5Wu

Then compare the old (stored) string to the sent
'gH4tGhKLNx'. If it matches, replace it by 'yHjke4c5Wu'.
No encryption needed at server side, and safe if it goes
over HTTPS.

(One common alternative that comes to mind is to use a
cookie where the old password is stored, so the user doesn't
need to retype it when he requests to change it.)

Isn't the problem with sending the password in plain text over HTTP that
someone may intercept the traffic and so acquire the password for later
use in gaining access that they are not entitled to?

However, if a 'hash' of the password is sent in plain text over HTTP, and
all the server knows is the 'hash' of the password, has the situation
really changed? What is to stop someone who knows the 'hash' of the
password inserting it into the appropriate location in an HTTP request
(by any of numerous means, including the executing of alien javascript on
the logon page)? Wouldn't the server recognise the intercepted 'hash' as
easily as it may have recognised the original password?

The advantage of HTTPS is that someone intercepting the HTTP traffic is
not going to find it easy to make any sense of what they observe.

Richard.
 
S

shimmyshack

Bart Van der Donck wrote:
<snip>







Isn't the problem with sending the password in plain text over HTTP that
someone may intercept the traffic and so acquire the password for later
use in gaining access that they are not entitled to?

However, if a 'hash' of the password is sent in plain text over HTTP, and
all the server knows is the 'hash' of the password, has the situation
really changed? What is to stop someone who knows the 'hash' of the
password inserting it into the appropriate location in an HTTP request
(by any of numerous means, including the executing of alien javascript on
the logon page)? Wouldn't the server recognise the intercepted 'hash' as
easily as it may have recognised the original password?

The advantage of HTTPS is that someone intercepting the HTTP traffic is
not going to find it easy to make any sense of what they observe.

Richard.

yes I fear that this is NOT secure. Take for instance the condition
that the user knows the previous password. The old password is stored
in the mysql database as SHA1 hash. (let us say for argument's sake
the old password was 'fred' and that the new is 'newpassword'
so the database contains the sha1 hash
$db_data = sha1('fred')
now the user typed in fred which with a salt was sha1'd by the client
and sent to the server.
js-> sha1(salt+sha1('fred'))
then sends this as hashed_data
the server must check that the user entered fred, but can only do this
by copying the procedure
server-> sha1($salt . $db_data ) and seeing if it is equal to what was
in the $_POST var
$_POST['hashed_data'].

Now what you are proposing is that the server checks this and when the
user has indeed verified that they know the old password, you then
_replace the old hash with sha1('newpassword')

now anyone listening to the traffic as Richard says now knows the new
hash they have eaves dropped
sha1('newpassword')

so the attacker just requests the logon page, gets given a new salt
and can now send this POST data (using some proxy or other or a header
editor)
$_POST['hashed_data'] = sha1( newsalt+sha1('newpassword') )
the attacker doesnt need to know the password.

The server accepts this and compares it against the database entry by
the smae method as before
server-> sha1($newsalt . $new_db_data )
where $new_db_data is sha1('newpassword')

they match and the attacker gets in


This shows that there is no security in sending the sha1(password)
where this string will then be directly stored in the database. I for
one _never use_ one way hashing to *change* passwords, only to
authenticate an existing one which *can* be secure I agree with you
there!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,818
Latest member
Brigette36

Latest Threads

Top