diff --git a/.gitignore b/.gitignore index 43ddd09..9699d66 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ elm-stuff node_modules tests.js tests/Doc +tests/VerifyExamples diff --git a/elm.json b/elm.json index 2a7de94..b01a6a5 100644 --- a/elm.json +++ b/elm.json @@ -10,6 +10,8 @@ ], "elm-version": "0.19.0 <= v < 0.20.0", "dependencies": { + "TSFoster/elm-bytes-extra": "1.3.0 <= v < 2.0.0", + "elm/bytes": "1.0.8 <= v < 2.0.0", "elm/core": "1.0.0 <= v < 2.0.0", "ktonon/elm-word": "2.1.2 <= v < 3.0.0" }, diff --git a/run-short-tests.sh b/run-short-tests.sh index e2a0436..6c16cb6 100755 --- a/run-short-tests.sh +++ b/run-short-tests.sh @@ -2,5 +2,5 @@ set -e -elm-verify-examples +elm-verify-examples --run-tests elm-test tests/Doc/**/*.elm tests/HMACTests.elm tests/SHA2ShortTests.elm diff --git a/src/Crypto/Hash.elm b/src/Crypto/Hash.elm index f11eeb1..78bcdd8 100644 --- a/src/Crypto/Hash.elm +++ b/src/Crypto/Hash.elm @@ -1,15 +1,40 @@ -module Crypto.Hash exposing (sha224, sha256, sha384, sha512, sha512_224, sha512_256) +module Crypto.Hash exposing + ( sha224, sha256, sha384, sha512, sha512_224, sha512_256 + , sha224_bytes, sha256_bytes, sha384_bytes, sha512_bytes, sha512_224_bytes, sha512_256_bytes + ) -{-| Secure Hash Algorithms. +{-| + + +# Secure Hash Algorithms. + + +## Hash a string into a Hex string. @docs sha224, sha256, sha384, sha512, sha512_224, sha512_256 + +## Hash `Bytes` into a hex string. + +@docs sha224_bytes, sha256_bytes, sha384_bytes, sha512_bytes, sha512_224_bytes, sha512_256_bytes + -} +import Bytes exposing (Bytes) +import Bytes.Encode +import Bytes.Extra import Crypto.SHA as SHA import Crypto.SHA.Alg exposing (Alg(..)) -import Word.Bytes as Bytes -import Word.Hex as Hex +import Word.Bytes +import Word.Hex + + +stringDigest : Alg -> String -> String +stringDigest alg message = + message + |> Word.Bytes.fromUTF8 + |> SHA.digest alg + |> Word.Hex.fromWordArray {-| Secure Hash Algorithm using 32-bit words and 64 rounds (truncated). @@ -23,10 +48,7 @@ import Word.Hex as Hex -} sha224 : String -> String sha224 message = - message - |> Bytes.fromUTF8 - |> SHA.digest SHA224 - |> Hex.fromWordArray + stringDigest SHA224 message {-| Secure Hash Algorithm using 32-bit words and 64 rounds. @@ -37,10 +59,7 @@ sha224 message = -} sha256 : String -> String sha256 message = - message - |> Bytes.fromUTF8 - |> SHA.digest SHA256 - |> Hex.fromWordArray + stringDigest SHA256 message {-| Secure Hash Algorithm using 64-bit words and 80 rounds (truncated). @@ -51,10 +70,7 @@ sha256 message = -} sha384 : String -> String sha384 message = - message - |> Bytes.fromUTF8 - |> SHA.digest SHA384 - |> Hex.fromWordArray + stringDigest SHA384 message {-| Secure Hash Algorithm using 64-bit words and 80 rounds. @@ -65,10 +81,7 @@ sha384 message = -} sha512 : String -> String sha512 message = - message - |> Bytes.fromUTF8 - |> SHA.digest SHA512 - |> Hex.fromWordArray + stringDigest SHA512 message {-| Secure Hash Algorithm using 64-bit words and 80 rounds (truncated to 224). @@ -79,10 +92,7 @@ sha512 message = -} sha512_224 : String -> String sha512_224 message = - message - |> Bytes.fromUTF8 - |> SHA.digest SHA512_224 - |> Hex.fromWordArray + stringDigest SHA512_224 message {-| Secure Hash Algorithm using 64-bit words and 80 rounds (truncated to 256). @@ -93,7 +103,96 @@ sha512_224 message = -} sha512_256 : String -> String sha512_256 message = - message - |> Bytes.fromUTF8 - |> SHA.digest SHA512_256 - |> Hex.fromWordArray + stringDigest SHA512_256 message + + +bytesDigest : Alg -> Bytes -> String +bytesDigest alg bytes = + -- TODO: pull the chunks out one at a time, instead of copying the whole thing. + Bytes.Extra.toByteValues bytes + |> SHA.digest alg + |> Word.Hex.fromWordArray + + +{-| Secure Hash Algorithm using 32-bit words and 64 rounds (truncated). + + import Bytes.Encode + + Crypto.Hash.sha224_bytes (Bytes.Encode.encode <| Bytes.Encode.string "") + --> "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f" + + Crypto.Hash.sha224_bytes + (Bytes.Encode.encode <| + Bytes.Encode.string "The quick brown fox jumps over the lazy dog" + ) + --> "730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525" + +-} +sha224_bytes : Bytes -> String +sha224_bytes bytes = + bytesDigest SHA224 bytes + + +{-| Secure Hash Algorithm using 32-bit words and 64 rounds. + + import Bytes.Encode + + Crypto.Hash.sha256_bytes (Bytes.Encode.encode <| Bytes.Encode.string "") + --> "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + +-} +sha256_bytes : Bytes -> String +sha256_bytes bytes = + bytesDigest SHA256 bytes + + +{-| Secure Hash Algorithm using 64-bit words and 80 rounds (truncated). + + import Bytes.Encode + + Crypto.Hash.sha384_bytes (Bytes.Encode.encode <| Bytes.Encode.string "") + --> "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b" + +-} +sha384_bytes : Bytes -> String +sha384_bytes bytes = + bytesDigest SHA384 bytes + + +{-| Secure Hash Algorithm using 64-bit words and 80 rounds. + + import Bytes.Encode + + Crypto.Hash.sha512_bytes (Bytes.Encode.encode <| Bytes.Encode.string "") + --> "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e" + +-} +sha512_bytes : Bytes -> String +sha512_bytes bytes = + bytesDigest SHA512 bytes + + +{-| Secure Hash Algorithm using 64-bit words and 80 rounds (truncated to 224). + + import Bytes.Encode + + Crypto.Hash.sha512_224_bytes (Bytes.Encode.encode <| Bytes.Encode.string "") + --> "6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4" + +-} +sha512_224_bytes : Bytes -> String +sha512_224_bytes bytes = + bytesDigest SHA512_224 bytes + + +{-| Secure Hash Algorithm using 64-bit words and 80 rounds (truncated to 256). + + import Bytes.Encode + + Crypto.Hash.sha512_256_bytes (Bytes.Encode.encode <| Bytes.Encode.string "") + --> "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a" + +-} +sha512_256_bytes : Bytes -> String +sha512_256_bytes bytes = + bytesDigest SHA512_256 bytes