হ্যাশ ফাংশন যা সংক্ষিপ্ত hashes উত্পাদন?


101

এনক্রিপশনের কোনও উপায় কি কোনও দৈর্ঘ্যের একটি স্ট্রিং নিতে পারে এবং একটি উপ-10-অক্ষরের হ্যাশ তৈরি করতে পারে? আমি যুক্তিসঙ্গতভাবে অনন্য আইডি তৈরি করতে চাই তবে এলোমেলোভাবে বার্তার পরিবর্তে বার্তার সামগ্রীর উপর ভিত্তি করে।

আমি বার্তাগুলি পূর্ণসংখ্যার মানগুলিতে সীমাবদ্ধ করে বাঁচতে পারি, যদিও স্বেচ্ছাসেবী দৈর্ঘ্যের স্ট্রিং অসম্ভব হয়ে থাকে। তবে, হ্যাশটি অবশ্যই একটানা দুটি পূর্ণসংখ্যার জন্য একই রকম হবে না।


এটিকে হ্যাশ বলা হয়। এটি অনন্য হবে না।
স্ল্যাक्स

4
এটি হ্যাশ ট্র্যাঙ্কেশন সমস্যাও তাই স্ট্যাকওভারফ্লো.com
পিটার ক্রাউস

4
এফওয়াইআই, উইকিপিডিয়ায় হ্যাশ ফাংশনগুলির একটি তালিকা দেখুন ।
বাসিল বার্ক

উত্তর:


80

আপনি যে কোনও সাধারণভাবে উপলভ্য হ্যাশ অ্যালগরিদম ব্যবহার করতে পারেন (উদাঃ SHA-1), যা আপনাকে যা প্রয়োজন তার চেয়ে কিছুটা দীর্ঘতর ফলাফল দেবে। কেবল পছন্দসই দৈর্ঘ্যে ফলাফল কেটে দিন, যা যথেষ্ট ভাল হতে পারে।

উদাহরণস্বরূপ, পাইথনে:

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

4
যে কোনও যুক্তিসঙ্গত হ্যাশ ফাংশন কেটে দেওয়া যেতে পারে।
রাষ্ট্রপতি জেমস কে পোলক

92
এটি কি আরও বেশি পরিমাণে সংঘর্ষের ঝুঁকি বাড়বে না?
গ্যাব্রিয়েল সানমার্টিন

144
@ ইরেসোমাস্টঙ্ক: বেস 6464 এর সাথে এনকোডিং সংঘর্ষ প্রতিরোধের জন্য কিছুই করে না, কারণ যদি এরপরে hash(a)সংঘর্ষ হয় hash(b)তবে এটির সাথে সংঘর্ষও base64(hash(a))হয় base64(hash(b))
গ্রেগ হিউগিল

57
@ গ্রেগ হিউগিল আপনি ঠিক বলেছেন, তবে আমরা আসল হ্যাশ অ্যালগরিদম সংঘর্ষের বিষয়ে বলছি না (হ্যাঁ, sha1সংঘর্ষ হয় তবে এটি অন্য গল্প)। যদি আপনার কাছে 10 টি অক্ষর হ্যাশ থাকে তবে এটি base64বনাম base16(বা হেক্স) এর সাথে এনকোড করা থাকলে উচ্চতর এনট্রপি পাবেন । কত উঁচু? সঙ্গে base16আপনি অক্ষর প্রতি তথ্য 4 টি বিট পেতে সঙ্গে base64এই চিত্র 6bits / গৃহস্থালির কাজ হয়। মোটামুটি একটি 10 ​​চর "হেক্স" হ্যাশটির ইনট্রপি 40 বিট থাকবে এবং বেস 64 bits০ বিট। সুতরাং এটি কিছুটা প্রতিরোধী, দুঃখিত যদি আমি সুপার ক্লিয়ার না হত।
জন এল জেগুটানিস

21
@ বায়ুমণ্ডল: ওহ আমি কী বলতে চাইছি তা দেখতে পেয়েছি, হ্যাঁ যদি আপনার ফলাফলের জন্য নির্দিষ্ট আকার থাকে তবে আপনি বেস 64৪ টি এনকোডিং বনাম হেক্স এনকোডিং সহ আরও গুরুত্বপূর্ণ বিট প্যাক করতে পারবেন।
গ্রেগ হিউগিল

46

আপনার যদি ইচ্ছাকৃত পরিবর্তনের বিরুদ্ধে শক্তিশালী অ্যালগরিদমের প্রয়োজন না হয় তবে আমি অ্যাডলার 32 নামে একটি অ্যালগরিদম পেয়েছি যা খুব ছোট (~ 8 অক্ষর) ফলাফল তৈরি করে produces এটি চেষ্টা করার জন্য এখানে ড্রপডাউন থেকে এটি চয়ন করুন:

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


