हैश फ़ंक्शन जो शॉर्ट हैश का उत्पादन करता है?


98

क्या एन्क्रिप्शन का एक तरीका है जो किसी भी लम्बाई की स्ट्रिंग ले सकता है और उप-10-चरित्र हैश का उत्पादन कर सकता है? मैं यथोचित रूप से नहीं बल्कि मैसेज कंटेंट के आधार पर यथोचित यूनिक आईडी का उत्पादन करना चाहता हूं।

मैं पूर्णांक मानों को संदेश देने के लिए विवश रह सकता हूं, हालांकि, अगर मनमाने ढंग से लंबाई के तार असंभव हैं। हालाँकि, हैश उस स्थिति में लगातार दो पूर्णांकों के समान नहीं होना चाहिए।


इसे हैश कहते हैं। यह अद्वितीय नहीं होगा।
SLAKs

1
यह भी एक हैश ट्रंकेशन समस्या है, इसलिए यह भी देखें stackoverflow.com/q/4784335
पीटर क्रूस

2
FYI करें, विकिपीडिया में हैश कार्यों की सूची देखें ।
बेसिल बोर्के

जवाबों:


78

आप किसी भी उपलब्ध हैश एल्गोरिथ्म (उदाहरण के लिए SHA-1) का उपयोग कर सकते हैं, जो आपको आपकी आवश्यकता के मुकाबले थोड़ा अधिक समय देगा। बस वांछित लंबाई के परिणाम को छोटा करें, जो काफी अच्छा हो सकता है।

उदाहरण के लिए, पायथन में:

>>> import hashlib
>>> hash = hashlib.sha1("my message".encode("UTF-8")).hexdigest()
>>> hash
'104ab42f1193c336aa2cf08a2c946d5c6fd0fcdb'
>>> hash[:10]
'104ab42f11'

3
किसी भी उचित हैश फ़ंक्शन को छोटा किया जा सकता है।
राष्ट्रपति जेम्स के। पोल्

89
क्या इससे टकराव का खतरा बहुत अधिक नहीं बढ़ जाता?
गेब्रियल सनमार्टिन

143
@erasmospunk: बेस 64 के साथ एन्कोडिंग टकराव के प्रतिरोध के लिए कुछ भी नहीं करता है, क्योंकि अगर इसके hash(a)साथ टकराता है hash(b)तो base64(hash(a))भी टकराता है base64(hash(b))
ग्रेग हेविल जिल

56
@GregHewgill आप सही हैं, लेकिन हम मूल हैश एल्गोरिथ्म के टकराने के बारे में नहीं बोल रहे हैं (हाँ, sha1टकराता है लेकिन यह एक और कहानी है)। यदि आपके पास 10 वर्ण हैश है तो आप उच्च एन्ट्रापी प्राप्त करते हैं यदि यह base64बनाम base16(या हेक्स) के साथ एन्कोडेड है । कितना ऊंचा है? आपके साथ base16प्रति चरित्र में 4 बिट्स की जानकारी मिलती है, base64इस आंकड़े के साथ 6 बिट्स / चार है। टोटल ए 10 चार "हेक्स" हैश में एंट्रॉपी के 40 बिट्स होंगे जबकि बेस 64 60बिट्स। इसलिए यह थोड़ा अधिक प्रतिरोधी है, अगर मैं सुपर स्पष्ट नहीं था तो क्षमा करें।
जॉन एल। जेगुटानिस

20
@erasmospunk: ओह मैं देख रहा हूं कि आपका क्या मतलब है, हां अगर आपके पास आपके परिणाम के लिए एक सीमित आकार है तो आप बेस 64 एन्कोडिंग बनाम हेक्स एन्कोडिंग के साथ अधिक महत्वपूर्ण बिट्स पैक कर सकते हैं।
ग्रेग हेवगिल

46

यदि आपको किसी ऐसे एल्गोरिथ्म की आवश्यकता नहीं है जो जानबूझकर संशोधन के खिलाफ मजबूत हो, तो मैंने एडलर 32 नामक एक एल्गोरिथ्म पाया है जो बहुत कम (~ 8 वर्ण) परिणाम पैदा करता है। इसे आज़माने के लिए इसे ड्रॉपडाउन में से चुनें:

http://www.sha1-online.com/


