Base58Check.hs (1407B)
1 {-# LANGUAGE ViewPatterns #-} 2 3 -- | 4 -- Module: Data.ByteString.Base58Check 5 -- Copyright: (c) 2024 Jared Tobin 6 -- License: MIT 7 -- Maintainer: Jared Tobin <jared@ppad.tech> 8 -- 9 -- base58check encoding and decoding of strict bytestrings. 10 -- 11 -- base58check is a versioned, checksummed base58 encoding. A checksum 12 -- is computed by SHA256d-ing a payload, appending its first 4 bytes, 13 -- and base58-encoding the result. 14 15 module Data.ByteString.Base58Check ( 16 encode 17 , decode 18 ) where 19 20 import Control.Monad (guard) 21 import qualified Crypto.Hash.SHA256 as SHA256 22 import qualified Data.ByteString as BS 23 import qualified Data.ByteString.Base58 as B58 24 25 -- | Encode a base256 'ByteString' as base58check. 26 -- 27 -- >>> encode (BS.singleton 0x00 <> "hello world") 28 -- "13vQB7B6MrGQZaxCqW9KER" 29 encode :: BS.ByteString -> BS.ByteString 30 encode pay = 31 let kek = BS.take 4 (SHA256.hash (SHA256.hash pay)) 32 in B58.encode (pay <> kek) 33 34 -- | Validate and decode a base58check-encoded string. Invalid 35 -- base58check inputs will produce 'Nothing'. 36 -- 37 -- >>> decode "13vQB7B6MrGQZaxCqW9KER" 38 -- Just "\NULhello world" 39 -- >>> decode "13uQB7B6MrGQZaxCqW9KER" -- s/v/u 40 -- Nothing 41 decode :: BS.ByteString -> Maybe BS.ByteString 42 decode mb = do 43 bs <- B58.decode mb 44 let len = BS.length bs 45 (pay, kek) = BS.splitAt (len - 4) bs 46 man = BS.take 4 (SHA256.hash (SHA256.hash pay)) 47 guard (kek == man) 48 pure pay 49