Follow upstream changes -- Bytestring updates
[git-darcs-import.git] / src / Crypt / SHA256.hs
blobe73f9e66a25967fd64cbe509652fb8d5e2293bf9
1 {-# OPTIONS_GHC -fffi -cpp #-}
2 {-# LANGUAGE CPP, ForeignFunctionInterface #-}
4 -- |
5 -- Module: Data.Digest.SHA256
6 -- Copyright: Zooko O'Whielacronx
7 -- License: GPL
8 --
9 -- Stability: experimental
11 -- ByteString-based, zero-copying binding to Crypto++'s sha interface
13 -- thanks to Don Stewart <dons@galois.com>, Matthew Sackman
14 -- <matthew@wellquite.org>, Brian O'Sullivan, lispy, Adam Langley
16 module Crypt.SHA256 ( sha256sum ) where
18 import Foreign
19 import Foreign.C.Types
20 import Numeric (showHex)
21 import Foreign.C.String ( withCString )
22 #if __GLASGOW_HASKELL__ > 606
23 import Data.ByteString.Unsafe (unsafeUseAsCStringLen)
24 #else
25 import Data.ByteString.Base (unsafeUseAsCStringLen)
26 #endif
27 import qualified Data.ByteString as B
29 sha256sum :: B.ByteString -> String
30 sha256sum p = unsafePerformIO $
31 withCString (take 64 $ repeat 'x') $ \digestCString ->
32 unsafeUseAsCStringLen p $ \(ptr,n) ->
33 do let digest = castPtr digestCString :: Ptr Word8
34 c_sha256 ptr (fromIntegral n) digest
35 go digest 0 []
36 where -- print it in 0-padded hex format
37 go :: Ptr Word8 -> Int -> [String] -> IO String
38 go q n acc | seq q n >= 32 = return $ concat (reverse acc)
39 | otherwise = do w <- peekElemOff q n
40 go q (n+1) (draw w : acc)
41 draw w = case showHex w [] of
42 [x] -> ['0', x]
43 x -> x
45 -- void sha256sum(const unsigned char *d, size_t n, unsigned char *md);
47 foreign import ccall unsafe "sha2.h sha256" c_sha256
48 :: Ptr CChar -> CSize -> Ptr Word8 -> IO ()