जावास्क्रिप्ट में स्ट्रिंग से एक हैश उत्पन्न करें


585

मुझे स्ट्रिंग्स को हैश के किसी रूप में बदलने की आवश्यकता है। क्या यह जावास्क्रिप्ट में संभव है?

मैं सर्वर-साइड भाषा का उपयोग नहीं कर रहा हूं, इसलिए मैं इसे इस तरह से नहीं कर सकता।


7
MD5 सुरक्षित नहीं है, इसलिए उस एक की तलाश न करें।
हेनरिकस्ट्रोम

166
@henrikstroem आपके पास हैशिंग पर निर्भर करता है; गैर-सुरक्षा उद्देश्यों के लिए हैश बनाने के लिए md5 का उपयोग करने में कुछ भी गलत नहीं है।
ब्रैड कोच

7
@BradKoch आप क्या कर रहे हैं पर निर्भर करता है; सुरक्षा उद्देश्यों के लिए md5 का उपयोग करने के लिए कुछ भी गलत नहीं है। हैशिंग पासवर्ड के लिए निश्चित रूप से बेहतर तरीके हैं, लेकिन URL पर हस्ताक्षर करने जैसी चीजों के लिए md5 ठीक है।
पॉल फेरेट

81
मुझे यह हास्यास्पद लगता है कि एमडी 5 की यहाँ टिप्पणियों में आलोचना की जाती है, लगभग सभी उत्तर बहुत खराब हैश एल्गोरिदम की सलाह देते हैं और बहुत सारे अपवोट प्राप्त करते हैं।
डोम

38
MD5 का उपयोग यह सत्यापित करने के लिए कि एक डाउनलोड बरकरार है जादुई आपके सभी सहकर्मियों को आपके पासवर्ड ईमेल करने के लिए नहीं जा रहा है।
जेम्स एम। ले

जवाबों:


788
Object.defineProperty(String.prototype, 'hashCode', {
  value: function() {
    var hash = 0, i, chr;
    for (i = 0; i < this.length; i++) {
      chr   = this.charCodeAt(i);
      hash  = ((hash << 5) - hash) + chr;
      hash |= 0; // Convert to 32bit integer
    }
    return hash;
  }
});

स्रोत: http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/


22
यह वही है जो जावा में उपयोग किया जाता है। के hash << 5 - hashरूप में ही है, hash * 31 + charलेकिन बहुत तेजी से है। यह अच्छा है क्योंकि यह बहुत तेज़ है, और 31 एक छोटा प्राइम है। वहां जीत मिली।
corsiKa

41
मैंने jsperf ( jsperf.com/hashing-strings ) पर कुछ परीक्षण किए और बिटकॉइन फ़ंक्शन वास्तव में संख्या आधारित फ़ंक्शन की तुलना में अधिक धीमा है।
स्केरिट

17
@PeterAronZentai यह "अनुपयोगी" क्यों है? संख्या-आधारित कोड (hash * 31) + charद्वारा उत्पादित आउटपुट शिफ्ट-आधारित कोड द्वारा उत्पादित आउटपुट के समान है ((hash<<5)-hash)+char, यहां तक ​​कि बहुत लंबे तार के लिए भी (मैंने इसे एक लाख से अधिक वर्णों के साथ परीक्षण किया है), इसलिए यह "अनुपयोगी" शब्दों में नहीं है सटीकता की। संख्या-आधारित और पारी-आधारित दोनों संस्करणों के लिए जटिलता O (n) है, इसलिए यह जटिलता के संदर्भ में "अनुपयोगी" नहीं है।
TachyonVortex

13
क्या कोई आउटपुट की विशिष्टता (या नहीं) पर टिप्पणी कर सकता है? विशेष रूप से, अगर मैं केवल लंबाई के साथ स्ट्रिंग्स के लिए इस हैश का उपयोग करता हूं, तो nसबसे बड़ा क्या है nजिसके लिए मैं संभवतः टकराव नहीं कर सकता हूं?
डॉन मैककरी

34
क्या कोई ऐसा कारण है जिसकी आवश्यकता (या) स्ट्रिंग प्रोटोटाइप पर होनी चाहिए? क्या यह किसी भी कम प्रभावी / कुशल होगा जैसे कि उदाहरण के लिए; var hashCode = function hashCode (str) {etc...}? और फिर उपयोग के रूप में hashCode("mystring")?
रैट्रे

146

संपादित करें

मेरे jsperf परीक्षणों के आधार पर, स्वीकृत उत्तर वास्तव में तेज़ है: http://jsperf.com/hashcodelordvlad

मूल

अगर किसी को दिलचस्पी है, तो यहां एक बेहतर (तेज़) संस्करण है, जो पुराने ब्राउज़र पर विफल हो जाएगा जिनके पास reduceसरणी फ़ंक्शन की कमी है ।

hashCode = function(s){
  return s.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0);              
}

एक-लाइनर तीर फ़ंक्शन संस्करण:

hashCode = s => s.split('').reduce((a,b)=>{a=((a<<5)-a)+b.charCodeAt(0);return a&a},0)

3
क्या हैश विच प्राप्त करने का एक तरीका केवल सकारात्मक संख्या है?
प्रस्तो व्यापारी

45
अजीब। मैंने अभी इसका परीक्षण किया और यह स्वीकार किए गए उत्तर की तुलना में वाया धीमा हो गया। jsperf.com/hashcodelordvlad
lordvlad

