Bảo mật trong Java với MD5 (phần 2)

Chào mừng các bạn đã quay trở lại với thachleblog. Ở bài viết trước, mình đã giới thiệu các cách để tạo MD5 hash trong Java. Mình đã có một ví dụ đơn giản về ứng dụng của MD5 đó là sử dụng để lưu trữ thông tin cho password. Bài viết hôm nay, mình sẽ giới thiệu đến với các bạn một tính năng rất phổ biến hash data đó là bảo đảm tính toàn vẹn của dữ liệu (checksum). Vậy checksum sử dụng như thế nào và cơ chế hoạt động của nó ra sao, chúng ta cùng bắt đầu nhé.

Giới thiệu

Có bao giờ bạn download phần mềm về để ý có phần checksum kèm theo, ví dụ:

checksum.png

Phần checksum này chính là đặc điểm nhận dạng của tập tin mà chúng ta tải về. Với mỗi tập tin này, thuật toán MD5 hoặc SHA256 sẽ tạo ra 1 mã duy nhất gửi kèm theo.

Khi tải về, chúng ta có thể sử dụng các phần mềm tạo mã MD5 hoặc SHA256 (MD5 & SHA Checksum Utility) để tạo ra mã MD5 hoặc SHA256 tương ứng. So sánh mã được cấp kèm theo và mã mà chúng ta tạo ra để đảm bảo là tập tin chúng ta tải về là đúng với tập tin gốc mà bên cung cấp đã gửi (ở trên là tập tin OpenOffice).

Ứng dụng

Trong các ứng dụng thực tế, đối với các request từ client lên server, chúng ta nên sử dụng checksum để bảo vệ tính toàn vẹn của dữ liệu trao đổi giữa client và server.

Ví dụ mình xài Restful với request như sau:

https://xxx.com?username=abc&size=20…&cs=6234a99f04a7077f0662fbb2f2650a00

Giá trị checksum (cs) 6234a99f04a7077f0662fbb2f2650a00 này sẽ được tạo ra từ dữ liệu gửi lên như username, size …. với một công thức nào đó. Trên server sau khi nhận dữ liệu cũng sẽ tạo ra giá trị checksum với công thức tương ứng để kiểm tra là dữ liệu gửi lên từ client không bị mất mát hay “thay đổi”  hay không.

Kết

Qua bài viết này, hy vọng các bạn đã hiểu được ứng dụng của checksum. Từ bây giờ có thể ứng dụng trong các trường hợp gửi file quan trọng (tạo ra hash key và gửi kèm theo cho bên nhận ^.^). Quan trọng hơn hết là hiểu được cơ chế để tạo checksum để tăng tính bảo mật trong ứng dụng client – server.

Ở bài trước, mình giới thiệu phương pháp hash MD5, vì nó đơn giản và được sử dụng rộng rãi (hiện tại dự án mình vẫn xài). Tuy nhiên, đã có phát hiện về lỗ hỗng của MD5, do đó, khi áp dụng các bạn cũng có thể áp dụng trong các phương pháp hash mới bảo mật cao hơn như SHA-2 hoặc SHA256. Cảm ơn ý kiến đóng góp của các bạn và hẹn gặp các bạn ở các bài viết sau.

Bài này cũng viết khá kỹ về checksum, các bạn cũng có thể tham khảo:

http://thegioitinhoc.vn/tin-hoc-can-ban/271557-thegioitinhoc-vn-checksum-la-gi-va-lam-the-nao-de-co-no-tot-nhat.html 

Bảo mật trong Java với MD5 hash

Chào mừng các bạn đã quay trở lại với thachleblog. Bài viết hôm nay mình sẽ giới thiệu với các bạn các cách để tạo MD5 hash trong Java. Tuy đơn giản nhưng khá hiệu quả và được sử dụng rộng rãi. Nào chúng ta cùng bắt đầu nhé.

Giới thiệu

MD5 (Message Digest version 5) là một trong một loạt các thuật toán digest message được thiết kế bởi giáo sư Ronald Rivest của MIT (Rivest, 1992). Các bạn có thể xem thêm thông tin về MD5 tại đây. Thuật toán MD5 sẽ tạo ra một giá trị hash 128 bit hoặc 16 – byte từ String hoặc byte[], giá trị này sẽ được thể hiện bằng 32 ký tự trong bảng mã Hex.

Bảo mật trong Java với MD5 hash

Mục đích

MD5 hash data được dùng trong các ứng dụng bảo mật và được sử dụng để kiểm tra tính toán vẹn dữ liệu (token). Bài viết hôm nay mình sẽ giới thiệu các cách để tạo ra mã MD5 trong Java

Ví dụ

