Kaip sukurti „HashCode“ .net (С #) eilutę, kuri yra saugi saugoti duomenų bazėje?

Citata iš vadovo ir „ Eric Lippert“ GetHashCode taisyklės :

Taisyklė: „ GetHashCode“ vartotojai negali pasitikėti tuo, kad laikui bėgant arba naudojant programas yra stabilūs.

Tarkime, kad turite kliento objektą, kuriame yra daugybė laukų, pvz., Vardas, adresas ir kt. Jei dviejuose skirtinguose procesuose gaminate du tokius objektus, kurių duomenys yra tokie patys, jiems nereikia grąžinti to paties maišos kodo. Jei tokį objektą antradienį atliksite viename procese, išjunkite jį ir paleiskite programą dar kartą. Trečiadienį maišos kodai gali būti skirtingi.

Tai šiek tiek žmonių praeityje. Sistemos „System.String.GetHashCode“ dokumentuose ypač nurodoma, kad dvi identiškos eilutės gali turėti skirtingus maišos kodus skirtingose ​​CLR versijose ir iš tikrųjų jos daro. Negalima laikyti maišos į duomenų bazes ir tikėtis, kad jos bus vienodos amžinai, nes jos nebus.

Taigi, koks yra tinkamas būdas sukurti HashCode eilutę, kurią galiu laikyti duomenų bazėje?

(Pasakykite man, kad aš nesu pirmasis asmuo, palikęs šią klaidą programinėje įrangoje, kurią parašiau!)

36
01 марта '11 в 16:14 2011-03-01 16:14 Ian Ringrose yra nustatytas kovo 1 d. 11 val. 16:14 2011-03-01 16:14
@ 4 atsakymai

Tai priklauso nuo to, kokias savybes norite turėti. Pavyzdžiui, galite tiesiog parašyti kažką panašaus į:

 public int HashString(string text) { // TODO: Determine nullity policy. unchecked { int hash = 23; foreach (char c in text) { hash = hash * 31 + c; } return hash; } } 

Tol, kol dokumentuojate, kad tokiu būdu apskaičiuojamas maišos, tai iš tikrųjų yra. Tai jokiu būdu nėra kriptografiškai saugus arba kažkas panašaus, bet jūs galite jį išsaugoti be problemų. Dvi eilutės, kurios yra absoliučiai lygios eilės prasme (t. Y. Be jokios kultūrinės lygybės ir tt) Tiksliai tas pats požymis turės tą patį maišą su šiuo kodu.

Problemos kyla, kai pasikliaujate dokumentais neturinčiu maišymu - tai yra kažkas, kas GetHashCode() , bet jokiu būdu nėra garantuota, kad ji išliks nepakitusi nuo versijos ... pvz., string.GetHashCode() .

Rašymas ir dokumentavimas savo „hash“, kaip šis, yra šiek tiek panašus: „Ši konfidenciali informacija yra sugadinta MD5 (ar kažkas kito).“ Kol jis yra gerai apibrėžtas maišos, tai gerai.

EDIT: Kiti atsakymai siūlomi naudojant kriptografinius maišus, tokius kaip SHA-1 arba MD5. Sakyčiau, kad kol nežinome, kad reikalingas kriptografinis saugumas, o ne tik stabilumas, nėra prasmės pereiti prie eilutės konvertavimo į baitų masyvą ir maišymą. Žinoma, jei maišos yra skirtos naudoti su saugumu, standartinis maišos variantas yra būtent tas, kurį turėtumėte siekti. Tačiau šis klausimas niekur nebuvo paminėtas.

60
01 марта '11 в 16:18 2011-03-01 16:18 atsakymą pateikė Jon Skeet kovo 1 d. 11 d. 16:18 2011-03-01 16:18

Pavyzdžiui, galite sukurti MD5 maišą.

6
01 марта '11 в 16:17 2011-03-01 16:17 atsakymas duotas Daniel Hilgarth kovo 1 d. 11 d. 16:17 2011-03-01 16:17

Čia yra dabartinio .NET metodo, kuris apskaičiuoja 64 bitų sistemų eilutės maišos kodą, pakartotinis įgyvendinimas. Tai nenaudoja nuorodų, pvz., Realaus „ GetHashCode() , todėl jis bus šiek tiek lėčiau, bet bus atsparesnis vidiniams pokyčiams string , jis suteiks tolygiau paskirstytą maišos kodą nei „ Jon Skeet“ , kuris gali padėti geriau ieškoti laiko žodynuose .

 public static class StringExtensionMethods { public static int GetStableHashCode(this string str) { unchecked { int hash1 = 5381; int hash2 = hash1; for(int i = 0; i < str.Length  str[i] != '\0'; i += 2) { hash1 = ((hash1 << 5) + hash1) ^ str[i]; if (i == str.Length - 1 || str[i+1] == '\0') break; hash2 = ((hash2 << 5) + hash2) ^ str[i+1]; } return hash1 + (hash2*1566083941); } } } 
5
25 апр. Scott Chamberlain atsakymas, pateiktas balandžio 25 d 2016-04-25 19:55 '16 at 7:55 pm 2016-04-25 19:55

Atsakymas yra tiesiog parašyti savo maišos funkciją. Kai kurių iš šių nuorodų šaltinį galite rasti komentaruose apie paskelbtą straipsnį. Arba galite naudoti įmontuotą maišos funkciją, kuri iš pradžių buvo skirta kriptografijai (MD5, SHA1 ir tt). Ir tiesiog nenaudokite visų bitų.

1
01 марта '11 в 16:18 2011-03-01 16:18 atsakymą pateikė Gabe kovo 1 d. 11 d. 16:18 2011-03-01 16:18

Kiti klausimai apie „ žymes arba „ Klauskite“