{-# LANGUAGE OverloadedStrings #-}
module Crypto.Ethereum.Signature
(
hashMessage
, signMessage
, signTransaction
) where
import Crypto.Hash (Digest, Keccak_256 (..), hashWith)
import Crypto.PubKey.ECC.ECDSA (PrivateKey (..))
import Data.ByteArray (ByteArray, ByteArrayAccess, convert)
import qualified Data.ByteArray as BA (length)
import Data.ByteString.Builder (intDec, toLazyByteString)
import qualified Data.ByteString.Lazy as LBS (toStrict)
import Data.Monoid ((<>))
import Data.Word (Word8)
import Crypto.Ecdsa.Signature (pack, sign)
signMessage :: (ByteArrayAccess message, ByteArray rsv)
=> PrivateKey
-> message
-> rsv
{-# INLINE signMessage #-}
signMessage pk = pack . sign pk . hashMessage
hashMessage :: ByteArrayAccess message => message -> Digest Keccak_256
hashMessage msg = hashWith Keccak_256 prefixed
where
len = LBS.toStrict . toLazyByteString . intDec . BA.length
prefixed = "\x19" <> "Ethereum Signed Message:\n" <> len msg <> convert msg
signTransaction :: ByteArray ba
=> (Maybe (Integer, Integer, Word8) -> ba)
-> PrivateKey
-> ba
signTransaction encode key = encode $ Just signed
where
unsigned = encode Nothing
signed = sign key (hashWith Keccak_256 unsigned)