ฉันจะสร้างแฮช MD5 ได้อย่างไร


1007

มีวิธีใดในการสร้าง MD5 hash ของสตริงใน Java?



40
MD5 อาจไม่ปลอดภัยเป็นคุณลักษณะความปลอดภัยทางเดียว แต่ก็ยังดีสำหรับแอปพลิเคชันตรวจสอบทั่วไป
rustyx

คุณอาจลองใน php แก้ไขได้ง่ายมาก
Anupam Haldkar

คำตอบ:


602

java.security.MessageDigestคุณจำเป็นต้อง

โทรMessageDigest.getInstance("MD5")เพื่อรับอินสแตนซ์ MD5 ของMessageDigestคุณสามารถใช้ได้

คำนวณแฮชโดยทำหนึ่งใน:

  • ฟีดอินพุตทั้งหมดเป็นbyte[]และคำนวณแฮชในหนึ่งการดำเนินการด้วยmd.digest(bytes)และคำนวณกัญชาในการดำเนินการกับ
  • ฟีดMessageDigestหนึ่งอันในเวลาโดยการเรียกbyte[] เมื่อคุณทำเสร็จเพิ่มไบต์การป้อนข้อมูลการคำนวณกัญชาด้วยmd.update(bytes) md.digest()

byte[]กลับโดยmd.digest()เป็นกัญชา MD5


144
สิ่งหนึ่งที่ไม่ได้กล่าวถึงที่นี่และจับฉันด้วยความประหลาดใจ คลาส MessageDigest ไม่ได้เป็นเธรดที่ปลอดภัย หากพวกเขาจะถูกใช้โดยเธรดที่แตกต่างกันเพียงแค่สร้างเธรดใหม่แทนที่จะพยายามใช้ซ้ำ
mjuarez

39
มันใช้หลายวิธีในการกลายพันธุ์สถานะภายใน การขาดความปลอดภัยของด้ายจะน่าแปลกใจได้อย่างไร?
Bombe

90
@Bombe: ทำไมเราคาดว่าจะต้องรู้เกี่ยวกับสถานะภายในของ MessageDigest?
Dan Barowy

28
@DanBarowy ดีคุณกำลังกลายพันธุ์ (เช่นวิธีการโทรที่ไม่ส่งคืนค่า แต่เป็นสาเหตุให้วิธีอื่นคืนค่าที่แตกต่างกัน) ดังนั้นจนกว่าจะได้รับการพิสูจน์แล้วมิฉะนั้นคุณควรสมมติว่าไม่ปลอดภัยสำหรับเธรด
Bombe

3
@ Traubenfuchs MessageDigestให้คุณป้อนข้อมูลเป็นกลุ่ม ที่เป็นไปไม่ได้ด้วยวิธีการคงที่ แม้ว่าคุณจะสามารถโต้แย้งได้ว่าพวกเขาควรจะเพิ่มหนึ่งเพื่อความสะดวกเมื่อคุณสามารถส่งข้อมูลทั้งหมดในครั้งเดียว
user253751

690

MessageDigestระดับสามารถให้คุณมีตัวอย่างของ MD5 ย่อย

เมื่อทำงานร่วมกับสตริงและเรียนการเข้ารหัสลับให้แน่ใจว่าจะเสมอระบุการเข้ารหัสที่คุณต้องการเป็นตัวแทนไบต์ใน. หากคุณเพียงแค่ใช้string.getBytes()มันจะใช้ค่าเริ่มต้นแพลตฟอร์ม (ไม่ใช่ทุกแพลตฟอร์มที่ใช้ค่าเริ่มต้นเดียวกัน)

import java.security.*;

..

byte[] bytesOfMessage = yourString.getBytes("UTF-8");

MessageDigest md = MessageDigest.getInstance("MD5");
byte[] thedigest = md.digest(bytesOfMessage);

หากคุณมีข้อมูลจำนวนมากลองดู.update(byte[])วิธีการที่สามารถเรียกซ้ำ ๆ ได้ จากนั้นโทร.digest()เพื่อรับแฮชที่ได้


“ LATIN1”! =“ ASCII” (หรือ“ US-ASCII”) ASCII เป็นชุดอักขระ 7 บิต Latin1 เป็นชุดอักขระ 8 บิต พวกเขาไม่เหมือนกัน
Bombe

8
(ดูjoelonsoftware.com/articles/Unicode.htmlเพื่อเหตุผลและคำอธิบายที่ดียิ่งขึ้น)
Piskvor ออกจากอาคาร

