web-dev-qa-db-ja.com

AndroidのMD5ハッシュ

単純なAndroidクライアントがあり、単純なC#HTTPリスナーと「通信」する必要があります。 POSTリクエストでユーザー名/パスワードを渡すことにより、基本レベルの認証を提供したいと思います。

MD5ハッシュはC#では簡単であり、私のニーズに十分なセキュリティを提供しますが、Androidの最後でこれを行う方法を見つけることができないようです。

編集:MD5の弱点について提起された懸念に対処するために、C#サーバーはAndroidクライアントのユーザーのPC上で実行されます。多くの場合、彼らは自分のLANでwi-fiを使用してサーバーにアクセスしますが、自分のリスクでインターネットからアクセスすることを選択する場合があります。また、サーバー上のサービスは、私が制御できないサードパーティアプリケーションへのMD5のパススルーを使用する必要があります。

86
Squonk

ここ は使用可能な実装です(最新のJava規則を使用するように更新されました-for:eachループ、StringBuilderの代わりにStringBuffer ):

public static final 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 壊れていると見なされ、簡単に悪用される可能性があります )、基本的なタスクには十分な場合があります。

210
Den Delimarsky

Android 2.2では、受け入れられた回答が機能しませんでした。理由はわかりませんが、ゼロ(0)の一部を「食べて」いました。 Apache commonsもAndroid 2.2で動作しませんでした。これはAndroid 2.3以降でのみサポートされるメソッドを使用するためです。バツ。また、文字列をMD5だけにしたい場合は、Apache commonsは複雑すぎます。ライブラリから小さな関数を使用するためにライブラリ全体を保持する必要がある理由...

最後に、次のコードスニペット here を見つけました。私はそれが誰かに役立つことを願っています...

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

Androidsnippets.comのコードは、0が結果のハッシュから切り取られているように見えるため、確実に機能しません。

より良い実装は here です。

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

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>
18
tbraun

DigestUtilsを使用した上記のソリューションは、私にとってはうまくいきませんでした。私のバージョンのApache commons(2013年の最新バージョン)には、そのようなクラスはありません。

私は別の解決策を見つけました ここで1つのブログで 。それは完璧に動作し、Apacheコモンを必要としません。上記の受け入れられた回答のコードよりも少し短く見えます。

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;
11
wzbozon

これは、上記のAndranikとDen Delimarskyの回答のわずかなバリエーションですが、もう少し簡潔で、ビット単位のロジックを必要としません。代わりに、組み込みのString.formatメソッドを使用して、バイトを2文字の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;
    }
}
9
rsimp

Kotlinで簡単なライブラリを作成しました。

ルートで追加build.gradle

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

app build.gradleで

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

使用法

コトリンで

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/1AboveAll/Hasher

3
Himanshu Rawat

MVCアプリケーションでは、長いパラメーターを生成します

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

Androidアプリケーションでも同じです(その後Andranikに役立ちます)

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
Oleg Grabets

私はあなたが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

本当に無駄なtoHex()変換は、他の提案にも行き渡っています。

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);
}
0
Gena Batsyan

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

これは、@ Andranikの回答からのKotlinバージョンです。 getBytestoByteArrayに変更する必要があり(toByteArrayのデフォルトの文字セットはUTF-8であるため、文字セットUTF-8を追加する必要はありません)、array [i]を整数にキャストします

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
}

お役に立てば幸いです

0
Phan Van Linh

MD5は少し古く、SHA-1はより良いアルゴリズムです ここに例があります

また、彼らがその投稿で言及しているように、Javaはこれを独自に処理し、Android固有のコードはありません。

0
Adam

これは私にとって完璧に機能しています。これを使用してLIST配列でMD5を取得し(それをJSONオブジェクトに変換します)、データに適用するだけでよい場合。形式を入力し、JsonObjectをyoursに置き換えます。

特に、python 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;


}
0
mehran