sha256

Pure Haskell SHA-256, HMAC-SHA256 (docs.ppad.tech/sha256).
git clone git://git.ppad.tech/sha256.git
Log | Files | Refs | README | LICENSE

commit db73828dd46029b902b1415bdda03aa5561d65cc
parent 3cc6c146ae36f67d73c6c207486a199dbc77658e
Author: Jared Tobin <jared@jtobin.io>
Date:   Mon,  6 Jan 2025 23:25:11 -0330

lib: minor optimisations

* avoid calling BS.length, using pattern synonym instead
* write fewer Word64's instead of more Word32's

Diffstat:
Mlib/Crypto/Hash/SHA256.hs | 47++++++++++++++++++++++-------------------------
1 file changed, 22 insertions(+), 25 deletions(-)

diff --git a/lib/Crypto/Hash/SHA256.hs b/lib/Crypto/Hash/SHA256.hs @@ -79,14 +79,14 @@ unsafe_splitAt n (BI.BS x l) = splitAt64 :: BL.ByteString -> SLPair splitAt64 = splitAt' (64 :: Int) where splitAt' _ BLI.Empty = SLPair mempty BLI.Empty - splitAt' n (BLI.Chunk c cs) = - if n < BS.length c + splitAt' n (BLI.Chunk c@(BI.PS _ _ l) cs) = + if n < l then -- n < BS.length c, so unsafe_splitAt is safe let !(SSPair c0 c1) = unsafe_splitAt n c in SLPair c0 (BLI.Chunk c1 cs) else - let SLPair cs' cs'' = splitAt' (n - BS.length c) cs + let SLPair cs' cs'' = splitAt' (n - l) cs in SLPair (c <> cs') cs'' -- variant of Data.ByteString.splitAt that behaves like an incremental @@ -110,10 +110,8 @@ sol l = -- RFC 6234 4.1 (strict) pad :: BS.ByteString -> BS.ByteString -pad m = BL.toStrict . BSB.toLazyByteString $ padded where - l = fi (BS.length m) +pad m@(BI.PS _ _ (fi -> l)) = BL.toStrict . BSB.toLazyByteString $ padded where padded = BSB.byteString m <> fill (sol l) (BSB.word8 0x80) - fill j !acc | j == 0 = acc <> BSB.word64BE (l * 8) | otherwise = fill (pred j) (acc <> BSB.word8 0x00) @@ -358,13 +356,16 @@ unsafe_hash_alg rs bs = block_hash rs (prepare_schedule (unsafe_parse bs)) -- register concatenation cat :: Registers -> BS.ByteString cat Registers {..} = - BL.toStrict - -- more efficient for small builder - . BE.toLazyByteStringWith (BE.safeStrategy 128 BE.smallChunkSize) mempty - $ mconcat [ - BSB.word32BE h0, BSB.word32BE h1, BSB.word32BE h2, BSB.word32BE h3 - , BSB.word32BE h4, BSB.word32BE h5, BSB.word32BE h6, BSB.word32BE h7 - ] + BL.toStrict + -- more efficient for small builder + . BE.toLazyByteStringWith (BE.safeStrategy 128 BE.smallChunkSize) mempty + $ BSB.word64BE w64_0 <> BSB.word64BE w64_1 + <> BSB.word64BE w64_2 <> BSB.word64BE w64_3 + where + !w64_0 = fi h0 `B.unsafeShiftL` 32 .|. fi h1 + !w64_1 = fi h2 `B.unsafeShiftL` 32 .|. fi h3 + !w64_2 = fi h4 `B.unsafeShiftL` 32 .|. fi h5 + !w64_3 = fi h6 `B.unsafeShiftL` 32 .|. fi h7 -- | Compute a condensed representation of a strict bytestring via -- SHA-256. @@ -439,7 +440,7 @@ hmac :: BS.ByteString -- ^ key -> BS.ByteString -- ^ text -> BS.ByteString -hmac mk text = +hmac mk@(BI.PS _ _ l) text = let step1 = k <> BS.replicate (64 - lk) 0x00 step2 = BS.map (B.xor 0x36) step1 step3 = step2 <> text @@ -448,11 +449,9 @@ hmac mk text = step6 = step5 <> step4 in hash step6 where - !(KeyAndLen k lk) = - let l = BS.length mk - in if l > 64 - then KeyAndLen (hash mk) 32 - else KeyAndLen mk l + !(KeyAndLen k lk) + | l > 64 = KeyAndLen (hash mk) 32 + | otherwise = KeyAndLen mk l -- | Produce a message authentication code for a lazy bytestring, based -- on the provided (strict, bytestring) key, via SHA-256. @@ -468,7 +467,7 @@ hmac_lazy :: BS.ByteString -- ^ key -> BL.ByteString -- ^ text -> BS.ByteString -hmac_lazy mk text = +hmac_lazy mk@(BI.PS _ _ l) text = let step1 = k <> BS.replicate (64 - lk) 0x00 step2 = BS.map (B.xor 0x36) step1 step3 = BL.fromStrict step2 <> text @@ -477,9 +476,7 @@ hmac_lazy mk text = step6 = step5 <> step4 in hash step6 where - !(KeyAndLen k lk) = - let l = BS.length mk - in if l > 64 - then KeyAndLen (hash mk) 32 - else KeyAndLen mk l + !(KeyAndLen k lk) + | l > 64 = KeyAndLen (hash mk) 32 + | otherwise = KeyAndLen mk l