Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Examples of SizedByteArray in Haskell

I've been trying to use the hsblst library and I having problems with Data.ByteArray.Sized. For example, to use keygen from Crypto.BLST with signature

keygen :: (ByteArrayAccess ba, 32 <= n, KnownNat n) => SizedByteArray n ba -> SecretKey

How do I make a SizedByteArray n ba object? In this link there is an example where

sk1 = keygen $ AS.unsafeSizedByteArray @32 @ByteString "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq"

where AS is an alias for Data.ByteArray.Sized. This example is not working for me. When I try to do the same those at_marks do not work.

Then I tried this code

import Data.ByteArray.Sized qualified as AS
import Data.Text.Encoding
import qualified Data.ByteString as B
import qualified Data.Text as T
import Data.Proxy (Proxy(..))
import Crypto.BLST

sk ="79cc407e6917b5673a1f6966c23c9e15\
     \d257e5ab46cfe7b9b2f64200f2b2843e"
skp = T.pack sk
skpb = encodeUtf8 skp

the name skpb is of type ByteString. So, according to the definition of sizedByteArray (shown below) I should get a Maybe SizedByteArray right?

-- | create a 'SizedByteArray' from the given 'ByteArrayAccess' if the
-- size is the same as the target size.
--
sizedByteArray :: forall n ba . (KnownNat n, ByteArrayAccess ba)
               => ba
               -> Maybe (SizedByteArray n ba)
sizedByteArray ba
    | length ba == n = Just $ SizedByteArray ba
    | otherwise      = Nothing
  where
    n = fromInteger $ natVal (Proxy @n)

After trying this I get these errors:

ghci> AS.sizedByteArray skpb

<interactive>:7:1: error: [GHC-39999]
    • No instance for ‘GHC.TypeNats.KnownNat n0’
        arising from a use of ‘it’
    • In the first argument of ‘print’, namely ‘it’
      In a stmt of an interactive GHCi command: print it

and

ghci> keygen $ AS.sizedByteArray skpb

<interactive>:8:1: error: [GHC-64725]
    • Cannot satisfy: 32 <= n0
    • In the first argument of ‘($)’, namely ‘keygen’
      In the expression: keygen $ AS.sizedByteArray skpb
      In an equation for ‘it’: it = keygen $ AS.sizedByteArray skpb

What am I doing wrong?

like image 954
Marcos Villagra Avatar asked Jan 21 '26 14:01

Marcos Villagra


1 Answers

The definition:

sk1 :: SecretKey
sk1 = keygen $ AS.unsafeSizedByteArray @32 @B.ByteString
               "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq"

will work fine, but you need to enable DataKinds to use 32 as a type, OverloadedStrings to use a string literal as a ByteString, and TypeApplications to allow those @-marks, which are applications to type-level arguments. So, the following should compile:

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}

import Crypto.BLST
import qualified Data.ByteArray.Sized as AS
import qualified Data.ByteString as B

sk1 :: SecretKey
sk1 = keygen $ AS.unsafeSizedByteArray @32 @B.ByteString
               "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq"

More generally, with those extensions enabled, you should be able to construct SizedByteArray values using any of the following methods:

-- type applications
sba2 = AS.unsafeSizedByteArray @64 @B.ByteString
       "0123456789012345678901234567890123456789012345678901234567890123"

-- top-level type signature
sba1 :: AS.SizedByteArray 64 B.ByteString
sba1 = AS.unsafeSizedByteArray
       "0123456789012345678901234567890123456789012345678901234567890123"

-- in-line type signature
sba3 = AS.unsafeSizedByteArray
       "0123456789012345678901234567890123456789012345678901234567890123"
       :: AS.SizedByteArray 64 B.ByteString

Note that these sizes aren't checked at compile time, so the following will compile:

sbabadlen = AS.unsafeSizedByteArray @100 @B.ByteString "too short"

but throw a runtime exception when it's evaluated. The "safe" version will also compile:

sbabadlen = AS.sizedByteArray @100 @B.ByteString "too short"

and will evaluate to Nothing instead of Just a SizedByteArray.

Oh, and I should add: there is no simple way of constructing a SizedByteArray without specifying its length explicitly in the source code, so that's why your attempt to have the compiler determine the length based on the actual contents failed with a missing KnownNat instance.

like image 101
K. A. Buhr Avatar answered Jan 24 '26 08:01

K. A. Buhr



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!