I. Hàm băm MD5 MD5 1.
Mô tả thuật toán MD5 Giả sử chúng ta có thông điệp b bit ở đầu vào, và ta muốn tìm mã số của thông điệp. Ở đây b là số không âm bất kỳ; b có thể bằng 0 và không cần chia hết cho 8, độ lớn có thể bất kỳ. Tưởng tượng rằng các bit của thông điệp được viết như sau : m_0 m_1 m_2 ... m_{b-1} Mã số thông điệp được tính qua 5 bước sau
3.1 - Bước 1 : Các bit gắn thêm Thông điệp được mở rộng, thêm bit vào phía sau sao cho độ dài của nó ( tính theo bit ) đồng dư với 448 theo môđun 512. Nghĩa là thông điệp được mở rộng sao cho nó còn thiếu 64 bit nữa thì sẽ có một độ dài chia hết cho 512. Việc này luông được thực hiện ngay cả khi bản thân độ dài thông điệp đã đồng dư với 448 theo môđun 512. Việc thêm bit này thực hiện như sau : một bit ``1`` được thêm vào sau thông điệp, sau đó các bit ``0`` được thêm vào để có một độ dài đồng dư với 448 môđun 512. Trong tất cả các trường hợp, có ít nhất 1 và nhiều nhất 512 bit được thêm vào. 3.2 - Bước 2 : Gắn thêm độ dài Dạng biểu diễn 64 bit độ dài b của chuỗi ban đầu được thêm vào phía sau kết quả của bước 1. Trong trường hợp b lớn hơn 2^64 thì chỉ có 64 bit thấp của b được sử dụng. ( Các bit này được thêm vào phía sau dưới dạng 2 word 32 bit, gắn word thấp trước theo quy ước ở trên ) 3.3 - Bước 3 : Khởi tạo bộ đệm MD Một bộ đệm 4 word (A,B,C,D) được dùng để tính mã số thông điệp. Ở đây mỗi A,B,C,D là một thanh ghi 32 bit. Những thanh ghi này được khởi tạo theo những giá trị hex sau ( các byte thấp trước ) : word A : 01 23 45 67 word B : 89 ab cd ef word C : fe dc ba 98 word D : 76 54 32 10 3.4 - Bước 4 : Xử lý thông điệp theo từng khối 16 word Trước hết ta định nghĩa các hàm phụ, các hàm này nhận đầu vào là 3 word 32 bit và tạo ra một word 32 bit. F(X,Y,Z) = XY v not(X) Z G(X,Y,Z)= XZ v Y not(Z) H(X,Y,Z) = X xor Y xor Z I(X,Y,Z) = Y xor (X v not(Z))
Với mỗi bit, F hoạt động như một điều kiện : nếu X thì Y nếu không thì Z. Hàm F có thể định nghĩa bằng phép + thay vì v bởi vì XY và not(X)Z không bao giờ có ``1`` ở cùng 1 vị trí bit.Các hàm G,H và I tương tự như F, ở chỗ chúng tác động theo từng bit tương ứng để tạo ra kết quả từ các bit của X,Y và Z Bước này sử dụng một bảng 64 giá trị T[1 .. 64] được tạo ra từ hàm sin. Gọi T[i] là phần tử thứ i của bảng, thì T[i]là phần nguyên của 4294967296*|sin(i)| , i được tính theo radian. Làm như sau : /* Xử lý mỗi khối 16 word */ For i = 0 to N/16-1 do /* Copy block i into X. */ For j = 0 to 15 do Set X[j] to M[i*16+j]. end /* of loop on j */ /* Lưu A vào AA, B vào BB, C vào CC, D và DD . */ AA = A BB = B CC = C DD = D /* Vòng 1. */ /* Ký hiệu [abcd k s i] nghĩa là thực hiện như sau : a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ /* Thực hiện : */ [ABCD 0 7 1] [DABC 1 12 2] [CDAB 2 17 3] [BCDA 3 22 4] [ABCD 4 7 5] [DABC 5 12 6] [CDAB 6 17 7] [BCDA 7 22 8] [ABCD 8 7 9] [DABC 9 12 10] [CDAB 10 17 11] [BCDA 11 22 12] [ABCD 12 7 13] [DABC 13 12 14] [CDAB 14 17 15] [BCDA 15 22 16] /* Vòng 2. */ /*Ký hiệu [abcd k s i] nghĩa là thực hiện như sau a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ /* Thực hiện : */ [ABCD 1 5 17] [DABC 6 9 18] [CDAB 11 14 19] [BCDA 0 20 20] [ABCD 5 5 21] [DABC 10 9 22] [CDAB 15 14 23] [BCDA 4 20 24] [ABCD 9 5 25] [DABC 14 9 26] [CDAB 3 14 27] [BCDA 8 20 28] [ABCD 13 5 29] [DABC 2 9 30] [CDAB 7 14 31] [BCDA 12 20 32] /* Vòng 3. */
/* Ký hiệu [abcd k s t] nghĩ là làm như sau a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ /* Thực hiện :*/ [ABCD 5 4 33] [DABC 8 11 34] [CDAB 11 16 35] [BCDA 14 23 36] [ABCD 1 4 37] [DABC 4 11 38] [CDAB 7 16 39] [BCDA 10 23 40] [ABCD 13 4 41] [DABC 0 11 42] [CDAB 3 16 43] [BCDA 6 23 44] [ABCD 9 4 45] [DABC 12 11 46] [CDAB 15 16 47] [BCDA 2 23 48] /* Vòng 4. */ /* Ký hiệu [abcd k s t] nghĩa là làm như sau a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ /* Thực hiên: */ [ABCD 0 6 49] [DABC 7 10 50] [CDAB 14 15 51] [BCDA 5 21 52] [ABCD 12 6 53] [DABC 3 10 54] [CDAB 10 15 55] [BCDA 1 21 56] [ABCD 8 6 57] [DABC 15 10 58] [CDAB 6 15 59] [BCDA 13 21 60] [ABCD 4 6 61] [DABC 11 10 62] [CDAB 2 15 63] [BCDA 9 21 64] /* Then perform the following additions. (That is increment each of the four registers by the value it had before this block was started.) */ /* Sau đó làm các phép cộng sau. ( Nghĩa là cộng vào mỗi thanh ghi giá trị của nó trước khi vào vòng lặp ) */ A = A + AA B = B + BB C = C + CC D = D + DD end /* of loop on i */ 3.5 - Bước 5 : In ra Mã số thông điệp được tạo ra là A,B,C,D. Nghĩa là chúng ta bắt đầu từ byte thấp của A, kết thúc với byte cao của D. 2.
Đặc điểm MD5 -
Việc tính MD5 đơn giản,có khả năng xác định được file có kích thước nhiều Gb
-
Không có khả năng tính ngược khi tìm ra MD
-
Do bản chất của hàm băm và số lượng cực lớn các giá trị hash có thể nên hầu như không thể có 2 bản tin phân biệt có cung giá trị Hash
-
Giá trị MD phụ thuộc vào bản tin tương ứng
-
Một chuỗi có duy nhất một hash
-
Giá trị MD phụ thuộc vào tất cả các bits tương ứng
3. Thời gian phá mã
a. Vì MD5 chỉ dò qua dữ liệu một lần, nếu hai tiền tố với cùng bảng băm được xây nên, thì cùng một hậu tố có thể cùng được thêm vào để khiến cho đụng độ dễ xảy ra. Tức là hai dữ liệu vào (input) X và Y hoàn toàn khác nhau nhưng có thể ra (output) được một md5 hash giống nhau . Tuy nhiên xác suất để xảy ra điều này là khá nhỏ. b. Vì những kỹ thuật tìm đụng độ hiện nay cho phép các trạng thái băm trước đó được xác định một cách ngẫu nhiên, có thể tìm thấy xung đột đối với bất kỳ tiền tố mong muốn nào; có nghĩa là, đối bất kỳ một chuỗi các ký tự X cho trước, hai tập tin đụng độ có thể được xác định mà đều bắt đầu với X. c. Tất cả những gì cần để tạo ra hai tập tin đụng độ là một tập tin mẫu, với một khối dữ liệu 128 byte được xếp trên giới hạn 64 byte, có thể thay đổi tự do bằng giải thuật tìm va chạm. d.
Như trên đã nói: từ 1 hashes ta tìm ngược lại string của nó được không? Điều này không bao giờ làm được. Vậy ở đây câu trả lời là : “Bạn không thể” . Cách hash một string có nghĩa là tín hiệu md xuất ra bằng thuật tóan MD5 là không thể đảo ngược. Không thể biết cách tìm ra chuổi origin từ tín hiệu MD5 hashes. Tức là chúng ta không thể nào “decode” (dịch ngược) được một chuỗi MD5 hashes. Chỉ có một cách có được chuổi origin là bằng cách “brute force cracking”. Tức là phải duyệt qua rất nhiều tổ họp các ký tự của chuổi vào cho đến khi một trong những chuỗi md được tạo ra của chúng bằng với chuổi md cần tìm origin. Tuy nhiên , với khả năng máy tính thời nay muốn làm điều này phải mất rất nhiều năm. Mặt khác ở đây chúng ta cần chú ý đó là tín hiệu MD5 hashes được thiết kế ra là “độc nhất vô nhị”. Trên lý thuyết cũng có khả năng 2 chuổi khác nhau có tín hiệu md giống nhau nhưng khả năng này rất rất nhỏ (1/(16^32) hay vào khoảng (3.4E+38), vì thế để brute force một md5 thì máy tính chắc chạy vài tuần cũng chưa tìm ra.
4. Phân tích thời gian thực hiện 5. Các mô hình áp dụng trong lưu trữ, truyền thong có thể áp dụng
a.
1/ MD5 được sử dụng rộng rải trong thế giới phần mềm để đảm bảo rằng tập tin tải về không bị hỏng. Người sử dụng có thể so sánh giữa thông số kiểm tra phần mềm bằng MD5 được công bố với thông số kiểm tra phần mềm tải về bằng MD5. Hệ điều hành Unix sử dụng MD5 để kiểm tra các gói mà nó phân phối, trong khi hệ điều hành Windows sử dụng phần mềm của hãng thứ ba. 2/ MD5 được dùng để mã hóa mật khẩu. Mục đích của việc mã hóa này là biến đổi một chuổi mật khẩu thành một đoạn mã khác, sao cho từ đoạn mã đó không thể nào lần trở lại mật khẩu. Có nghĩa là việc giải mã là không thể hoặc phải mất một khoãng thời gian vô tận (đủ để làm nản lòng các hacker).
b.
Các đồng hóa MD5 được dùng rộng rãi trong các phần mềm trên toàn thế giới để đảm bảo việc truyền tập tin được nguyên vẹn. Ví dụ, máy chủ tập tin thường cung cấp một checksum MD5 được tính toán trước cho tập tin, để người dùng có thể so sánh với checksum của tập tin đã tải về. Những hệ điều hành dựa trên nền tảng Unix luôn kèm theo tính năng MD5 sum trong các gói phân phối của họ, trong khi người dùng Windows sử dụng ứng dụng của hãng thứ ba.
c.
Tuy nhiên, hiện nay dễ dàng tạo ra xung đột MD5, một người có thể tạo ra một tập tin để tạo ra tập tin thứ hai với cùng một checksum, do đó kỹ thuật này không thể chống lại một vài dạng giả mạo nguy hiểm. Ngoài ra, trong một số trường hợp checksum không thể tin tưởng được (ví dụ, nếu nó được lấy từ một lệnh như tập tin đã tải về), trong trường hợp đó MD5 chỉ có thể có chức năng kiểm tra lỗi: nó sẽ nhận ra một lỗi hoặc tải về chưa xong, rất dễ xảy ra khi tải tập tin lớn.
d.
MD5 được dùng rộng rãi để lưu trữ mật khẩu. Để giảm bớt sự dễ thương tổn đề cập ở trên, ta có thể thêm salt vào mật khẩu trước khi băm chúng. Một vài hiện thực có thể áp dụng vào hàm băm hơn một lần-xem làm mạnh thêm khóa.
e.
-Nó thường được dùng để checksum toàn bộ file. Các nhà phát triển ứng dụng thường dùng MD5 trong việc cho phép download file trên NET. Họ sẽ cho “xuất bản” một tín hiệu md của file download. Khi chúng ta tải file về , thì file chúng ta vừa download sẽ có một tín hiệu md, nếu tín hiệu này khớp với tín hiệu các nhà phát triển ứng dụng đã “xuất bản” ở trên. Thì OK, không có vấn đề. Nếu hai tín hiệu md này khác nhau, có thể có trong file download có virut hay cái gì đó tương tự. -Một ứng dụng thường được dùng nữa là hash một password. Được dùng cho việc bảo mật một ứng dụng, hay những gì tương tự …v….v….
II. Tìm hiểu SHA
1.
Giới thiệu a.
SHA (Secure Hash Algorithm) là năm thuật giải được chấp nhận bởi FPS (Federal Information Processing Standards) dùng để chuyển một đoạn dữ liệu nhất định thành một đoạn dữ liệu có chiều dài không đổi với xác suất khác biệt cao. Có năm thuật giải SHA là SHA-1 (trả lại kết quả dài 160 bit), SHA-224 (trả lại kết quả dài 224 bit), SHA-256 (trả lại kết quả dài 256 bit), SHA384 (trả lại kết quả dài 384 bit), và SHA-512 (trả lại kết quả dài 512 bit). Thuật giải SHA là thuật giải băm mật được phát triển bởi cục an ninh quốc gia Mĩ (National Security Agency hay NSA) và được xuất bản thành chuẩn của chính phủ Mĩ bởi viện công nghệ và chuẩn quốc gia Mĩ (National Institute of Standards and Technology hay NIST). Bốn thuật giải sau thường được gọi chung là SHA-2. SHA-1 được sử dụng rộng rãi trong nhiều ứng dụng và giao thức an ninh khác nhau, bao gồm TLS và SSL, PGP, SSH, S/MIME, và IPSec. SHA-1 được coi là thuật giải thay thế MD5, một thuật giải băm 128 bit phổ biến khác. Hiện nay, SHA-1 không còn được coi là an toàn bởi đầu năm 2005, ba nhà mật mã học người Trung Quốc đã phát triển thành công một thuật giải dùng để tìm được hai đoạn dữ liệu nhất định có cùng kết quả băm tạo ra bởi SHA-1. Mặc dù chưa có ai làm được điều tương tự với SHA-2, nhưng vì về thuật giải, SHA-2 không khác biệt mấy so với SHA-1 nên nhiều nhà khoa học đã bắt đầu phát triển một thuật giải khác tốt hơn SHA. NIST cũng đã khởi đầu một cuộc thi phát triển thuật giải băm mới an toàn hơn SHA, giống như quy trình phát triển chuẩn mã hóa tiên tiến (Advanced Encryption Standard hay AES).
2.
2. SHA-2
SHA-2 bao gồm bốn giải thuật SHA-224, SHA-256, SHA-384 và SHA-512. Ba thuật giải SHA-256, SHA-384 và SHA-512 được xuất bản lần đầu năm 2001 trong bản phác thảo FIPS PUB 180-2. Năm 2002, FIPS PUB 180-2, bao gồm cả SHA-1 được chấp nhận thành chuẩn chính thức. Năm 2004, FIPS PUB 180-2 được bổ sung thêm một biến thể - SHA-224, với mục đích tạo ra một biến thể SHA-2 có độ dài khóa trùng với DES ba lần với 2 khóa (2TDES) - 112 bit. Những biến thể SHA-2 này được đăng ký Bằng sáng chế Hoa Kỳ số 6.829.355 . 3.
Mã giả của thuật giải SHA-256:
4.
Chú ý: Tất cả các biến đều là 32 bit không dấu quay vòng modulo 2 32 khi tính
5. 6. Khởi tạo biến 7. (32 bit đầu tiên của phần phân số của căn bậc 2 của 8 số nguyên tố đầu tiên 2..19): 8. h0 := 0x6a09e667 9. h1 := 0xbb67ae85 10. h2 := 0x3c6ef372 11. h3 := 0xa54ff53a 12. h4 := 0x510e527f 13. h5 := 0x9b05688c 14. h6 := 0x1f83d9ab 15. h7 := 0x5be0cd19 16. 17. Khởi tạo hằng số 18. (32 bit đầu tiên của phần phân số của căn bậc 3 của 64 số nguyên tố đầu tiên 2..311): 19. k[0..63] := 20. 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 21. 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 22. 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 23. 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 24. 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 25. 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 26. 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 27. 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 28. 29. Tiền xử lý: 30. Thêm bit '1' vào cuối đoạn dữ liệu gốc 31. Thêm k bit '0', trong đó k là số nhỏ nhất >= 0 sao cho chiều dài của đoạn dữ liệu gốc (tính bằng bit ) đồng dư với 448 (mod 512) 32. 33. Thêm độ dài của đoạn dữ liệu gốc (trước giai đoạn tiền xử lý), tính băng bits thể hiện bằng một số 64 bit big endian vào cuối đoạn dữ liệu 34. 35. 36. Xử lý đoạn dữ liệu từng 512 bit một: 37. Tách đoạn dữ liệu ra thành tứng nhóm 512 bit 38. Với mỗi nhóm 39. Tách nhóm ra thành 16 nhóm 32 bit big endian w[0..15]
40. Mở rộng 16 nhóm này thành 64 nhóm 32 bit: for i từ 16 đến 63 42. s0 := (w[i-15] quay vòng phải 7) xor (w[i-15] quay vòng phải 18) xor 43. (w[i-15] dịch phải 3) s1 := (w[i-2] quay vòng phải 17) xor (w[i-2] quay vòng phải 19) xor 44. (w[i-2] dịch phải 10) w[i] := w[i-16] + s0 + w[i-7] + s1 45. 46. Khởi tạo giá trị băm cho nhóm này: 47. 48. a := h0 49. b := h1 50. c := h2 51. d := h3 52. e := h4 53. f := h5 54. g := h6 55. h := h7 56. 57. Vòng lặp chính: for i từ 0 đến 63 58. s0 := (a xoay vòng phải 2) xor (a xoay vòng phải 13) xor (a xoay 59. vòng phải 22) maj := (a and b) xor (a and c) xor (b and c) 60. 61. t2 := s0 + maj s1 := (e xoay vòng phải 6) xor (e xoay vòng phải 11) xor (e xoay 62. vòng phải 25) ch := (e and f) xor ((not e) and g) 63. 64. t1 := h + s1 + ch + k[i] + w[i] 65. 66. h := g 67. g := f 68. f := e 69. e := d + t1 70. d := c 71. c := b 72. b := a 73. a := t1 + t2 74. 75. Cộng giá trị băm vừa tính vào kết quả: 76. h0 := h0 + a 77. h1 := h1 + b 78. h2 := h2 + c 79. h3 := h3 + d 80. h4 := h4 + e 81. h5 := h5 + f 82. h6 := h6 + g 41.
83. h7 := h7 + h 84. 85. Tạo kết quả cuối cùng (big endian): 86. digest = hash = h0 nối với h1 nối với h2 nối với h3 nối với h4 nối với h5 nối với h6 nối với h7 87.
Mã nguồn SHA-256 bằng PHP, tương thích với UTF-8:
88.
121. { 122. $M[$i][] = (ord(substr($msg, $i * 64 + $j * 4, 1)) << 24) | 123. (ord(substr($msg, $i * 64 + $j * 4 + 1, 1)) << 16) | 124. (ord(substr($msg, $i * 64 + $j * 4 + 2, 1)) << 8) | 125. (ord(substr($msg, $i * 64 + $j * 4 + 3, 1))); 126. } 127. } 128. 129. $M[$N-1][14] = Hash::SHR((strlen($msg) - 1) * 8, 32); 130. $M[$N-1][15] = ((strlen($msg) - 1) * 8) & 0xffffffff; 131. 132. $H = array( 133. 0x6a09e667, 0xbb67ae85, 134. 0x3c6ef372, 0xa54ff53a, 135. 0x510e527f, 0x9b05688c, 136. 0x1f83d9ab, 0x5be0cd19 137. ); 138. 139. $K = array( 140. 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 141. 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 142. 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 143. 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 144. 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 145. 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 146. 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 147. 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 148. ); 149. 150. $W = array(); 151. 152. for ($i = 0; $i < $N; $i++) 153. { 154. for ($t = 0; $t < 16; $t++) $W[$t] = $M[$i][$t]; 155. for ($t = 16; $t < 64; $t++) 156. $W[$t] = Hash::sum(Hash::gamma1($W[$t - 2]), $W[$t - 7], Hash::gamma0($W[$t - 15]), $W[$t - 16]); 157. 158. $a = $H[0];
159. $b = $H[1]; 160. $c = $H[2]; 161. $d = $H[3]; 162. $e = $H[4]; 163. $f = $H[5]; 164. $g = $H[6]; 165. $h = $H[7]; 166. 167. for ($t = 0; $t < 64; $t++) 168. { 169. $T1 = Hash::sum($h, Hash::sigma1($e), Hash::Ch($e, $f, $g), $K[$t], $W[$t]); 170. $T2 = Hash::sum(Hash::sigma0($a), Hash::Maj($a, $b, $c)); 171. $h = $g; 172. $g = $f; 173. $f = $e; 174. $e = Hash::sum($d, $T1); 175. $d = $c; 176. $c = $b; 177. $b = $a; 178. $a = Hash::sum($T1, $T2); 179. } 180. 181. $H[0] = Hash::sum($a, $H[0]); 182. $H[1] = Hash::sum($b, $H[1]); 183. $H[2] = Hash::sum($c, $H[2]); 184. $H[3] = Hash::sum($d, $H[3]); 185. $H[4] = Hash::sum($e, $H[4]); 186. $H[5] = Hash::sum($f, $H[5]); 187. $H[6] = Hash::sum($g, $H[6]); 188. $H[7] = Hash::sum($h, $H[7]); 189. } 190. 191. $hash = ""; 192. for ($i = 0; $i < 8; $i++) 193. { 194. $H[$i] = dechex($H[$i]); 195. while (strlen($H[$i]) < 8) $H[$i] = '0'.$H[$i]; 196. $hash .= $H[$i] 197. } 198. 199. return $hash; 200. } 201. 202. function gamma0($x) 203. {
204. return (Hash::ROTR($x, 7) ^ Hash::ROTR($x, 18) ^ (Hash::SHR($x, 3))); 205. } 206. 207. function gamma1($x) 208. { 209. return (Hash::ROTR($x, 17) ^ Hash::ROTR($x, 19) ^ (Hash::SHR($x, 10))); 210. } 211. 212. function sigma0($x) 213. { 214. return (Hash::ROTR($x, 2) ^ Hash::ROTR($x, 13) ^ Hash::ROTR($x, 22)); 215. } 216. 217. function sigma1($x) 218. { 219. return (Hash::ROTR($x, 6) ^ Hash::ROTR($x, 11) ^ Hash::ROTR($x, 25)); 220. } 221. 222. function Ch($x, $y, $z) 223. { 224. return (($x & $y) ^ (~$x & $z)); 225. } 226. 227. function Maj($x, $y, $z) 228. { 229. return (($x & $y) ^ ($x & $z) ^ ($y & $z)); 230. } 231. 232. function ROTR($x, $n) 233. { 234. return (Hash::SHR($x, $n) | ($x << (32 - $n))); 235. } 236. 237. function SHR($a, $b) 238. { 239. return ($a >> $b) & (pow(2, 32 - $b) - 1); 240. } 241. 242. // Hàm được viết bởi Fyed 243. function sum() 244. { 245. $T = 0; 246.
247. 248. 249. 250. 251. 252. 253. 254. 255. 256. 257. 258. 259. 260. 261. 262. 263. 264. 265. 266. 267. 268. 269. 270. 271. 272. 273. 274. 275. 276. 277. 278. 279. 280. 281. 282. 283. 284. 285. 286. 287. 288. 289. 290. 291. 292. 293.
for($x = 0, $y = func_num_args(); $x < $y; $x++) { $a = func_get_arg($x); $c = 0; for($i = 0; $i < 32; $i++) { $j = (($T >> $i) & 1) + (($a >> $i) & 1) + $c; $c = ($j >> 1) & 1; $j &= 1; $T &= ~(1 << $i); $T |= $j << $i; } } return $T; } // Dựa trên đoạn code viết bởi Angel Martin & Paul Johnston function utf8Encode($msg) { $utfText = ""; for ($n = 0; $n < strlen($msg); $n++) { $c = ord(substr($msg, $n, 1)); if ($c < 128) { $utfText .= chr($c); } else if (($c > 127) && ($c < 2048)) { $utfText .= chr(($c >> 6) | 192); $utfText .= chr(($c & 63) | 128); } else { $utfText .= chr(($c >> 12) | 224); $utfText .= chr((($c >> 6) & 63) | 128); $utfText .= chr(($c & 63) | 128); } } return $utfText; } }
294.
?>
[sửa]Ví dụ
Dưới đây là một số ví dụ sử dụng thuật giải SHA. Đoạn dữ liệu gốc được ngầm hiểu sử dụng bảng mã ASCII.
295.
[sửa]SHA-1 296.
297.
SHA1("The quick brown fox jumps over the lazy dog") = 2fd4e1c6 7a2d28fc ed849ee1 bb76e739 1b93eb12
Ngay cả một thay đổi nhỏ trong đoạn dữ liệu gốc sẽ có khả năng rất lớn tạo nên một giá trị băm hoàn toàn khác do hiệu ứng tuyết lở. Ví dụ, sửa d thành c:
298.
299. 300. 301. 302. 303.
SHA1("The quick brown fox jumps over the lazy cog") = de9f2c7f d25e1b3a fad3e85a 0bd17d9b 100db4b3 Giá trị băm của một đoạn dữ liệu rỗng: SHA1("") = da39a3ee 5e6b4b0d 3255bfef 95601890 afd80709
[sửa]SHA-256
304. SHA256("The quick brown fox jumps over the lazy dog") 305. = d7a8fbb3 07d78094 69ca9abc b0082e4f 8d5651e4 6d3cdb76 2d02d0bf 37c9e592 306.
Hiệu ứng tuyết lở khi sửa từ cuối cùng thành "cog":
307. SHA256("The quick brown fox jumps over the lazy cog") 308. = e4c4d8f3 bf76b692 de791a17 3e053211 50f7a345 b46484fe 427f6acc 7ecc81be 309.
Giá trị băm của đoạn dữ liệu rỗng:
310. SHA256("") 311. = e3b0c442 98fc1c14 9afbf4c8 996fb924 27ae41e4 649b934c a495991b 7852b855
[sửa]SHA-512
312. SHA512("The quick brown fox jumps over the lazy dog") 313. = 07e547d9 586f6a73 f73fbac0 435ed769 51218fb7 d0c8d788 a309d785 436bbb64 314. 2e93a252 a954f239 12547d1e 8a3b5ed6 e1bfd709 7821233f a0538f3d b854fee6 315.
Hiệu ứng tuyết lở khi sửa từ cuối cùng thành "cog":
316. SHA512("The quick brown fox jumps over the lazy cog") 317. = 3eeee1d0 e11733ef 152a6c29 503b3ae2 0c4f1f3c da4cb26f 1bc1a41f 91c7fe4a 318. b3bd8649 4049e201 c4bd5155 f31ecb7a 3c860684 3c4cc8df cab7da11 c8ae5045 319.
Giá trị băm của đoạn dữ liệu rỗng:
320. SHA512("") 321. = cf83e135 7eefb8bd f1542850 d66d8007 d620e405 0b5715dc 83f4a921 d36ce9ce 322. 47d0d13c 5d85f2b0 ff8318d2 877eec2f 63b931bd 47417a81 a538327a f927da3 323.