diff --git a/src/constants.jl b/src/constants.jl index 37c152e..546aeee 100644 --- a/src/constants.jl +++ b/src/constants.jl @@ -13,7 +13,7 @@ const SHA1_initial_hash_value = UInt32[ # Hash constant words K for SHA-256: -const K256 = UInt32[ +const K256 = ( 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, @@ -30,7 +30,7 @@ const K256 = UInt32[ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -] +) # Initial hash value H for SHA-224: const SHA2_224_initial_hash_value = UInt32[ @@ -45,7 +45,7 @@ const SHA2_256_initial_hash_value = UInt32[ ] # Hash constant words K for SHA-384 and SHA-512: -const K512 = UInt64[ +const K512 = ( 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019, @@ -86,7 +86,7 @@ const K512 = UInt64[ 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817 -] +) # Initial hash value H for SHA-384 const SHA2_384_initial_hash_value = UInt64[ diff --git a/src/sha2.jl b/src/sha2.jl index 741e13f..0c64743 100644 --- a/src/sha2.jl +++ b/src/sha2.jl @@ -1,134 +1,135 @@ -function transform!(context::T) where {T<:Union{SHA2_224_CTX,SHA2_256_CTX}} - pbuf = buffer_pointer(context) - # Initialize registers with the previous intermediate values (our state) - a = context.state[1] - b = context.state[2] - c = context.state[3] - d = context.state[4] - e = context.state[5] - f = context.state[6] - g = context.state[7] - h = context.state[8] - - # Run initial rounds - for j = 1:16 - @inbounds begin - # We bitswap every input byte - v = bswap(unsafe_load(pbuf, j)) - unsafe_store!(pbuf, v, j) - - # Apply the SHA-256 compression function to update a..h - T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + v - T2 = Sigma0_256(a) + Maj(a, b, c) - h = g - g = f - f = e - e = UInt32(d + T1) - d = c - c = b - b = a - a = UInt32(T1 + T2) - end +macro R1_16(j, T) + + ww = (:a, :b, :c, :d, :e, :f, :g, :h) + + a = ww[((81 - j) % 8) + 1] + b = ww[((82 - j) % 8) + 1] + c = ww[((83 - j) % 8) + 1] + d = ww[((84 - j) % 8) + 1] + e = ww[((85 - j) % 8) + 1] + f = ww[((86 - j) % 8) + 1] + g = ww[((87 - j) % 8) + 1] + h = ww[((88 - j) % 8) + 1] + + if T == 512 + Sigma0 = :Sigma0_512 + Sigma1 = :Sigma1_512 + K = :K512 + elseif T == 256 + Sigma0 = :Sigma0_256 + Sigma1 = :Sigma1_256 + K = :K256 end - for j = 17:64 - @inbounds begin - # Implicit message block expansion: - s0 = unsafe_load(pbuf, mod1(j + 1, 16)) - s0 = sigma0_256(s0) - s1 = unsafe_load(pbuf, mod1(j + 14, 16)) - s1 = sigma1_256(s1) - - # Apply the SHA-256 compression function to update a..h - v = unsafe_load(pbuf, mod1(j, 16)) + s1 + unsafe_load(pbuf, mod1(j + 9, 16)) + s0 - unsafe_store!(pbuf, v, mod1(j, 16)) - T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + v - T2 = Sigma0_256(a) + Maj(a, b, c) - h = g - g = f - f = e - e = UInt32(d + T1) - d = c - c = b - b = a - a = UInt32(T1 + T2) - end + return esc(quote + # We byteswap every input byte + v = bswap(unsafe_load(pbuf, $j)) + unsafe_store!(pbuf, v, $j) + + # Apply the SHA-256 compression function to update a..h + T1 = $h + $Sigma1($e) + Ch($e, $f, $g) + $K[$j] + v + $h = $Sigma0($a) + Maj($a, $b, $c) + $d += T1 + $h += T1 + end) +end + +macro R17_80(j, T) + + ww = (:a, :b, :c, :d, :e, :f, :g, :h) + + a = ww[((81 - j) % 8) + 1] + b = ww[((82 - j) % 8) + 1] + c = ww[((83 - j) % 8) + 1] + d = ww[((84 - j) % 8) + 1] + e = ww[((85 - j) % 8) + 1] + f = ww[((86 - j) % 8) + 1] + g = ww[((87 - j) % 8) + 1] + h = ww[((88 - j) % 8) + 1] + + if T == 512 + Sigma0 = :Sigma0_512 + Sigma1 = :Sigma1_512 + sigma0 = :sigma0_512 + sigma1 = :sigma1_512 + K = :K512 + elseif T == 256 + Sigma0 = :Sigma0_256 + Sigma1 = :Sigma1_256 + sigma0 = :sigma0_256 + sigma1 = :sigma1_256 + K = :K256 end - # Compute the current intermediate hash value - context.state[1] += a - context.state[2] += b - context.state[3] += c - context.state[4] += d - context.state[5] += e - context.state[6] += f - context.state[7] += g - context.state[8] += h + return esc(quote + s0 = unsafe_load(pbuf, mod1($j + 1, 16)) + s0 = $sigma0(s0) + s1 = unsafe_load(pbuf, mod1($j + 14, 16)) + s1 = $sigma1(s1) + + # Apply the SHA-256 compression function to update a..h + v = unsafe_load(pbuf, mod1($j, 16)) + s1 + unsafe_load(pbuf, mod1($j + 9, 16)) + s0 + unsafe_store!(pbuf, v, mod1($j, 16)) + T1 = $h + $Sigma1($e) + Ch($e, $f, $g) + $K[$j] + v + $h = $Sigma0($a) + Maj($a, $b, $c) + $d += T1 + $h += T1 + end) end +macro R_init(T) + expr = :() + for i in 1:16 + expr = :($expr; @R1_16($i, $T)) + end + return esc(expr) +end -function transform!(context::Union{SHA2_384_CTX,SHA2_512_CTX}) - pbuf = buffer_pointer(context) - # Initialize registers with the prev. intermediate value - a = context.state[1] - b = context.state[2] - c = context.state[3] - d = context.state[4] - e = context.state[5] - f = context.state[6] - g = context.state[7] - h = context.state[8] +macro R_end(T) - for j = 1:16 - @inbounds begin - v = bswap(unsafe_load(pbuf, j)) - unsafe_store!(pbuf, v, j) - - # Apply the SHA-512 compression function to update a..h - T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + v - T2 = Sigma0_512(a) + Maj(a, b, c) - h = g - g = f - f = e - e = d + T1 - d = c - c = b - b = a - a = T1 + T2 - end + if T == 256 + n_rounds = 64 + elseif T == 512 + n_rounds = 80 + end + + expr = :() + for i in 17:n_rounds + expr = :($expr; @R17_80($i, $T)) + end + + return esc(expr) +end + +@generated function transform!(context::Union{SHA2_224_CTX, SHA2_256_CTX, + SHA2_384_CTX, SHA2_512_CTX}) + if context <: Union{SHA2_224_CTX,SHA2_256_CTX} + T = 256 + elseif context <: Union{SHA2_384_CTX,SHA2_512_CTX} + T = 512 end - for j = 17:80 + return quote + pbuf = buffer_pointer(context) + # Initialize registers with the previous intermediate values (our state) + a, b, c, d, e, f, g, h = context.state + + # Initial Rounds + @R_init($T) + + # Other Rounds + @R_end($T) + + # Compute the current intermediate hash value @inbounds begin - # Implicit message block expansion: - s0 = unsafe_load(pbuf, mod1(j + 1, 16)) - s0 = sigma0_512(s0) - s1 = unsafe_load(pbuf, mod1(j + 14, 16)) - s1 = sigma1_512(s1) - - # Apply the SHA-512 compression function to update a..h - v = unsafe_load(pbuf, mod1(j, 16)) + s1 + unsafe_load(pbuf, mod1(j + 9, 16)) + s0 - unsafe_store!(pbuf, v, mod1(j, 16)) - T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + v - T2 = Sigma0_512(a) + Maj(a, b, c) - h = g - g = f - f = e - e = d + T1 - d = c - c = b - b = a - a = T1 + T2 + context.state[1] += a + context.state[2] += b + context.state[3] += c + context.state[4] += d + context.state[5] += e + context.state[6] += f + context.state[7] += g + context.state[8] += h end end - - # Compute the current intermediate hash value - context.state[1] += a - context.state[2] += b - context.state[3] += c - context.state[4] += d - context.state[5] += e - context.state[6] += f - context.state[7] += g - context.state[8] += h end