4
এটি খুব পুরানো, খুব নির্ভরযোগ্য নয়।
মাস্কারপোন

4
@ মাস্কারপোন "খুব নির্ভরযোগ্য নয়" - উত্স? এটির সীমাবদ্ধতা রয়েছে, আপনি যদি তাদের জানেন তবে এটি কতটা পুরানো matter
বিটি

8
@ মাস্কারপোন "কম দুর্বলতা" - আবার কি কি দুর্বলতা? আপনি কেন মনে করেন যে এই অ্যালগরিদম অপের ব্যবহারের জন্য 100% নিখুঁত নয়?
বিটি

4
@ মাশারপোন ওপিতে তারা ক্রিপ্টো-গ্রেডের হ্যাশ চায় তা বলে না। ওটিওএইচ, অ্যাডলার 32 একটি চেকসাম, হ্যাশ নয়, সুতরাং ওপি আসলে এটি কী করছে তার উপর নির্ভর করে এটি উপযুক্ত নাও হতে পারে।
প্রধানমন্ত্রী 2Ring

4
অ্যাডলার 32- তে একটি সাবধানতা রয়েছে, উইকিপিডিয়াটি উদ্ধৃত করে : অ্যাডলার -32 এর কয়েক শ বাইট সহ সংক্ষিপ্ত বার্তাগুলির দুর্বলতা রয়েছে, কারণ এই বার্তাগুলির চেকসামগুলিতে 32 টি বিট উপলব্ধ নয় coverage
বাসিল বার্ক

13

একটি ডাইজেস্ট নিয়ে আসতে আপনাকে সামগ্রীগুলি হ্যাশ করতে হবে। অনেকগুলি হ্যাশ উপলব্ধ রয়েছে তবে ফলাফলের জন্য 10-অক্ষরগুলি বেশ ছোট। ফিরে যাওয়ার পথে লোকেরা সিআরসি -32 ব্যবহার করেছিল, যা 33-বিট হ্যাশ তৈরি করে (মূলত 4 টি অক্ষর এবং এক বিট)। এছাড়াও CRC-64 রয়েছে যা 65-বিট হ্যাশ তৈরি করে। এমডি 5, যা একটি 128-বিট হ্যাশ তৈরি করে (16 বাইট / অক্ষর) ক্রিপ্টোগ্রাফিক উদ্দেশ্যে ভাঙ্গা হিসাবে বিবেচিত হয় কারণ দুটি বার্তা পাওয়া যেতে পারে যার একই হ্যাশ রয়েছে। এটি বলার অপেক্ষা রাখে না যে আপনি যে কোনও সময় 16 টি বাইট ডাইজেস্ট স্বেচ্ছাসেবী দৈর্ঘ্যের বার্তাটি তৈরি করার পরে ডুপ্লিকেট দিয়ে শেষ করতে চলেছেন। ডাইজেস্ট যত খাটো, সংঘর্ষের ঝুঁকি তত বেশি।

তবে আপনার উদ্বেগ যে টানা দুটি বার্তাগুলির জন্য হ্যাশটি একই রকম নয় (পূর্ণসংখ্যাগুলি হোক বা না হোক) সমস্ত হ্যাশের সাথে সত্য হওয়া উচিত। এমনকি মূল বার্তায় একটি বিট পরিবর্তনের ফলেও সম্পূর্ণ ভিন্ন ফলাফল হজম হওয়া উচিত।

