There is a registration on the site. After registration, all user data is in the Users table. Just put the password in the form of a normal string, which is wrong. How do I encrypt it?

  • What level of protection do you want? What could a hacker potentially steal? - Monk
  • Pass the MD5 password, this is the easiest option - Dmitry Chistik
  • @Dmitry Chistik the author writes that the storage of the password does not suit. What do you mean "pass". - Monk
  • one
    @DmitryChistik and store md5 in the database? So to sense that, then the attacker intercepts and transmits md5, without knowing the password, to the point of zero protection from protection. - Monk
  • one
    md5 - not for ciphers. It would be better to say that a hacker can steal from which you are defending. - Monk

4 answers 4

Hashing vs Encryption.

First you need to understand that hashing is not encryption. Password hashing on the client does not replace the encryption, and does not allow to protect against traffic interception. When you transfer, the password / its hash (if you really want to write a bike on JS) does not replace encryption. You should use HTTPS. All other methods, including self-written asymmetric encryption, are unreliable .

Password Hashing

Hashing protects only against data leakage from the database. The main problem with such a leak is the ability to recover passwords on a hash and use them for a password reuse attack — try to access the same services with the same email / username / password. For example, on Github . Those. You will force users not only to change the password to your service, but also to change the password to all other services (yes, it’s not good to use the same password everywhere, but everyone does that!)

This directly follows the requirements for hashing:

  1. A villain should not be able to quickly recover popular hash passwords. Using the popular MD5 / SHA1 allows you to quickly recover passwords. 5f4dcc3b5aa765d61d8327deb882cf99 decrypt any online service the first time.
  2. The villain should not be able to recover brute force passwords for all users at once. The same password used by different users should give a different hash. This will increase the decryption time in proportion to the number of users.

There is a reliable standard way to solve both problems at once - Key Derivation Function ( Key generation function ).

The essence of the solution:

  1. At initial hashing, generate a random value - salt, and calculate the hash from "salt + password". Salt used is stored as part of the result.
  2. When checking the password, hash the "salt + password to be verified" and compare it with the value obtained in (1).

This approach yields different meanings even if one user uses the same password twice.

In .NET there are ready KDF implementations, for example Rfc2898DeriveBytes . Used like this:

Hashing:

 public static string HashPassword(string password) { byte[] salt; byte[] buffer2; if (password == null) { throw new ArgumentNullException("password"); } using (Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(password, 0x10, 0x3e8)) { salt = bytes.Salt; buffer2 = bytes.GetBytes(0x20); } byte[] dst = new byte[0x31]; Buffer.BlockCopy(salt, 0, dst, 1, 0x10); Buffer.BlockCopy(buffer2, 0, dst, 0x11, 0x20); return Convert.ToBase64String(dst); } 

Check

 public static bool VerifyHashedPassword(string hashedPassword, string password) { byte[] buffer4; if (hashedPassword == null) { return false; } if (password == null) { throw new ArgumentNullException("password"); } byte[] src = Convert.FromBase64String(hashedPassword); if ((src.Length != 0x31) || (src[0] != 0)) { return false; } byte[] dst = new byte[0x10]; Buffer.BlockCopy(src, 1, dst, 0, 0x10); byte[] buffer3 = new byte[0x20]; Buffer.BlockCopy(src, 0x11, buffer3, 0, 0x20); using (Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(password, dst, 0x3e8)) { buffer4 = bytes.GetBytes(0x20); } return ByteArraysEqual(buffer3, buffer4); } 

