Search code examples
haskellrandomshabytestring

Trying to pass a random string to SHA in Haskell


I'm trying to pass a random string (which happens to be a number) "4176730.5" to SHA in Haskell to get a larger random string like "2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881".

I have this code to generate a random number and cast it to a string

  num <- randomIO :: IO Float

  let x = C.pack (show (num*10000000))

  print x

but when I pass it to SHA with

  let a = sha256 x

I get the error

Couldn't match expected type ‘Data.ByteString.Lazy.Internal.ByteString’
            with actual type ‘C.ByteString’

I've tried casting my number to C.ByteString, but I think there are two types of Bytestring, according to the Haskell compiler.

The full code is:

import Data.Digest.Pure.SHA
import System.Random
import qualified Data.ByteString.Char8 as C

main :: IO ()

main = do
  num <- randomIO :: IO Float

  let x = C.pack (show (num*10000000))

  print x

  let a = sha256 x

      b = hmacSha256 "key" "some test message"
  mapM_ print [showDigest a, showDigest b]

Seeing as how there are apparently two types of Bytestring, and I'm casting to the wrong one, how do I cast my random string correctly?

Further to @Cubic's answer below if I replace import qualified Data.ByteString.Char8 as C with

import qualified Data.ByteString.Lazy as C

I just get these errors

Couldn't match type ‘Char’ with ‘GHC.Word.Word8’
Expected type: [GHC.Word.Word8]
  Actual type: String

and

Couldn't match expected type ‘C.ByteString’
            with actual type ‘[Char]’

Solution

  • The issue is that a ByteString is a sequence of bytes, while a String is a sequence of chars. There are many ways to turn chars into bytes, so you need to specify which encoding you want. Most likely, you want an ASCII or UTF8 encoding. If so, you can use this solution below, which converts strings into "UTF8 bytes" as needed.

    import Data.Digest.Pure.SHA
    import System.Random
    import qualified Data.ByteString.Lazy as C
    import qualified Data.ByteString.Lazy.UTF8 as U
    
    main :: IO ()
    
    main = do
      num <- randomIO :: IO Float
    
      let x = U.fromString (show (num*10000000))
    
      print x
    
      let a = sha256 x
    
          b = hmacSha256 (U.fromString "key") (U.fromString "some test message")
      mapM_ print [showDigest a, showDigest b]