14
หัวข้อนี้ยังมีประโยชน์หากคุณต้องการแปลงไบต์ผลลัพธ์เป็นสตริงฐานสิบหก
สัปดาห์ที่

1
แล้วคุณจะแปลงความน่าสนใจนี้เป็นสตริงเพื่อให้เราสามารถแทรกลงใน mysql ได้อย่างไร?
Humphrey

2
yourString.getBytes(StandardCharsets.UTF_8)ยังดีกว่าที่ใช้เป็นไปได้ UnsupportedEncodingExceptionจัดการป้องกันไม่ให้นี้
Hummeling Engineering BV

267

หากคุณต้องการคำตอบกลับเป็นสตริงแทนที่จะเป็นอาร์เรย์ไบต์คุณสามารถทำสิ่งนี้ได้เสมอ:

String plaintext = "your text here";
MessageDigest m = MessageDigest.getInstance("MD5");
m.reset();
m.update(plaintext.getBytes());
byte[] digest = m.digest();
BigInteger bigInt = new BigInteger(1,digest);
String hashtext = bigInt.toString(16);
// Now we need to zero pad it if you actually want the full 32 chars.
while(hashtext.length() < 32 ){
  hashtext = "0"+hashtext;
}

12
@BalusC: ไม่เป็นความจริงเมธอด BigInteger.toString จะส่งคืนหมายเลขเต็มในฐานที่ระบุ 0x0606 จะถูกพิมพ์เป็น 606 เพียงละเว้นค่าศูนย์ต่อท้าย
Spidey

11
nitpick เล็กน้อย: m.reset () ไม่จำเป็นหลังจากโทรหา getInstance ผู้เยาว์เพิ่มเติม: 'ข้อความของคุณที่นี่' ต้องใช้เครื่องหมายคำพูดคู่
David Leppik

จาก Java 11 on คุณสามารถใช้hashtext = "0".repeat(32 - hashtext.length()) + hashtextแทนwhileดังนั้นผู้แก้ไขจะไม่เตือนคุณว่าคุณกำลังเชื่อมต่อสตริงภายในลูป
ทอม

แทน m.update (plaintext.getBytes ()); ฉันขอแนะนำให้ระบุการเข้ารหัส เช่น m.update (plaintext.getBytes ("UTF-8")); getBytes () ไม่รับประกันการเข้ารหัสและอาจแตกต่างกันไปตามระบบซึ่งอาจส่งผลให้ผลลัพธ์ MD5 ที่แตกต่างกันระหว่างระบบสำหรับ String เดียวกัน
user1819780

256

คุณอาจต้องการดูคลาสDigestUtilsของ apache commons codec project ซึ่งให้วิธีการที่สะดวกมากในการสร้าง MD5 หรือ SHA digests


2
โดยเฉพาะอย่างยิ่งวิธีการที่ส่งกลับการแสดงที่เข้ารหัส "ปลอดภัย" ของข้อมูลไบต์ในรูปแบบสตริง
Rob

4
อย่างไรก็ตามไม่มีวิธีง่ายๆในการทำให้คลาส DigestUtils เข้าในโครงการของคุณโดยไม่ต้องเพิ่ม libs จำนวนมากหรือทำการย้ายคลาส "ต่อมือ" ซึ่งต้องมีคลาสเพิ่มอีกอย่างน้อยสองคลาส
iuiz

ไม่สามารถหาได้ใน maven repos เช่นกัน Grrrr
sparkyspider

5
ควรอยู่ในที่เก็บ Maven กลางเว้นแต่ว่าฉันจะบ้า: groupId = commons-codec artifactId = commons-codec version = 1.5
Nick Spacek

160

พบสิ่งนี้:

public String MD5(String md5) {
   try {
        java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
        byte[] array = md.digest(md5.getBytes());
        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) {
    }
    return null;
}

บนเว็บไซต์ด้านล่างฉันไม่ได้รับเครดิต แต่เป็นวิธีแก้ปัญหาที่ใช้งานได้! สำหรับฉันรหัสอื่น ๆ จำนวนมากทำงานไม่ถูกต้องฉันลงเอยด้วยการขาด 0s ในแฮช อันนี้ดูเหมือนจะเหมือนกับ PHP ที่มีอยู่ แหล่งที่มา: http://m2tec.be/blog/2010/02/03/java-md5-hex-0093


15
คุณควรระบุการเข้ารหัสที่จะใช้getBytes()มิฉะนั้นรหัสของคุณจะได้รับผลลัพธ์ที่แตกต่างกันในการตั้งค่าแพลตฟอร์ม / ผู้ใช้ที่แตกต่างกัน
Paŭlo Ebermann