Code taken from enSO: ASP.NET Identity default Password Hasher, how is it secured?

  • one
    I used it, but it was too lazy to paint, and the names did not know the specific algorithms. The author may be superfluous, but in general - the safest option. - Monk
  • Well, in one of the comments I wrote that one of the most effective SSL options, but not everywhere it is real, you can use the hash to "hide" the password itself. By the way, tell me the link to the hash opening service, it became very interesting. But the public key system, or the formation of a shared key can solve the problem, however, the first is that the second option is broken by an intermediate listener. Our company certificate is replaced by its own, in order to "control" all traffic. - Dmitry Chistik
  • @DmitryChistik no, does not break. At your company, certificate substitution only works because all certificate machines have their certificate authority installed, most likely through domain policies. Those. the substitution only works because the administrator has forced each machine to trust the intermediate listener. This is not man in the middle, but simply a confirmation of the fact that the admin has full control over the machine. On the Internet, this does not work, at least for now. From services - for example, md5online.org . - PashaPash
  • The first hash of @PashaPash, as it was suspected to search already in the created hash bases, does not exist a decrypt as such. The maximum that you get duck is an analogue of the password but not him. - Dmitry Chistik
  • @DmitryChistik Well, yes, there is no decrypt - this is a hash. Database search allows you to recover popular passwords. Selection through rainbow tables allows you to recover the rest of the passwords (letters + numbers). Rainbow tables give a brute force of 10 ^ 13 passwords per second - i.e. Any c00lpa55 is selected instantly. Yes, with some probability, busting will not give out a password, but a collision - but for short ones (<10 characters) you will almost certainly recover the password itself. - PashaPash

On Sharpe, the hash can be calculated somehow like this:

 public static string GetHash(string password) { using (var hash = SHA1.Create()) { return string.Concat(hash.ComputeHash(Encoding.UTF8.GetBytes(password)).Select(x => x.ToString("X2"))); } } 

Instead of SHA1, any algorithm, including MD5, will do.

You have to understand that for an attacker this is not a delay at all, especially if you allow access by the hash itself - then there’s no difference, the password leaked or its hash.

  • one
    Perhaps the most secure method is either a public key cryptosystem or an electronic signature . But in some cases they do not save. Although the signature is probably the most reliable, only expensive ... - Dmitry Chistik
  • @Monk can explain what it means no difference, password leaked or its hash ?. When a hash is entered in a password string, a hash is also calculated from it. And how the password will not work. In general, the hash functions are needed in order to ensure that the attacker does not have access to all accounts when the database is lost. - Trymount
  • Here the author is right, in fact, by posting the request, you send MD5, which prevents the attacker from slipping the already created MD5 instead of the password, which is essentially translated into MD5 JS. The main thing is to get a couple of logins on the server, well, this is already determined by the cryptographic protection necessary for you personally. - Dmitry Chistik
  • @Trymount is only a hacker limited to the input form. But if a hacker has access to the database, then maybe he still has access to what? In fact, when accessing the database, I already rely on the worst-case scenario when there is access to the server too. It means that you can enter the hash directly, and not the password where it is necessary, it will be able to. - Monk
  • @Dimitri Chistik asymmetric encryption really looks best, in terms of cheap and stable implementations. - Monk

