Trying to pass a random string to SHA in Haskell

173 Views Asked by At

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]’
3

There are 3 best solutions below

0
chi On BEST ANSWER

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]
2
Cubic On

You need Data.ByteString.Lazy, not Data.ByteString.Char8.

In general, you almost never want Data.ByteString.Char8.

0
Thomas M. DuBuisson On

Just use the lazy bytestrings as @leftaroundabout mentioned. Your try didn't work because you want to pack from Strings, so you need to import the .Char8 module to achieve that:

import Data.ByteString.Lazy.Char8 as C