Skip to content

Commit de59699

Browse files
dcjonesstaticfloat
authored andcommitted
Optimize SHA1 implementation. (#47)
1 parent 5ca2ad1 commit de59699

File tree

5 files changed

+33
-28
lines changed

5 files changed

+33
-28
lines changed

src/common.jl

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@ function update!(context::T, data::U) where {T<:SHA_CTX,
1313
usedspace = context.bytecount % blocklen(T)
1414
while len - data_idx + usedspace >= blocklen(T)
1515
# Fill up as much of the buffer as we can with the data given us
16-
for i in 1:(blocklen(T) - usedspace)
17-
context.buffer[usedspace + i] = data[data_idx + i]
18-
end
16+
copy!(context.buffer, usedspace + 1, data, data_idx + 1, blocklen(T) - usedspace)
1917

2018
transform!(context)
2119
context.bytecount += blocklen(T) - usedspace
@@ -25,9 +23,7 @@ function update!(context::T, data::U) where {T<:SHA_CTX,
2523

2624
# There is less than a complete block left, but we need to save the leftovers into context.buffer:
2725
if len > data_idx
28-
for i = 1:(len - data_idx)
29-
context.buffer[usedspace + i] = data[data_idx + i]
30-
end
26+
copy!(context.buffer, usedspace + 1, data, data_idx + 1, len - data_idx)
3127
context.bytecount += len - data_idx
3228
end
3329
end

src/constants.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ const SHA3_ROTC = UInt64[
123123
]
124124

125125
# Permutation indices for SHA3 rounds (+1'ed so as to work with julia's 1-based indexing)
126-
const SHA3_PILN = UInt64[
126+
const SHA3_PILN = Int[
127127
11, 8, 12, 18, 19, 4, 6, 17, 9, 22, 25, 5,
128128
16, 24, 20, 14, 13, 3, 21, 15, 23, 10, 7, 2
129129
]

src/sha3.jl

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,43 +4,48 @@ function transform!(context::T) where {T<:SHA3_CTX}
44
for idx in 1:div(blocklen(T),8)
55
context.state[idx] = context.state[idx] unsafe_load(pbuf, idx)
66
end
7-
bc = Vector{UInt64}(uninitialized, 5)
7+
bc = context.bc
8+
state = context.state
89

910
# We always assume 24 rounds
10-
for round in 0:23
11+
@inbounds for round in 0:23
1112
# Theta function
1213
for i in 1:5
13-
bc[i] = context.state[i] context.state[i + 5] context.state[i + 10] context.state[i + 15] context.state[i + 20]
14+
bc[i] = state[i] state[i + 5] state[i + 10] state[i + 15] state[i + 20]
1415
end
1516

16-
for i in 1:5
17-
temp = bc[mod1(i + 4, 5)] L64(1, bc[mod1(i + 1, 5)])
18-
for j in 0:5:20
19-
context.state[i + j] = context.state[i + j] temp
17+
for i in 0:4
18+
temp = bc[rem(i + 4, 5) + 1] L64(1, bc[rem(i + 1, 5) + 1])
19+
j = 0
20+
while j <= 20
21+
state[Int(i + j + 1)] = state[i + j + 1] temp
22+
j += 5
2023
end
2124
end
2225

2326
# Rho Pi
24-
temp = context.state[2]
27+
temp = state[2]
2528
for i in 1:24
2629
j = SHA3_PILN[i]
27-
bc[1] = context.state[j]
28-
context.state[j] = L64(SHA3_ROTC[i], temp)
30+
bc[1] = state[j]
31+
state[j] = L64(SHA3_ROTC[i], temp)
2932
temp = bc[1]
3033
end
3134

3235
# Chi
33-
for j in 0:5:20
36+
j = 0
37+
while j <= 20
3438
for i in 1:5
35-
bc[i] = context.state[i + j]
39+
bc[i] = state[i + j]
3640
end
37-
for i in 1:5
38-
context.state[j + i] = context.state[j + i] (~bc[mod1(i + 1, 5)] & bc[mod1(i + 2, 5)])
41+
for i in 0:4
42+
state[j + i + 1] = state[j + i + 1] (~bc[rem(i + 1, 5) + 1] & bc[rem(i + 2, 5) + 1])
3943
end
44+
j += 5
4045
end
4146

4247
# Iota
43-
context.state[1] = context.state[1] SHA3_ROUND_CONSTS[round+1]
48+
state[1] = state[1] SHA3_ROUND_CONSTS[round+1]
4449
end
4550

4651
return context.state

src/types.jl

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,21 +51,25 @@ mutable struct SHA3_224_CTX <: SHA3_CTX
5151
state::Array{UInt64,1}
5252
bytecount::UInt128
5353
buffer::Array{UInt8,1}
54+
bc::Array{UInt64,1}
5455
end
5556
mutable struct SHA3_256_CTX <: SHA3_CTX
5657
state::Array{UInt64,1}
5758
bytecount::UInt128
5859
buffer::Array{UInt8,1}
60+
bc::Array{UInt64,1}
5961
end
6062
mutable struct SHA3_384_CTX <: SHA3_CTX
6163
state::Array{UInt64,1}
6264
bytecount::UInt128
6365
buffer::Array{UInt8,1}
66+
bc::Array{UInt64,1}
6467
end
6568
mutable struct SHA3_512_CTX <: SHA3_CTX
6669
state::Array{UInt64,1}
6770
bytecount::UInt128
6871
buffer::Array{UInt8,1}
72+
bc::Array{UInt64,1}
6973
end
7074

7175
# Define constants via functions so as not to bloat context objects. Yay dispatch!
@@ -111,10 +115,10 @@ SHA2_256_CTX() = SHA2_256_CTX(copy(SHA2_256_initial_hash_value), 0, zeros(UInt8,
111115
SHA2_384_CTX() = SHA2_384_CTX(copy(SHA2_384_initial_hash_value), 0, zeros(UInt8, blocklen(SHA2_384_CTX)))
112116
SHA2_512_CTX() = SHA2_512_CTX(copy(SHA2_512_initial_hash_value), 0, zeros(UInt8, blocklen(SHA2_512_CTX)))
113117

114-
SHA3_224_CTX() = SHA3_224_CTX(zeros(UInt64, 25), 0, zeros(UInt8, blocklen(SHA3_224_CTX)))
115-
SHA3_256_CTX() = SHA3_256_CTX(zeros(UInt64, 25), 0, zeros(UInt8, blocklen(SHA3_256_CTX)))
116-
SHA3_384_CTX() = SHA3_384_CTX(zeros(UInt64, 25), 0, zeros(UInt8, blocklen(SHA3_384_CTX)))
117-
SHA3_512_CTX() = SHA3_512_CTX(zeros(UInt64, 25), 0, zeros(UInt8, blocklen(SHA3_512_CTX)))
118+
SHA3_224_CTX() = SHA3_224_CTX(zeros(UInt64, 25), 0, zeros(UInt8, blocklen(SHA3_224_CTX)), Vector{UInt64}(5))
119+
SHA3_256_CTX() = SHA3_256_CTX(zeros(UInt64, 25), 0, zeros(UInt8, blocklen(SHA3_256_CTX)), Vector{UInt64}(5))
120+
SHA3_384_CTX() = SHA3_384_CTX(zeros(UInt64, 25), 0, zeros(UInt8, blocklen(SHA3_384_CTX)), Vector{UInt64}(5))
121+
SHA3_512_CTX() = SHA3_512_CTX(zeros(UInt64, 25), 0, zeros(UInt8, blocklen(SHA3_512_CTX)), Vector{UInt64}(5))
118122

119123
# Nickname'd outer constructor methods for SHA2
120124
const SHA224_CTX = SHA2_224_CTX
@@ -129,7 +133,7 @@ SHA1_CTX() = SHA1_CTX(copy(SHA1_initial_hash_value), 0, zeros(UInt8, blocklen(SH
129133
# Copy functions
130134
copy(ctx::T) where {T<:SHA1_CTX} = T(copy(ctx.state), ctx.bytecount, copy(ctx.buffer), copy(ctx.W))
131135
copy(ctx::T) where {T<:SHA2_CTX} = T(copy(ctx.state), ctx.bytecount, copy(ctx.buffer))
132-
copy(ctx::T) where {T<:SHA3_CTX} = T(copy(ctx.state), ctx.bytecount, copy(ctx.buffer))
136+
copy(ctx::T) where {T<:SHA3_CTX} = T(copy(ctx.state), ctx.bytecount, copy(ctx.buffer), Array{UInt64}(5))
133137

134138

135139
# Make printing these types a little friendlier

test/perf.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ function do_tests(filepath)
1212
print("read: ")
1313
@time begin
1414
const fh = open(filepath, "r")
15-
const bytes = readbytes(fh)
15+
const bytes = read(fh)
1616
end
1717
gc()
1818

0 commit comments

Comments
 (0)