Android में MD5 हैशिंग


91

मेरे पास एक सरल एंड्रॉइड क्लाइंट है जिसे एक साधारण सी # HTTP श्रोता को 'बात' करने की आवश्यकता है। मैं POST अनुरोधों में उपयोगकर्ता नाम / पासवर्ड पारित करके प्रमाणीकरण का एक मूल स्तर प्रदान करना चाहता हूं।

एमडी 5 हैशिंग सी # में तुच्छ है और मेरी जरूरतों के लिए पर्याप्त सुरक्षा प्रदान करता है, लेकिन मुझे यह नहीं मिल रहा है कि एंड्रॉइड के अंत में ऐसा कैसे करें।

संपादित करें: एमडी 5 की कमजोरी के बारे में उठाई गई चिंताओं को दूर करने के लिए - सी # सर्वर मेरे एंड्रॉइड क्लाइंट के उपयोगकर्ताओं के पीसी पर चलता है। कई मामलों में, वे अपने LAN पर wi-fi का उपयोग करके सर्वर तक पहुँच सकते हैं लेकिन, अपने जोखिम पर, वे इसे इंटरनेट से एक्सेस करना चुन सकते हैं। इसके अलावा सर्वर पर सेवा को एमडी 5 के लिए पास-थ्रू का उपयोग करने की आवश्यकता है एक 3 पार्टी एप्लिकेशन पर जिसका मेरे पास कोई नियंत्रण नहीं है।


6
MD5 का उपयोग न करें। SHA512 का उपयोग करें।
SLaks

1
क्यों? SHA512 MD5 से अधिक कठिन नहीं है। आप MD5 का उपयोग कर विरासत ग्राहकों के साथ अब से पांच साल से अटके रहना नहीं चाहते हैं।
SLaks

2
मुझे आशा है कि आप अपने प्रोटोकॉल में एक गैर का उपयोग कर रहे हैं, ताकि आप फिर से खेलना हमलों को दूर कर सकें।
31:11

1
@NickJohnson: आपके प्रश्न का उत्तर देने के लिए आप जानबूझकर कमजोर विकल्प का चयन क्यों करेंगे? एक अन्य प्रश्न के साथ ... 16 महीने पहले मेरे द्वारा पोस्ट किए गए प्रश्न पर टिप्पणी करने की आवश्यकता क्यों महसूस होगी? लेकिन अगर आप वास्तव में जानना चाहते हैं (यदि आप एसएलएसी से ऊपर की टिप्पणी को देखते हैं), तो यह अल्फा स्टेज कोड था और पीसी एंड (मेरे द्वारा लिखित नहीं) एमडी 5 हैशिंग का उपयोग किया गया था। आवश्यकता अतिरिक्त जटिलता को शामिल किए बिना मूल रूप से पास-थ्रू परिदृश्य के लिए थी। मेरे पास उस समय लगभग 10 अल्फा-स्टेज परीक्षक थे जो जोखिमों को जानते थे। प्रश्न पूछने के बाद से अधिक जटिल सुरक्षा को शामिल किया गया है।
स्क्वैंक

1
...क्या? नहीं, यह गलत नहीं है, यह खतरनाक रूप से गलत है।
निक जॉनसन

जवाबों:


230

यहां एक कार्यान्वयन है जिसे आप उपयोग कर सकते हैं (जावा सम्मेलनों - for:eachलूप के StringBuilderबजाय और अधिक उपयोग करने के लिए अद्यतन किया गया है StringBuffer), आदि।