@ PaŭloEbermannทำ MessageDigest.getInstance ("MD5"); ไม่พอ? ฉันพยายามที่จะเพิ่ม "MD5" ใน getBytes () แต่มันกลับข้อผิดพลาด
Blaze Tama

2
@BlazeTama "MD5" ไม่ใช่การเข้ารหัสมันเป็นอัลกอริธึมย่อยข้อความ (และไม่ใช่อันที่ควรใช้ในแอปพลิเคชันใหม่) การเข้ารหัสเป็นคู่อัลกอริทึมที่แปลงไบต์เป็นสตริงและสตริงเป็นไบต์ ตัวอย่างจะเป็น "UTF-8", "US-ASCII", "ISO-8859-1", "UTF-16BE" และที่คล้ายกัน ใช้การเข้ารหัสเช่นเดียวกับทุกฝ่ายที่คำนวณแฮชของสตริงนี้มิฉะนั้นคุณจะได้ผลลัพธ์ที่แตกต่างกัน
Paŭlo Ebermann

6
สำหรับตัวอย่างของชุดอักขระ ... (ใช้ UTF-8 ที่ดีที่สุดและเข้ากันได้มากที่สุดในความคิดของฉัน) ...byte[] array = md.digest(md5.getBytes(Charset.forName("UTF-8")));
Richard Richard

เนื่องจากมันไม่ใช่ทางออกของฉันและฉันไม่ได้ทดสอบทุกสถานการณ์ด้วยตัวเองฉันจะปล่อยให้มันไม่เปลี่ยนแปลงแม้ว่าฉันคิดว่าการเข้ารหัสแบบเจาะจงจะเป็นความคิดที่ดี
dac2009

88

นี่คือวิธีที่ฉันใช้:

final MessageDigest messageDigest = MessageDigest.getInstance("MD5");
messageDigest.reset();
messageDigest.update(string.getBytes(Charset.forName("UTF8")));
final byte[] resultByte = messageDigest.digest();
final String result = new String(Hex.encodeHex(resultByte));

ที่ซวยคือorg.apache.commons.codec.binary.Hexจากโครงการ Apache คอมมอนส์


14
หากคุณใช้ Apache Commons Codec อยู่ดีคุณสามารถใช้: commons.apache.org/codec/api-release/org/apache/commons/codec/ …
squiddle

13
ฉันจะแทนที่บรรทัดสุดท้ายด้วยสิ่งนี้:String result = Hex.encodeHexString(resultByte);
สีน้ำเงิน

84

ฉันเพิ่งดาวน์โหลดcommons-codec.jarและได้ php ที่สมบูรณ์แบบเช่น md5 นี่คือคู่มือ

เพียงนำเข้าสู่โครงการของคุณและใช้

String Url = "your_url";

System.out.println( DigestUtils.md5Hex( Url ) );

และที่นั่นคุณมีมัน


1
นี่คือวิธีการที่ให้ผลตอบแทนเช่นเดียวกับฟังก์ชั่น MySQL md5 (str) คำตอบอื่น ๆ จำนวนมากได้คืนค่าอื่น ๆ
rwitzel

1
สิ่งนี้ใช้ไม่ได้บน Android เนื่องจากชุดรวมของ Android Commons-codec 1.2 ซึ่งคุณต้องการวิธีแก้ปัญหานี้: stackoverflow.com/a/9284092/2413303
EpicPandaForce

76

ฉันพบสิ่งนี้เป็นวิธีที่ชัดเจนและรัดกุมที่สุดในการทำ:

MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(StandardCharsets.UTF_8.encode(string));
return String.format("%032x", new BigInteger(1, md5.digest()));

3
ยิ่งใหญ่ ไม่ตกหลุมพรางของการตัดศูนย์นำหน้า
Markus Pscheidt

2
ระวังสิ่งนี้จะไม่ทำงานสำหรับ Android หากคุณใช้ระดับ API <19 แต่คุณต้องเปลี่ยนบรรทัดที่สองด้วย md5.update (string.getBytes ("UTF-8")); สิ่งนี้จะเพิ่มอีกหนึ่งข้อยกเว้นที่ได้รับการตรวจสอบเพื่อจัดการแม้ว่า ...
Fran Marzoa

34

พบโซลูชันนี้ซึ่งมีความสะอาดกว่ามากในแง่ของการได้รับการแสดง String กลับจากแฮช MD5