112
अच्छा आदमी @lordvlad, वास्तव में अपने स्वयं के उत्तर का परीक्षण कर रहा था, और तब रिपोर्ट कर रहा था जब यह धीमा था।
मिकमेकाना

9
मुझे बस एहसास हुआ: यह सही अर्थ है कि स्वीकृत उत्तर तेज है, क्योंकि मेरे संस्करण को पहले स्ट्रिंग को एक सरणी में बदलना है, नई मेमोरी आवंटित करना और हर चरित्र की नकल करना ...
lordvlad

5
[] .reduce.call (str, (p, c, i, a) => (p << 5) - p + a.charCodeAt (i), 0);
डिजी

107

नोट: सबसे अच्छा 32-बिट हैश के साथ भी टकराव होगा अभी या बाद में पाए जाते हैं।

हैश टकराव की संभावना की गणना इस प्रकार की जा सकती है 1 - ई ^ (-के (के -1) / 2 एन, जैसा कि के ^ 2/2 एन ( यहाँ देखें )। यह अंतर्ज्ञान से अधिक हो सकता है पता चलता है:
एक 32-बिट हैश और k = 10,000 वस्तुओं को मानते हुए, एक टकराव 1.2% की संभावना के साथ होगा। 77,163 नमूनों के लिए संभावना 50% हो जाती है! ( कैलकुलेटर )।
मैं नीचे एक समाधान सुझाता हूं।

इस प्रश्न के उत्तर में कि अद्वितीयता और गति के लिए कौन सा हैशिंग एल्गोरिथ्म सबसे अच्छा है? , इयान बॉयड ने गहराई से विश्लेषण में एक अच्छा पोस्ट किया । संक्षेप में (जैसा कि मैं इसकी व्याख्या करता हूं), वह इस निष्कर्ष पर पहुंचता है कि मुरम सबसे अच्छा है, उसके बाद एफएनवी -1 ए।
जावा के String.hashCode () एल्गोरिथ्म जो एस्मीराल्हा ने प्रस्तावित किया था, वह डीजेबी 2 का एक संस्करण प्रतीत होता है।

  • एफएनवी -1 ए का डीजेबी 2 की तुलना में बेहतर वितरण है, लेकिन यह धीमा है
  • डीजेबी 2 एफएनवी -1 ए की तुलना में तेज है, लेकिन अधिक टकराव पैदा करता है
  • MurmurHash3 डीजेबी 2 और एफएनवी -1 ए से बेहतर और तेज है (लेकिन अनुकूलित कार्यान्वयन के लिए एफएनवी और डीजेबी 2 की तुलना में कोड की अधिक लाइनों की आवश्यकता होती है)

बड़े इनपुट स्ट्रिंग्स के साथ कुछ बेंचमार्क: http://jsperf.com/32-bit-hash
जब शॉर्ट इनपुट स्ट्रिंग्स हैशेड होते हैं, तो डीजे 2 बी और एफएनवी -1 ए के सापेक्ष मुरम का प्रदर्शन गिर जाता है: http ://jsperf-32- बिट-हैश / 3

तो सामान्य तौर पर मैं murmur3 की सिफारिश करूंगा।
जावास्क्रिप्ट कार्यान्वयन के लिए यहां देखें: https://github.com/garycourt/murmurhash-js

यदि इनपुट स्ट्रिंग कम हैं और वितरण गुणवत्ता की तुलना में प्रदर्शन अधिक महत्वपूर्ण है, तो डीजेबी 2 का उपयोग करें (जैसा कि एस्मीराल्हा द्वारा स्वीकृत उत्तर द्वारा प्रस्तावित किया गया है)।

यदि गुणवत्ता और छोटे कोड का आकार गति से अधिक महत्वपूर्ण है, तो मैं FNV-1a के कार्यान्वयन ( इस कोड के आधार पर ) का उपयोग करता हूं ।

/**
 * Calculate a 32 bit FNV-1a hash
 * Found here: https://gist.github.com/vaiorabbit/5657561
 * Ref.: http://isthe.com/chongo/tech/comp/fnv/
 *
 * @param {string} str the input value
 * @param {boolean} [asString=false] set to true to return the hash value as 
 *     8-digit hex string instead of an integer
 * @param {integer} [seed] optionally pass the hash of the previous chunk
 * @returns {integer | string}
 */
function hashFnv32a(str, asString, seed) {
    /*jshint bitwise:false */
    var i, l,
        hval = (seed === undefined) ? 0x811c9dc5 : seed;

    for (i = 0, l = str.length; i < l; i++) {
        hval ^= str.charCodeAt(i);
        hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
    }
    if( asString ){
        // Convert to 8 digit hex string
        return ("0000000" + (hval >>> 0).toString(16)).substr(-8);
    }
    return hval >>> 0;
}

टकराव की संभावना में सुधार

जैसा कि यहाँ बताया गया है , हम इस ट्रिक का उपयोग करके हैश बिट साइज़ को बढ़ा सकते हैं:

function hash64(str) {
    var h1 = hash32(str);  // returns 32 bit (as 8 byte hex string)
    return h1 + hash32(h1 + str);  // 64 bit (as 16 byte hex string)
}

देखभाल के साथ इसका उपयोग करें और हालांकि बहुत ज्यादा उम्मीद न करें।


क्यों करते हो ("0000000" + (hval >>> 0).toString(16)).substr(-8);? क्या ऐसा नहीं है (hval >>> 0).toString(16)?
मैनुअल मीरर

3
यह अग्रणी '0 जोड़ रहा है ताकि परिणामस्वरूप हैश हमेशा 8 वर्ण लंबा हो। आउटपुट में पढ़ने और पहचानने में आसान, लेकिन यह मेरी निजी राय है
mar10

आह ठीक है, मैं समझ गया। छोटे के लिए hval, (hval >>> 0).toString(16)8 अक्षर से कम हो सकता है, इसलिए आप इसे शून्य के साथ पैड करते हैं। मैं सिर्फ भ्रमित था क्योंकि (hval >>> 0).toString(16)हमेशा मेरे लिए एक बिल्कुल 8 वर्ण स्ट्रिंग का परिणाम था।
मैनुअल मेयेर

3
मुझे यह उत्तर बहुत पसंद है क्योंकि यह एक बेहतर वितरित वितरित हैश का उत्पादन करता है: यहाँ प्रस्तावित अन्य कार्य परिणामी हैश मूल्यों को बनाएंगे। जैसे `हैश (" उदाहरण 1 ") - हैश (" उदाहरण 2 ") == 1", जबकि यह एक बहुत अधिक अप्रत्याशित है।
गैविनोप्रोफनी

1
"एफएनवी -1 ए का डीजेबी 2 की तुलना में बेहतर वितरण है, लेकिन धीमी है" के जवाब में - मुझे लगता है कि यह कहा जाना चाहिए कि ईएस 6 Math.imulफ़ंक्शन का उपयोग करते हुए एफएनवी 1 ए बेहद तेज हो सकता है। यह अकेले इसे शीर्ष बेंचमार्क बनाता है, और अंततः लंबे समय में डीजेबी 2 से बेहतर विकल्प है।
19

65

ES6 में स्वीकृत उत्तर के आधार पर । छोटे, रखरखाव योग्य और आधुनिक ब्राउज़रों में काम करता है।

function hashCode(str) {
  return str.split('').reduce((prevHash, currVal) =>
    (((prevHash << 5) - prevHash) + currVal.charCodeAt(0))|0, 0);
}

// Test
console.log("hashCode(\"Hello!\"): ", hashCode('Hello!'));

EDIT (2019-11-04) :

एक-लाइनर तीर फ़ंक्शन संस्करण:

const hashCode = s => s.split('').reduce((a,b) => (((a << 5) - a) + b.charCodeAt(0))|0, 0)

// test
console.log(hashCode('Hello!'))


1
साझा करने के लिए धन्यवाद str += ""हैशिंग से पहले जोड़ा गया था कि str.split is not a functionजब गैर-तार को मापदंडों के रूप में पारित किया गया था, तब से बचने के लिए हैशिंग
बीटलज्यूइस

4
लेकिन इनमें से किसी की तुलना में बहुत अधिक, बहुत धीमा: https://jsperf.com/hashing-strings
AndyO

मैंने यह भी देखा कि सबसे तेज़ "रेट्रो" समाधान वास्तव में छोटा है यदि आप लाइन फीड को हटाते हैं तो यह केवल 3 पंक्तियाँ हैं।
एंडियो

2
किसी भी तरह से यह केवल सकारात्मक लेकिन अभी भी अद्वितीय परिणाम है?
दिनांक

3
@deekshith स्वीकृत उत्तर hash |= 0को 32 बिट इंट में बदलने के लिए उपयोग करता है। यह कार्यान्वयन नहीं करता है। क्या यह एक बग है?
सुकिमा

48

लगभग आधे उत्तर जावा के कार्यान्वयन हैं String.hashCode, जो न तो उच्च गुणवत्ता वाले हैं और न ही सुपर फास्ट हैं। यह बहुत खास नहीं है, यह सिर्फ प्रत्येक चरित्र के लिए 31 से गुणा करता है। इसे केवल एक लाइन में और कुशलता से लागू किया जा सकता है, और इसके साथ बहुत तेज़ है Math.imul:

hashCode=s=>{for(var i=0,h;i<s.length;i++)h=Math.imul(31,h)+s.charCodeAt(i)|0;return h}

उस रास्ते से बाहर, यहाँ कुछ बेहतर है - cyrb53 , एक सरल लेकिन उच्च गुणवत्ता वाला 53-बिट हैश। यह काफी तेज़ है, बहुत अच्छा हैश वितरण प्रदान करता है, और किसी भी 32-बिट हैश की तुलना में टकराव की दर काफी कम है ।

const cyrb53 = function(str, seed = 0) {
    let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
    for (let i = 0, ch; i < str.length; i++) {
        ch = str.charCodeAt(i);
        h1 = Math.imul(h1 ^ ch, 2654435761);
        h2 = Math.imul(h2 ^ ch, 1597334677);
    }
    h1 = Math.imul(h1 ^ h1>>>16, 2246822507) ^ Math.imul(h2 ^ h2>>>13, 3266489909);
    h2 = Math.imul(h2 ^ h2>>>16, 2246822507) ^ Math.imul(h1 ^ h1>>>13, 3266489909);
    return 4294967296 * (2097151 & h2) + (h1>>>0);
};

प्रसिद्ध मुरमुरश / xxHash एल्गोरिदम के समान, यह गुणा और Xorshift के संयोजन का उपयोग करता है हैश उत्पन्न करने के लिए , लेकिन पूरी तरह से नहीं। परिणामस्वरूप यह जावास्क्रिप्ट में या तो तेजी से लागू होता है और इसे लागू करने के लिए काफी सरल है।

यह हिमस्खलन (गैर-सख्त) को प्राप्त करता है, जिसका अर्थ है कि इनपुट में छोटे परिवर्तन से आउटपुट में बड़े परिवर्तन होते हैं, जिसके परिणामस्वरूप हैश यादृच्छिक दिखाई देता है:

0xc2ba782c97901 = cyrb53("a")
0xeda5bc254d2bf = cyrb53("b")
0xe64cc3b748385 = cyrb53("revenge")
0xd85148d13f93a = cyrb53("revenue")

आप एक ही इनपुट के वैकल्पिक धाराओं के लिए एक बीज भी दे सकते हैं:

0xee5e6598ccd5c = cyrb53("revenue", 1)
0x72e2831253862 = cyrb53("revenue", 2)
0x0de31708e6ab7 = cyrb53("revenue", 3)

तकनीकी रूप से यह 64-बिट हैश (समानांतर में दो असंबंधित 32-बिट हैश) है, लेकिन जावास्क्रिप्ट 53-बिट पूर्णांक तक सीमित है। यदि आवश्यक हो, पूर्ण 64-बिट आउटपुट अभी भी उपयोग किया जा सकता है हेक्स स्ट्रिंग या सरणी के लिए रिटर्न लाइन को बदलकर किया ।

ध्यान रखें कि हेक्स स्ट्रिंग्स का निर्माण प्रदर्शन-महत्वपूर्ण परिस्थितियों में बैच प्रसंस्करण को काफी धीमा कर सकता है।

return (h2>>>0).toString(16).padStart(8,0)+(h1>>>0).toString(16).padStart(8,0);
// or
return [h2>>>0, h1>>>0];

और सिर्फ मज़े के लिए, यहाँ पर FNV या DJB2 की तुलना में उच्च गुणवत्ता के साथ 89 वर्णों में न्यूनतम 32-बिट हैश है :

TSH=s=>{for(var i=0,h=9;i<s.length;)h=Math.imul(h^s.charCodeAt(i++),9**9);return h^h>>>9}

4
वाह, यह सामान्य से बहुत बेहतर है * 31 एक छोटी (या समान) आदानों के लिए। :)
लैपो

2
कहां से chआरंभ किया गया है?
Hellowill89

3
@ hellowill89 woops, मैं इसे घोषित करना भूल गया और वैश्विक दायरे में खून बह रहा था। अभी ठीक किया गया है, धन्यवाद: ')
bryc

IE 11 के लिए विफल: ऑब्जेक्ट संपत्ति या विधि का समर्थन नहीं करता है 'imul'
21

2
@BachT आप एक का उपयोग कर सकते polyfill या एक पूर्ण ES6 शिम । लेकिन IE11 2009 में बिना किसी अपडेट के ट्रेजिकली फ्रोजन है।
bryc

28

यदि यह किसी की मदद करता है, तो मैंने शीर्ष दो उत्तरों को पुराने-ब्राउज़र-सहिष्णु संस्करण में संयोजित किया, जो reduceकि उपलब्ध होने पर तेज़ संस्करण का उपयोग करता है और यदि यह नहीं है तो एस्मीराल्हा के समाधान पर वापस आ जाता है।

/**
 * @see http://stackoverflow.com/q/7616461/940217
 * @return {number}
 */
String.prototype.hashCode = function(){
    if (Array.prototype.reduce){
        return this.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0);              
    } 
    var hash = 0;
    if (this.length === 0) return hash;
    for (var i = 0; i < this.length; i++) {
        var character  = this.charCodeAt(i);
        hash  = ((hash<<5)-hash)+character;
        hash = hash & hash; // Convert to 32bit integer
    }
    return hash;
}

उपयोग की तरह है:

var hash = "some string to be hashed".hashCode();

हर ब्राउज़र में तेज़ी से चलने के लिए इस कोड को कैसे ऑप्टिमाइज़ करें। String.prototype.hashCode = function(){ var hash = 5381; if (this.length === 0) return hash; for (var i = 0; i < this.length; i++) { var character = this.charCodeAt(i); hash = ((hash<<5)+hash)^character; // Convert to 32bit integer } return hash; }
मुसाखिर सैय्यद

26

यह एक परिष्कृत और बेहतर प्रदर्शन वाला संस्करण है:

String.prototype.hashCode = function() {
    var hash = 0, i = 0, len = this.length;
    while ( i < len ) {
        hash  = ((hash << 5) - hash + this.charCodeAt(i++)) << 0;
    }
    return hash;
};

यह जावा के मानक के कार्यान्वयन से मेल खाता है object.hashCode()

यहाँ भी एक है जो केवल सकारात्मक हैशकोड लौटाता है:

String.prototype.hashcode = function() {
    return (this.hashCode() + 2147483647) + 1;
};

और यहाँ जावा के लिए एक मेल है जो केवल सकारात्मक हैशकोड लौटाता है:

public static long hashcode(Object obj) {
    return ((long) obj.hashCode()) + Integer.MAX_VALUE + 1l;
}

का आनंद लें!


2
महान जवाब, लेकिन << 0 का उद्देश्य क्या है?
कूलंग

8
@koolaang यह लेफ्ट शिट ऑपरेटर है, developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
mmm

29
@ मोमोमो क्या आपका मतलब बायीं पारी है ?
wdh

2
@ मोमोमो मुझे लगता है कि वह पूछ रहा था कि यह शून्य बिट्स की बाईं पारी क्यों थी।
jpfx1342

3
@ मयकोन (2 ^ 32 - 1)
निज्राज गेलानी

24

मुझे थोड़ी हैरानी हुई कि किसी ने भी अभी तक SubtleCrypto API के बारे में बात नहीं की है।

एक स्ट्रिंग से हैश प्राप्त करने के लिए, आप subtle.digestविधि का उपयोग कर सकते हैं :

function getHash(str, algo = "SHA-256") {
  let strBuf = new TextEncoder('utf-8').encode(str);
  return crypto.subtle.digest(algo, strBuf)
    .then(hash => {
      window.hash = hash;
      // here hash is an arrayBuffer, 
      // so we'll connvert it to its hex version
      let result = '';
      const view = new DataView(hash);
      for (let i = 0; i < hash.byteLength; i += 4) {
        result += ('00000000' + view.getUint32(i).toString(16)).slice(-8);
      }
      return result;
    });
}

getHash('hello world')
  .then(hash => {
    console.log(hash);
  });


4
मैं सहमत हूँ। हेक्स में रूपांतरण थोड़ा अलग किया जा सकता था ...var promise = crypto.subtle.digest({name: "SHA-256"}, Uint8Array.from(data)); promise.then(function(result){ console.log(Array.prototype.map.call(new Uint8Array(result), x => x.toString(16).padStart(2, '0')).join('')); });
डेनिस गिफेलर

3
स्ट्रिंग्स के लिए एक क्रिप्टोग्राफिक हैश फ़ंक्शन थोड़ा ओवरकिल है .. cryptoबिल्कुल प्रदर्शन नहीं है।
bryc

विश्वसनीय गुणवत्ता यादृच्छिक बिना परीक्षण चलने वाले लोगों पर भरोसा करने के लिए, अंतर्निहित (कोई कस्टम कार्यान्वयन की आवश्यकता नहीं), बीजनीय, और मुझे केवल एक गेम मैप बनाने के लिए कुछ सौ नंबरों की आवश्यकता थी, यह एकदम सही लग रहा था। लेकिन यह पता चला है कि इसे तुल्यकालिक रूप से करने का कोई तरीका नहीं है। हर बार जब आप अपने बोए गए यादृच्छिक इंजन को कॉल करते हैं तो कुछ एसिंक्स कॉलबैक चीज प्रदान करना, कोड को सुपर अपठनीय बनाता है और हास्यास्पद लगता है। मुझे ऐसा नहीं लगता जो इस भद्दे crypto.subtle इंटरफ़ेस के साथ आया है, इसलिए मुझे अंत में मुझे इस उत्तर से xmur3 + sfc32 के साथ जाना पड़ा: stackoverflow.com/a/47593316/1201863
Luc

7

उदाहरण के लिए mar10 द्वारा धन्यवाद, मुझे FNV-1a के लिए C # और जावास्क्रिप्ट में समान परिणाम प्राप्त करने का एक तरीका मिला। यदि यूनिकोड चार्ट मौजूद हैं, तो ऊपरी भाग प्रदर्शन के लिए छोड़ दिया गया है। न जाने क्यों हैशिंग के समय इसे बनाए रखना उपयोगी होगा, क्योंकि अभी के लिए केवल हैशिंग यूआरएल मार्ग हैं।

सी # संस्करण

private static readonly UInt32 FNV_OFFSET_32 = 0x811c9dc5;   // 2166136261
private static readonly UInt32 FNV_PRIME_32 = 0x1000193;     // 16777619

// Unsigned 32bit integer FNV-1a
public static UInt32 HashFnv32u(this string s)
{
    // byte[] arr = Encoding.UTF8.GetBytes(s);      // 8 bit expanded unicode array
    char[] arr = s.ToCharArray();                   // 16 bit unicode is native .net 

    UInt32 hash = FNV_OFFSET_32;
    for (var i = 0; i < s.Length; i++)
    {
        // Strips unicode bits, only the lower 8 bits of the values are used
        hash = hash ^ unchecked((byte)(arr[i] & 0xFF));
        hash = hash * FNV_PRIME_32;
    }
    return hash;
}

// Signed hash for storing in SQL Server
public static Int32 HashFnv32s(this string s)
{
    return unchecked((int)s.HashFnv32u());
}

जावास्क्रिप्ट संस्करण

var utils = utils || {};

utils.FNV_OFFSET_32 = 0x811c9dc5;

utils.hashFnv32a = function (input) {
    var hval = utils.FNV_OFFSET_32;

    // Strips unicode bits, only the lower 8 bits of the values are used
    for (var i = 0; i < input.length; i++) {
        hval = hval ^ (input.charCodeAt(i) & 0xFF);
        hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
    }

    return hval >>> 0;
}

utils.toHex = function (val) {
    return ("0000000" + (val >>> 0).toString(16)).substr(-8);
}

@mathiasrw यूनिकोड वर्णों के लिए 8 बिट्स से अधिक की मेमोरी संभव है, इसलिए मुझे लगता है कि 0xFF बस उस रेंज के बाहर किसी भी चीज से मास्क करता है। CharCodeAt () के बारे में अधिक यहां देखें: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
djabraham

यदि ES6 उपलब्ध है (सभी आधुनिक इंजन इसका समर्थन करते हैं), Math.imulका उपयोग गुणन चरण के लिए किया जा सकता है, जो प्रदर्शन में सुधार करता है । केवल मुद्दा यह है कि यह IE11 में बिना शिम के काम नहीं करेगा ।
19 को bryc

6

एक तेज़ और संक्षिप्त जिसे यहाँ से अनुकूलित किया गया था :

String.prototype.hashCode = function() {
  var hash = 5381, i = this.length
  while(i)
    hash = (hash * 33) ^ this.charCodeAt(--i)
  return hash >>> 0;
}

5

मुझे उपयोगकर्ता नाम और वर्तमान समय के आधार पर एक विशिष्ट-ईश आईडी बनाने के लिए एक समान फ़ंक्शन (लेकिन अलग) की आवश्यकता थी। इसलिए:

window.newId = ->
  # create a number based on the username
  unless window.userNumber?
    window.userNumber = 0
  for c,i in window.MyNamespace.userName
    char = window.MyNamespace.userName.charCodeAt(i)
    window.MyNamespace.userNumber+=char
  ((window.MyNamespace.userNumber + Math.floor(Math.random() * 1e15) + new Date().getMilliseconds()).toString(36)).toUpperCase()

पैदा करता है:

2DVFXJGEKL
6IZPAKFQFL
ORGOENVMG
... etc 

संपादित करें जून 2015: नए कोड के लिए मैं संक्षिप्त का उपयोग करता हूं: https://www.npmjs.com/package/shortid


2
@ t0r0X अच्छी तरह से अब मैं शॉर्टिड नामक एक मॉड्यूल का उपयोग करता हूं: npmjs.com/package/shortid
jcollum

1
आप उपयोगकर्ता नाम का उपयोग कैसे कर रहे हैं? यह सिर्फ आईडी उत्पन्न करने के लिए लगता है, लेकिन मैं यह नहीं देखता कि आप स्ट्रिंग से हैश उत्पन्न करने के लिए कैसे उपयोग कर रहे हैं
cyberwombat

1
इस उत्तर में 3 डाउनवोट हैं। मेरे जीवन के लिए मैं सोच भी नहीं सकता। किसी ने भी कुछ नहीं कहा ...: - /
jcollum

1
@jcollum यही कारण है कि मैं लगभग कभी भी बासी सवालों का जवाब नहीं देता .. मारा और रन किसी का ध्यान नहीं जाता। उत्तर को ठीक करने के बाद भी, कोई भी इसे संतुलित करने के लिए नहीं आता है।
bryc

5

मेरा त्वरित (बहुत लंबा) एफएनवी की Multiply+Xorविधि पर आधारित एक लाइनर :

my_string.split('').map(v=>v.charCodeAt(0)).reduce((a,v)=>a+((a<<7)+(a<<3))^v).toString(16);

5

SubtleCrypto.digest

मैं सर्वर-साइड भाषा का उपयोग नहीं कर रहा हूं, इसलिए मैं इसे इस तरह से नहीं कर सकता।

क्या आप वाकई इस तरह से नहीं कर सकते हैं? ?

क्या आप भूल गए कि आप जावास्क्रिप्ट का उपयोग कर रहे हैं, कभी विकसित होने वाली भाषा?

कोशिश करो SubtleCrypto। यह SHA-1, SHA-128, SHA-256 और SHA-512 हैश फ़ंक्शन का समर्थन करता है।


async function hash(message/*: string */) {
	const text_encoder = new TextEncoder;
	const data = text_encoder.encode(message);
	const message_digest = await window.crypto.subtle.digest("SHA-512", data);
	return message_digest;
} // -> ArrayBuffer

function in_hex(data/*: ArrayBuffer */) {
	const octets = new Uint8Array(data);
	const hex = [].map.call(octets, octet => octet.toString(16).padStart(2, "0")).join("");
	return hex;
} // -> string

(async function demo() {
	console.log(in_hex(await hash("Thanks for the magic.")));
})();


आपके द्वारा दो साल पहले काइदो के जवाब से यह कैसे अलग है ?
ल्यूक

@ यह स्पष्ट नहीं है।
Константин Ван

3

मैं पार्टी में देर से आता हूं, लेकिन आप इस मॉड्यूल का उपयोग कर सकते हैं: क्रिप्टो :

const crypto = require('crypto');

const SALT = '$ome$alt';

function generateHash(pass) {
  return crypto.createHmac('sha256', SALT)
    .update(pass)
    .digest('hex');
}

इस फ़ंक्शन का परिणाम हमेशा 64वर्ण स्ट्रिंग होता है; कुछ इस तरह:"aa54e7563b1964037849528e7ba068eb7767b1fab74a8d80fe300828b996714a"


2

मैंने दो सॉल्यूशंस (यूजर्स एस्मीराल्हा और लॉर्डव्लाड) को एक फंक्शन में मिला दिया है, जो उन ब्राउजर्स के लिए तेज होना चाहिए जो js फंक्शन कम () का समर्थन करते हैं और अभी भी पुराने ब्राउजर्स के साथ संगत हैं:

String.prototype.hashCode = function() {

    if (Array.prototype.reduce) {
        return this.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0);   
    } else {

        var hash = 0, i, chr, len;
        if (this.length == 0) return hash;
        for (i = 0, len = this.length; i < len; i++) {
        chr   = this.charCodeAt(i);
        hash  = ((hash << 5) - hash) + chr;
        hash |= 0; // Convert to 32bit integer
        }
        return hash;
    }
};

उदाहरण:

my_string = 'xyz';
my_string.hashCode();

2

यदि आप टकराव से बचना चाहते हैं तो आप SHA-256 की तरह सुरक्षित हैश का उपयोग करना चाहते हैं । कई जावास्क्रिप्ट SHA-256 कार्यान्वयन हैं।

मैंने कई हैश कार्यान्वयनों की तुलना करने के लिए परीक्षण लिखे, https://github.com/brillout/test-javascript-hash-implementations देखें

या परीक्षणों को चलाने के लिए http://brillout.github.io/test-javascript-hash-implementations/ पर जाएं ।


1
सुरक्षित क्रिप्टोग्राफिक हैश का उपयोग करना बेहद धीमा हो सकता है। टकराव से बचना बिट चौड़ाई का एक उत्पाद है, सुरक्षा नहीं। 128 बिट गैर-क्रिप्टोग्राफिक हैश या यहां तक ​​कि 64 बिट्स अधिकांश प्रयोजनों के लिए पर्याप्त से अधिक होना चाहिए। मुरमुरश 3_x86_128 काफी तेज़ है और इसमें टकराव की संभावना बहुत कम है।
bryc

2

यह कुछ अन्य उत्तरों की तुलना में थोड़ा अधिक सुरक्षित हैश होना चाहिए, लेकिन एक फ़ंक्शन में, किसी भी प्रीलोडेड स्रोत के बिना

मैंने मूल रूप से sha1 का एक छोटा सरलीकृत संस्करण बनाया
आप स्ट्रिंग के बाइट्स लेते हैं और उन्हें 4 से 32 बिट "शब्दों" द्वारा समूहित करते हैं
फिर हम हर 8 शब्दों को 40 शब्दों (परिणाम पर बड़े प्रभाव के लिए) तक बढ़ाते हैं।
यह हैशिंग फ़ंक्शन (अंतिम कम) पर जाता है जहां हम वर्तमान स्थिति और इनपुट के साथ कुछ गणित करते हैं। हमें हमेशा 4 शब्द मिलते हैं।
यह लगभग एक-कमांड / वन-लाइन संस्करण है जो नक्शे का उपयोग करता है, कम करता है ... लूप के बजाय, लेकिन यह अभी भी बहुत तेज है

String.prototype.hash = function(){
    var rot = (word, shift) => word << shift | word >>> (32 - shift);
    return unescape(encodeURIComponent(this.valueOf())).split("").map(char =>
            char.charCodeAt(0)
        ).reduce((done, byte, idx, arr) =>
            idx % 4 == 0 ? [...done, arr.slice(idx, idx + 4)] : done
        , []).reduce((done, group) =>
            [...done, group[0] << 24 | group[1] << 16 | group[2] << 8 | group[3]]
        , []).reduce((done, word, idx, arr) =>
            idx % 8 == 0 ? [...done, arr.slice(idx, idx + 8)] : done
        , []).map(group => {
            while(group.length < 40)
                group.push(rot(group[group.length - 2] ^ group[group.length - 5] ^ group[group.length - 8], 3));
            return group;
        }).flat().reduce((state, word, idx, arr) => {
            var temp = ((state[0] + rot(state[1], 5) + word + idx + state[3]) & 0xffffffff) ^ state[idx % 2 == 0 ? 4 : 5](state[0], state[1], state[2]);
            state[0] = rot(state[1] ^ state[2], 11);
            state[1] = ~state[2] ^ rot(~state[3], 19);
            state[2] = rot(~state[3], 11);
            state[3] = temp;
            return state;
        }, [0xbd173622, 0x96d8975c, 0x3a6d1a23, 0xe5843775,
            (w1, w2, w3) => (w1 & rot(w2, 5)) | (~rot(w1, 11) & w3),
            (w1, w2, w3) => w1 ^ rot(w2, 5) ^ rot(w3, 11)]
        ).slice(0, 4).map(p =>
            p >>> 0
        ).map(word =>
            ("0000000" + word.toString(16)).slice(-8)
        ).join("");
};

हम शब्द सरणी के बजाय स्ट्रिंग प्राप्त करने के लिए आउटपुट को हेक्स में परिवर्तित करते हैं।
उपयोग सरल है। "a string".hash()वापसी के लिए वापसी होगी"88a09e8f9cc6f8c71c4497fbb36f84cd"


1

मैं हेक्स स्ट्रिंग्स में परिवर्तित चार कोड का एक सरल संयोजन के लिए गया था। यह एक अपेक्षाकृत संकीर्ण उद्देश्य के रूप में कार्य करता है, अर्थात् बस एक SHORT स्ट्रिंग (जैसे शीर्षक, टैग) के हैश प्रतिनिधित्व की आवश्यकता होती है जो एक सर्वर पक्ष के साथ आदान-प्रदान किया जाता है जो प्रासंगिक कारणों के लिए आसानी से स्वीकार किए गए हैशकोड जावा पोर्ट को लागू नहीं कर सकता है। जाहिर है यहां कोई सुरक्षा आवेदन नहीं है।

String.prototype.hash = function() {
  var self = this, range = Array(this.length);
  for(var i = 0; i < this.length; i++) {
    range[i] = i;
  }
  return Array.prototype.map.call(range, function(i) {
    return self.charCodeAt(i).toString(16);
  }).join('');
}

इसे अंडरस्कोर के साथ और अधिक ट्रोल और ब्राउज़र-सहिष्णु बनाया जा सकता है। उदाहरण:

"Lorem Ipsum".hash()
"4c6f72656d20497073756d"

मुझे लगता है कि अगर आप इसी तरह के फैशन में बड़े स्ट्रिंग्स करना चाहते हैं, तो आप चार कोड को कम कर सकते हैं और एक साथ व्यक्तिगत वर्णों को समेटने के बजाय परिणामी राशि को बढ़ा सकते हैं:

String.prototype.hashLarge = function() {
  var self = this, range = Array(this.length);
  for(var i = 0; i < this.length; i++) {
    range[i] = i;
  }
  return Array.prototype.reduce.call(range, function(sum, i) {
    return sum + self.charCodeAt(i);
  }, 0).toString(16);
}

'One time, I hired a monkey to take notes for me in class. I would just sit back with my mind completely blank while the monkey scribbled on little pieces of paper. At the end of the week, the teacher said, "Class, I want you to write a paper using your notes." So I wrote a paper that said, "Hello! My name is Bingo! I like to climb on things! Can I have a banana? Eek, eek!" I got an F. When I told my mom about it, she said, "I told you, never trust a monkey!"'.hashLarge()
"9ce7"

इस पद्धति के साथ स्वाभाविक रूप से टकराव का अधिक जोखिम है, हालांकि आप कम में अंकगणित के साथ बेला कर सकते हैं, हालांकि आप हैश को विविधता और लंबा करना चाहते थे।


1

@ Esmiralha के उत्तर का थोड़ा सरल संस्करण।

मैं इस संस्करण में स्ट्रिंग को ओवरराइड नहीं करता, क्योंकि इससे कुछ अवांछित व्यवहार हो सकता है।

function hashCode(str) {
    var hash = 0;
    for (var i = 0; i < str.length; i++) {
        hash = ~~(((hash << 5) - hash) + str.charCodeAt(i));
    }
    return hash;
}

1

इसे जोड़ना क्योंकि किसी ने अभी तक नहीं किया था, और ऐसा लगता है कि इसके लिए कहा गया है और बहुत से हैश के साथ लागू किया गया है, लेकिन यह हमेशा बहुत खराब तरीके से किया जाता है ...

यह एक स्ट्रिंग इनपुट लेता है, और अधिकतम संख्या जिसे आप हैश के बराबर चाहते हैं, और स्ट्रिंग इनपुट के आधार पर एक अद्वितीय संख्या का उत्पादन करते हैं।

आप छवियों के एक सरणी में एक अद्वितीय सूचकांक का उत्पादन करने के लिए इसका उपयोग कर सकते हैं (यदि आप किसी उपयोगकर्ता के लिए एक विशिष्ट अवतार लौटना चाहते हैं, यादृच्छिक पर चुना जाता है, लेकिन उनके नाम के आधार पर भी चुना जाता है, इसलिए यह हमेशा उस नाम के साथ किसी को सौंपा जाएगा )।

आप किसी अन्य व्यक्ति के नाम के आधार पर अद्वितीय अवतार पृष्ठभूमि रंगों को उत्पन्न करने के लिए, अनुक्रमणिका को रंगों की एक सरणी में वापस करने के लिए, इसका भी उपयोग कर सकते हैं।

function hashInt (str, max = 1000) {
    var hash = 0;
    for (var i = 0; i < str.length; i++) {
      hash = ((hash << 5) - hash) + str.charCodeAt(i);
      hash = hash & hash;
    }
    return Math.round(max * Math.abs(hash) / 2147483648);
}

-1

मुझे तैयार-टू-यूज़ समाधानों के बजाय इस ओवर-कॉम्प्लेक्टेड क्रिप्टो कोड का उपयोग करने का कोई कारण नहीं दिखता है, जैसे ऑब्जेक्ट-हैश लाइब्रेरी, या वेंडर पर निर्भरता अधिक उत्पादक है, समय बचाता है और रखरखाव लागत को कम करता है।

बस https://github.com/puleos/object-hash का उपयोग करें

var hash = require('object-hash');

hash({foo: 'bar'}) // => '67b69634f9880a282c14a0f0cb7ba20cf5d677e9'
hash([1, 2, 2.718, 3.14159]) // => '136b9b88375971dff9f1af09d7356e3e04281951'

उस परिवाद का स्रोत कोड भी पठनीय नहीं है .. केवल 50k की न्यूनतम कोड।
bryc

1
@bryc यह है कि विक्रेता कोड कैसा दिखना चाहिए :) और स्रोतों के लिए आप github.com/puleos/object-hash/blob/master/index.js
Oleg Abrazhaev

न्यूनतम कोड 35.4 KB है जबकि पूर्ण स्रोत 14.2 KB है? इसका कोई अर्थ नही बन रहा है।
bryc

2
@bryc क्या आपने इस लाइन पर विचार किया है? var crypto = require('crypto');। मुझे लगता है कि यह एक निर्माण के दौरान इस विक्रेता से निर्भरता कोड को न्यूनतम संस्करण में जोड़ता है।
ओलेग अब्राजेव

अगर आपको वास्तव में हैश ऑब्जेक्ट्स की आवश्यकता है, तो मैंने किसी भी ऑब्जेक्ट को क्रमबद्ध कुंजियों के साथ क्रमबद्ध करने के लिए लिखा है , फिर cyrb53 को base36 हैश उत्पन्न करने के लिए।
पोलव
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.