การแฮชเชิงเข้ารหัสด้วย MessageDigest
แฮชรหัสผ่านด้วย SHA-256 เติม salt เพื่อป้องกันการโจมตีด้วยตาราง rainbow และเปรียบเทียบไดเจสต์อย่างปลอดภัย
การแฮชเชิงเข้ารหัสด้วย MessageDigest เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
การแฮชเชิงเข้ารหัสคืออะไร
ฟังก์ชันแฮชเชิงเข้ารหัสจะแปลงข้อมูลที่มีขนาดใดก็ได้ให้เป็นค่าไดเจสต์ที่มีขนาดคงที่ ฟังก์ชันนี้เป็นแบบทางเดียว (ไม่สามารถย้อนกลับได้) ให้ผลแน่นอนเหมือนเดิม และต้านทานการชนกัน ใช้สำหรับจัดเก็บรหัสผ่าน ตรวจสอบความถูกต้องครบถ้วนของข้อมูล และสร้างลายเซ็นดิจิทัล
API MessageDigest
MessageDigest.getInstance("SHA-256") จะส่งคืนตัวประมวลผล SHA-256 เรียก digest(bytes) เพื่อคำนวณแฮชและรับอาร์เรย์ไบต์
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hash = md.digest("password123".getBytes(StandardCharsets.UTF_8));
String hex = HexFormat.of().formatHex(hash);
System.out.println(hex); // 64-char hex stringอัลกอริทึมที่ใช้กันทั่วไป
JDK รองรับ: MD5 (ถูกทำลายแล้ว — ห้ามใช้เพื่อความปลอดภัย), SHA-1 (เลิกแนะนำเพื่อความปลอดภัย), SHA-256 (มาตรฐาน), SHA-512 (แข็งแกร่งกว่า) และ SHA3-256 (สมัยใหม่) สำหรับโค้ดใหม่ ให้ใช้ SHA-256 หรือ SHA-512 เสมอ
MessageDigest.getInstance("SHA-256"); // recommended
MessageDigest.getInstance("SHA-512"); // stronger
MessageDigest.getInstance("SHA3-256"); // SHA-3 family
// Never: MessageDigest.getInstance("MD5"); // cryptographically brokenการแปลงแฮชเป็นสตริงเลขฐานสิบหก
ต้องแปลงผลลัพธ์อาร์เรย์ไบต์เป็นสตริงเลขฐานสิบหกเพื่อจัดเก็บหรือเปรียบเทียบ ใช้ HexFormat (Java 17 ขึ้นไป) หรือ String.format สำหรับเวอร์ชันเก่า
// Java 17+:
String hex = HexFormat.of().formatHex(hash);
// Older Java:
StringBuilder sb = new StringBuilder();
for (byte b : hash) sb.append(String.format("%02x", b));
String hex = sb.toString();ซอลต์: การเอาชนะตาราง Rainbow
ตาราง Rainbow จะจับคู่รหัสผ่านที่ใช้กันทั่วไปกับแฮชของรหัสผ่านเหล่านั้น การเติมซอลต์คือการเพิ่มค่าสุ่มให้กับรหัสผ่านแต่ละรายการก่อนแฮช ทำให้ตาราง Rainbow ใช้งานไม่ได้ ควรจัดเก็บซอลต์ไว้คู่กับแฮช
SecureRandom random = new SecureRandom();
byte[] salt = new byte[16];
random.nextBytes(salt);
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(salt);
byte[] hash = md.digest("password".getBytes(StandardCharsets.UTF_8));
// Store: Base64.encode(salt) + ":" + Base64.encode(hash)การแฮชรหัสผ่าน — ใช้ BCrypt แทน
SHA-256 ที่ใช้ร่วมกับซอลต์ดีกว่า SHA-256 แบบไม่มีซอลต์ แต่ยังคงทำงานได้รวดเร็ว ผู้โจมตีจึงอาจลองเดาได้หลายพันล้านครั้งต่อวินาที โปรดใช้ KDF ที่ทำงานช้า เช่น BCryptPasswordEncoder (Spring Security), PBKDF2 หรือ Argon2 สำหรับรหัสผ่าน
// Spring Security — proper password hashing:
PasswordEncoder encoder = new BCryptPasswordEncoder(12); // cost factor 12
String hash = encoder.encode("password123");
boolean match = encoder.matches("password123", hash); // trueการตรวจสอบความถูกต้องครบถ้วนของไฟล์
แฮชไฟล์เพื่อตรวจจับความเสียหายหรือการแก้ไขข้อมูล แล้วเปรียบเทียบแฮชที่คำนวณได้กับค่ามาตรฐานที่ทราบว่าถูกต้อง
MessageDigest md = MessageDigest.getInstance("SHA-256");
try (InputStream is = Files.newInputStream(Path.of("app.jar"))) {
byte[] buf = new byte[8192];
int n;
while ((n = is.read(buf)) > 0) md.update(buf, 0, n);
}
String hash = HexFormat.of().formatHex(md.digest());
System.out.println("SHA-256: " + hash);การเปรียบเทียบแฮชอย่างปลอดภัย
ใช้ MessageDigest.isEqual() เพื่อเปรียบเทียบโดยใช้เวลาเท่ากันทุกกรณีและป้องกันการโจมตีจากเวลา ห้ามใช้ String.equals() เพื่อเปรียบเทียบแฮช
byte[] expected = computeHash(storedHash);
byte[] actual = computeHash(inputPassword);
boolean match = MessageDigest.isEqual(expected, actual); // constant-timeการอัปเดตแบบต่อเนื่อง
เรียก md.update(bytes) หลายครั้งก่อนเรียก md.digest() เพื่อแฮชข้อมูลที่มาถึงเป็นส่วน ๆ (แบบสตรีม)
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update("part1".getBytes());
md.update("part2".getBytes());
byte[] hash = md.digest(); // hash of "part1" + "part2"การเข้ารหัสแฮชเพื่อจัดเก็บ
จัดเก็บแฮชไบนารีเป็นสตริง Base64 (สั้นกว่าเลขฐานสิบหก) หรือสตริงเลขฐานสิบหก Base64 ใช้อักขระ 43 ตัวสำหรับ SHA-256 เทียบกับเลขฐานสิบหกที่ใช้ 64 ตัว ทั้งสองวิธีถูกต้อง — ขอเพียงใช้ให้สม่ำเสมอ
byte[] hash = md.digest(data);
String base64 = Base64.getEncoder().encodeToString(hash); // 44 chars (with padding)
String hex = HexFormat.of().formatHex(hash); // 64 charsDigestInputStream สำหรับการสตรีม
ครอบ InputStream ด้วย DigestInputStream เพื่อคำนวณแฮชขณะอ่านข้อมูล วิธีนี้ช่วยหลีกเลี่ยงการโหลดไฟล์ทั้งหมดไว้ในหน่วยความจำ
MessageDigest md = MessageDigest.getInstance("SHA-256");
try (DigestInputStream dis = new DigestInputStream(Files.newInputStream(path), md)) {
dis.transferTo(OutputStream.nullOutputStream());
}
String hash = HexFormat.of().formatHex(md.digest());ตรวจสอบอย่างรวดเร็ว
เหตุใดจึงยังไม่แนะนำให้ใช้ SHA-256 ร่วมกับซอลต์สำหรับจัดเก็บรหัสผ่าน
สรุปทบทวน
ใช้ MessageDigest.getInstance("SHA-256") เพื่อตรวจสอบความถูกต้องครบถ้วนของข้อมูล เติมซอลต์ให้รหัสผ่านเสมอ แต่สำหรับการจัดเก็บรหัสผ่าน ให้ใช้ BCrypt/Argon2 ไม่ใช่ SHA แบบดิบ ใช้การเปรียบเทียบโดยใช้เวลาเท่ากันทุกกรณี (MessageDigest.isEqual) เพื่อป้องกันการโจมตีจากเวลา
เรียนรู้ Java ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 104
- บทเรียน
- 374
คำถามที่พบบ่อย
บทเรียน “การแฮชเชิงเข้ารหัสด้วย MessageDigest” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การแฮชเชิงเข้ารหัสด้วย MessageDigest” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การแฮชเชิงเข้ารหัสด้วย MessageDigest”
แฮชรหัสผ่านด้วย SHA-256 เติม salt เพื่อป้องกันการโจมตีด้วยตาราง rainbow และเปรียบเทียบไดเจสต์อย่างปลอดภัย คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “การแฮชเชิงเข้ารหัสด้วย MessageDigest” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม
ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การแฮชเชิงเข้ารหัสด้วย MessageDigest
- การเข้ารหัสแบบสมมาตร AES
- HMAC-SHA256 เพื่อความถูกต้องครบถ้วนของข้อความ
- JWT: โครงสร้าง การสร้าง และการตรวจสอบ