Made it using this method:

 public string CalculateMD5Hash(string input) { // step 1, calculate MD5 hash from input MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input); byte[] hash = md5.ComputeHash(inputBytes); // step 2, convert byte array to hex string StringBuilder sb = new StringBuilder(); for (int i = 0; i < hash.Length; i++) { sb.Append(hash[i].ToString("X2")); } return sb.ToString(); } 
  • This is a very bad decision. MD5 for the current time is very weak for password hashing (and by the standards of 2016 too) - tutankhamun

As an option MD5

 var MD5 = function (string) { function RotateLeft(lValue, iShiftBits) { return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits)); } function AddUnsigned(lX,lY) { var lX4,lY4,lX8,lY8,lResult; lX8 = (lX & 0x80000000); lY8 = (lY & 0x80000000); lX4 = (lX & 0x40000000); lY4 = (lY & 0x40000000); lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF); if (lX4 & lY4) { return (lResult ^ 0x80000000 ^ lX8 ^ lY8); } if (lX4 | lY4) { if (lResult & 0x40000000) { return (lResult ^ 0xC0000000 ^ lX8 ^ lY8); } else { return (lResult ^ 0x40000000 ^ lX8 ^ lY8); } } else { return (lResult ^ lX8 ^ lY8); } } function F(x,y,z) { return (x & y) | ((~x) & z); } function G(x,y,z) { return (x & z) | (y & (~z)); } function H(x,y,z) { return (x ^ y ^ z); } function I(x,y,z) { return (y ^ (x | (~z))); } function FF(a,b,c,d,x,s,ac) { a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac)); return AddUnsigned(RotateLeft(a, s), b); }; function GG(a,b,c,d,x,s,ac) { a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac)); return AddUnsigned(RotateLeft(a, s), b); }; function HH(a,b,c,d,x,s,ac) { a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac)); return AddUnsigned(RotateLeft(a, s), b); }; function II(a,b,c,d,x,s,ac) { a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac)); return AddUnsigned(RotateLeft(a, s), b); }; function ConvertToWordArray(string) { var lWordCount; var lMessageLength = string.length; var lNumberOfWords_temp1=lMessageLength + 8; var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64; var lNumberOfWords = (lNumberOfWords_temp2+1)*16; var lWordArray=Array(lNumberOfWords-1); var lBytePosition = 0; var lByteCount = 0; while ( lByteCount < lMessageLength ) { lWordCount = (lByteCount-(lByteCount % 4))/4; lBytePosition = (lByteCount % 4)*8; lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<<lBytePosition)); lByteCount++; } lWordCount = (lByteCount-(lByteCount % 4))/4; lBytePosition = (lByteCount % 4)*8; lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition); lWordArray[lNumberOfWords-2] = lMessageLength<<3; lWordArray[lNumberOfWords-1] = lMessageLength>>>29; return lWordArray; }; function WordToHex(lValue) { var WordToHexValue="",WordToHexValue_temp="",lByte,lCount; for (lCount = 0;lCount<=3;lCount++) { lByte = (lValue>>>(lCount*8)) & 255; WordToHexValue_temp = "0" + lByte.toString(16); WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2); } return WordToHexValue; }; function Utf8Encode(string) { string = string.replace(/\r\n/g,"\n"); var utftext = ""; for (var n = 0; n < string.length; n++) { var c = string.charCodeAt(n); if (c < 128) { utftext += String.fromCharCode(c); } else if((c > 127) && (c < 2048)) { utftext += String.fromCharCode((c >> 6) | 192); utftext += String.fromCharCode((c & 63) | 128); } else { utftext += String.fromCharCode((c >> 12) | 224); utftext += String.fromCharCode(((c >> 6) & 63) | 128); utftext += String.fromCharCode((c & 63) | 128); } } return utftext; }; var x=Array(); var k,AA,BB,CC,DD,a,b,c,d; var S11=7, S12=12, S13=17, S14=22; var S21=5, S22=9 , S23=14, S24=20; var S31=4, S32=11, S33=16, S34=23; var S41=6, S42=10, S43=15, S44=21; string = Utf8Encode(string); x = ConvertToWordArray(string); a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476; for (k=0;k<x.length;k+=16) { AA=a; BB=b; CC=c; DD=d; a=FF(a,b,c,d,x[k+0], S11,0xD76AA478); d=FF(d,a,b,c,x[k+1], S12,0xE8C7B756); c=FF(c,d,a,b,x[k+2], S13,0x242070DB); b=FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE); a=FF(a,b,c,d,x[k+4], S11,0xF57C0FAF); d=FF(d,a,b,c,x[k+5], S12,0x4787C62A); c=FF(c,d,a,b,x[k+6], S13,0xA8304613); b=FF(b,c,d,a,x[k+7], S14,0xFD469501); a=FF(a,b,c,d,x[k+8], S11,0x698098D8); d=FF(d,a,b,c,x[k+9], S12,0x8B44F7AF); c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1); b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE); a=FF(a,b,c,d,x[k+12],S11,0x6B901122); d=FF(d,a,b,c,x[k+13],S12,0xFD987193); c=FF(c,d,a,b,x[k+14],S13,0xA679438E); b=FF(b,c,d,a,x[k+15],S14,0x49B40821); a=GG(a,b,c,d,x[k+1], S21,0xF61E2562); d=GG(d,a,b,c,x[k+6], S22,0xC040B340); c=GG(c,d,a,b,x[k+11],S23,0x265E5A51); b=GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA); a=GG(a,b,c,d,x[k+5], S21,0xD62F105D); d=GG(d,a,b,c,x[k+10],S22,0x2441453); c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681); b=GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8); a=GG(a,b,c,d,x[k+9], S21,0x21E1CDE6); d=GG(d,a,b,c,x[k+14],S22,0xC33707D6); c=GG(c,d,a,b,x[k+3], S23,0xF4D50D87); b=GG(b,c,d,a,x[k+8], S24,0x455A14ED); a=GG(a,b,c,d,x[k+13],S21,0xA9E3E905); d=GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8); c=GG(c,d,a,b,x[k+7], S23,0x676F02D9); b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A); a=HH(a,b,c,d,x[k+5], S31,0xFFFA3942); d=HH(d,a,b,c,x[k+8], S32,0x8771F681); c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122); b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C); a=HH(a,b,c,d,x[k+1], S31,0xA4BEEA44); d=HH(d,a,b,c,x[k+4], S32,0x4BDECFA9); c=HH(c,d,a,b,x[k+7], S33,0xF6BB4B60); b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70); a=HH(a,b,c,d,x[k+13],S31,0x289B7EC6); d=HH(d,a,b,c,x[k+0], S32,0xEAA127FA); c=HH(c,d,a,b,x[k+3], S33,0xD4EF3085); b=HH(b,c,d,a,x[k+6], S34,0x4881D05); a=HH(a,b,c,d,x[k+9], S31,0xD9D4D039); d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5); c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8); b=HH(b,c,d,a,x[k+2], S34,0xC4AC5665); a=II(a,b,c,d,x[k+0], S41,0xF4292244); d=II(d,a,b,c,x[k+7], S42,0x432AFF97); c=II(c,d,a,b,x[k+14],S43,0xAB9423A7); b=II(b,c,d,a,x[k+5], S44,0xFC93A039); a=II(a,b,c,d,x[k+12],S41,0x655B59C3); d=II(d,a,b,c,x[k+3], S42,0x8F0CCC92); c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D); b=II(b,c,d,a,x[k+1], S44,0x85845DD1); a=II(a,b,c,d,x[k+8], S41,0x6FA87E4F); d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0); c=II(c,d,a,b,x[k+6], S43,0xA3014314); b=II(b,c,d,a,x[k+13],S44,0x4E0811A1); a=II(a,b,c,d,x[k+4], S41,0xF7537E82); d=II(d,a,b,c,x[k+11],S42,0xBD3AF235); c=II(c,d,a,b,x[k+2], S43,0x2AD7D2BB); b=II(b,c,d,a,x[k+9], S44,0xEB86D391); a=AddUnsigned(a,AA); b=AddUnsigned(b,BB); c=AddUnsigned(c,CC); d=AddUnsigned(d,DD); } var temp = WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d); return temp.toLowerCase(); } 

Using:

 MD5("whatever"); 

You can use the Diffie-Hellman protocol . But here it is necessary to establish a common key between the client and the server. In principle, there is no specially protected method, except ssh, but it can also be faked by an intermediate proxy.

  • four
    C # has an embedded md5 implementation. - Qwertiy
  • @Qwertiy as far as I understand, it is proposed to encrypt on the client, and send a hash to the server. It is much easier to send the password as is, but via https, and encrypt it already on the server. - PashaPash
  • 2
    @PashaPash, then this is a crazy and useless proposition. - Qwertiy
  • @Qwertiy yes, you see - there is a green jackdaw on it. So this is the right answer :) - PashaPash