Chúng ta có thể tạo MD5 hash từ String hoặc byte[] bằng nhiều cách, sử dụng MessageDigest trong gói java.security, sử dụng libs apache codec hoặc spring. Ví dụ dưới đây mình sẽ demo tạo MD5 hash bằng cả 3 cách.

Ví dụ trường hợp mình cần lưu thông tin username và password vào cơ sở dữ liệu. Để password được an toàn, password sẽ được “hash” thành dạng Hex 32 ký tự không đọc được để lưu trữ. Lưu ý là MD5 không có quá trình dịch ngược Hex thành chuỗi ban đầu nên ta sẽ dùng giá trị “hash” này luôn mà không cần dịch ngược lại.

  1. package thach.le.example;
  2. import java.io.UnsupportedEncodingException;
  3. import java.security.MessageDigest;
  4. import java.security.NoSuchAlgorithmException;
  5. import org.apache.commons.codec.digest.DigestUtils;
  6. /**
  7.  *
  8.  * @author thachlp
  9.  */
  10. public class MD5Example {
  11.  
  12. public static void main(String args[]) {
  13.  
  14. String password = "thachlp";
  15.  
  16. System.out.println("MD5 hash generated using Java : " + md5Java(password));
  17. System.out.println("MD5 digest generated using Spring : " + md5Spring(password));
  18. System.out.println("MD5 message created by Apache commons codec : " + md5ApacheCommonsCodec(password));
  19.  
  20. }
  21.  
  22. public static String md5Java(String message) {
  23. String digest = null;
  24. try {
  25. MessageDigest md = MessageDigest.getInstance("MD5");
  26. byte[] hash = md.digest(message.getBytes("UTF-8"));
  27.  
  28. //converting byte array to Hexadecimal String
  29. StringBuilder sb = new StringBuilder(2 * hash.length);
  30. for (byte b : hash) {
  31. sb.append(String.format("%02x", b & 0xff));
  32. }
  33.  
  34. digest = sb.toString();
  35.  
  36.  
  37. }
  38. return digest;
  39. }
  40.  
  41. /*
  42.   * Spring framework also provides overloaded md5 methods. You can pass input
  43.   * as String or byte array and Spring can return hash or digest either as byte
  44.   * array or Hex String. Here we are passing String as input and getting
  45.   * MD5 hash as hex String.
  46.   */
  47. public static String md5Spring(String text) {
  48. return org.springframework.util.DigestUtils.md5DigestAsHex(text.getBytes());
  49. }
  50.  
  51. /*
  52.   * Apache commons code provides many overloaded methods to generate md5 hash. It contains
  53.   * md5 method which can accept String, byte[] or InputStream and can return hash as 16 element byte
  54.   * array or 32 character hex String.
  55.   */
  56. public static String md5ApacheCommonsCodec(String content) {
  57. return DigestUtils.md5Hex(content);
  58.  
  59. }
  60.  
  61. }

Kết quả:

  1. MD5 hash generated using Java : 6234a99f04a7077f0662fbb2f2650a00
  2. MD5 digest generated using Spring : 6234a99f04a7077f0662fbb2f2650a00
  3. MD5 message created by Apache commons codec : 6234a99f04a7077f0662fbb2f2650a00

Khi lưu trữ giá trị với kiểu hash này, ta sẽ hạn chế tối đa khả năng rủi ro nếu bị lộ database (tất nhiên các bạn có thể sử dụng các loại hash bảo mật cao hơn)

Kết

Dạo gần đây, có rất nhiều vụ để lộ thông tin người dùng của các hệ thống lớn như vietnamwork, cgv… và gần đây nhất mà mình được biết là lozi, may mắn là được phát hiện bởi 1 developer “có tâm” là toidicodedao, bạn này đã báo cho admin và giải quyết êm đẹp.

Thông thường lỗ hổng bảo mật được “tạo ra” bởi sự bất cẩn hoặc tệ hơn nữa là sự thiếu kiến thức về bảo mật của các lập trình viên (trong đó có mình, hehe). Hy vọng bài viết của mình sẽ giúp các bạn có được mối quan tâm về bảo mật mỗi khi phát triển hệ thống.

Cuối cùng, lời khuyên dành cho tất cả mọi người không chỉ là lập trình viên là hãy quan tâm đến vấn đề bảo mật hơn, nhất là trong môi trường internet, việc đơn giản nhất là hãy sử dụng bảo mật 2 lớp cho mật khẩu của google, facebook, đặt mật khẩu “phức tạp” cho các tài khoản ….. vv

Mọi ý kiến đóng góp vui lòng comment bên dưới, mình sẽ ghi nhận, xin cảm ơn và hẹn gặp lại các bạn ở các bài viết sau. Thân.

Xem thêm:
http://javarevisited.blogspot.com/2013/03/generate-md5-hash-in-java-string-byte-array-example-tutorial.html