import java.security.*;
import java.math.*;

public class MD5 {
    public static void main(String args[]) throws Exception{
        String s="This is a test";
        MessageDigest m=MessageDigest.getInstance("MD5");
        m.update(s.getBytes(),0,s.length());
        System.out.println("MD5: "+new BigInteger(1,m.digest()).toString(16));
    }
}

รหัสถูกสกัดจากที่นี่


2
ทำไมคำตอบนี้ถึง -1 ในขณะที่คำตอบอื่น ๆ ที่สั้นกว่าและน้อยกว่านั้นมี +146
Nilzor

4
ใช้ BigInteger เพื่อรับค่าฐานสิบหก +1
Dave.B

5
ฉันเพิ่งพบว่าในบางกรณีนี้เพียงสร้างผลรวม MD5 ยาว 31 ตัวไม่ใช่ 32 เท่าที่ควรจะเป็น
kovica

3
@kovica นี้เป็นเพราะศูนย์เริ่มต้นถูกตัดถ้าฉันจำได้ถูกต้อง .. String.format("%032x", new BigInteger(1, hash)); นี่ควรแก้ปัญหานี้ 'hash' เป็นไบต์ [] ของ hash
Heshan Perera

คำตอบนี้มีข้อผิดพลาดประเภท charset!
Dawid Drozd

31

ตัวเลือกอื่นคือการใช้วิธีการล้างข้อมูลของ Guava :

Hasher hasher = Hashing.md5().newHasher();
hasher.putString("my string");
byte[] md5 = hasher.hash().asBytes();

มีประโยชน์ถ้าคุณใช้ Guava อยู่แล้ว (ซึ่งถ้าคุณไม่ใช่คุณก็ควรจะเป็น)


3
หรือใช้วิธีลัดอย่างใดอย่างหนึ่ง:Hashing.md5().hashString("my string").asBytes();
Kurt Alfred Kluever

4
@KurtAlfredKluever อย่าลืมใส่ชุดอักขระเช่น 'Hashing.md5 (). hashString ("สตริงของฉัน", Charsets.UTF_8) .asBytes ()'
Justin

31

การใช้งานอื่น:

import javax.xml.bind.DatatypeConverter;

String hash = DatatypeConverter.printHexBinary( 
           MessageDigest.getInstance("MD5").digest("SOMESTRING".getBytes("UTF-8")));

2
มีเพียงหนึ่งซับที่ฉันเห็นซึ่งไม่ได้ใช้ไลบรารี่ภายนอก
holmis83

นอกจากว่าฉันเข้าใจผิดว่าผลตอบแทนนี้จะเป็นตัวพิมพ์ใหญ่ซึ่งจะไม่สอดคล้องกับ md5 ที่สร้างขึ้นโดยไม่ใช้ hex ไม่แน่ใจจริงๆว่ามันจะเป็น md5 จริง
walshie4

2
@ walshie4 ไม่มี MD5 ที่ไม่มี hex (ดูietf.org/rfc/rfc1321.txt ) เพื่อให้เป็นตัวพิมพ์เล็กให้เพิ่ม. toLower () เปรียบเทียบผลลัพธ์กับตัวอย่างในen.wikipedia.org/wiki/MD5เช่นนั้นคุณจะมีโอกาสที่ดีกว่าที่จะเชื่อว่ารหัสไลบรารี Javas นั้นถูกต้อง
stacker

28

ฉันมีคลาส (แฮช) เพื่อแปลงข้อความธรรมดาเป็นแฮชในรูปแบบ: md5 หรือ sha1, simillar ที่ฟังก์ชัน php ( md5 , sha1 ):

public class Hash {
    /**
     * 
     * @param txt, text in plain format
     * @param hashType MD5 OR SHA1
     * @return hash in hashType 
     */
    public static String getHash(String txt, String hashType) {
        try {
                    java.security.MessageDigest md = java.security.MessageDigest.getInstance(hashType);
                    byte[] array = md.digest(txt.getBytes());
                    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) {
                //error action
            }
            return null;
    }

    public static String md5(String txt) {
        return Hash.getHash(txt, "MD5");
    }

    public static String sha1(String txt) {
        return Hash.getHash(txt, "SHA1");
    }
}

ทดสอบกับ JUnit และ PHP

สคริปต์ PHP:

<?php

echo 'MD5 :' . md5('Hello World') . "\n";
echo 'SHA1:' . sha1('Hello World') . "\n";

สคริปต์ PHP เอาท์พุท:

