TSFoster / elm-sha1 / SHA1

SHA-1 is a cryptographic hash function. Although it is no longer considered cryptographically secure (as collisions can be found faster than brute force), it is still very suitable for a broad range of uses, and is a lot stronger than MD5.

This package provides a way of creating SHA-1 digests from Strings, Bytes, or List Ints (where each Int is between 0 and 255, and represents a byte). It can also take those Digests and format them in hexadecimal or base64 notation. Alternatively, you can get the binary digest, using either Bytes or List Int to represent the bytes.


type Digest

A type to represent a message digest. SHA1.Digests are equatable, and you may want to consider keeping any digests you need in your Model as Digests, not as Strings created by toHex or toBase64.

Creating digests

fromString : String -> Digest

Create a digest from a String.

"hello world" |> SHA1.fromString |> SHA1.toHex
--> "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed"

Formatting digests

toHex : Digest -> String

One of the two canonical ways of representing a SHA-1 digest is with 40 hexadecimal digits.

"And our friends are all aboard"
    |> SHA1.fromString
    |> SHA1.toHex
--> "f9a0c23ddcd40f6956b0cf59cd9b8800d71de73d"

toBase64 : Digest -> String

One of the two canonical ways of representing a SHA-1 digest is in a 20 digit long Base64 binary to ASCII text encoding.

"Many more of them live next door"
    |> SHA1.fromString
    |> SHA1.toBase64
--> "jfL0oVb5xakab6BMLplGe2XPbj8="

Binary data

fromBytes : Bytes -> Digest

Create a digest from Bytes

import Bytes.Encode as Encode
import Bytes exposing (Bytes, Endianness(..))

42
    |> Encode.unsignedInt32 BE
    |> Encode.encode
    |> SHA1.fromBytes
    |> SHA1.toHex
--> "25f0c736f1fad0770bbb9a265ded159517c1e68c"

fromByteValues : List Basics.Int -> Digest

Sometimes you have binary data that's not representable in a string. Create a digest from the raw "bytes", i.e. a List of Ints. Any items not between 0 and 255 are discarded.

SHA1.fromByteValues [72, 105, 33, 32, 240, 159, 152, 132]
--> SHA1.fromString "Hi! 😄"

[0x00, 0xFF, 0x34, 0xA5] |> SHA1.fromByteValues |> SHA1.toBase64
--> "sVQuFckyE6K3fsdLmLHmq8+J738="

toByteValues : Digest -> List Basics.Int

Turn a digest into List Int, each Int representing a byte of data.

"And the band begins to play"
    |> SHA1.fromString
    |> SHA1.toByteValues
--> [ 0xF3, 0x08, 0x73, 0x13
--> , 0xD6, 0xBC, 0xE5, 0x5B
--> , 0x60, 0x0C, 0x69, 0x2F
--> , 0xE0, 0x92, 0xF4, 0x53
--> , 0x87, 0x3F, 0xAE, 0x91
--> ]

Advanced usage

toInt32s : Digest -> { a : Basics.Int, b : Basics.Int, c : Basics.Int, d : Basics.Int, e : Basics.Int }

Internally, Digest models its 160 bits of data in 5 (unsigned 32-bit) Ints. If you really want to get the raw digest data for your own data processing, this function will allow you to do that.

"And the band begins to play"
    |> SHA1.fromString
    |> SHA1.toInt32s
--> { a = 0xF3087313
--> , b = 0xD6BCE55B
--> , c = 0x600C692F
--> , d = 0xE092F453
--> , e = 0x873FAE91
--> }