[android] Android의 MD5 해싱

간단한 C # HTTP 리스너와 ‘대화’해야하는 간단한 안드로이드 클라이언트가 있습니다. POST 요청에서 사용자 이름 / 암호를 전달하여 기본 수준의 인증을 제공하고 싶습니다.

MD5 해싱은 C #에서 사소하고 내 요구에 충분한 보안을 제공하지만 Android 쪽에서이 작업을 수행하는 방법을 찾을 수없는 것 같습니다.

편집 : MD5 약점에 대해 제기 된 문제를 해결하기 위해 C # 서버는 내 안드로이드 클라이언트 사용자의 PC에서 실행됩니다. 대부분의 경우 그들은 자신의 LAN에서 Wi-Fi를 사용하여 서버에 액세스하지만 자신의 책임하에 인터넷에서 액세스하도록 선택할 수 있습니다. 또한 서버의 서비스는 내가 제어 할 수없는 타사 응용 프로그램에 대한 MD5 패스 스루를 사용해야합니다.



답변

여기에 – 당신이 사용할 수있는 구현입니다 (날짜 Java 규약에 더 많은 최대 사용하도록 업데이트 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 "";
}

기본 보안 수준 (MD5 는 손상된 것으로 간주되고 쉽게 악용 될 수 있음 ) 까지 포함하는 시스템에는 권장되지 않지만 때로는 기본 작업에 충분합니다.


답변

받아 들인 대답은 Android 2.2에서 작동하지 않았습니다. 이유는 모르겠지만 제로 (0)의 일부를 “먹고”있었습니다.
Apache commons 는 Android 2.3.x부터 만 지원되는 메서드를 사용하기 때문에 Android 2.2에서도 작동하지 않았습니다. 또한 MD5 문자열을 원한다면 Apache commons는 너무 복잡합니다. 작은 기능 만 사용하기 위해 전체 라이브러리를 유지해야하는 이유 …

마지막으로 여기 에서 완벽하게 작동 하는 다음 코드 스 니펫을 찾았 습니다. 누군가에게 도움이 되길 바랍니다 …

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;
}


답변

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;
}


답변

Apache Commons Codec을 사용하는 것이 옵션 인 경우 구현이 더 짧습니다.

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

또는 SHA :

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

위의 출처 .

링크를 따라 그의 솔루션을 찬성하여 올바른 사람을 선정하십시오.


Maven 저장소 링크 : https://mvnrepository.com/artifact/commons-codec/commons-codec

현재 Maven 종속성 (2016 년 7 월 6 일 기준) :

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


답변

DigestUtils를 사용하는 위의 솔루션은 저에게 효과적이지 않았습니다. 내 버전의 Apache commons (2013 년 최신 버전)에는 그러한 클래스가 없습니다.

여기 한 블로그에서 또 다른 해결책을 찾았습니다 . 완벽하게 작동하며 Apache commons가 필요하지 않습니다. 위의 답변에 나온 코드보다 약간 짧아 보입니다.

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;


답변

이것은 위의 Andranik 및 Den Delimarsky 답변의 약간 변형이지만 조금 더 간결하고 비트 논리가 필요하지 않습니다. 대신 내장 String.format메서드를 사용하여 바이트를 두 문자 16 진수 문자열로 변환합니다 (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의 답변과 같이 BigInteger를 사용하면 답변을 더욱 간결하게 만들 수 있습니다.

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;
    }
}


답변

Kotlin에서 간단한 라이브러리를 만들었습니다.

루트 build.gradle에 추가

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

App build.gradle에서

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

용법

Kotlin에서

val ob = Hasher()

그런 다음 hash () 메서드 사용

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