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