create or replace package body hash_util_pkg as type ta_number is table of number index by binary_integer; type tr_ctx is record ( h ta_number, total_length number, leftover_buffer raw(256), leftover_buffer_length number, words_array ta_number ); m_ctx tr_ctx; m_k ta_number; m_result ta_number; -- Constants for message padding c_bits_00 raw(1) := hextoraw('00'); c_bits_80 raw(1) := hextoraw('80'); -- Constant for 32bit bitwise operations c_bits_80000000 number := to_number('80000000','xxxxxxxx'); c_bits_ffffffc0 number := to_number('FFFFFFC0','xxxxxxxx'); c_bits_ffffffff number := to_number('FFFFFFFF','xxxxxxxx'); -- Constant for 64bit bitwise operations c_bits_8000000000000000 number := to_number('8000000000000000','xxxxxxxxxxxxxxxx'); c_bits_ffffffffffffff80 number := to_number('FFFFFFFFFFFFFF80','xxxxxxxxxxxxxxxx'); c_bits_ffffffffffffffff number := to_number('FFFFFFFFFFFFFFFF','xxxxxxxxxxxxxxxx'); --- --- Bitwise operators --- function bitor(x in number, y in number) return number as begin return (x + y - bitand(x, y)); end; function bitxor(x in number, y in number) return number as begin return bitor(x, y) - bitand(x, y); end; function bitnot32(x in number) return number as begin return c_bits_ffffffff - x; end; function leftshift32(x in number, y in number) return number as tmp number := x; begin for idx in 1..y loop tmp := tmp * 2; end loop; return bitand(tmp, c_bits_ffffffff); end; function rightshift32(x in number, y in number) return number as tmp number := x; begin for idx in 1..y loop tmp := trunc(tmp / 2); end loop; return bitand(tmp, c_bits_ffffffff); end; function cyclic32(x in number, y in number) return number as begin return bitor(rightshift32(x, y), leftshift32(x, 32-y)); end; function bitnot64(x in number) return number as begin return c_bits_ffffffffffffffff - x; end; function leftshift64(x in number, y in number) return number as tmp number := x; begin for idx in 1..y loop tmp := tmp * 2; end loop; return bitand(tmp, c_bits_ffffffffffffffff); end; function rightshift64(x in number, y in number) return number as tmp number := x; begin for idx in 1..y loop tmp := trunc(tmp / 2); end loop; return bitand(tmp, c_bits_ffffffffffffffff); end; function cyclic64(x in number, y in number) return number as begin return bitor(rightshift64(x, y), leftshift64(x, 64-y)); end; --- --- Operators defined in FIPS 180-2:4.1.2. --- function op_maj(x in number, y in number, z in number) return number as begin return bitxor(bitxor(bitand(x,y), bitand(x,z)), bitand(y,z)); end; function op_ch_32(x in number, y in number, z in number) return number as begin return bitxor(bitand(x, y), bitand(bitnot32(x), z)); end; function op_s0_32(x in number) return number as begin return bitxor(bitxor(cyclic32(x, 2), cyclic32(x, 13)), cyclic32(x, 22)); end; function op_s1_32(x in number) return number as begin return bitxor(bitxor(cyclic32(x, 6), cyclic32(x, 11)), cyclic32(x, 25)); end; function op_r0_32(x in number) return number as begin return bitxor(bitxor(cyclic32(x, 7), cyclic32(x, 18)), rightshift32(x, 3)); end; function op_r1_32(x in number) return number as begin return bitxor(bitxor(cyclic32(x, 17), cyclic32(x, 19)), rightshift32(x, 10)); end; function op_ch_64(x in number, y in number, z in number) return number as begin return bitxor(bitand(x, y), bitand(bitnot64(x), z)); end; function op_s0_64(x in number) return number as begin return bitxor(bitxor(cyclic64(x, 28), cyclic64(x, 34)), cyclic64(x, 39)); end; function op_s1_64(x in number) return number as begin return bitxor(bitxor(cyclic64(x, 14), cyclic64(x, 18)), cyclic64(x, 41)); end; function op_r0_64(x in number) return number as begin return bitxor(bitxor(cyclic64(x, 1), cyclic64(x, 8)), rightshift64(x, 7)); end; function op_r1_64(x in number) return number as begin return bitxor(bitxor(cyclic64(x, 19), cyclic64(x, 61)), rightshift64(x, 6)); end; -- -- SHA-1 -- procedure sha1_init_ctx as begin m_ctx.h(0) := to_number('67452301', 'xxxxxxxx'); m_ctx.h(1) := to_number('efcdab89', 'xxxxxxxx'); m_ctx.h(2) := to_number('98badcfe', 'xxxxxxxx'); m_ctx.h(3) := to_number('10325476', 'xxxxxxxx'); m_ctx.h(4) := to_number('c3d2e1f0', 'xxxxxxxx'); m_ctx.total_length := 0; m_ctx.leftover_buffer := null; m_ctx.leftover_buffer_length := 0; for idx in 0..15 loop m_ctx.words_array(idx) := 0; end loop; end sha1_init_ctx; procedure sha1_process_block(p_words_array in ta_number, p_words_count in number) as l_words_array ta_number := p_words_array; l_words_count number := p_words_count; l_words_idx number; t number; a number := m_ctx.h(0); b number := m_ctx.h(1); c number := m_ctx.h(2); d number := m_ctx.h(3); e number := m_ctx.h(4); w ta_number; a_save number; b_save number; c_save number; d_save number; e_save number; f number; k number; temp number; begin -- Process all bytes in the buffer with 64 bytes in each round of the loop. l_words_idx := 0; while (l_words_count > 0) loop a_save := a; b_save := b; c_save := c; d_save := d; e_save := e; for t in 0..15 loop w(t) := l_words_array(l_words_idx); l_words_idx := l_words_idx + 1; end loop; for t in 16..79 loop w(t) := cyclic32(bitxor(bitxor(bitxor(w(t-3), w(t-8)), w(t-14)), w(t-16)), 32-1); end loop; for t in 0..79 loop if t between 0 and 19 then f := bitor(bitand(b, c), bitand(bitnot32(b), d)); k := to_number('5a827999', 'xxxxxxxx'); elsif t between 20 and 39 then f := bitxor(bitxor(b, c), d); k := to_number('6ed9eba1', 'xxxxxxxx'); elsif t between 40 and 59 then f := bitor(bitor(bitand(b, c), bitand(b, d)), bitand(c, d)); k := to_number('8f1bbcdc', 'xxxxxxxx'); elsif t between 60 and 79 then f := bitxor(bitxor(b, c), d); k := to_number('ca62c1d6', 'xxxxxxxx'); end if; temp := bitand(cyclic32(a, 32-5) + f + e + k + w(t), c_bits_ffffffff); e := d; d := c; c := cyclic32(b, 32-30); b := a; a := temp; end loop; a := bitand(a + a_save, c_bits_ffffffff); b := bitand(b + b_save, c_bits_ffffffff); c := bitand(c + c_save, c_bits_ffffffff); d := bitand(d + d_save, c_bits_ffffffff); e := bitand(e + e_save, c_bits_ffffffff); -- Prepare for the next round. l_words_count := l_words_count - 16; end loop; -- Put checksum in context given as argument. m_ctx.h(0) := a; m_ctx.h(1) := b; m_ctx.h(2) := c; m_ctx.h(3) := d; m_ctx.h(4) := e; end sha1_process_block; procedure sha1_process_bytes(p_buffer in raw, p_buffer_length in number) as l_buffer raw(16640); l_buffer_length number; l_words_array ta_number; begin -- First increment the byte count. FIPS 180-2 specifies the possible -- length of the file up to 2^64 bits. Here we only compute the number of -- bytes. m_ctx.total_length := m_ctx.total_length + nvl(p_buffer_length, 0); -- When we already have some bits in our internal buffer concatenate both inputs first. if (m_ctx.leftover_buffer_length = 0) then l_buffer := p_buffer; l_buffer_length := nvl(p_buffer_length, 0); else l_buffer := m_ctx.leftover_buffer || p_buffer; l_buffer_length := m_ctx.leftover_buffer_length + nvl(p_buffer_length, 0); end if; -- Process available complete blocks. if (l_buffer_length >= 64) then declare l_words_count number := bitand(l_buffer_length, c_bits_ffffffc0) / 4; l_max_idx number := l_words_count - 1; l_numberraw raw(4); l_numberhex varchar(8); l_number number; begin for idx in 0..l_max_idx loop l_numberraw := sys.utl_raw.substr(l_buffer, idx * 4 + 1, 4); l_numberhex := rawtohex(l_numberraw); l_number := to_number(l_numberhex, 'xxxxxxxx'); l_words_array(idx) := l_number; end loop; sha1_process_block(l_words_array, l_words_count); l_buffer_length := bitand(l_buffer_length, 63); if (l_buffer_length > 0) then l_buffer := sys.utl_raw.substr(l_buffer, l_words_count * 4 + 1, l_buffer_length); end if; end; end if; -- Move remaining bytes into internal buffer. if (l_buffer_length > 0) then m_ctx.leftover_buffer := l_buffer; m_ctx.leftover_buffer_length := l_buffer_length; end if; end sha1_process_bytes; procedure sha1_finish_ctx(p_resultbuf out nocopy ta_number) as l_filesizeraw raw(8); begin m_ctx.leftover_buffer := m_ctx.leftover_buffer || c_bits_80; m_ctx.leftover_buffer_length := m_ctx.leftover_buffer_length + 1; while ((m_ctx.leftover_buffer_length mod 64) <> 56) loop m_ctx.leftover_buffer := m_ctx.leftover_buffer || c_bits_00; m_ctx.leftover_buffer_length := m_ctx.leftover_buffer_length + 1; end loop; l_filesizeraw := hextoraw(to_char(m_ctx.total_length * 8, 'FM0xxxxxxxxxxxxxxx')); m_ctx.leftover_buffer := m_ctx.leftover_buffer || l_filesizeraw; m_ctx.leftover_buffer_length := m_ctx.leftover_buffer_length + 8; sha1_process_bytes(null, 0); for idx in 0..4 loop p_resultbuf(idx) := m_ctx.h(idx); end loop; end sha1_finish_ctx; function sha1(p_buffer in raw) return sha1_checksum_raw as l_result sha1_checksum_raw; begin sha1_init_ctx; sha1_process_bytes(p_buffer, sys.utl_raw.length(p_buffer)); sha1_finish_ctx(m_result); l_result := hextoraw( to_char(m_result(0), 'FM0xxxxxxx') || to_char(m_result(1), 'FM0xxxxxxx') || to_char(m_result(2), 'FM0xxxxxxx') || to_char(m_result(3), 'FM0xxxxxxx') || to_char(m_result(4), 'FM0xxxxxxx') ); return l_result; end sha1; function sha1(p_buffer in blob) return sha1_checksum_raw as l_result sha1_checksum_raw; l_buffer raw(16384); l_amount number := 16384; l_offset number := 1; begin sha1_init_ctx; begin loop sys.dbms_lob.read(p_buffer, l_amount, l_offset, l_buffer); sha1_process_bytes(l_buffer, l_amount); l_offset := l_offset + l_amount; l_amount := 16384; end loop; exception when no_data_found then null; end; sha1_finish_ctx(m_result); l_result := hextoraw( to_char(m_result(0), 'FM0xxxxxxx') || to_char(m_result(1), 'FM0xxxxxxx') || to_char(m_result(2), 'FM0xxxxxxx') || to_char(m_result(3), 'FM0xxxxxxx') || to_char(m_result(4), 'FM0xxxxxxx') ); return l_result; end sha1; -- -- SHA-256 -- procedure sha256_init_k as begin m_k(0) := to_number('428a2f98', 'xxxxxxxx'); m_k(1) := to_number('71374491', 'xxxxxxxx'); m_k(2) := to_number('b5c0fbcf', 'xxxxxxxx'); m_k(3) := to_number('e9b5dba5', 'xxxxxxxx'); m_k(4) := to_number('3956c25b', 'xxxxxxxx'); m_k(5) := to_number('59f111f1', 'xxxxxxxx'); m_k(6) := to_number('923f82a4', 'xxxxxxxx'); m_k(7) := to_number('ab1c5ed5', 'xxxxxxxx'); m_k(8) := to_number('d807aa98', 'xxxxxxxx'); m_k(9) := to_number('12835b01', 'xxxxxxxx'); m_k(10) := to_number('243185be', 'xxxxxxxx'); m_k(11) := to_number('550c7dc3', 'xxxxxxxx'); m_k(12) := to_number('72be5d74', 'xxxxxxxx'); m_k(13) := to_number('80deb1fe', 'xxxxxxxx'); m_k(14) := to_number('9bdc06a7', 'xxxxxxxx'); m_k(15) := to_number('c19bf174', 'xxxxxxxx'); m_k(16) := to_number('e49b69c1', 'xxxxxxxx'); m_k(17) := to_number('efbe4786', 'xxxxxxxx'); m_k(18) := to_number('0fc19dc6', 'xxxxxxxx'); m_k(19) := to_number('240ca1cc', 'xxxxxxxx'); m_k(20) := to_number('2de92c6f', 'xxxxxxxx'); m_k(21) := to_number('4a7484aa', 'xxxxxxxx'); m_k(22) := to_number('5cb0a9dc', 'xxxxxxxx'); m_k(23) := to_number('76f988da', 'xxxxxxxx'); m_k(24) := to_number('983e5152', 'xxxxxxxx'); m_k(25) := to_number('a831c66d', 'xxxxxxxx'); m_k(26) := to_number('b00327c8', 'xxxxxxxx'); m_k(27) := to_number('bf597fc7', 'xxxxxxxx'); m_k(28) := to_number('c6e00bf3', 'xxxxxxxx'); m_k(29) := to_number('d5a79147', 'xxxxxxxx'); m_k(30) := to_number('06ca6351', 'xxxxxxxx'); m_k(31) := to_number('14292967', 'xxxxxxxx'); m_k(32) := to_number('27b70a85', 'xxxxxxxx'); m_k(33) := to_number('2e1b2138', 'xxxxxxxx'); m_k(34) := to_number('4d2c6dfc', 'xxxxxxxx'); m_k(35) := to_number('53380d13', 'xxxxxxxx'); m_k(36) := to_number('650a7354', 'xxxxxxxx'); m_k(37) := to_number('766a0abb', 'xxxxxxxx'); m_k(38) := to_number('81c2c92e', 'xxxxxxxx'); m_k(39) := to_number('92722c85', 'xxxxxxxx'); m_k(40) := to_number('a2bfe8a1', 'xxxxxxxx'); m_k(41) := to_number('a81a664b', 'xxxxxxxx'); m_k(42) := to_number('c24b8b70', 'xxxxxxxx'); m_k(43) := to_number('c76c51a3', 'xxxxxxxx'); m_k(44) := to_number('d192e819', 'xxxxxxxx'); m_k(45) := to_number('d6990624', 'xxxxxxxx'); m_k(46) := to_number('f40e3585', 'xxxxxxxx'); m_k(47) := to_number('106aa070', 'xxxxxxxx'); m_k(48) := to_number('19a4c116', 'xxxxxxxx'); m_k(49) := to_number('1e376c08', 'xxxxxxxx'); m_k(50) := to_number('2748774c', 'xxxxxxxx'); m_k(51) := to_number('34b0bcb5', 'xxxxxxxx'); m_k(52) := to_number('391c0cb3', 'xxxxxxxx'); m_k(53) := to_number('4ed8aa4a', 'xxxxxxxx'); m_k(54) := to_number('5b9cca4f', 'xxxxxxxx'); m_k(55) := to_number('682e6ff3', 'xxxxxxxx'); m_k(56) := to_number('748f82ee', 'xxxxxxxx'); m_k(57) := to_number('78a5636f', 'xxxxxxxx'); m_k(58) := to_number('84c87814', 'xxxxxxxx'); m_k(59) := to_number('8cc70208', 'xxxxxxxx'); m_k(60) := to_number('90befffa', 'xxxxxxxx'); m_k(61) := to_number('a4506ceb', 'xxxxxxxx'); m_k(62) := to_number('bef9a3f7', 'xxxxxxxx'); m_k(63) := to_number('c67178f2', 'xxxxxxxx'); end sha256_init_k; procedure sha256_init_ctx as begin m_ctx.h(0) := to_number('6a09e667', 'xxxxxxxx'); m_ctx.h(1) := to_number('bb67ae85', 'xxxxxxxx'); m_ctx.h(2) := to_number('3c6ef372', 'xxxxxxxx'); m_ctx.h(3) := to_number('a54ff53a', 'xxxxxxxx'); m_ctx.h(4) := to_number('510e527f', 'xxxxxxxx'); m_ctx.h(5) := to_number('9b05688c', 'xxxxxxxx'); m_ctx.h(6) := to_number('1f83d9ab', 'xxxxxxxx'); m_ctx.h(7) := to_number('5be0cd19', 'xxxxxxxx'); m_ctx.total_length := 0; m_ctx.leftover_buffer := null; m_ctx.leftover_buffer_length := 0; for idx in 0..15 loop m_ctx.words_array(idx) := 0; end loop; end sha256_init_ctx; procedure sha256_process_block(p_words_array in ta_number, p_words_count in number) as l_words_array ta_number := p_words_array; l_words_count number := p_words_count; l_words_idx number; t number; a number := m_ctx.h(0); b number := m_ctx.h(1); c number := m_ctx.h(2); d number := m_ctx.h(3); e number := m_ctx.h(4); f number := m_ctx.h(5); g number := m_ctx.h(6); h number := m_ctx.h(7); w ta_number; a_save number; b_save number; c_save number; d_save number; e_save number; f_save number; g_save number; h_save number; t1 number; t2 number; begin -- Process all bytes in the buffer with 64 bytes in each round of the loop. l_words_idx := 0; while (l_words_count > 0) loop a_save := a; b_save := b; c_save := c; d_save := d; e_save := e; f_save := f; g_save := g; h_save := h; -- Compute the message schedule according to FIPS 180-2:6.2.2 step 2. for t in 0..15 loop w(t) := l_words_array(l_words_idx); l_words_idx := l_words_idx + 1; end loop; for t in 16..63 loop w(t) := bitand(op_r1_32(w(t - 2)) + w(t - 7) + op_r0_32(w(t - 15)) + w(t - 16), c_bits_ffffffff); end loop; -- The actual computation according to FIPS 180-2:6.2.2 step 3. for t in 0..63 loop t1 := bitand(h + op_s1_32(e) + op_ch_32(e, f, g) + m_k(t) + w(t), c_bits_ffffffff); t2 := bitand(op_s0_32(a) + op_maj(a, b, c), c_bits_ffffffff); h := g; g := f; f := e; e := bitand(d + t1, c_bits_ffffffff); d := c; c := b; b := a; a := bitand(t1 + t2, c_bits_ffffffff); end loop; -- Add the starting values of the context according to FIPS 180-2:6.2.2 step 4. a := bitand(a + a_save, c_bits_ffffffff); b := bitand(b + b_save, c_bits_ffffffff); c := bitand(c + c_save, c_bits_ffffffff); d := bitand(d + d_save, c_bits_ffffffff); e := bitand(e + e_save, c_bits_ffffffff); f := bitand(f + f_save, c_bits_ffffffff); g := bitand(g + g_save, c_bits_ffffffff); h := bitand(h + h_save, c_bits_ffffffff); -- Prepare for the next round. l_words_count := l_words_count - 16; end loop; -- Put checksum in context given as argument. m_ctx.h(0) := a; m_ctx.h(1) := b; m_ctx.h(2) := c; m_ctx.h(3) := d; m_ctx.h(4) := e; m_ctx.h(5) := f; m_ctx.h(6) := g; m_ctx.h(7) := h; end sha256_process_block; procedure sha256_process_bytes(p_buffer in raw, p_buffer_length in number) as l_buffer raw(16640); l_buffer_length number; l_words_array ta_number; begin -- First increment the byte count. FIPS 180-2 specifies the possible -- length of the file up to 2^64 bits. Here we only compute the number of -- bytes. m_ctx.total_length := m_ctx.total_length + nvl(p_buffer_length, 0); -- When we already have some bits in our internal buffer concatenate both inputs first. if (m_ctx.leftover_buffer_length = 0) then l_buffer := p_buffer; l_buffer_length := nvl(p_buffer_length, 0); else l_buffer := m_ctx.leftover_buffer || p_buffer; l_buffer_length := m_ctx.leftover_buffer_length + nvl(p_buffer_length, 0); end if; -- Process available complete blocks. if (l_buffer_length >= 64) then declare l_words_count number := bitand(l_buffer_length, c_bits_ffffffc0) / 4; l_max_idx number := l_words_count - 1; l_numberraw raw(4); l_numberhex varchar2(8); l_number number; begin for idx in 0..l_max_idx loop l_numberraw := sys.utl_raw.substr(l_buffer, idx * 4 + 1, 4); l_numberhex := rawtohex(l_numberraw); l_number := to_number(l_numberhex,'xxxxxxxx'); l_words_array(idx) := l_number; end loop; sha256_process_block(l_words_array, l_words_count); l_buffer_length := bitand(l_buffer_length, 63); if (l_buffer_length > 0) then l_buffer := sys.utl_raw.substr(l_buffer, l_words_count * 4 + 1, l_buffer_length); end if; end; end if; -- Move remaining bytes into internal buffer. if (l_buffer_length > 0) then m_ctx.leftover_buffer := l_buffer; m_ctx.leftover_buffer_length := l_buffer_length; end if; end sha256_process_bytes; procedure sha256_finish_ctx(p_resultbuf out nocopy ta_number) as l_filesizeraw raw(8); begin m_ctx.leftover_buffer := m_ctx.leftover_buffer || c_bits_80; m_ctx.leftover_buffer_length := m_ctx.leftover_buffer_length + 1; while ((m_ctx.leftover_buffer_length mod 64) <> 56) loop m_ctx.leftover_buffer := m_ctx.leftover_buffer || c_bits_00; m_ctx.leftover_buffer_length := m_ctx.leftover_buffer_length + 1; end loop; l_filesizeraw := hextoraw(to_char(m_ctx.total_length * 8, 'FM0xxxxxxxxxxxxxxx')); m_ctx.leftover_buffer := m_ctx.leftover_buffer || l_filesizeraw; m_ctx.leftover_buffer_length := m_ctx.leftover_buffer_length + 8; sha256_process_bytes(null, 0); for idx in 0..7 loop p_resultbuf(idx) := m_ctx.h(idx); end loop; end sha256_finish_ctx; function sha256(p_buffer in raw) return sha256_checksum_raw as l_result sha256_checksum_raw; begin sha256_init_k; sha256_init_ctx; sha256_process_bytes(p_buffer, sys.utl_raw.length(p_buffer)); sha256_finish_ctx(m_result); l_result := hextoraw( to_char(m_result(0),'FM0xxxxxxx') || to_char(m_result(1),'FM0xxxxxxx') || to_char(m_result(2),'FM0xxxxxxx') || to_char(m_result(3),'FM0xxxxxxx') || to_char(m_result(4),'FM0xxxxxxx') || to_char(m_result(5),'FM0xxxxxxx') || to_char(m_result(6),'FM0xxxxxxx') || to_char(m_result(7),'FM0xxxxxxx') ); return l_result; end sha256; function sha256(p_buffer in blob) return sha256_checksum_raw as l_result sha256_checksum_raw; l_buffer raw(16384); l_amount number := 16384; l_offset number := 1; begin sha256_init_k; sha256_init_ctx; begin loop sys.dbms_lob.read(p_buffer, l_amount, l_offset, l_buffer); sha256_process_bytes(l_buffer, l_amount); l_offset := l_offset + l_amount; l_amount := 16384; end loop; exception when no_data_found then null; end; sha256_finish_ctx(m_result); l_result := hextoraw( to_char(m_result(0),'FM0xxxxxxx') || to_char(m_result(1),'FM0xxxxxxx') || to_char(m_result(2),'FM0xxxxxxx') || to_char(m_result(3),'FM0xxxxxxx') || to_char(m_result(4),'FM0xxxxxxx') || to_char(m_result(5),'FM0xxxxxxx') || to_char(m_result(6),'FM0xxxxxxx') || to_char(m_result(7),'FM0xxxxxxx') ); return l_result; end sha256; -- -- SHA-224 -- procedure sha224_init_ctx as begin m_ctx.h(0) := to_number('c1059ed8', 'xxxxxxxx'); m_ctx.h(1) := to_number('367cd507', 'xxxxxxxx'); m_ctx.h(2) := to_number('3070dd17', 'xxxxxxxx'); m_ctx.h(3) := to_number('f70e5939', 'xxxxxxxx'); m_ctx.h(4) := to_number('ffc00b31', 'xxxxxxxx'); m_ctx.h(5) := to_number('68581511', 'xxxxxxxx'); m_ctx.h(6) := to_number('64f98fa7', 'xxxxxxxx'); m_ctx.h(7) := to_number('befa4fa4', 'xxxxxxxx'); m_ctx.total_length := 0; m_ctx.leftover_buffer := null; m_ctx.leftover_buffer_length := 0; for idx in 0..15 loop m_ctx.words_array(idx) := 0; end loop; end sha224_init_ctx; function sha224(p_buffer in raw) return sha224_checksum_raw as l_result sha224_checksum_raw; begin sha256_init_k; sha224_init_ctx; sha256_process_bytes(p_buffer, sys.utl_raw.length(p_buffer)); sha256_finish_ctx(m_result); l_result := hextoraw( to_char(m_result(0),'FM0xxxxxxx') || to_char(m_result(1),'FM0xxxxxxx') || to_char(m_result(2),'FM0xxxxxxx') || to_char(m_result(3),'FM0xxxxxxx') || to_char(m_result(4),'FM0xxxxxxx') || to_char(m_result(5),'FM0xxxxxxx') || to_char(m_result(6),'FM0xxxxxxx') ); return l_result; end sha224; function sha224(p_buffer in blob) return sha224_checksum_raw as l_result sha224_checksum_raw; l_buffer raw(16384); l_amount number := 16384; l_offset number := 1; begin sha256_init_k; sha224_init_ctx; begin loop sys.dbms_lob.read(p_buffer, l_amount, l_offset, l_buffer); sha256_process_bytes(l_buffer, l_amount); l_offset := l_offset + l_amount; l_amount := 16384; end loop; exception when no_data_found then null; end; sha256_finish_ctx(m_result); l_result := hextoraw( to_char(m_result(0),'FM0xxxxxxx') || to_char(m_result(1),'FM0xxxxxxx') || to_char(m_result(2),'FM0xxxxxxx') || to_char(m_result(3),'FM0xxxxxxx') || to_char(m_result(4),'FM0xxxxxxx') || to_char(m_result(5),'FM0xxxxxxx') || to_char(m_result(6),'FM0xxxxxxx') ); return l_result; end sha224; -- -- SHA-512 -- procedure sha512_init_k as begin m_k(0) := to_number('428a2f98d728ae22', 'xxxxxxxxxxxxxxxx'); m_k(1) := to_number('7137449123ef65cd', 'xxxxxxxxxxxxxxxx'); m_k(2) := to_number('b5c0fbcfec4d3b2f', 'xxxxxxxxxxxxxxxx'); m_k(3) := to_number('e9b5dba58189dbbc', 'xxxxxxxxxxxxxxxx'); m_k(4) := to_number('3956c25bf348b538', 'xxxxxxxxxxxxxxxx'); m_k(5) := to_number('59f111f1b605d019', 'xxxxxxxxxxxxxxxx'); m_k(6) := to_number('923f82a4af194f9b', 'xxxxxxxxxxxxxxxx'); m_k(7) := to_number('ab1c5ed5da6d8118', 'xxxxxxxxxxxxxxxx'); m_k(8) := to_number('d807aa98a3030242', 'xxxxxxxxxxxxxxxx'); m_k(9) := to_number('12835b0145706fbe', 'xxxxxxxxxxxxxxxx'); m_k(10) := to_number('243185be4ee4b28c', 'xxxxxxxxxxxxxxxx'); m_k(11) := to_number('550c7dc3d5ffb4e2', 'xxxxxxxxxxxxxxxx'); m_k(12) := to_number('72be5d74f27b896f', 'xxxxxxxxxxxxxxxx'); m_k(13) := to_number('80deb1fe3b1696b1', 'xxxxxxxxxxxxxxxx'); m_k(14) := to_number('9bdc06a725c71235', 'xxxxxxxxxxxxxxxx'); m_k(15) := to_number('c19bf174cf692694', 'xxxxxxxxxxxxxxxx'); m_k(16) := to_number('e49b69c19ef14ad2', 'xxxxxxxxxxxxxxxx'); m_k(17) := to_number('efbe4786384f25e3', 'xxxxxxxxxxxxxxxx'); m_k(18) := to_number('0fc19dc68b8cd5b5', 'xxxxxxxxxxxxxxxx'); m_k(19) := to_number('240ca1cc77ac9c65', 'xxxxxxxxxxxxxxxx'); m_k(20) := to_number('2de92c6f592b0275', 'xxxxxxxxxxxxxxxx'); m_k(21) := to_number('4a7484aa6ea6e483', 'xxxxxxxxxxxxxxxx'); m_k(22) := to_number('5cb0a9dcbd41fbd4', 'xxxxxxxxxxxxxxxx'); m_k(23) := to_number('76f988da831153b5', 'xxxxxxxxxxxxxxxx'); m_k(24) := to_number('983e5152ee66dfab', 'xxxxxxxxxxxxxxxx'); m_k(25) := to_number('a831c66d2db43210', 'xxxxxxxxxxxxxxxx'); m_k(26) := to_number('b00327c898fb213f', 'xxxxxxxxxxxxxxxx'); m_k(27) := to_number('bf597fc7beef0ee4', 'xxxxxxxxxxxxxxxx'); m_k(28) := to_number('c6e00bf33da88fc2', 'xxxxxxxxxxxxxxxx'); m_k(29) := to_number('d5a79147930aa725', 'xxxxxxxxxxxxxxxx'); m_k(30) := to_number('06ca6351e003826f', 'xxxxxxxxxxxxxxxx'); m_k(31) := to_number('142929670a0e6e70', 'xxxxxxxxxxxxxxxx'); m_k(32) := to_number('27b70a8546d22ffc', 'xxxxxxxxxxxxxxxx'); m_k(33) := to_number('2e1b21385c26c926', 'xxxxxxxxxxxxxxxx'); m_k(34) := to_number('4d2c6dfc5ac42aed', 'xxxxxxxxxxxxxxxx'); m_k(35) := to_number('53380d139d95b3df', 'xxxxxxxxxxxxxxxx'); m_k(36) := to_number('650a73548baf63de', 'xxxxxxxxxxxxxxxx'); m_k(37) := to_number('766a0abb3c77b2a8', 'xxxxxxxxxxxxxxxx'); m_k(38) := to_number('81c2c92e47edaee6', 'xxxxxxxxxxxxxxxx'); m_k(39) := to_number('92722c851482353b', 'xxxxxxxxxxxxxxxx'); m_k(40) := to_number('a2bfe8a14cf10364', 'xxxxxxxxxxxxxxxx'); m_k(41) := to_number('a81a664bbc423001', 'xxxxxxxxxxxxxxxx'); m_k(42) := to_number('c24b8b70d0f89791', 'xxxxxxxxxxxxxxxx'); m_k(43) := to_number('c76c51a30654be30', 'xxxxxxxxxxxxxxxx'); m_k(44) := to_number('d192e819d6ef5218', 'xxxxxxxxxxxxxxxx'); m_k(45) := to_number('d69906245565a910', 'xxxxxxxxxxxxxxxx'); m_k(46) := to_number('f40e35855771202a', 'xxxxxxxxxxxxxxxx'); m_k(47) := to_number('106aa07032bbd1b8', 'xxxxxxxxxxxxxxxx'); m_k(48) := to_number('19a4c116b8d2d0c8', 'xxxxxxxxxxxxxxxx'); m_k(49) := to_number('1e376c085141ab53', 'xxxxxxxxxxxxxxxx'); m_k(50) := to_number('2748774cdf8eeb99', 'xxxxxxxxxxxxxxxx'); m_k(51) := to_number('34b0bcb5e19b48a8', 'xxxxxxxxxxxxxxxx'); m_k(52) := to_number('391c0cb3c5c95a63', 'xxxxxxxxxxxxxxxx'); m_k(53) := to_number('4ed8aa4ae3418acb', 'xxxxxxxxxxxxxxxx'); m_k(54) := to_number('5b9cca4f7763e373', 'xxxxxxxxxxxxxxxx'); m_k(55) := to_number('682e6ff3d6b2b8a3', 'xxxxxxxxxxxxxxxx'); m_k(56) := to_number('748f82ee5defb2fc', 'xxxxxxxxxxxxxxxx'); m_k(57) := to_number('78a5636f43172f60', 'xxxxxxxxxxxxxxxx'); m_k(58) := to_number('84c87814a1f0ab72', 'xxxxxxxxxxxxxxxx'); m_k(59) := to_number('8cc702081a6439ec', 'xxxxxxxxxxxxxxxx'); m_k(60) := to_number('90befffa23631e28', 'xxxxxxxxxxxxxxxx'); m_k(61) := to_number('a4506cebde82bde9', 'xxxxxxxxxxxxxxxx'); m_k(62) := to_number('bef9a3f7b2c67915', 'xxxxxxxxxxxxxxxx'); m_k(63) := to_number('c67178f2e372532b', 'xxxxxxxxxxxxxxxx'); m_k(64) := to_number('ca273eceea26619c', 'xxxxxxxxxxxxxxxx'); m_k(65) := to_number('d186b8c721c0c207', 'xxxxxxxxxxxxxxxx'); m_k(66) := to_number('eada7dd6cde0eb1e', 'xxxxxxxxxxxxxxxx'); m_k(67) := to_number('f57d4f7fee6ed178', 'xxxxxxxxxxxxxxxx'); m_k(68) := to_number('06f067aa72176fba', 'xxxxxxxxxxxxxxxx'); m_k(69) := to_number('0a637dc5a2c898a6', 'xxxxxxxxxxxxxxxx'); m_k(70) := to_number('113f9804bef90dae', 'xxxxxxxxxxxxxxxx'); m_k(71) := to_number('1b710b35131c471b', 'xxxxxxxxxxxxxxxx'); m_k(72) := to_number('28db77f523047d84', 'xxxxxxxxxxxxxxxx'); m_k(73) := to_number('32caab7b40c72493', 'xxxxxxxxxxxxxxxx'); m_k(74) := to_number('3c9ebe0a15c9bebc', 'xxxxxxxxxxxxxxxx'); m_k(75) := to_number('431d67c49c100d4c', 'xxxxxxxxxxxxxxxx'); m_k(76) := to_number('4cc5d4becb3e42b6', 'xxxxxxxxxxxxxxxx'); m_k(77) := to_number('597f299cfc657e2a', 'xxxxxxxxxxxxxxxx'); m_k(78) := to_number('5fcb6fab3ad6faec', 'xxxxxxxxxxxxxxxx'); m_k(79) := to_number('6c44198c4a475817', 'xxxxxxxxxxxxxxxx'); end sha512_init_k; procedure sha512_init_ctx as begin m_ctx.h(0) := to_number('6a09e667f3bcc908', 'xxxxxxxxxxxxxxxx'); m_ctx.h(1) := to_number('bb67ae8584caa73b', 'xxxxxxxxxxxxxxxx'); m_ctx.h(2) := to_number('3c6ef372fe94f82b', 'xxxxxxxxxxxxxxxx'); m_ctx.h(3) := to_number('a54ff53a5f1d36f1', 'xxxxxxxxxxxxxxxx'); m_ctx.h(4) := to_number('510e527fade682d1', 'xxxxxxxxxxxxxxxx'); m_ctx.h(5) := to_number('9b05688c2b3e6c1f', 'xxxxxxxxxxxxxxxx'); m_ctx.h(6) := to_number('1f83d9abfb41bd6b', 'xxxxxxxxxxxxxxxx'); m_ctx.h(7) := to_number('5be0cd19137e2179', 'xxxxxxxxxxxxxxxx'); m_ctx.total_length := 0; m_ctx.leftover_buffer := null; m_ctx.leftover_buffer_length := 0; for idx in 0..15 loop m_ctx.words_array(idx) := 0; end loop; end sha512_init_ctx; procedure sha512_process_block(p_words_array in ta_number, p_words_count in number) as l_words_array ta_number := p_words_array; l_words_count number := p_words_count; l_words_idx number; t number; a number := m_ctx.h(0); b number := m_ctx.h(1); c number := m_ctx.h(2); d number := m_ctx.h(3); e number := m_ctx.h(4); f number := m_ctx.h(5); g number := m_ctx.h(6); h number := m_ctx.h(7); w ta_number; a_save number; b_save number; c_save number; d_save number; e_save number; f_save number; g_save number; h_save number; t1 number; t2 number; begin -- Process all bytes in the buffer with 64 bytes in each round of the loop. l_words_idx := 0; while (l_words_count > 0) loop a_save := a; b_save := b; c_save := c; d_save := d; e_save := e; f_save := f; g_save := g; h_save := h; -- Compute the message schedule according to FIPS 180-2:6.2.2 step 2. for t in 0..15 loop w(t) := l_words_array(l_words_idx); l_words_idx := l_words_idx + 1; end loop; for t in 16..79 loop w(t) := bitand(op_r1_64(w(t - 2)) + w(t - 7) + op_r0_64(w(t - 15)) + w(t - 16), c_bits_ffffffffffffffff); end loop; -- The actual computation according to FIPS 180-2:6.2.2 step 3. for t in 0..79 loop t1 := bitand(h + op_s1_64(e) + op_ch_64(e, f, g) + m_k(t) + w(t), c_bits_ffffffffffffffff); t2 := bitand(op_s0_64(a) + op_maj(a, b, c), c_bits_ffffffffffffffff); h := g; g := f; f := e; e := bitand(d + t1, c_bits_ffffffffffffffff); d := c; c := b; b := a; a := bitand(t1 + t2, c_bits_ffffffffffffffff); end loop; -- Add the starting values of the context according to FIPS 180-2:6.2.2 step 4. a := bitand(a + a_save, c_bits_ffffffffffffffff); b := bitand(b + b_save, c_bits_ffffffffffffffff); c := bitand(c + c_save, c_bits_ffffffffffffffff); d := bitand(d + d_save, c_bits_ffffffffffffffff); e := bitand(e + e_save, c_bits_ffffffffffffffff); f := bitand(f + f_save, c_bits_ffffffffffffffff); g := bitand(g + g_save, c_bits_ffffffffffffffff); h := bitand(h + h_save, c_bits_ffffffffffffffff); -- Prepare for the next round. l_words_count := l_words_count - 16; end loop; -- Put checksum in context given as argument. m_ctx.h(0) := a; m_ctx.h(1) := b; m_ctx.h(2) := c; m_ctx.h(3) := d; m_ctx.h(4) := e; m_ctx.h(5) := f; m_ctx.h(6) := g; m_ctx.h(7) := h; end sha512_process_block; procedure sha512_process_bytes(p_buffer in raw, p_buffer_length in number) as l_buffer raw(16640); l_buffer_length number; l_words_array ta_number; begin m_ctx.total_length := m_ctx.total_length + nvl(p_buffer_length, 0); -- When we already have some bits in our internal buffer concatenate both inputs first. if (m_ctx.leftover_buffer_length = 0) then l_buffer := p_buffer; l_buffer_length := nvl(p_buffer_length, 0); else l_buffer := m_ctx.leftover_buffer || p_buffer; l_buffer_length := m_ctx.leftover_buffer_length + nvl(p_buffer_length, 0); end if; -- Process available complete blocks. if (l_buffer_length >= 128) then declare l_words_count number := bitand(l_buffer_length, c_bits_ffffffffffffff80) / 8; l_max_idx number := l_words_count - 1; l_numberraw raw(8); l_numberhex varchar2(16); l_number number; begin for idx in 0..l_max_idx loop l_numberraw := sys.utl_raw.substr(l_buffer, idx * 8 + 1, 8); l_numberhex := rawtohex(l_numberraw); l_number := to_number(l_numberhex,'xxxxxxxxxxxxxxxx'); l_words_array(idx) := l_number; end loop; sha512_process_block(l_words_array, l_words_count); l_buffer_length := bitand(l_buffer_length, 127); if (l_buffer_length > 0) then l_buffer := sys.utl_raw.substr(l_buffer, l_words_count * 8 + 1, l_buffer_length); end if; end; end if; -- Move remaining bytes into internal buffer. if (l_buffer_length > 0) then m_ctx.leftover_buffer := l_buffer; m_ctx.leftover_buffer_length := l_buffer_length; end if; end sha512_process_bytes; procedure sha512_finish_ctx(p_resultbuf out nocopy ta_number) as l_filesizeraw raw(16); begin m_ctx.leftover_buffer := m_ctx.leftover_buffer || c_bits_80; m_ctx.leftover_buffer_length := m_ctx.leftover_buffer_length + 1; while ((m_ctx.leftover_buffer_length mod 128) <> 112) loop m_ctx.leftover_buffer := m_ctx.leftover_buffer || c_bits_00; m_ctx.leftover_buffer_length := m_ctx.leftover_buffer_length + 1; end loop; l_filesizeraw := hextoraw(to_char(m_ctx.total_length * 8, 'FM0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')); m_ctx.leftover_buffer := m_ctx.leftover_buffer || l_filesizeraw; m_ctx.leftover_buffer_length := m_ctx.leftover_buffer_length + 16; sha512_process_bytes(null, 0); for idx in 0..7 loop p_resultbuf(idx) := m_ctx.h(idx); end loop; end sha512_finish_ctx; function sha512(p_buffer in raw) return sha512_checksum_raw as l_result sha512_checksum_raw; begin sha512_init_k; sha512_init_ctx; sha512_process_bytes(p_buffer, sys.utl_raw.length(p_buffer)); sha512_finish_ctx(m_result); l_result := hextoraw( to_char(m_result(0),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(1),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(2),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(3),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(4),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(5),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(6),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(7),'FM0xxxxxxxxxxxxxxx') ); return l_result; end sha512; function sha512(p_buffer in blob) return sha512_checksum_raw as l_result sha512_checksum_raw; l_buffer raw(16384); l_amount number := 16384; l_offset number := 1; begin sha512_init_k; sha512_init_ctx; begin loop sys.dbms_lob.read(p_buffer, l_amount, l_offset, l_buffer); sha512_process_bytes(l_buffer, l_amount); l_offset := l_offset + l_amount; l_amount := 16384; end loop; exception when no_data_found then null; end; sha512_finish_ctx(m_result); l_result := hextoraw( to_char(m_result(0),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(1),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(2),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(3),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(4),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(5),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(6),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(7),'FM0xxxxxxxxxxxxxxx') ); return l_result; end sha512; -- -- SHA-384 -- procedure sha384_init_ctx as begin m_ctx.h(0) := to_number('CBBB9D5DC1059ED8', 'xxxxxxxxxxxxxxxx'); m_ctx.h(1) := to_number('629A292A367CD507', 'xxxxxxxxxxxxxxxx'); m_ctx.h(2) := to_number('9159015A3070DD17', 'xxxxxxxxxxxxxxxx'); m_ctx.h(3) := to_number('152FECD8F70E5939', 'xxxxxxxxxxxxxxxx'); m_ctx.h(4) := to_number('67332667FFC00B31', 'xxxxxxxxxxxxxxxx'); m_ctx.h(5) := to_number('8EB44A8768581511', 'xxxxxxxxxxxxxxxx'); m_ctx.h(6) := to_number('DB0C2E0D64F98FA7', 'xxxxxxxxxxxxxxxx'); m_ctx.h(7) := to_number('47B5481DBEFA4FA4', 'xxxxxxxxxxxxxxxx'); m_ctx.total_length := 0; m_ctx.leftover_buffer := null; m_ctx.leftover_buffer_length := 0; for idx in 0..15 loop m_ctx.words_array(idx) := 0; end loop; end sha384_init_ctx; function sha384(p_buffer in raw) return sha384_checksum_raw as l_result sha384_checksum_raw; begin sha512_init_k; sha384_init_ctx; sha512_process_bytes(p_buffer, sys.utl_raw.length(p_buffer)); sha512_finish_ctx(m_result); l_result := hextoraw( to_char(m_result(0),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(1),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(2),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(3),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(4),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(5),'FM0xxxxxxxxxxxxxxx') ); return l_result; end sha384; function sha384(p_buffer in blob) return sha384_checksum_raw as l_result sha384_checksum_raw; l_buffer raw(16384); l_amount number := 16384; l_offset number := 1; begin sha512_init_k; sha384_init_ctx; begin loop sys.dbms_lob.read(p_buffer, l_amount, l_offset, l_buffer); sha512_process_bytes(l_buffer, l_amount); l_offset := l_offset + l_amount; l_amount := 16384; end loop; exception when no_data_found then null; end; sha512_finish_ctx(m_result); l_result := hextoraw( to_char(m_result(0),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(1),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(2),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(3),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(4),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(5),'FM0xxxxxxxxxxxxxxx') ); return l_result; end sha384; -- -- SHA-512/224 -- procedure sha512_224_init_ctx as begin m_ctx.h(0) := to_number('8C3D37C819544DA2', 'xxxxxxxxxxxxxxxx'); m_ctx.h(1) := to_number('73E1996689DCD4D6', 'xxxxxxxxxxxxxxxx'); m_ctx.h(2) := to_number('1DFAB7AE32FF9C82', 'xxxxxxxxxxxxxxxx'); m_ctx.h(3) := to_number('679DD514582F9FCF', 'xxxxxxxxxxxxxxxx'); m_ctx.h(4) := to_number('0F6D2B697BD44DA8', 'xxxxxxxxxxxxxxxx'); m_ctx.h(5) := to_number('77E36F7304C48942', 'xxxxxxxxxxxxxxxx'); m_ctx.h(6) := to_number('3F9D85A86A1D36C8', 'xxxxxxxxxxxxxxxx'); m_ctx.h(7) := to_number('1112E6AD91D692A1', 'xxxxxxxxxxxxxxxx'); m_ctx.total_length := 0; m_ctx.leftover_buffer := null; m_ctx.leftover_buffer_length := 0; for idx in 0..15 loop m_ctx.words_array(idx) := 0; end loop; end sha512_224_init_ctx; function sha512_224(p_buffer in raw) return sha224_checksum_raw as l_result sha224_checksum_raw; begin sha512_init_k; sha512_224_init_ctx; sha512_process_bytes(p_buffer, sys.utl_raw.length(p_buffer)); sha512_finish_ctx(m_result); l_result := hextoraw( to_char(m_result(0),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(1),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(2),'FM0xxxxxxxxxxxxxxx') || substr(to_char(m_result(3),'FM0xxxxxxxxxxxxxxx'), 1, 8) ); return l_result; end sha512_224; function sha512_224(p_buffer in blob) return sha224_checksum_raw as l_result sha224_checksum_raw; l_buffer raw(16384); l_amount number := 16384; l_offset number := 1; begin sha512_init_k; sha512_224_init_ctx; begin loop sys.dbms_lob.read(p_buffer, l_amount, l_offset, l_buffer); sha512_process_bytes(l_buffer, l_amount); l_offset := l_offset + l_amount; l_amount := 16384; end loop; exception when no_data_found then null; end; sha512_finish_ctx(m_result); l_result := hextoraw( to_char(m_result(0),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(1),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(2),'FM0xxxxxxxxxxxxxxx') || substr(to_char(m_result(3),'FM0xxxxxxxxxxxxxxx'), 1, 8) ); return l_result; end sha512_224; -- -- SHA-512/256 -- procedure sha512_256_init_ctx as begin m_ctx.h(0) := to_number('22312194FC2BF72C', 'xxxxxxxxxxxxxxxx'); m_ctx.h(1) := to_number('9F555FA3C84C64C2', 'xxxxxxxxxxxxxxxx'); m_ctx.h(2) := to_number('2393B86B6F53B151', 'xxxxxxxxxxxxxxxx'); m_ctx.h(3) := to_number('963877195940EABD', 'xxxxxxxxxxxxxxxx'); m_ctx.h(4) := to_number('96283EE2A88EFFE3', 'xxxxxxxxxxxxxxxx'); m_ctx.h(5) := to_number('BE5E1E2553863992', 'xxxxxxxxxxxxxxxx'); m_ctx.h(6) := to_number('2B0199FC2C85B8AA', 'xxxxxxxxxxxxxxxx'); m_ctx.h(7) := to_number('0EB72DDC81C52CA2', 'xxxxxxxxxxxxxxxx'); m_ctx.total_length := 0; m_ctx.leftover_buffer := null; m_ctx.leftover_buffer_length := 0; for idx in 0..15 loop m_ctx.words_array(idx) := 0; end loop; end sha512_256_init_ctx; function sha512_256(p_buffer in raw) return sha256_checksum_raw as l_result sha256_checksum_raw; begin sha512_init_k; sha512_256_init_ctx; sha512_process_bytes(p_buffer, sys.utl_raw.length(p_buffer)); sha512_finish_ctx(m_result); l_result := hextoraw( to_char(m_result(0),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(1),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(2),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(3),'FM0xxxxxxxxxxxxxxx') ); return l_result; end sha512_256; function sha512_256(p_buffer in blob) return sha256_checksum_raw as l_result sha256_checksum_raw; l_buffer raw(16384); l_amount number := 16384; l_offset number := 1; begin sha512_init_k; sha512_256_init_ctx; begin loop sys.dbms_lob.read(p_buffer, l_amount, l_offset, l_buffer); sha512_process_bytes(l_buffer, l_amount); l_offset := l_offset + l_amount; l_amount := 16384; end loop; exception when no_data_found then null; end; sha512_finish_ctx(m_result); l_result := hextoraw( to_char(m_result(0),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(1),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(2),'FM0xxxxxxxxxxxxxxx') || to_char(m_result(3),'FM0xxxxxxxxxxxxxxx') ); return l_result; end sha512_256; --- --- Unittest --- procedure unittest as l_blob blob; l_raw raw(100); begin dbms_lob.createtemporary(l_blob, true); l_raw := sys.utl_raw.cast_to_raw('The quick brown fox jumps over the lazy dog' || chr(13) || chr(10)); for i in 1..1000 loop dbms_lob.writeappend(l_blob, sys.utl_raw.length(l_raw), l_raw); end loop; if lower(rawtohex(sha1(sys.utl_raw.cast_to_raw('')))) = 'da39a3ee5e6b4b0d3255bfef95601890afd80709' then dbms_output.put_line('SHA-1. Test 1 passed'); else dbms_output.put_line('SHA-1. Test 1 failed'); end if; if lower(rawtohex(sha1(sys.utl_raw.cast_to_raw('The quick brown fox jumps over the lazy dog')))) = '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12' then dbms_output.put_line('SHA-1. Test 2 passed'); else dbms_output.put_line('SHA-1. Test 2 failed'); end if; if lower(rawtohex(sha1(l_blob))) = '65d489cb70cae1cd7661a3043dc6ee51e41efb01' then dbms_output.put_line('SHA-1. Test 3 passed'); else dbms_output.put_line('SHA-1. Test 3 failed'); end if; if lower(rawtohex(sha224(sys.utl_raw.cast_to_raw('')))) = 'd14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f' then dbms_output.put_line('SHA-224. Test 1 passed'); else dbms_output.put_line('SHA-224. Test 1 failed'); end if; if lower(rawtohex(sha224(sys.utl_raw.cast_to_raw('The quick brown fox jumps over the lazy dog')))) = '730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525' then dbms_output.put_line('SHA-224. Test 2 passed'); else dbms_output.put_line('SHA-224. Test 2 failed'); end if; if lower(rawtohex(sha224(l_blob))) = 'daa4ac7e3d679550368d98cbf59e0805fbccbdd9c88b41c879a3ad6c' then dbms_output.put_line('SHA-224. Test 3 passed'); else dbms_output.put_line('SHA-224. Test 3 failed'); end if; if lower(rawtohex(sha256(sys.utl_raw.cast_to_raw('')))) = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' then dbms_output.put_line('SHA-256. Test 1 passed'); else dbms_output.put_line('SHA-256. Test 1 failed'); end if; if lower(rawtohex(sha256(sys.utl_raw.cast_to_raw('The quick brown fox jumps over the lazy dog')))) = 'd7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592' then dbms_output.put_line('SHA-256. Test 2 passed'); else dbms_output.put_line('SHA-256. Test 2 failed'); end if; if lower(rawtohex(sha256(l_blob))) = '6a8fd57827ee3c24359730e5c64b6badc41da43758990964ff1b20e5d62ea5f0' then dbms_output.put_line('SHA-256. Test 3 passed'); else dbms_output.put_line('SHA-256. Test 3 failed'); end if; if lower(rawtohex(sha384(sys.utl_raw.cast_to_raw('')))) = '38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b' then dbms_output.put_line('SHA-384. Test 1 passed'); else dbms_output.put_line('SHA-384. Test 1 failed'); end if; if lower(rawtohex(sha384(sys.utl_raw.cast_to_raw('The quick brown fox jumps over the lazy dog')))) = 'ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1' then dbms_output.put_line('SHA-384. Test 2 passed'); else dbms_output.put_line('SHA-384. Test 2 failed'); end if; if lower(rawtohex(sha384(l_blob))) = '0f35cb80adadaede011868e4cb79d760ca5bc80a7e84075b1b3e703ca12cc13366bd60b42e699e2d3d1744a617ab50da' then dbms_output.put_line('SHA-384. Test 3 passed'); else dbms_output.put_line('SHA-384. Test 3 failed'); end if; if lower(rawtohex(sha512(sys.utl_raw.cast_to_raw('')))) = 'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e' then dbms_output.put_line('SHA-512. Test 1 passed'); else dbms_output.put_line('SHA-512. Test 1 failed'); end if; if lower(rawtohex(sha512(sys.utl_raw.cast_to_raw('The quick brown fox jumps over the lazy dog')))) = '07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6' then dbms_output.put_line('SHA-512. Test 2 passed'); else dbms_output.put_line('SHA-512. Test 2 failed'); end if; if lower(rawtohex(sha512(l_blob))) = '3211cc7c5868f4f14878f93ab5dc82a12d5e8b9dbdc65eb7c7793a368cc93fbb5d9c130333b87db538a1cf86911aa60e1da4248ab8c6bb5bc14d381f556b99f4' then dbms_output.put_line('SHA-512. Test 3 passed'); else dbms_output.put_line('SHA-512. Test 3 failed'); end if; if lower(rawtohex(sha512_224(sys.utl_raw.cast_to_raw('')))) = '6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4' then dbms_output.put_line('SHA-512/224. Test 1 passed'); else dbms_output.put_line('SHA-512/224. Test 1 failed'); end if; if lower(rawtohex(sha512_224(sys.utl_raw.cast_to_raw('The quick brown fox jumps over the lazy dog')))) = '944cd2847fb54558d4775db0485a50003111c8e5daa63fe722c6aa37' then dbms_output.put_line('SHA-512/224. Test 2 passed'); else dbms_output.put_line('SHA-512/224. Test 2 failed'); end if; if lower(rawtohex(sha512_256(sys.utl_raw.cast_to_raw('')))) = 'c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a' then dbms_output.put_line('SHA-512/256. Test 1 passed'); else dbms_output.put_line('SHA-512/256. Test 1 failed'); end if; if lower(rawtohex(sha512_256(sys.utl_raw.cast_to_raw('The quick brown fox jumps over the lazy dog')))) = 'dd9d67b371519c339ed8dbd25af90e976a1eeefd4ad3d889005e532fc5bef04d' then dbms_output.put_line('SHA-512/256. Test 2 passed'); else dbms_output.put_line('SHA-512/256. Test 2 failed'); end if; end unittest; end hash_util_pkg; /