This module contains functions to add padding for cryptographic hashes.
module Padding.Hash
(
sha1Padding, padSHA1
, md4Padding, padMD4
) where
import Bytes ( HasBytes(..), Bytes )
import Bytes.Integral ( bigEndian, littleEndian )
import qualified Data.ByteString as BAccording to RFC3174, SHA-1 padding consists of:
- A single '1' bit;
- Enough '0' bits to fill out the final block to 448 bits (56 bytes)
- The last 64 bits (8 bytes) are taken by the length (in bits) of the original mesage and are presented in 64-bit big-endian ("If l < 2^32 then the first word is all zeroes.")
In practice then, we append to a w-byte message:
sha1Padding :: Int -> Bytes
sha1Padding w =a single byte of value 128 (a single '1' followed by seven '0's);
B.singleton 128 <>(-(w + 9) mod 64) bytes of zero;
B.replicate ((-(w + 9)) `mod` 64) 0 <>and finally the big-endian 64-bit integer representation of 8w.
bigEndian 8 (w * 8)padSHA1 :: HasBytes text => text -> Bytes
padSHA1 text =
let bs = toBytes text
in bs <> sha1Padding (numBytes bs)MD4 padding is almost the same as SHA-1. However, the appended size is in two 32-bit big-endian words, presented in little-endian order. ("These bits are appended as two 32-bit words and appended low-order word first in accordance with the previous conventions.")
The cryptonite implementation, however, seems to use pure little endian.
md4Padding :: Int -> Bytes
md4Padding w = B.singleton 128 <>
B.replicate ((-(w + 9)) `mod` 64) 0 <>
littleEndian 8 (w * 8)
padMD4 :: HasBytes text => text -> Bytes
padMD4 text =
let bs = toBytes text
in bs <> md4Padding (numBytes bs)