public static String md5(final String s) {
    final String MD5 = "MD5";
    try {
        // Create MD5 Hash
        MessageDigest digest = java.security.MessageDigest
                .getInstance(MD5);
        digest.update(s.getBytes());
        byte messageDigest[] = digest.digest();

        // Create Hex String
        StringBuilder hexString = new StringBuilder();
        for (byte aMessageDigest : messageDigest) {
            String h = Integer.toHexString(0xFF & aMessageDigest);
            while (h.length() < 2)
                h = "0" + h;
            hexString.append(h);
        }
        return hexString.toString();

    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return "";
}

यद्यपि यह उन प्रणालियों के लिए अनुशंसित नहीं है, जिनमें सुरक्षा का मूल स्तर भी शामिल है (एमडी 5 को टूटा हुआ माना जाता है और इसका आसानी से फायदा उठाया जा सकता है ), यह कभी-कभी बुनियादी कार्यों के लिए पर्याप्त होता है।


धन्यवाद कि चाल चलेगा। इस चरण में MD5 क्यों पर्याप्त होगा, इसके लिए मेरा संपादन देखें।
स्क्वांक

6
इस नीचे IMO को वोट करें ताकि नीचे दिए गए अधिक सही उत्तर सामने आए।
एडम

4
0 के रूप में नीचे जवाब दिया है, पूरा नहीं किया है।
सोहेलअज़ीज़

नए जावा मानकों का उपयोग करने के लिए अपडेट किया गया है (के लिए: प्रत्येक,
स्ट्रिंगबर्ल

3
क्या कोई एंड्रॉइड ऑपरेटिंग सिस्टम है जो एमडी 5 लागू नहीं किया है (कारण फेंकने का NoSuchAlgorithmException)?
वीएसबी

49

स्वीकृत उत्तर Android 2.2 में मेरे लिए काम नहीं किया। मुझे पता नहीं क्यों, लेकिन यह मेरे कुछ शून्य (0) को "खा रहा था"। अपाचे कॉमन्स भी एंड्रॉइड 2.2 पर काम नहीं करते थे, क्योंकि यह उन तरीकों का उपयोग करता है जो केवल एंड्रॉइड 2.3.x से शुरू होने का समर्थन करते हैं। इसके अलावा, यदि आप एमडी 5 को एक स्ट्रिंग करना चाहते हैं, तो अपाचे कॉमन्स उसके लिए बहुत जटिल है। क्यों एक छोटे से समारोह का उपयोग करने के लिए एक पूरे पुस्तकालय रखना चाहिए ...

अंत में मुझे यहाँ निम्न कोड स्निपेट मिले जो मेरे लिए पूरी तरह से काम करते थे। मुझे उम्मीद है कि यह किसी के लिए उपयोगी होगा ...

public String MD5(String md5) {
   try {
        java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
        byte[] array = md.digest(md5.getBytes("UTF-8"));
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < array.length; ++i) {
          sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1,3));
       }
        return sb.toString();
    } catch (java.security.NoSuchAlgorithmException e) {
    } catch(UnsupportedEncodingException ex){
    }
    return null;
}

4
मेरे लिए काम किया। मैंने md5.getBytes ("UTF-8") बदल दिया है । मैंने इसके साथ जाँच की है: उपरोक्त कोड के साथ q4m'x68n6_YDB4ty8VC4 &} wqBtn ^ 68W , परिणाम 0c70bb931f03b75af1591f26beb7777d0b है , न कि c70bb931f03b75af1591f261b777 पर । 0 जगह पर है
Inoy

27

Androidsnippets.com कोड मज़बूती से काम नहीं करता है क्योंकि 0 परिणामी हैश से कट जाता है।

एक बेहतर कार्यान्वयन यहाँ है

public static String MD5_Hash(String s) {
    MessageDigest m = null;

    try {
            m = MessageDigest.getInstance("MD5");
    } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
    }

    m.update(s.getBytes(),0,s.length());
    String hash = new BigInteger(1, m.digest()).toString(16);
    return hash;
}

क्या "m" कभी भी इस मामले में Android पर शून्य हो सकता है?
Android डेवलपर

3
@androiddeveloper आप पूरी तरह से सही हैं। कैच ब्लॉक को यहां खराब तरीके से लागू किया गया है, रिटर्न स्टेटमेंट की आवश्यकता है या जब m.update कहा जाता है तो एक शून्य संदर्भ त्रुटि होगी। इसके अलावा, मुझे यकीन नहीं है, लेकिन जब तक यह व्यक्तिगत बाइट्स पर 0 पट्टी नहीं कर सकता है, मुझे लगता है कि यह अभी भी पूरे 32 चार हैश पर 0 अग्रणी हो सकता है। स्टर्लिंग (16) के बजाय मुझे लगता है कि स्ट्रिंग.फॉर्म ("% 032X", बिगआईंट) इरादा के अनुसार काम करता है। इसके अलावा आप चुन सकते हैं कि आप ऊपरी या निचले मामले में हेक्स चाहते हैं (निचले के लिए "% 032x")।
१६

1
यह संस्करण त्रुटिपूर्ण है। यदि आपका MD5 "0" से शुरू होता है, तो उत्पन्न MD5 में एक अग्रणी नहीं होगा 0. कृपया इस समाधान का उपयोग न करें।
एल्कसो

