diff --git a/docs/src/index.md b/docs/src/index.md index e042a9a..0797f83 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -72,6 +72,8 @@ sha2_224 sha2_256 sha2_384 sha2_512 +sha2_512_224 +sha2_512_256 ``` **SHA-3** @@ -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** diff --git a/src/SHA.jl b/src/SHA.jl index 7aeac4b..dbc2acd 100644 --- a/src/SHA.jl +++ b/src/SHA.jl @@ -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 @@ -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), diff --git a/src/constants.jl b/src/constants.jl index 546aeee..59b24c2 100644 --- a/src/constants.jl +++ b/src/constants.jl @@ -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[ @@ -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, diff --git a/src/sha2.jl b/src/sha2.jl index 0c64743..b26e8cd 100644 --- a/src/sha2.jl +++ b/src/sha2.jl @@ -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 diff --git a/src/types.jl b/src/types.jl index 6bc83d2..7270425 100644 --- a/src/types.jl +++ b/src/types.jl @@ -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}} @@ -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 @@ -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 @@ -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 @@ -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)) @@ -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) +""" +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() @@ -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") diff --git a/test/constants.jl b/test/constants.jl index 0f11983..105940f 100644 --- a/test/constants.jl +++ b/test/constants.jl @@ -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( @@ -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", diff --git a/test/runtests.jl b/test/runtests.jl index cbd7c2f..2dd9106 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -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"