MD5 :b10a8db164e0754105b7a99be72e3fe5
SHA1:0a4d55a8d778e5022fab701977c5d840bbc486d0

ใช้ตัวอย่างและทดสอบกับ JUnit:

    public class HashTest {

    @Test
    public void test() {
        String txt = "Hello World";
        assertEquals("b10a8db164e0754105b7a99be72e3fe5", Hash.md5(txt));
        assertEquals("0a4d55a8d778e5022fab701977c5d840bbc486d0", Hash.sha1(txt));
    }

}

รหัสใน GitHub

https://github.com/fitorec/java-hashes


@CedricSimon พูดว่านั่นคือสิ่งที่ฉันกำลังมองหา โหวตขึ้นที่นี่ .. ขอบคุณ!
Joabe Lucena

24

ไม่จำเป็นต้องทำให้ซับซ้อนเกินไป
DigestUtilsทำงานได้ดีและทำให้คุณรู้สึกสะดวกสบายขณะทำงานกับmd5แฮช

DigestUtils.md5Hex(_hash);

หรือ

DigestUtils.md5(_hash);

ไม่ว่าคุณจะสามารถใช้วิธีการเข้ารหัสอื่น ๆ เช่นหรือshamd


22

คำตอบที่ไม่ค่อยเปิดเผยของฉัน:

private String md5(String s) {
    try {
        MessageDigest m = MessageDigest.getInstance("MD5");
        m.update(s.getBytes(), 0, s.length());
        BigInteger i = new BigInteger(1,m.digest());
        return String.format("%1$032x", i);         
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return null;
}

และString.format("%1$032X", big)มีรูปแบบตัวพิมพ์ใหญ่
อเล็กซ์

17

มีDigestUtilsชั้นเรียนในฤดูใบไม้ผลิด้วย:

http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/util/DigestUtils.html

ชั้นนี้มีวิธีmd5DigestAsHex()การทำงาน


BTW: ประสิทธิภาพของสิ่งนี้ดีกว่ามากแล้วใช้ BigInteger เพื่อสร้างการแสดงสตริง hex
James

17

คุณสามารถลองต่อไปนี้ ดูรายละเอียดและรหัสดาวน์โหลดได้ที่นี่: http://jkssweetlife.com/java-hashgenerator-md5-sha-1/

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MD5Example {

public static void main(String[] args) throws Exception {

    final String inputString = "Hello MD5";

    System.out.println("MD5 hex for '" + inputString + "' :");
    System.out.println(getMD5Hex(inputString));
}

public static String getMD5Hex(final String inputString) throws NoSuchAlgorithmException {

    MessageDigest md = MessageDigest.getInstance("MD5");
    md.update(inputString.getBytes());

    byte[] digest = md.digest();

    return convertByteToHex(digest);
}

private static String convertByteToHex(byte[] byteData) {

    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < byteData.length; i++) {
        sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
    }

    return sb.toString();
}
}

16

คำตอบของ Bombe นั้นถูกต้องอย่างไรก็ตามโปรดทราบว่าหากคุณไม่จำเป็นต้องใช้ MD5 (เช่นบังคับให้คุณใช้งานร่วมกันได้) ทางเลือกที่ดีกว่าคือ SHA1 เนื่องจาก MD5 มีจุดอ่อนสำหรับการใช้งานระยะยาว

ฉันควรเพิ่มว่า SHA1 ยังมีช่องโหว่ทางทฤษฎี แต่ไม่รุนแรงเหมือนกัน สถานะปัจจุบันของศิลปะในการแปลงแป้นพิมพ์คือมีฟังก์ชันแฮชแทนจำนวนมาก แต่ยังไม่มีวิธีปฏิบัติที่ดีที่สุดในการแทนที่ SHA1 ดังนั้นขึ้นอยู่กับความต้องการของคุณคุณจะได้รับคำแนะนำที่ดีในการกำหนดอัลกอริทึมแฮชของคุณเพื่อให้สามารถเปลี่ยนได้ในอนาคต


คุณช่วยชี้ให้ฉันดูทรัพยากรบางอย่างที่ฉันสามารถอ่านเกี่ยวกับข้อดีและข้อเสียของแต่ละรายการได้หรือไม่
Akshay

อาจเป็นสิ่งที่ดีที่สุดที่คุณสามารถทำได้ในขณะนี้คือใช้ SHA1 และพร้อมที่จะเปลี่ยนในอนาคต คุณสามารถใช้ฟังก์ชั่นที่ใหม่กว่า แต่ยังไม่ได้รับการวิจัยจำนวนมาก คุณสามารถติดตามแหล่งข้อมูลความปลอดภัยออนไลน์เพื่อดูว่ามีการเปลี่ยนแปลงเช่นบล็อกของ Bruce Schneier
frankodwyer