20

यदि Apache Commons Codec का उपयोग करना एक विकल्प है, तो यह एक छोटा कार्यान्वयन होगा:

String md5Hex = new String(Hex.encodeHex(DigestUtils.md5(data)));

या SHA:

String shaHex= new String(Hex.encodeHex(DigestUtils.sha("textToHash")));

ऊपर के लिए स्रोत

कृपया लिंक का अनुसरण करें और सही व्यक्ति को पुरस्कार देने के लिए उसके समाधान को बढ़ाएं।


मावेन रेपो लिंक: https://mvnrepository.com/artifact/commons-codec/commons-codec

वर्तमान मावेन निर्भरता (6 जुलाई 2016 तक):

<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.10</version>
</dependency>

1
किसी भी कारण से आप एपीआई के लिए एक बाहरी पुस्तकालय का उपयोग करेंगे जो पहले से ही मानक पुस्तकालय में मौजूद है?
m0skit0

12

DigestUtils का उपयोग करने के ऊपर एक समाधान मेरे लिए काम नहीं किया। अपाचे कॉमन्स के मेरे संस्करण में (2013 के लिए नवीनतम) ऐसा कोई वर्ग नहीं है।

मुझे यहाँ एक ब्लॉग में एक और समाधान मिला । यह सही काम करता है और अपाचे कॉमन्स की जरूरत नहीं है। ऊपर दिए गए स्वीकृत उत्तर में यह कोड की तुलना में थोड़ा छोटा है।

public static String getMd5Hash(String input) {
    try {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] messageDigest = md.digest(input.getBytes());
        BigInteger number = new BigInteger(1, messageDigest);
        String md5 = number.toString(16);

        while (md5.length() < 32)
            md5 = "0" + md5;

        return md5;
    } catch (NoSuchAlgorithmException e) {
        Log.e("MD5", e.getLocalizedMessage());
        return null;
    }
}

आपको इन आयातों की आवश्यकता होगी:

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

MD5 हैश जानने के लिए महत्वपूर्ण है 32 char लंबाई या उससे कम, धन्यवाद!
पेलेन्स

3
अंतिम कुछ पंक्तियों को संभवतः बस के साथ प्रतिस्थापित किया जा सकता है: रिटर्न स्ट्रिंग.फॉर्मैट ("% 032X", संख्या); वरना मुझे वास्तव में यह जवाब पसंद है।
१६

10

यह ऊपर एंड्रानिक और डेन डेलिमार्स्की के जवाबों की थोड़ी भिन्नता है, लेकिन यह थोड़ा अधिक संक्षिप्त है और इसके लिए किसी बिटवाइज़ तर्क की आवश्यकता नहीं है। इसके बजाय यह String.formatबाइट्स को दो वर्ण हेक्साडेसिमल स्ट्रिंग्स में परिवर्तित करने के लिए अंतर्निहित विधि का उपयोग करता है (0 पट्टी नहीं करता है)। आम तौर पर मैं सिर्फ उनके जवाब पर टिप्पणी करूंगा, लेकिन मेरे पास ऐसा करने के लिए प्रतिष्ठा नहीं है।

public static String md5(String input) {
    try {
        MessageDigest md = MessageDigest.getInstance("MD5");

        StringBuilder hexString = new StringBuilder();
        for (byte digestByte : md.digest(input.getBytes()))
            hexString.append(String.format("%02X", digestByte));

        return hexString.toString();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
        return null;
    }
}

यदि आप इसके बजाय कम केस स्ट्रिंग वापस करना चाहते हैं, तो बस बदल %02Xदें %02x

संपादित करें: बिगबेंजर का उपयोग करना जैसे wzbozon के उत्तर के साथ, आप उत्तर को और अधिक संक्षिप्त बना सकते हैं:

public static String md5(String input) {
    try {
        MessageDigest md = MessageDigest.getInstance("MD5");
        BigInteger md5Data = new BigInteger(1, md.digest(input.getBytes()));
        return String.Format("%032X", md5Data);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
        return null;
    }
}

4

मैंने कोटलिन में एक साधारण पुस्तकालय बनाया है।

Root build.gradle पर जोड़ें

allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }

App build.gradle पर

implementation 'com.github.1AboveAll:Hasher:-SNAPSHOT'

प्रयोग

कोटलिन में

val ob = Hasher()

तब उपयोग हैश () विधि