সুতরাং, সিআরসি-64৪ (এবং ফলাফল-বেস' 64'র মতো কিছু ব্যবহার করে আপনি যে আশেপাশে খুঁজছেন তা আপনাকে পাওয়া উচিত।


4
সিআরসি'এইচএএ -1 হ্যাশ এবং তারপরে বেস-64৪'র ফলাফলের ফলে ফলাফলটি আইডি সংঘর্ষের জন্য আরও প্রতিরোধী হয়?

4
"তবে, আপনার উদ্বেগ যে টানা দুটি বার্তাগুলির জন্য হ্যাশটি একই রকম নয় [...] সমস্ত হ্যাশের সাথে সত্য হওয়া উচিত।" - এটি অগত্যা সত্য নয়। উদাহরণস্বরূপ, হ্যাশ ফাংশনগুলির জন্য যা ক্লাস্টারিং বা ক্লোন সনাক্তকরণের জন্য ব্যবহৃত হয়, তার ঠিক বিপরীতটি সত্য, আসলে: আপনি অনুরূপ (বা এমনকি একই) হ্যাশ মানগুলি অর্জন করতে অনুরূপ নথি চান । হ্যাশ অ্যালগরিদমের একটি সুপরিচিত উদাহরণ যা বিশেষত অনুরূপ ইনপুটটির জন্য অভিন্ন মূল্য নির্ধারণের জন্য ডিজাইন করা হয়েছে তা হচ্ছে সাউন্ডেক্স।
জার্গ ডব্লু মিট্টাগ

আমি বার্তাটির স্বাক্ষরটির প্রমাণীকরণের জন্য হ্যাশগুলি ব্যবহার করছি। সুতরাং মূলত, একটি পরিচিত বার্তা এবং নির্দিষ্ট স্বাক্ষরের জন্য, হ্যাশটি সঠিক হতে হবে। যদিও মিথ্যা পজিটিভের একটি ছোট শতাংশ থাকবে কিনা তা আমি চিন্তা করি না। এটি সম্পূর্ণ গ্রহণযোগ্য। সুবিধার জন্য আমি বর্তমানে বেস 62 (সংক্ষেপিত এমন কিছু যা আমি দ্রুত বেত্রাঘাত করি) সংক্ষিপ্তভাবে কাটা SHA-512 হ্যাশ ব্যবহার করি।

সাউন্ডএক্সে @ জার্গডব্লিউমিতাগল দুর্দান্ত পয়েন্ট। আমি সংশোধন করেছি. না সব হ্যাশ একই বৈশিষ্ট্য থাকে।
জন

12

কেবলমাত্র একটি উত্তর সংক্ষিপ্ত করে যা আমার পক্ষে সহায়ক ছিল (বেস-64৪ এনকোডিং ব্যবহার সম্পর্কে @ ইরাস্টমাস্টঙ্কের মন্তব্য লক্ষ্য করা)। আমার লক্ষ্যটি ছিল একটি সংক্ষিপ্ত স্ট্রিং যা বেশিরভাগ অনন্য ছিল ...

আমি কোনও বিশেষজ্ঞ নই, সুতরাং এটির কোনও সুস্পষ্ট ত্রুটি থাকলে এটি সংশোধন করুন (স্বীকৃত উত্তরের মতো পাইথনে আবারও):

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()) তাই এটি সম্ভাবনা কম এর একটি সংঘর্ষের (যে, একটি হেক্স হজম চেয়ে অগ্রভাগ ছাঁটিয়া নিরাপদ হওয়া উচিত) আছে।

দ্রষ্টব্য: ইউআইউডি 4 (এলোমেলো) ব্যবহার করা। অন্যান্য প্রকারের জন্য http://en.wikedia.org/wiki/Universally_unique_phanfier দেখুন ।


8

আপনার যদি প্রয়োজন হয় "sub-10-character hash" আপনি ফ্লেচার -32 এলগোরিদম ব্যবহার করতে পারেন যা 8 টি অক্ষর হ্যাশ (32 বিট), সিআরসি -32 বা অ্যাডলার -32 তৈরি করে

সিআরসি -32 অ্যাডলার 32 এর চেয়ে 20% - 100% এর একটি ফ্যাক্টর দ্বারা ধীর।

ফ্ল্যাচার -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 অ্যালগরিদম যথেষ্ট জটিল নয়


7

আপনি একটি বিদ্যমান হ্যাশ অ্যালগরিদম ব্যবহার করতে পারেন যা MD5 (128 বিট) বা SHA1 (160) এর মতো সংক্ষিপ্ত কিছু তৈরি করে। তারপরে আপনি আরও সংক্ষেপে অন্যান্য বিভাগের সাথে ডাইজেস্টের XORing বিভাগগুলি দ্বারা সংক্ষিপ্ত করতে পারেন। এটি সংঘর্ষের সম্ভাবনা বাড়িয়ে তুলবে, তবে ডাইজেস্টকে ছোট করে দেওয়ার মতো খারাপ নয়।

এছাড়াও, আপনি আরও অনন্য করতে ফলাফলের অংশ হিসাবে মূল ডেটার দৈর্ঘ্য অন্তর্ভুক্ত করতে পারেন। উদাহরণস্বরূপ, দ্বিতীয়ার্ধের সাথে এমডি 5 ডাইজেস্টের প্রথমার্ধে জোরিংয়ের ফলে b৪ বিট হবে। ডেটার দৈর্ঘ্যের জন্য 32 বিট যুক্ত করুন (বা আপনি যদি জানেন যে দৈর্ঘ্যটি সর্বদা কম বিটগুলিতে ফিট হয়ে যায়) lower এর ফলে 96৯-বিট (12-বাইট) ফলাফল হতে পারে যা আপনি পরে 24-অক্ষরের হেক্স স্ট্রিংয়ে রূপান্তর করতে পারেন। পর্যায়ক্রমে, আপনি এটি আরও খাটো করতে বেস 64 এনকোডিংটি ব্যবহার করতে পারেন।


