Wednesday, 28 October 2015

[crypto] md5, sha, bit, byte, và hex

8 bits = 1 byte
1 byte biểu diễn được 2^8 = 256 "ký tự"
4 bits biểu diễn được 2^4 = 16 "ký tự".

Một ký tự thuộc hệ hexadecimal (hệ số 16) là một ký tự trong khoảng: 0123456789abcdef
Vậy chỉ cần 4 bits là có thể biểu diễn 1 ký tự hex, 2 ký tự hex = 1 byte

MD5 là gì?
MD5 là tên một thuật toán hash được sử dụng rộng rãi, được định nghĩa đầy đủ trong rfc1321.
Thuật toán hash hiểu nôm na là thuật toán nhận 1 đầu vào thì sẽ cho ra 1 kết quả duy nhất, 2 đầu vào khác nhau sẽ phải cho ra 2 đầu ra khác nhau.
nhận đầu vào có kích thước tuỳ ý nhưng trả về đầu ra với kích thước cố định. Các hàm hash dùng trong bảo mật thường có thêm tính chất: với 2 đầu vào khác nhau sẽ luôn cho ra 2 đầu ra khác nhau.
Giá trị được trả về bởi hash function gọi là "hash value", "hash codes", "hash sums", hay "hash".

Ví dụ:
$ printf "familug" | md5sum
b2bc686c91b99bd9cd92e70cdeaadf40  -
$ printf "FAMILUG" | md5sum
60e29026b93e27f815e73123efedad31  -
$ printf "FAMILUG" | md5sum | cut -d' ' -f1 | tr -d '\n' | wc -c
32
Ví dụ trên cho thấy giá trị MD5 của 2 string khác nhau là khác nhau, mã MD5 (MD5 checksum) có độ dài là 32 ký tự.
Chú ý các ký tự này đều trong khoảng [0-9a-f] tức đều là biểu diễn dạng hexadecimal của giá trị ẩn dưới đó.
Giống như với số 10, khi biểu diễn ở hệ số 2 thì là 1010, còn biểu diễn ở dạng hex thì chỉ là chữ a - cần phân biệt dạng biểu diễn và giá trị thực của nó.
Do hệ số 16 là hệ số có thể biểu diễn nhiều byte bằng ít ký tự nhất (so với các hệ 2, 8, 10) nên thường được dùng để biểu diễn byte trên máy tính.
Ví dụ: Số 256 (hệ 10 - 3 ký tự) = 11111111 (hệ 2, 8 ký tự) = ff (hệ 16 - 2 ký tự)

Vậy 32 ký tự hex tương ứng với:
(32 x 4) bits = 128 bits = (128 : 8) bytes = 16 bytes.

Vậy giá trị MD5 luôn có kích thước là 16 bytes (mặc dù độ dài thể hiện thì là 32 ký tự hex)

Tại sao mã SHA256 lại có độ 64 ký tự khi nó chỉ có kích thước 32 bytes?
Tương tự, giá trị hash sinh bởi thuật toán SHA256 có kích thước là 256 bits = (256:8) bytes = 32 bytes. Mã này khi biểu diễn ở dạng hex sẽ có độ dài 32 x 2 = 64
$ printf "FAMILUG" | shasum -a256
42e4e4e26c8751bd54abd2e9ce51d030555438152fbbb00d04b03eca2b17bb17  -
$ printf "FAMILUG" | shasum -a256 | cut -d' ' -f1 | tr -d '\n' | wc -c
64
Công thức kết luận
Số ký tự hex để biểu diễn = số byte x 2 = số bit : 4
Bài viết thực hiện trên
$ lsb_release -d
Description:    Ubuntu 14.04.3 LTS
Tham khảo:
https://golang.org/pkg/crypto/md5/
https://golang.org/pkg/crypto/sha256/
http://stackoverflow.com/questions/6317276/md5-is-128-bits-but-why-is-it-32-characters
http://stackoverflow.com/questions/2240973/when-using-a-sha256-hash-how-long-is-the-hash-ie-how-long-should-my-mysql-va