ob.hash("String_You_Want_To_Encode",Hasher.MD5)

ob.hash("String_You_Want_To_Encode",Hasher.SHA_1)

यह MD5 और SHA-1 को क्रमशः लौटाएगा।

लाइब्रेरी के बारे में अधिक

https://github.com/ihimanshurawat/Hasher


2

यहाँ @Andranik उत्तर से Kotlin संस्करण है। हम परिवर्तन करने की आवश्यकता है getBytesके लिए toByteArray(चारसेट UTF-8 को जोड़ने के लिए की वजह से डिफ़ॉल्ट चारसेट की जरूरत नहीं है toByteArrayऔर कलाकारों सरणी [i] पूर्णांक तक UTF-8 है)

fun String.md5(): String? {
    try {
        val md = MessageDigest.getInstance("MD5")
        val array = md.digest(this.toByteArray())
        val sb = StringBuffer()
        for (i in array.indices) {
            sb.append(Integer.toHexString(array[i].toInt() and 0xFF or 0x100).substring(1, 3))
        }
        return sb.toString()
    } catch (e: java.security.NoSuchAlgorithmException) {
    } catch (ex: UnsupportedEncodingException) {
    }
    return null
}

आशा है कि यह मदद करेगा


1

एमडी 5 थोड़ा पुराना है, एसएचए -1 एक बेहतर एल्गोरिदम है, यहां एक उदाहरण है

( इसके अलावा जब वे उस पोस्ट पर ध्यान देते हैं, तो जावा इस पर खुद को संभालता है, कोई एंड्रॉइड विशिष्ट कोड नहीं है। )


4
नहीं - मैं एमडी 5 के विकल्प नहीं चाहता था जब मैंने जनवरी 2011 (19 महीने पहले) में यह सवाल पूछा था और मुझे यकीन नहीं है कि आपको इस बिंदु पर मेरे सवाल का जवाब देने की आवश्यकता क्यों महसूस हुई।
स्क्वॉन्क

21
@Squonk मैंने जवाब दिया क्योंकि स्टैकओवरफ़्लो के पीछे सामान्य विचार है। तथ्य के कितने समय बाद तक, हमेशा उन लोगों के लिए बेहतर उत्तर प्राप्त करने का प्रयास करें जो बाद में प्रश्न में आ सकते हैं। SHA-1 का सुझाव देने के लिए, मेरे लिए यह जानने का कोई तरीका नहीं था कि आप विशेष रूप से SHA-1 के खिलाफ थे, लेकिन कई अन्य नहीं होंगे, इसलिए, यह भविष्य में अन्य लोगों की मदद कर सकता है जो इस पार आते हैं, और उन्हें निर्देशित करते हैं एक और अधिक आधुनिक एल्गोरिथ्म के लिए।
एडम

3
मैं एक भी स्थिति के बारे में नहीं सोच सकता जहाँ एमडी 5 एक बुरा विकल्प है लेकिन SHA1 एक अच्छा है। यदि आपको टकराव प्रतिरोध की आवश्यकता है, तो आपको SHA2 की आवश्यकता है SHA1 नहीं। अगर आपके पास पासवर्ड है, तो आपको bcrypt या PBKDF2 चाहिए। या ओपी के मामले में उचित समाधान संभवतः एसएसएल है।
कोडइन्चौट्स

3
@ एडम यह एक जवाब नहीं है यह एक टिप्पणी है।
अंजी

1

हमारे एमवीसी एप्लिकेशन में हम लंबे समय के लिए उत्पन्न करते हैं

using System.Security.Cryptography;
using System.Text;
    ...
    public static string getMD5(long id)
    {
        // convert
        string result = (id ^ long.MaxValue).ToString("X") + "-ANY-TEXT";
        using (MD5 md5Hash = MD5.Create())
        {
            // Convert the input string to a byte array and compute the hash. 
            byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(result));

            // Create a new Stringbuilder to collect the bytes and create a string.
            StringBuilder sBuilder = new StringBuilder();
            for (int i = 0; i < data.Length; i++)
                sBuilder.Append(data[i].ToString("x2"));

            // Return the hexadecimal string. 
            result = sBuilder.ToString().ToUpper();
        }

        return result;
    }

