blob: 9af3eb5d9fe2cb196e16fd20e7a18cc0790fd31d (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
module Base58 where
import Crypto.Hash
import Data.ByteArray (convert)
import qualified Data.ByteString as S
import Data.Maybe
import Data.List
import Data.Word ( Word8 )
import Control.Monad
base58chars :: [Char]
base58chars = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
base58digits :: [Char] -> Maybe [Int]
base58digits str = sequence mbs
where
mbs = map (flip elemIndex base58chars) str
-- 5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ
base58_decode :: [Char] -> Maybe (Word8,[Word8])
base58_decode str = do
ds <- base58digits str
let n = foldl' (\a b-> a*58 + b) 0 $ ( map fromIntegral ds :: [Integer] )
rbytes = unfoldr getbyte n
getbyte d = do
guard (d/=0)
let (q,b) = d `divMod` 256
return (fromIntegral b,q)
let (rcksum,rpayload) = splitAt 4 $ rbytes
a_payload = reverse rpayload
hash_result = S.take 4 . convert $ digest
where digest = hash diges1 :: Digest SHA256
diges1 = hash (S.pack a_payload) :: Digest SHA256
expected_hash = S.pack $ reverse rcksum
(network_id,payload) = splitAt 1 a_payload
network_id <- listToMaybe network_id
guard (hash_result==expected_hash)
return (network_id,payload)
base58_encode :: S.ByteString -> String
base58_encode hsh = replicate zcount '1' ++ map (base58chars !!) (reverse rdigits)
where
zcount = S.length . S.takeWhile (==0) $ hsh
cksum = S.take 4 (convert digest2 :: S.ByteString)
where digest2 = hash ( convert digest1 :: S.ByteString) :: Digest SHA256
digest1 = hash hsh :: Digest SHA256
n = foldl' (\a b->a*256+b) 0 . map asInteger $ concatMap S.unpack [hsh, cksum]
asInteger x = fromIntegral x :: Integer
rdigits = unfoldr getdigit n
where
getdigit d = do
guard (d/=0)
let (q,b) = d `divMod` 58
return (fromIntegral b,q)
|