4
FWIW, এটি এক্সওআর-ভাঁজ হিসাবে পরিচিত।
প্রধানমন্ত্রী 2Ring

6

টার্মিনালে কেবল এটি চালান (ম্যাকোস বা লিনাক্সে):

crc32 <(echo "some string")

8 টি অক্ষর দীর্ঘ।


6

আপনি পাইথনের জন্য হ্যাশলিব লাইব্রেরি ব্যবহার করতে পারেন । Shake_128 এবং shake_256 আলগোরিদিম পরিবর্তনশীল দৈর্ঘ্য হ্যাশ প্রদান। এখানে কিছু কার্যকরী কোড (পাইথন 3):

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

লক্ষ করুন যে দৈর্ঘ্যের প্যারামিটার x (উদাহরণস্বরূপ 5) দিয়ে ফাংশনটি 2x দৈর্ঘ্যের একটি হ্যাশ মান প্রদান করে ।


2

এটি এখন 2019 এবং আরও ভাল বিকল্প রয়েছে। যথা, এক্সএক্স্যাশ

~ echo test | xxhsum                                                           
2d7f1808da1fa63c  stdin

এই লিঙ্কটি নষ্ট হয়ে গেছে। আরও সম্পূর্ণ উত্তর প্রদান করা ভাল।
এরি0o

0

একটি সাধারণ স্ট্রিং হ্রাস ফাংশনের লাইন ধরে আমার সম্প্রতি কিছু দরকার ছিল। মূলত, কোডটি এরকম কিছু দেখায় (সি / সি ++ কোড এগিয়ে):

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 জনকে অন্য মৌলিক সংখ্যায় পরিবর্তন করুন)। এই স্নিপেটের একটি আকর্ষণীয় বৈশিষ্ট্য হ'ল এসসিআরটি যখন ডেস্টের চেয়ে ছোট হয়, ডাস্ট শেষ হিসাবে ইনপুট স্ট্রিংয়ের সাথে শেষ হয় (0 * 37 + মান = মান)। প্রক্রিয়া শেষে আপনি যদি কিছু "পঠনযোগ্য" চান তবে নর্মালাইজ ক্রমবর্ধমান সংঘর্ষের ব্যয়ে রূপান্তরিত বাইটগুলি সামঞ্জস্য করবে।

সূত্র:

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


এসটিডি :: হ্যাশ কিছু নির্দিষ্ট ব্যবহারের ক্ষেত্রে সমাধান করে না (উদাহরণস্বরূপ ফুলে ফেঁপে যাওয়া এসটিডি :: টেমপ্লেটগুলিতে টানাটানি এড়ানো যখন কোডের কয়েকটি অতিরিক্ত লাইনই যথেষ্ট হবে)। এখানে নিরীহ কিছু নেই। ম্যাক ওএসএক্সের বড় সীমাবদ্ধতাগুলি মোকাবেলা করার জন্য সাবধানতার সাথে চিন্তা করা হয়েছিল। আমি পূর্ণসংখ্যা চাই না তার জন্য, আমি djb2 ব্যবহার করতে পারতাম এবং এখনও std :: টেমপ্লেটগুলি ব্যবহার করা এড়াতে পারি।
কিউবিকসফট

এটি এখনও নির্বোধ শোনায়। কেন তুমি হবে কি কখনো একটি ব্যবহার DestSize4 (32 বিট) তার চেয়ে অনেক বেশী যখন হ্যাশ নিজেই তাই ন্যক্কারজনক হয়? যদি আপনি কোনও int এর চেয়ে বড় আউটপুট দ্বারা সরবরাহ করা সংঘর্ষ প্রতিরোধের চেয়েছিলেন তবে আপনি SHA ব্যবহার করবেন।
নবীন

দেখুন, এটি আসলে ট্র্যাডিশনাল হ্যাশ নয়। এটিতে দরকারী বৈশিষ্ট্য রয়েছে যেখানে ব্যবহারকারীরা নির্দিষ্ট ওএসে (যেমন ম্যাক ওএসএক্স) অত্যন্ত সীমিত বাফার স্থান রয়েছে এমন জায়গায় স্ট্রিং আকার ঘোষণা করতে পারে এবং ফলস্বরূপ প্রকৃত ফাইলের নামের সীমিত ডোমেনের মধ্যে ফিট করতে হয় এবং তারা কেবল ছাঁটাই করতে চায় না নাম কারণ যে সংঘর্ষের কারণ হবে (তবে ছোট স্ট্রিং একা বাকি আছে)। একটি ক্রিপ্টোগ্রাফিক হ্যাশ সর্বদা সঠিক উত্তর হয় না এবং স্ট্যান্ড :: হ্যাশও সর্বদা সঠিক উত্তর হয় না।
কিউবিকসফট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.