7
SHA1 overkill เว้นแต่ว่าคุณต้องการแฮชที่เข้ารหัสลับนั่นคือคุณไม่ต้องการแฮชที่จะช่วยในการสร้างข้อความต้นฉบับขึ้นมาใหม่และคุณไม่ต้องการให้ผู้โจมตีที่ชาญฉลาดสร้างข้อความใหม่ที่ตรงกับแฮช หากต้นฉบับไม่ใช่ความลับและไม่ใช้แฮชเพื่อความปลอดภัย MD5 นั้นรวดเร็วและง่ายดาย ตัวอย่างเช่น Google Web Toolkit ใช้ MD5 hash ใน JavaScript URL (เช่น foo.js? hash = 12345)
David Leppik

12

การใช้งานอื่น: การดำเนินการอย่างรวดเร็วของ MD5 ใน Java

String hash = MD5.asHex(MD5.getHash(new File(filename)));

1
นี่เป็นไลบรารี่แบบสแตนด์อโลนที่มีการพึ่งพาน้อยที่สุด สิ่งที่ดี.
Ajax

ฉันพบว่ามันมีประโยชน์มาก ใช้เวลา 15357 มิลลิวินาทีสำหรับไฟล์ 4.57GB ในขณะที่การใช้งาน inbuilt ของจาวาใช้เวลา 19094 มิลลิวินาที
bkrish

11

ฉันไม่ทราบว่าสิ่งนี้เกี่ยวข้องกับใครก็ตามที่อ่านข้อความนี้หรือไม่ แต่ฉันเพิ่งมีปัญหาที่ฉันต้องการ

  • ดาวน์โหลดไฟล์จาก URL ที่กำหนดและ
  • เปรียบเทียบ MD5 กับค่าที่ทราบ

ฉันต้องการที่จะทำกับชั้นเรียน JRE เท่านั้น (ไม่มี Apache Commons หรือคล้ายกัน) การค้นหาเว็บอย่างรวดเร็วไม่ได้แสดงตัวอย่างโค้ดที่ทำทั้งสองอย่างในเวลาเดียวกันโดยแยกเฉพาะแต่ละงาน เนื่องจากสิ่งนี้ต้องการอ่านไฟล์เดียวกันสองครั้งฉันคิดว่ามันอาจจะคุ้มค่าในขณะที่เขียนโค้ดซึ่งรวมทั้งงานทั้งสองคำนวณการตรวจสอบการทำงานของไฟล์ในขณะที่ดาวน์โหลดไฟล์ นี่คือผลลัพธ์ของฉัน (ขออภัยถ้ามันไม่ได้เป็นจาวาที่สมบูรณ์แบบ แต่ฉันคิดว่าคุณจะได้รับความคิดต่อไป):

import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.security.DigestOutputStream;        // new
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

void downloadFile(String fromURL, String toFile, BigInteger md5)
    throws IOException, NoSuchAlgorithmException
{
    ReadableByteChannel in = Channels.newChannel(new URL(fromURL).openStream());
    MessageDigest md5Digest = MessageDigest.getInstance("MD5");
    WritableByteChannel out = Channels.newChannel(
        //new FileOutputStream(toFile));  // old
        new DigestOutputStream(new FileOutputStream(toFile), md5Digest));  // new
    ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024);  // 1 MB

    while (in.read(buffer) != -1) {
        buffer.flip();
        //md5Digest.update(buffer.asReadOnlyBuffer());  // old
        out.write(buffer);
        buffer.clear();
    }

    BigInteger md5Actual = new BigInteger(1, md5Digest.digest()); 
    if (! md5Actual.equals(md5))
        throw new RuntimeException(
            "MD5 mismatch for file " + toFile +
            ": expected " + md5.toString(16) +
            ", got " + md5Actual.toString(16)
        );
}

1
โอ้ BTW ก่อนที่ทุกคนยกเว้นตัวเองสังเกตเห็นว่าไม่ดีความรู้ JRE ของฉันจริงๆคือ: ผมเพิ่งค้นพบDigestInputStreamและDigestOutputStream ฉันจะแก้ไขคำตอบดั้งเดิมของฉันเพื่อสะท้อนสิ่งที่ฉันเพิ่งเรียนรู้
kriegaex

6