और एंड्रॉइड एप्लिकेशन में भी ऐसा ही है (तब एंड्रानिक की मदद करता है)

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
...
public String getIdHash(long id){
    String hash = null;
    long intId = id ^ Long.MAX_VALUE;
    String md5 = String.format("%X-ANY-TEXT", intId);
    try {
        MessageDigest md = java.security.MessageDigest.getInstance("MD5");
        byte[] arr = md.digest(md5.getBytes());
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < arr.length; ++i)
            sb.append(Integer.toHexString((arr[i] & 0xFF) | 0x100).substring(1,3));

        hash = sb.toString();
    } catch (NoSuchAlgorithmException e) {
        Log.e("MD5", e.getMessage());
    }

    return hash.toUpperCase();
}

1

मैंने स्ट्रिंग को पास करके मुझे md5 देने के लिए नीचे विधि का उपयोग किया है जिसके लिए आप md5 प्राप्त करना चाहते हैं

public static String getMd5Key(String password) {

//        String password = "12131123984335";

        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(password.getBytes());

            byte byteData[] = md.digest();

            //convert the byte to hex format method 1
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < byteData.length; i++) {
                sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
            }

            System.out.println("Digest(in hex format):: " + sb.toString());

            //convert the byte to hex format method 2
            StringBuffer hexString = new StringBuffer();
            for (int i = 0; i < byteData.length; i++) {
                String hex = Integer.toHexString(0xff & byteData[i]);
                if (hex.length() == 1) hexString.append('0');
                hexString.append(hex);
            }
            System.out.println("Digest(in hex format):: " + hexString.toString());

            return hexString.toString();

        } catch (Exception e) {
            // TODO: handle exception
        }

        return "";
}

1

कृपया SHA-512 का उपयोग करें, MD5 असुरक्षित है

public static String getSHA512SecurePassword(String passwordToHash) {
    String generatedPassword = null;
    try {
        MessageDigest md = MessageDigest.getInstance("SHA-512");
        md.update("everybreathyoutake".getBytes());
        byte[] bytes = md.digest(passwordToHash.getBytes());
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
        }
        generatedPassword = sb.toString();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return generatedPassword;
}

0

बहुत दूर तक बेकार टॉक्स () रूपांतरण अन्य सुझावों में निहित है, वास्तव में।

private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();

public static String md5string(String s) {
    return toHex(md5plain(s));
}

public static byte[] md5plain(String s) {
    final String MD5 = "MD5";
    try {
        // Create MD5 Hash
        MessageDigest digest = java.security.MessageDigest.getInstance(MD5);
        digest.update(s.getBytes());
        return digest.digest();
    } catch (NoSuchAlgorithmException e) {
        // never happens
        e.printStackTrace();
        return null;
    }
}

public static String toHex(byte[] buf) {
    char[] hexChars = new char[buf.length * 2];
    int v;
    for (int i = 0; i < buf.length; i++) {
        v = buf[i] & 0xFF;
        hexChars[i * 2] = HEX_ARRAY[v >>> 4];
        hexChars[i * 2 + 1] = HEX_ARRAY[v & 0x0F];
    }
    return new String(hexChars);
}

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

0

यह मेरे लिए पूरी तरह से काम कर रहा है, मैंने इसका उपयोग LIST Array पर MD5 प्राप्त करने के लिए किया (फिर इसे JSON ऑब्जेक्ट में कनवर्ट करें), लेकिन अगर आपको इसे केवल अपने डेटा पर लागू करना है। स्वरूप टाइप करें, JsonObject को अपने साथ बदलें।

विशेष रूप से यदि आपके पास अजगर MD5 कार्यान्वयन के साथ एक बेमेल है इसका उपयोग करें!

private static String md5(List<AccelerationSensor> sensor) {

    Gson gson= new Gson();
    byte[] JsonObject = new byte[0];
    try {
        JsonObject = gson.toJson(sensor).getBytes("UTF-8");
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }

    MessageDigest m = null;

    try {
        m = MessageDigest.getInstance("MD5");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }

    byte[] thedigest = m.digest(JsonObject);
    String hash = String.format("%032x", new BigInteger(1, thedigest));
    return hash;


}

-1

स्काला भाषा के लिए उपलब्ध समाधान (थोड़ा छोटा):

def getMd5(content: Array[Byte]) =
    try {
        val md = MessageDigest.getInstance("MD5")
        val bytes = md.digest(content)
        bytes.map(b => Integer.toHexString((b + 0x100) % 0x100)).mkString
    } catch {
        case ex: Throwable => null
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.