2
यह बहुत पुराना है, बहुत विश्वसनीय नहीं है।
मस्करपोन

1
@ मस्करपोन "बहुत विश्वसनीय नहीं" - स्रोत? इसकी सीमाएँ हैं, यदि आप उन्हें जानते हैं तो इससे कोई फर्क नहीं पड़ता कि यह कितनी पुरानी है।
बीटी

8
@Mascarpone "कम कमजोरियों" - फिर, क्या कमजोरियां? आपको क्या लगता है कि यह एल्गोरिथ्म ओपी के उपयोग के लिए 100% सही नहीं है?
BT

3
@ मस्करपोन ओपी यह नहीं कहता कि वे एक क्रिप्टो-ग्रेड हैश चाहते हैं। OTOH, Adler32 एक चेकसम है, हैश नहीं, इसलिए यह उपयुक्त नहीं हो सकता है, यह इस बात पर निर्भर करता है कि ओपी वास्तव में इसके बारे में क्या कर रहा है।
PM 2Ring

2
वहाँ Adler32 करने के लिए एक चेतावनी के हवाले है विकिपीडिया : Adler32 कुछ सौ बाइट्स के साथ संक्षिप्त संदेश के लिए एक कमजोरी है, क्योंकि इन संदेशों के लिए चेकसम 32 उपलब्ध बिट्स के एक गरीब कवरेज।
बेसिल बोर्के

13

आपको एक पाचन के साथ आने वाली सामग्री को हैश करने की आवश्यकता है। कई हैश उपलब्ध हैं, लेकिन 10-वर्ण परिणाम सेट के लिए बहुत छोटा है। जिस तरह से, लोगों ने सीआरसी -32 का उपयोग किया, जो 33-बिट हैश (मूल रूप से 4 अक्षर प्लस एक बिट) का उत्पादन करता है। CRC-64 भी है जो 65-बिट हैश का उत्पादन करता है। MD5, जो 128-बिट हैश (16 बाइट्स / वर्ण) का उत्पादन करता है क्रिप्टोग्राफ़िक उद्देश्यों के लिए टूटा हुआ माना जाता है क्योंकि दो संदेश मिल सकते हैं जिनमें एक ही हैश है। यह कहे बिना जाना चाहिए कि किसी भी समय आप एक 16-बाइट को पचाने के लिए एक मनमाना लंबाई संदेश से बाहर निकलते हैं जिसे आप डुप्लिकेट के साथ समाप्त करने जा रहे हैं। पाचन जितना छोटा होगा, टकरावों का खतरा उतना ही अधिक होगा।

हालांकि, आपकी चिंता यह है कि हैश लगातार दो संदेशों (चाहे पूर्णांक या नहीं) सभी हैश के साथ समान होना चाहिए। यहां तक ​​कि मूल संदेश में एक भी परिवर्तन थोड़ा बहुत अलग परिणामी पाचन का उत्पादन करना चाहिए।

