--- id: 5eb3e4c3a894c333d2811a3f title: SHA-256 challengeType: 5 forumTopicId: 385328 dashedName: sha-256 --- # --description-- `SHA-2` 家族是比 `SHA-1` 更強大的替代。 兩者最主要的不同是散列的長度。 即 `SHA-1` 提供了更短的編碼,也意味着組合的唯一性概率更低。 `SHA-2` 或 `SHA-256` 創建了較長的散列,從而增加了唯一性的概率。 # --instructions-- 研究實現細節並編寫一個函數,該函數以字符串爲參數並使用 `SHA-256` 返回哈希值 # --hints-- `SHA256` 應該是一個函數。 ```js assert(typeof SHA256 === 'function'); ``` `SHA256("Rosetta code")` 應該返回一個字符串。 ```js assert(typeof SHA256('Rosetta code') === 'string'); ``` `SHA256("Rosetta code")` 應該返回 `"764faf5c61ac315f1497f9dfa542713965b785e5cc2f707d6468d7d1124cdfcf"`。 ```js assert.equal( SHA256('Rosetta code'), '764faf5c61ac315f1497f9dfa542713965b785e5cc2f707d6468d7d1124cdfcf' ); ``` `SHA256("SHA-256 Hash")` 應該返回 `"bee8c0cabdcf8c7835f40217dd35a8b0dba9134520e633f1c57285f35ca7ee3e"`。 ```js assert.equal( SHA256('SHA-256 Hash'), 'bee8c0cabdcf8c7835f40217dd35a8b0dba9134520e633f1c57285f35ca7ee3e' ); ``` `SHA256("implementation")` 應該返回 `"da31012c40330e7e21538e7dd57503b16e8a0839159e96137090cccc9910b171"`。 ```js assert.equal( SHA256('implementation'), 'da31012c40330e7e21538e7dd57503b16e8a0839159e96137090cccc9910b171' ); ``` `SHA256("algorithm")` 應該返回 `"b1eb2ec8ac9f31ff7918231e67f96e6deda83a9ff33ed2c67443f1df81e5ed14"`。 ```js assert.equal( SHA256('algorithm'), 'b1eb2ec8ac9f31ff7918231e67f96e6deda83a9ff33ed2c67443f1df81e5ed14' ); ``` `SHA256("language")` 應該返回 `"a4ef304ba42a200bafd78b046e0869af9183f6eee5524aead5dcb3a5ab5f8f3f"` ```js assert.equal( SHA256('language'), 'a4ef304ba42a200bafd78b046e0869af9183f6eee5524aead5dcb3a5ab5f8f3f' ); ``` # --seed-- ## --seed-contents-- ```js function SHA256(input) { } ``` # --solutions-- ```js function SHA256(input) { var chrsz = 8; var hexcase = 0; function safe_add(x, y) { var lsw = (x & 0xffff) + (y & 0xffff); var msw = (x >> 16) + (y >> 16) + (lsw >> 16); return (msw << 16) | (lsw & 0xffff); } function S(X, n) { return (X >>> n) | (X << (32 - n)); } function R(X, n) { return X >>> n; } function Ch(x, y, z) { return (x & y) ^ (~x & z); } function Maj(x, y, z) { return (x & y) ^ (x & z) ^ (y & z); } function Sigma0256(x) { return S(x, 2) ^ S(x, 13) ^ S(x, 22); } function Sigma1256(x) { return S(x, 6) ^ S(x, 11) ^ S(x, 25); } function Gamma0256(x) { return S(x, 7) ^ S(x, 18) ^ R(x, 3); } function Gamma1256(x) { return S(x, 17) ^ S(x, 19) ^ R(x, 10); } function Sigma0512(x) { return S(x, 28) ^ S(x, 34) ^ S(x, 39); } function Sigma1512(x) { return S(x, 14) ^ S(x, 18) ^ S(x, 41); } function Gamma0512(x) { return S(x, 1) ^ S(x, 8) ^ R(x, 7); } function Gamma1512(x) { return S(x, 19) ^ S(x, 61) ^ R(x, 6); } function core_sha256(m, l) { var K = new Array( 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0xfc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x6ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 ); var HASH = new Array( 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 ); var W = new Array(64); var a, b, c, d, e, f, g, h, i, j; var T1, T2; m[l >> 5] |= 0x80 << (24 - (l % 32)); m[(((l + 64) >> 9) << 4) + 15] = l; for (var i = 0; i < m.length; i += 16) { a = HASH[0]; b = HASH[1]; c = HASH[2]; d = HASH[3]; e = HASH[4]; f = HASH[5]; g = HASH[6]; h = HASH[7]; for (var j = 0; j < 64; j++) { if (j < 16) W[j] = m[j + i]; else W[j] = safe_add( safe_add( safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15]) ), W[j - 16] ); T1 = safe_add( safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j] ); T2 = safe_add(Sigma0256(a), Maj(a, b, c)); h = g; g = f; f = e; e = safe_add(d, T1); d = c; c = b; b = a; a = safe_add(T1, T2); } HASH[0] = safe_add(a, HASH[0]); HASH[1] = safe_add(b, HASH[1]); HASH[2] = safe_add(c, HASH[2]); HASH[3] = safe_add(d, HASH[3]); HASH[4] = safe_add(e, HASH[4]); HASH[5] = safe_add(f, HASH[5]); HASH[6] = safe_add(g, HASH[6]); HASH[7] = safe_add(h, HASH[7]); } return HASH; } function core_sha512(m, l) { var K = new Array( 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817 ); var HASH = new Array( 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179 ); var W = new Array(80); var a, b, c, d, e, f, g, h, i, j; var T1, T2; } function str2binb(str) { var bin = Array(); var mask = (1 << chrsz) - 1; for (var i = 0; i < str.length * chrsz; i += chrsz) bin[i >> 5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - (i % 32)); return bin; } function binb2str(bin) { var str = ''; var mask = (1 << chrsz) - 1; for (var i = 0; i < bin.length * 32; i += chrsz) str += String.fromCharCode((bin[i >> 5] >>> (24 - (i % 32))) & mask); return str; } function binb2hex(binarray) { var hex_tab = hexcase ? '0123456789ABCDEF' : '0123456789abcdef'; var str = ''; for (var i = 0; i < binarray.length * 4; i++) { str += hex_tab.charAt((binarray[i >> 2] >> ((3 - (i % 4)) * 8 + 4)) & 0xf) + hex_tab.charAt((binarray[i >> 2] >> ((3 - (i % 4)) * 8)) & 0xf); } return str; } function binb2b64(binarray) { var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; var str = ''; for (var i = 0; i < binarray.length * 4; i += 3) { var triplet = (((binarray[i >> 2] >> (8 * (3 - (i % 4)))) & 0xff) << 16) | (((binarray[(i + 1) >> 2] >> (8 * (3 - ((i + 1) % 4)))) & 0xff) << 8) | ((binarray[(i + 2) >> 2] >> (8 * (3 - ((i + 2) % 4)))) & 0xff); for (var j = 0; j < 4; j++) { if (i * 8 + j * 6 > binarray.length * 32) str += ''; else str += tab.charAt((triplet >> (6 * (3 - j))) & 0x3f); } } return str; } function hex_sha2(s) { return binb2hex(core_sha256(str2binb(s), s.length * chrsz)); } function b64_sha2(s) { return binb2b64(core_sha256(str2binb(s), s.length * chrsz)); } function str_sha2(s) { return binb2str(core_sha256(str2binb(s), s.length * chrsz)); } return hex_sha2(input); } ```