views:

70

answers:

4

When a user registers at our site we check the address with an address validation service. This service can return an address suggestion if the entered address is found but has some errors. This sugggestion is returned to the user.

The user can accept the suggestion and is trusted. If he changes the address he is not trusted.

Is there a good way to check if the data displayed to the user is the same as the data he posts? I guess I need a hidden field with the hash of the addressdata. But I am not shure which algorithm I should take. The algorithm should be case insensitive if possible.

The algorithm should create a tamper-proof oneway hash.

EDIT:

This worked pretty well so far. I still have to test with umlaute (ä,ü ).

                StringBuilder addressData = new StringBuilder();
            addressData.Append(FirstName);
            addressData.Append(LastName);
            addressData.Append(StreetNumber);
            addressData.Append(StreetName);               
            addressData.Append(City);
            addressData.Append(CountryISO);
            addressData.Append(Zip);
            string stringVal = addressData.ToString().ToLower();

            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            byte[] keyByte = encoding.GetBytes(ApplicationConfiguration.ShaKey);
            byte[] messageBytes = encoding.GetBytes(stringVal);

            HMACSHA256 hmacsha256 = new HMACSHA256(keyByte);
            byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
            string hash = ByteToString(hashmessage);

            return hash
A: 

Is there a good way to check if the data displayed to the user is the same as the data he posts?

Yes - you may store in the database the data that you send to the user.

When the user submits the form, compare the data that's in the database to the data that the user supplied. You may convert the data to a CRC32 hash, but it's important to concatenate different data objects the same way, if you choose to compare hash strings.

Edit: BTW, I think that creating a hash string would be useless, because that the data is stored in the database anyway and not for a long time.

Dor
CRC32 can be tampered with. I need a secure oneway hash.
Malcolm Frexner
@Mathias Fritsch: Consider MD5.
Dor
+1  A: 

Use an HMAC (Hash-based Message Authentication Code) -- HMACs were invented for precisely this purpose; to authenticate data with a symmetric key. I am not familiar with .NET myself, but the standard library seems to provide many such classes inheriting from System.Security.Cryptography.HMAC. HMAC is better than a plain hash because it is not vulnerable to hash length extension attacks.

HMACSHA256 looks like a good candidate.

You should also consider adding a unique value (a nonce) to the string if you want to prevent prevent replay attacks -- otherwise a user can re-send an earlier email with the accompanying earlier HMAC signature.

The HMAC key must be a server-side secret.

intgr
A: 

i like your idea.. you concatenate the address parts make it one big string and do a GetHashCode of ToLower version of the string. and then use the same method to compare.

ps
A: 

If JavaScript is allowed, maybe you can use jQuery change() Event, and check this by setting client side hidden value, to know if something changed:

The change event fires when a control loses the input focus and its value has been modified since gaining focus.

$("input[type='text']").change( function() {
  //do something here, maybe set a hidden value
});

Then on your controller you can check this hidden value, or maybe you can go fancy, and check the value right away with some ajax, but maybe because of your security requirements this may be risky.

Omar
Javascript is not an option, because the user could still tamper the data returned to the server.
Malcolm Frexner
Well that's really a problem... i don't think there is and easy way on this one, maybe if you salt the hashed place, it may comes that you must save one salt per place and hashed(salt + place), like with the passwords salted in SHA-1. But this is redundant because in this case we don't know which is the selected value. We need something else like an ID (user name in the case of login), that let us know exactly which salt to choose, and this must be in the form hidden value two way hashed.Another possible option is somehow save a key in the user session and use it to compare the POSTed value.
Omar
Jeez, why reinvent the wheel with potential security flaws if you can just use an HMAC and be done with it. Leave cryptography to cryptographers.
intgr
@intgr: jeje.. yep, I really don't think this overcomplexity is needed, if you are doing a POST almost anything can be tampered, maybe something basic like checking the header for the POSt referer and use The Antiforgery Token, and stay with the hidden field can work well.
Omar