इसलिए, CRC-64 (और आधार -64 'परिणाम) जैसी किसी चीज़ का उपयोग करके आपको उस पड़ोस में प्राप्त करना चाहिए जिसे आप खोज रहे हैं।


1
क्या एक SHA-1 हैश और फिर आधार -64 'CRC'ing करने से परिणामी ID टकराव के लिए अधिक प्रतिरोधी हो जाती है?

5
"हालांकि, आपकी चिंता यह है कि हैश लगातार दो संदेशों के समान नहीं है [...] सभी हैश के साथ सच होना चाहिए।" - यह जरूरी नहीं कि सच हो। उदाहरण के लिए, हैश फ़ंक्शंस के लिए जो क्लस्टरिंग या क्लोन डिटेक्शन के लिए उपयोग किए जाते हैं, वास्तव में इसके विपरीत सही है, वास्तव में: आप चाहते हैं कि समान दस्तावेज़ (समान या यहां तक ​​कि समान) हैश मान प्राप्त करें। हैश एल्गोरिथ्म का एक प्रसिद्ध उदाहरण जो विशेष रूप से इसी तरह के इनपुट के लिए समान मूल्यों का उत्पादन करने के लिए डिज़ाइन किया गया है।
जोर्ग डब्ल्यू मित्तग

मैं संदेश के हस्ताक्षर को प्रमाणित करने के लिए हैश का उपयोग कर रहा हूं। इसलिए मूल रूप से, एक ज्ञात संदेश और निर्दिष्ट हस्ताक्षर के लिए, हैश सही होना चाहिए। मुझे परवाह नहीं है अगर वहाँ झूठी सकारात्मक का एक छोटा प्रतिशत होगा, यद्यपि। यह पूरी तरह से स्वीकार्य है। मैं वर्तमान में सुविधा के लिए बेस 62 (कुछ मैं जल्दी से मार पड़ी) के साथ संकुचित SHA-512 हैश का उपयोग करता हूं।

@ JörgWMittag SoundEx पर उत्कृष्ट बिंदु। मुझे सही साबित होना है। नहीं सभी हैश ही विशेषताएं हैं।
जॉन

12

बस एक जवाब का सारांश है जो मेरे लिए उपयोगी था (आधार -64 एन्कोडिंग का उपयोग करने के बारे में @ erasmospunk की टिप्पणी को देखते हुए)। मेरा लक्ष्य एक छोटी स्ट्रिंग थी जो ज्यादातर अनोखी थी ...

मैं कोई विशेषज्ञ नहीं हूं, इसलिए कृपया इसे ठीक करें अगर इसमें कोई चमकता हुआ त्रुटि है (स्वीकार किए गए उत्तर की तरह फिर से पायथन में):

import base64
import hashlib
import uuid

unique_id = uuid.uuid4()
# unique_id = UUID('8da617a7-0bd6-4cce-ae49-5d31f2a5a35f')

hash = hashlib.sha1(str(unique_id).encode("UTF-8"))
# hash.hexdigest() = '882efb0f24a03938e5898aa6b69df2038a2c3f0e'

result = base64.b64encode(hash.digest())
# result = b'iC77DySgOTjliYqmtp3yA4osPw4='

resultयहाँ सिर्फ हेक्स वर्णों से अधिक उपयोग कर रहा है (यदि आप का इस्तेमाल किया है कि तुम क्या मिल चाहते हैं hash.hexdigest()) तो यह संभावना कम है एक टक्कर (है कि, एक हेक्स पचाने से काटना सुरक्षित होना चाहिए) है।

नोट: UUID4 (यादृच्छिक) का उपयोग करना। अन्य प्रकारों के लिए http://en.wikipedia.org/wiki/Universally_unique_identifier देखें ।


7

आप एक मौजूदा हैश एल्गोरिथ्म का उपयोग कर सकते हैं जो एमडी 5 (128 बिट्स) या एसएचए 1 (160) की तरह कुछ छोटा पैदा करता है। फिर आप अन्य वर्गों के साथ पाचन के XORing वर्गों द्वारा इसे और छोटा कर सकते हैं। यह टकराव की संभावना को बढ़ाएगा, लेकिन उतना ही बुरा नहीं होगा जितना कि पाचन को कमजोर कर देगा।

इसके अलावा, आप इसे और अधिक विशिष्ट बनाने के लिए परिणाम के हिस्से के रूप में मूल डेटा की लंबाई शामिल कर सकते हैं। उदाहरण के लिए, MD5 की पहली छमाही को दूसरी छमाही के साथ पचाने के परिणामस्वरूप 64 बिट्स हो जाएंगे। डेटा की लंबाई के लिए 32 बिट्स जोड़ें (या यदि आपको पता है कि लंबाई हमेशा कम बिट्स में फिट होगी)। इसका परिणाम 96-बिट (12-बाइट) के रूप में होगा, जिसके परिणामस्वरूप आप 24-वर्ण हेक्स स्ट्रिंग में बदल सकते हैं। वैकल्पिक रूप से, आप इसे छोटा करने के लिए बेस 64 एन्कोडिंग का उपयोग कर सकते हैं।


2
एफडब्ल्यूआईडब्ल्यू, इसे एक्सओआर-फोल्डिंग के रूप में जाना जाता है।
PM 2Ring

7

यदि आपको आवश्यकता "sub-10-character hash" हो तो आप फ्लेचर -32 एल्गोरिथ्म का उपयोग कर सकते हैं जो 8 वर्ण हैश (32 बिट्स), सीआरसी -32 या एडलर -32 का उत्पादन करता है

CRC-32 20% - 100% के कारक Adler32 से धीमा है।

फ्लेचर -32 एडलर -32 की तुलना में थोड़ा अधिक विश्वसनीय है। एडलर चेकसम की तुलना में इसकी कम कम्प्यूटेशनल लागत है: फ्लेचर बनाम एडलर तुलना

कुछ फ्लेचर कार्यान्वयन के साथ एक नमूना कार्यक्रम नीचे दिया गया है:

    #include <stdio.h>
    #include <string.h>
    #include <stdint.h> // for uint32_t

    uint32_t fletcher32_1(const uint16_t *data, size_t len)
    {
            uint32_t c0, c1;
            unsigned int i;

            for (c0 = c1 = 0; len >= 360; len -= 360) {
                    for (i = 0; i < 360; ++i) {
                            c0 = c0 + *data++;
                            c1 = c1 + c0;
                    }
                    c0 = c0 % 65535;
                    c1 = c1 % 65535;
            }
            for (i = 0; i < len; ++i) {
                    c0 = c0 + *data++;
                    c1 = c1 + c0;
            }
            c0 = c0 % 65535;
            c1 = c1 % 65535;
            return (c1 << 16 | c0);
    }

    uint32_t fletcher32_2(const uint16_t *data, size_t l)
    {
        uint32_t sum1 = 0xffff, sum2 = 0xffff;

        while (l) {
            unsigned tlen = l > 359 ? 359 : l;
            l -= tlen;
            do {
                sum2 += sum1 += *data++;
            } while (--tlen);
            sum1 = (sum1 & 0xffff) + (sum1 >> 16);
            sum2 = (sum2 & 0xffff) + (sum2 >> 16);
        }
        /* Second reduction step to reduce sums to 16 bits */
        sum1 = (sum1 & 0xffff) + (sum1 >> 16);
        sum2 = (sum2 & 0xffff) + (sum2 >> 16);
        return (sum2 << 16) | sum1;
    }

    int main()
    {
        char *str1 = "abcde";  
        char *str2 = "abcdef";

        size_t len1 = (strlen(str1)+1) / 2; //  '\0' will be used for padding 
        size_t len2 = (strlen(str2)+1) / 2; // 

        uint32_t f1 = fletcher32_1(str1,  len1);
        uint32_t f2 = fletcher32_2(str1,  len1);

        printf("%u %X \n",    f1,f1);
        printf("%u %X \n\n",  f2,f2);

        f1 = fletcher32_1(str2,  len2);
        f2 = fletcher32_2(str2,  len2);

        printf("%u %X \n",f1,f1);
        printf("%u %X \n",f2,f2);

        return 0;
    }

आउटपुट:

4031760169 F04FC729                                                                                                                                                                                                                              
4031760169 F04FC729                                                                                                                                                                                                                              

1448095018 56502D2A                                                                                                                                                                                                                              
1448095018 56502D2A                                                                                                                                                                                                                              

टेस्ट वैक्टर के साथ सहमत हैं :

"abcde"  -> 4031760169 (0xF04FC729)
"abcdef" -> 1448095018 (0x56502D2A)

एडलर -32 में कुछ सौ बाइट के साथ छोटे संदेशों के लिए कमजोरी है, क्योंकि इन संदेशों के चेकसम में 32 उपलब्ध बिट्स की खराब कवरेज है। इसे देखो:

एडलर 32 एल्गोरिदम तुलनात्मक चेकसमों के साथ प्रतिस्पर्धा करने के लिए पर्याप्त जटिल नहीं है


6

बस इसे टर्मिनल (MacOS या लिनक्स पर) में चलाएं:

crc32 <(echo "some string")

8 अक्षर लंबे।


4

आप पायथन के लिए हैशलीब लाइब्रेरी का उपयोग कर सकते हैं । Shake_128 और shake_256 एल्गोरिदम चर लंबाई हैश प्रदान करते हैं। यहाँ कुछ काम कोड (Python3) है:

import hashlib
>>> my_string = 'hello shake'
>>> hashlib.shake_256(my_string.encode()).hexdigest(5)
'34177f6a0a'

ध्यान दें कि एक लंबाई पैरामीटर x (उदाहरण में 5) फ़ंक्शन की लंबाई 2x का हैश मान है ।


1

यह अब 2019 है और बेहतर विकल्प हैं। अर्थात्, xxhash

~ echo test | xxhsum                                                           
2d7f1808da1fa63c  stdin

यह लिंक टूट गया है। अधिक पूर्ण उत्तर प्रदान करना बेहतर है।
एरियो ०

0

मुझे हाल ही में एक साधारण स्ट्रिंग कमी फ़ंक्शन की तर्ज पर कुछ की आवश्यकता थी। मूल रूप से, कोड कुछ इस तरह दिखता था (C / C ++ कोड आगे):

size_t ReduceString(char *Dest, size_t DestSize, const char *Src, size_t SrcSize, bool Normalize)
{
    size_t x, x2 = 0, z = 0;

    memset(Dest, 0, DestSize);

    for (x = 0; x < SrcSize; x++)
    {
        Dest[x2] = (char)(((unsigned int)(unsigned char)Dest[x2]) * 37 + ((unsigned int)(unsigned char)Src[x]));
        x2++;

        if (x2 == DestSize - 1)
        {
            x2 = 0;
            z++;
        }
    }

    // Normalize the alphabet if it looped.
    if (z && Normalize)
    {
        unsigned char TempChr;
        y = (z > 1 ? DestSize - 1 : x2);
        for (x = 1; x < y; x++)
        {
            TempChr = ((unsigned char)Dest[x]) & 0x3F;

            if (TempChr < 10)  TempChr += '0';
            else if (TempChr < 36)  TempChr = TempChr - 10 + 'A';
            else if (TempChr < 62)  TempChr = TempChr - 36 + 'a';
            else if (TempChr == 62)  TempChr = '_';
            else  TempChr = '-';

            Dest[x] = (char)TempChr;
        }
    }

    return (SrcSize < DestSize ? SrcSize : DestSize);
}

यह संभवतः वांछित होने की तुलना में अधिक टकराव है, लेकिन यह क्रिप्टोग्राफिक हैश फ़ंक्शन के रूप में उपयोग करने के लिए अभिप्रेत नहीं है। यदि आप बहुत से टकराव प्राप्त करते हैं, तो आप विभिन्न गुणक (यानी 37 को दूसरे अभाज्य संख्या में बदल सकते हैं) आज़मा सकते हैं। इस स्निपेट की एक दिलचस्प विशेषता यह है कि जब Src गंतव्य से छोटा होता है, तो गंतव्य इनपुट स्ट्रिंग के साथ समाप्त होता है (-* * 37 + मान = मान)। यदि आप प्रक्रिया के अंत में कुछ "पठनीय" चाहते हैं, तो सामान्यीकरण बढ़ती टकराव की कीमत पर परिवर्तित बाइट्स को समायोजित करेगा।

स्रोत:

https://github.com/cubiclesoft/cross-platform-cpp/blob/master/sync/sync_util.cpp


std :: hash कुछ उपयोग-मामलों को हल नहीं करता है (जैसे कि bloaty std में खींचने से परहेज :: टेम्पलेट जब कोड की कुछ अतिरिक्त पंक्तियाँ पर्याप्त होंगी)। यहाँ मूर्खतापूर्ण कुछ भी नहीं है। मैक ओएसएक्स में प्रमुख सीमाओं से निपटने के लिए सावधानीपूर्वक सोचा गया था। मैं एक पूर्णांक नहीं चाहता था। उसके लिए, मैं djb2 का उपयोग कर सकता था और अभी भी std :: टेम्पलेट्स का उपयोग करने से बचता था।
क्यूबिकलसॉफ्ट

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

देखिए, यह वास्तव में पारंपरिक हैश नहीं है। इसमें उपयोगी गुण हैं जहां उपयोगकर्ता उन स्थानों पर स्ट्रिंग आकार की घोषणा कर सकता है जहां कुछ OS पर अत्यंत सीमित बफर स्थान होता है (जैसे मैक OSX) और परिणाम को वास्तविक फ़ाइल नाम के सीमित डोमेन में फिट होना पड़ता है और वे केवल छोटा नहीं करना चाहते हैं वह नाम क्योंकि WOULD टकराव का कारण बनता है (लेकिन छोटे तार अकेले रह जाते हैं)। एक क्रिप्टोग्राफिक हैश हमेशा सही उत्तर नहीं होता है और एसटीएच :: हैश भी हमेशा सही उत्तर नहीं होता है।
क्यूबिकलसॉफ्ट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.