ลองดูที่ลิงค์ต่อไปนี้ตัวอย่างได้รับ MD5 Hash ของภาพที่ให้มา: MD5 Hash ของรูปภาพ


6

สำหรับสิ่งที่คุ้มค่าฉันสะดุดกับสิ่งนี้เพราะฉันต้องการสังเคราะห์ GUID จากคีย์ธรรมชาติสำหรับโปรแกรมที่จะติดตั้งคอมโพเนนต์ COM; ฉันต้องการ syhthesize เพื่อที่จะไม่จัดการวงจรชีวิตของ GUID ฉันจะใช้ MD5 แล้วใช้คลาส UUID เพื่อดึงสตริงออกมา (http://stackoverflow.com/questions/2190890/how-can-i-generate-guid-for-a-string-values/12867439 ทำให้เกิดปัญหานี้ขึ้น)

ไม่ว่าในกรณีใด java.util.UUID สามารถรับสตริงที่ดีจาก MD5 ไบต์

return UUID.nameUUIDFromBytes(md5Bytes).toString();

ที่จริงแล้วมันไม่เพียง แต่ยอมรับอาร์เรย์ MD5 ไบต์เท่านั้น (ขนาด == 16) คุณสามารถผ่านอาร์เรย์ไบต์ที่มีความยาวเท่าใดก็ได้ มันจะถูกแปลงเป็นอาร์เรย์ MD5 ไบต์โดยใช้ MD5 MessageDigest(ดูซอร์สโค้ด nameUUIDFromBytes () )
Lu55

6
import java.security.*;
import javax.xml.bind.*;

byte[] bytesOfMessage = yourString.getBytes("UTF-8");
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] bytesOfDigest = md.digest(bytesOfMessage);
String digest = DatatypeConverter.printHexBinary(bytesOfDigest).toLowerCase();

6

ซึ่งแตกต่างจาก PHP ที่คุณสามารถทำ MD5 hashing ข้อความของคุณโดยเพียงแค่เรียกฟังก์ชั่น md5 เช่นmd5($text)ใน Java มันมีความซับซ้อนเล็กน้อย ฉันมักจะใช้มันโดยการเรียกฟังก์ชั่นซึ่งจะส่งกลับข้อความแฮช md5 นี่คือวิธีที่ฉันใช้มันขั้นแรกสร้างฟังก์ชั่นที่มีชื่อmd5hashingในคลาสหลักของคุณตามที่ระบุด้านล่าง

public static String md5hashing(String text)
    {   String hashtext = null;
        try 
        {
            String plaintext = text;
            MessageDigest m = MessageDigest.getInstance("MD5");
            m.reset();
            m.update(plaintext.getBytes());
            byte[] digest = m.digest();
            BigInteger bigInt = new BigInteger(1,digest);
            hashtext = bigInt.toString(16);
            // Now we need to zero pad it if you actually want the full 32 chars.
            while(hashtext.length() < 32 ){
              hashtext = "0"+hashtext;   
            }
        } catch (Exception e1) 
        {
            // TODO: handle exception
            JOptionPane.showMessageDialog(null,e1.getClass().getName() + ": " + e1.getMessage());   
        }
        return hashtext;     
    }

ตอนนี้เรียกใช้ฟังก์ชั่นเมื่อใดก็ตามที่คุณต้องการตามที่ระบุด้านล่าง

String text = textFieldName.getText();
String pass = md5hashing(text);

ที่นี่คุณจะเห็นว่า hashtext ต่อท้ายด้วยศูนย์เพื่อให้ตรงกับ md5 hashing ใน PHP


5

MD5 นั้นสมบูรณ์แบบถ้าคุณไม่ต้องการการรักษาความปลอดภัยที่ดีที่สุดและถ้าคุณกำลังทำสิ่งต่าง ๆ เช่นการตรวจสอบความสมบูรณ์ของไฟล์การรักษาความปลอดภัยนั้นไม่ใช่การพิจารณา ในกรณีเช่นนี้คุณอาจต้องการพิจารณาบางสิ่งที่ง่ายขึ้นและเร็วขึ้นเช่น Adler32 ซึ่งรองรับโดยไลบรารี Java


2
อะไรทำให้คุณคิดว่าความสมบูรณ์ของไฟล์ไม่ใช่ปัญหาด้านความปลอดภัย
Jeremy Huiskamp

5

อันนี้ให้ md5 ตรงตามที่คุณได้รับจากฟังก์ชั่น md5 ของ mysql หรือฟังก์ชั่น md5 ของ php เป็นต้นนี่คือสิ่งที่ฉันใช้ (คุณสามารถเปลี่ยนได้ตามความต้องการของคุณ)

