Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SHA-512: impl SHA-512/224, SHA-512/256 #98

Merged
merged 6 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ sha2_224
sha2_256
sha2_384
sha2_512
sha2_512_224
sha2_512_256
```

**SHA-3**
Expand Down Expand Up @@ -150,6 +152,8 @@ SHA2_224_CTX
SHA2_256_CTX
SHA2_384_CTX
SHA2_512_CTX
SHA2_512_224_CTX
SHA2_512_256_CTX
```

**SHA-3**
Expand Down
4 changes: 4 additions & 0 deletions src/SHA.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,12 @@ module SHA
export sha1, SHA1_CTX, update!, digest!
export sha224, sha256, sha384, sha512
export sha2_224, sha2_256, sha2_384, sha2_512
export sha2_512_224, sha2_512_256
export sha3_224, sha3_256, sha3_384, sha3_512
export shake128, shake256
export SHA224_CTX, SHA256_CTX, SHA384_CTX, SHA512_CTX
export SHA2_224_CTX, SHA2_256_CTX, SHA2_384_CTX, SHA2_512_CTX
export SHA2_512_224_CTX, SHA2_512_256_CTX
export SHA3_224_CTX, SHA3_256_CTX, SHA3_384_CTX, SHA3_512_CTX
export SHAKE_128_CTX, SHAKE_256_CTX
export HMAC_CTX, hmac_sha1
Expand Down Expand Up @@ -74,6 +76,8 @@ for (f, ctx) in [(:sha1, :SHA1_CTX),
(:sha2_256, :SHA2_256_CTX),
(:sha2_384, :SHA2_384_CTX),
(:sha2_512, :SHA2_512_CTX),
(:sha2_512_224, :SHA2_512_224_CTX),
(:sha2_512_256, :SHA2_512_256_CTX),
(:sha3_224, :SHA3_224_CTX),
(:sha3_256, :SHA3_256_CTX),
(:sha3_384, :SHA3_384_CTX),
Expand Down
23 changes: 22 additions & 1 deletion src/constants.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# SHA initial hash values and constants
"""SHA initial hash values and constants

Reference:
- SHA-1, SHA2: FIPS 180-4: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
"""

# Hash constant words K for SHA1
const K1 = UInt32[
Expand Down Expand Up @@ -104,6 +108,23 @@ const SHA2_512_initial_hash_value = UInt64[
0x1f83d9abfb41bd6b, 0x5be0cd19137e2179
]

# Initial hash value H for SHA-512/224
const SHA2_512_224_initial_hash_value = UInt64[
0x8C3D37C819544DA2, 0x73E1996689DCD4D6,
0x1DFAB7AE32FF9C82, 0x679DD514582F9FCF,
0x0F6D2B697BD44DA8, 0x77E36F7304C48942,
0x3F9D85A86A1D36C8, 0x1112E6AD91D692A1
]

# Initial hash value H for SHA-512/256
const SHA2_512_256_initial_hash_value = UInt64[
0x22312194FC2BF72C, 0x9F555FA3C84C64C2,
0x2393B86B6F53B151, 0x963877195940EABD,
0x96283EE2A88EFFE3, 0xBE5E1E2553863992,
0x2B0199FC2C85B8AA, 0x0EB72DDC81C52CA2
]


# Round constants for SHA3 rounds
const SHA3_ROUND_CONSTS = UInt64[
0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
Expand Down
5 changes: 3 additions & 2 deletions src/sha2.jl
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,11 @@ macro R_end(T)
end

@generated function transform!(context::Union{SHA2_224_CTX, SHA2_256_CTX,
SHA2_384_CTX, SHA2_512_CTX})
SHA2_384_CTX, SHA2_512_CTX,
SHA2_512_224_CTX, SHA512_256_CTX})
if context <: Union{SHA2_224_CTX,SHA2_256_CTX}
T = 256
elseif context <: Union{SHA2_384_CTX,SHA2_512_CTX}
elseif context <: Union{SHA2_384_CTX,SHA2_512_CTX,SHA2_512_224_CTX,SHA512_256_CTX}
T = 512
end

Expand Down
44 changes: 42 additions & 2 deletions src/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,20 @@ mutable struct SHA2_512_CTX <: SHA2_CTX
used::Bool
end

mutable struct SHA2_512_224_CTX <: SHA2_CTX
state::Vector{UInt64}
bytecount::UInt128
buffer::Vector{UInt8}
used::Bool
end

mutable struct SHA2_512_256_CTX <: SHA2_CTX
state::Vector{UInt64}
bytecount::UInt128
buffer::Vector{UInt8}
used::Bool
end

function Base.getproperty(ctx::SHA2_CTX, fieldname::Symbol)
if fieldname === :state
return getfield(ctx, :state)::Union{Vector{UInt32},Vector{UInt64}}
Expand All @@ -64,7 +78,8 @@ const SHA224_CTX = SHA2_224_CTX
const SHA256_CTX = SHA2_256_CTX
const SHA384_CTX = SHA2_384_CTX
const SHA512_CTX = SHA2_512_CTX

const SHA512_224_CTX = SHA2_512_224_CTX
const SHA512_256_CTX = SHA2_512_256_CTX

# SHA3 224/256/384/512-bit context structures
mutable struct SHA3_224_CTX <: SHA3_CTX
Expand Down Expand Up @@ -123,6 +138,8 @@ digestlen(::Type{SHA3_256_CTX}) = 32
digestlen(::Type{SHA2_384_CTX}) = 48
digestlen(::Type{SHA3_384_CTX}) = 48
digestlen(::Type{SHA2_512_CTX}) = 64
digestlen(::Type{SHA2_512_224_CTX}) = 28
digestlen(::Type{SHA2_512_256_CTX}) = 32
digestlen(::Type{SHA3_512_CTX}) = 64

# SHA1 and SHA2 have differing element types for the internal state objects
Expand All @@ -131,6 +148,8 @@ state_type(::Type{SHA2_224_CTX}) = UInt32
state_type(::Type{SHA2_256_CTX}) = UInt32
state_type(::Type{SHA2_384_CTX}) = UInt64
state_type(::Type{SHA2_512_CTX}) = UInt64
state_type(::Type{SHA2_512_224_CTX}) = UInt64
state_type(::Type{SHA2_512_256_CTX}) = UInt64
state_type(::Type{T}) where {T<:SHA3_CTX} = UInt64

# blocklen is the number of bytes of data processed by the transform!() function at once
Expand All @@ -139,7 +158,8 @@ blocklen(::Type{SHA2_224_CTX}) = UInt64(64)
blocklen(::Type{SHA2_256_CTX}) = UInt64(64)
blocklen(::Type{SHA2_384_CTX}) = UInt64(128)
blocklen(::Type{SHA2_512_CTX}) = UInt64(128)

blocklen(::Type{SHA2_512_224_CTX}) = UInt64(128)
blocklen(::Type{SHA2_512_256_CTX}) = UInt64(128)
blocklen(::Type{SHA3_224_CTX}) = UInt64(25*8 - 2*digestlen(SHA3_224_CTX))
blocklen(::Type{SHA3_256_CTX}) = UInt64(25*8 - 2*digestlen(SHA3_256_CTX))
blocklen(::Type{SHA3_384_CTX}) = UInt64(25*8 - 2*digestlen(SHA3_384_CTX))
Expand Down Expand Up @@ -175,6 +195,24 @@ SHA2_384_CTX() = SHA2_384_CTX(copy(SHA2_384_initial_hash_value), 0, zeros(UInt8,
Construct an empty SHA2_512 context.
"""
SHA2_512_CTX() = SHA2_512_CTX(copy(SHA2_512_initial_hash_value), 0, zeros(UInt8, blocklen(SHA2_512_CTX)), false)
"""
SHA2_512_224_CTX()

Construct an empty SHA2_512/224 context and set the initial hash value.

For the source of the initial value,
refer to [FIPS 180-4, 5.3.6.1 SHA-512/224](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf)
"""
inkydragon marked this conversation as resolved.
Show resolved Hide resolved
SHA2_512_224_CTX() = SHA2_512_224_CTX(copy(SHA2_512_224_initial_hash_value), 0, zeros(UInt8, blocklen(SHA2_512_224_CTX)), false)
"""
SHA2_512_256_CTX()

Construct an empty SHA2_512/256 context and set the initial hash value.

For the source of the initial value,
refer to [FIPS 180-4, 5.3.6.2 SHA-512/256](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf)
"""
SHA2_512_256_CTX() = SHA2_512_256_CTX(copy(SHA2_512_256_initial_hash_value), 0, zeros(UInt8, blocklen(SHA2_512_256_CTX)), false)

"""
SHA3_224_CTX()
Expand Down Expand Up @@ -229,6 +267,8 @@ show(io::IO, ::SHA2_224_CTX) = print(io, "SHA2 224-bit hash state")
show(io::IO, ::SHA2_256_CTX) = print(io, "SHA2 256-bit hash state")
show(io::IO, ::SHA2_384_CTX) = print(io, "SHA2 384-bit hash state")
show(io::IO, ::SHA2_512_CTX) = print(io, "SHA2 512-bit hash state")
show(io::IO, ::SHA2_512_224_CTX) = print(io, "SHA2 512/224-bit hash state")
show(io::IO, ::SHA2_512_256_CTX) = print(io, "SHA2 512/256-bit hash state")
show(io::IO, ::SHA3_224_CTX) = print(io, "SHA3 224-bit hash state")
show(io::IO, ::SHA3_256_CTX) = print(io, "SHA3 256-bit hash state")
show(io::IO, ::SHA3_384_CTX) = print(io, "SHA3 384-bit hash state")
Expand Down
21 changes: 21 additions & 0 deletions test/constants.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,19 @@ data_desc = ["the empty string", "the string \"test\"", "lorem ipsum",
"0 file", "one million a's Array", "one million a's Tuple"]
sha_types = Dict(sha1 => SHA.SHA1_CTX,
sha2_224 => SHA.SHA2_224_CTX, sha2_256 => SHA.SHA2_256_CTX, sha2_384 => SHA.SHA2_384_CTX, sha2_512 => SHA.SHA2_512_CTX,
sha2_512_224 => SHA.SHA2_512_224_CTX, sha2_512_256 => SHA.SHA2_512_256_CTX,
sha3_224 => SHA.SHA3_224_CTX, sha3_256 => SHA.SHA3_256_CTX, sha3_384 => SHA.SHA3_384_CTX, sha3_512 => SHA.SHA3_512_CTX)
sha_funcs = [sha1,
sha2_224, sha2_256, sha2_384, sha2_512,
sha2_512_224, sha2_512_256,
sha3_224, sha3_256, sha3_384, sha3_512]
ctxs = [SHA1_CTX,
SHA2_224_CTX, SHA2_256_CTX, SHA2_384_CTX, SHA2_512_CTX,
SHA2_512_224_CTX, SHA2_512_256_CTX,
SHA3_224_CTX, SHA3_256_CTX, SHA3_384_CTX, SHA3_512_CTX]
shws = ["SHA1 hash state",
"SHA2 224-bit hash state", "SHA2 256-bit hash state", "SHA2 384-bit hash state", "SHA2 512-bit hash state",
"SHA2 512/224-bit hash state", "SHA2 512/256-bit hash state",
"SHA3 224-bit hash state", "SHA3 256-bit hash state", "SHA3 384-bit hash state", "SHA3 512-bit hash state"]

answers = Dict(
Expand Down Expand Up @@ -62,6 +66,23 @@ answers = Dict(
"e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b",
"e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"
],
sha2_512_224 => [
"6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4",
"06001bf08dfb17d2b54925116823be230e98b5c6c278303bc4909a8c",
"3a312b004a593b706790a4a5b25309eb7c83efb85a4d1f0a8440e09e",
"283bb59af7081ed08197227d8f65b9591ffe1155be43e9550e57f941",
"37ab331d76f0d36de422bd0edeb22a28accd487b7a8453ae965dd287",
"37ab331d76f0d36de422bd0edeb22a28accd487b7a8453ae965dd287"
],
sha2_512_256 => [
"c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a",
"3d37fe58435e0d87323dee4a2c1b339ef954de63716ee79f5747f94d974f913f",
"9423e3863ebb6f22b9464aeb873a39d757ef6b6a87c4bc55642f69052741fc43",
"10baad1713566ac2333467bddb0597dec9066120dd72ac2dcb8394221dcbe43d",
"9a59a052930187a97038cae692f30708aa6491923ef5194394dc68d56c74fb21",
"9a59a052930187a97038cae692f30708aa6491923ef5194394dc68d56c74fb21"
],

sha3_224 => [
"6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7",
"3797bf0afbbfca4a7bbba7602a2b552746876517a7f9b7ce2db0ae7b",
Expand Down
13 changes: 13 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,19 @@ end
end
end

@testset "SHA-512/t" begin
# https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA512_224.pdf
@test sha2_512_224("abc") |> bytes2hex ==
"4634270f707b6a54daae7530460842e20e37ed265ceee9a43e8924aa"
@test sha2_512_224("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu") |> bytes2hex ==
"23fec5bb94d60b23308192640b0c453335d664734fe40e7268674af9"
# https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA512_256.pdf
@test sha2_512_256("abc") |> bytes2hex ==
"53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23"
@test sha2_512_256("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu") |> bytes2hex ==
"3928e184fb8690f840da3988121d31be65cb9d3ef83ee6146feac861e19b563a"
end

@testset "SHA3" begin
@test sha3_512("0" ^ 70) |> bytes2hex ==
"1ec3e5ebb442c09e7ab7a1ee18edfa1a9ec771ad243e3e3d65cad1730416109a0890e29f9314babd7ab018a246b2f9639af29ee09aec2352a2f94dc12a2f6109"
Expand Down
Loading