public static String md5( String input ) {
    try {
        java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
        byte[] array = md.digest(input.getBytes( "UTF-8" ));
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < array.length; i++) {
            sb.append( String.format( "%02x", array[i]));
        }
        return sb.toString();
    } catch ( NoSuchAlgorithmException | UnsupportedEncodingException e) {
        return null;            
    }

}

4

ลองนี้:

public static String getHashMD5(String string) {
    try {
        MessageDigest md = MessageDigest.getInstance("MD5");
        BigInteger bi = new BigInteger(1, md.digest(string.getBytes()));
        return bi.toString(16);
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(MD5Utils.class
                .getName()).log(Level.SEVERE, null, ex);

        return "";
    }
}

2
นี่อาจเป็นทางออกที่เลวร้ายที่สุดเพราะจะตัดศูนย์นำหน้า
Jannick

4
import java.security.MessageDigest

val digest = MessageDigest.getInstance("MD5")

//Quick MD5 of text
val text = "MD5 this text!"
val md5hash1 = digest.digest(text.getBytes).map("%02x".format(_)).mkString

//MD5 of text with updates
digest.update("MD5 ".getBytes())
digest.update("this ".getBytes())
digest.update("text!".getBytes())
val md5hash2 = digest.digest().map(0xFF & _).map("%02x".format(_)).mkString

//Output
println(md5hash1 + " should be the same as " + md5hash2)

1
เป็นภาษา Kotlin หรือไม่
Isuru

3
@Isuru ดูเหมือน Scala
gildor

4

คุณสามารถสร้าง MD5 แฮชสำหรับข้อความที่กำหนดโดยใช้วิธีการในMessageDigestชั้นเรียนในjava.securityแพ็คเกจ ด้านล่างนี้เป็นข้อมูลโค้ดที่สมบูรณ์

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.xml.bind.DatatypeConverter;

public class MD5HashGenerator 
{

   public static void main(String args[]) throws NoSuchAlgorithmException
   {
       String stringToHash = "MyJavaCode"; 
       MessageDigest messageDigest = MessageDigest.getInstance("MD5");
       messageDigest.update(stringToHash.getBytes());
       byte[] digiest = messageDigest.digest();
       String hashedOutput = DatatypeConverter.printHexBinary(digiest);
       System.out.println(hashedOutput);
   }
}

เอาต์พุตจากฟังก์ชัน MD5 คือแฮช 128 บิตที่แสดงด้วยเลขฐานสิบหก 32 ตัว

ในกรณีที่ถ้าคุณใช้ฐานข้อมูลเช่น MySQL คุณสามารถทำได้ด้วยวิธีที่ง่ายกว่าเช่นกัน แบบสอบถามSelect MD5(“text here”)จะส่งคืนแฮช MD5 ของข้อความในวงเล็บ


2

นี่คือสิ่งที่ฉันมาที่นี่เพื่อฟังก์ชั่นสกาล่าที่มีประโยชน์ซึ่งส่งคืนสตริงของ MD5 แฮช:

def md5(text: String) : String = java.security.MessageDigest.getInstance("MD5").digest(text.getBytes()).map(0xFF & _).map { "%02x".format(_) }.foldLeft(""){_ + _}

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

/**
* MD5 encryption
*
* @author Hongten
*
*/
public class MD5 {

 public static void main(String[] args) {
     System.out.println(MD5.getMD5("123456"));
 }

 /**
  * Use md5 encoded code value
  *
  * @param sInput
  * clearly
  * @ return md5 encrypted password
  */
 public static String getMD5(String sInput) {

     String algorithm = "";
     if (sInput == null) {
         return "null";
     }
     try {
         algorithm = System.getProperty("MD5.algorithm", "MD5");
     } catch (SecurityException se) {
     }
     MessageDigest md = null;
     try {
         md = MessageDigest.getInstance(algorithm);
     } catch (NoSuchAlgorithmException e) {
         e.printStackTrace();
     }
     byte buffer[] = sInput.getBytes();

     for (int count = 0; count < sInput.length(); count++) {
         md.update(buffer, 0, count);
     }
     byte bDigest[] = md.digest();
     BigInteger bi = new BigInteger(bDigest);
     return (bi.toString(16));
 }
}

มีบทความเกี่ยวกับ Codingkit เกี่ยวกับเรื่องนี้ ลองดู: http://codingkit.com/a/JAVA/2013/1020/2216.html

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.