{-# 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.Word (Word8)
import Crypto.Ecdsa.Signature (pack, sign)
signMessage :: (ByteArrayAccess message, ByteArray rsv)
=> PrivateKey
-> message
-> rsv
{-# INLINE signMessage #-}
signMessage :: PrivateKey -> message -> rsv
signMessage PrivateKey
pk = (Integer, Integer, Word8) -> rsv
forall rsv. ByteArray rsv => (Integer, Integer, Word8) -> rsv
pack ((Integer, Integer, Word8) -> rsv)
-> (message -> (Integer, Integer, Word8)) -> message -> rsv
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PrivateKey -> Digest Keccak_256 -> (Integer, Integer, Word8)
forall bin.
ByteArrayAccess bin =>
PrivateKey -> bin -> (Integer, Integer, Word8)
sign PrivateKey
pk (Digest Keccak_256 -> (Integer, Integer, Word8))
-> (message -> Digest Keccak_256)
-> message
-> (Integer, Integer, Word8)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. message -> Digest Keccak_256
forall message.
ByteArrayAccess message =>
message -> Digest Keccak_256
hashMessage
hashMessage :: ByteArrayAccess message => message -> Digest Keccak_256
hashMessage :: message -> Digest Keccak_256
hashMessage message
msg = Keccak_256 -> ByteString -> Digest Keccak_256
forall ba alg.
(ByteArrayAccess ba, HashAlgorithm alg) =>
alg -> ba -> Digest alg
hashWith Keccak_256
Keccak_256 ByteString
prefixed
where
len :: message -> ByteString
len = ByteString -> ByteString
LBS.toStrict (ByteString -> ByteString)
-> (message -> ByteString) -> message -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> ByteString
toLazyByteString (Builder -> ByteString)
-> (message -> Builder) -> message -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Builder
intDec (Int -> Builder) -> (message -> Int) -> message -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. message -> Int
forall ba. ByteArrayAccess ba => ba -> Int
BA.length
prefixed :: ByteString
prefixed = ByteString
"\x19" ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
"Ethereum Signed Message:\n" ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> message -> ByteString
len message
msg ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> message -> ByteString
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
convert message
msg
signTransaction :: ByteArray ba
=> (Maybe (Integer, Integer, Word8) -> ba)
-> PrivateKey
-> ba
signTransaction :: (Maybe (Integer, Integer, Word8) -> ba) -> PrivateKey -> ba
signTransaction Maybe (Integer, Integer, Word8) -> ba
encode PrivateKey
key = Maybe (Integer, Integer, Word8) -> ba
encode (Maybe (Integer, Integer, Word8) -> ba)
-> Maybe (Integer, Integer, Word8) -> ba
forall a b. (a -> b) -> a -> b
$ (Integer, Integer, Word8) -> Maybe (Integer, Integer, Word8)
forall a. a -> Maybe a
Just (Integer, Integer, Word8)
signed
where
unsigned :: ba
unsigned = Maybe (Integer, Integer, Word8) -> ba
encode Maybe (Integer, Integer, Word8)
forall a. Maybe a
Nothing
signed :: (Integer, Integer, Word8)
signed = PrivateKey -> Digest Keccak_256 -> (Integer, Integer, Word8)
forall bin.
ByteArrayAccess bin =>
PrivateKey -> bin -> (Integer, Integer, Word8)
sign PrivateKey
key (Keccak_256 -> ba -> Digest Keccak_256
forall ba alg.
(ByteArrayAccess ba, HashAlgorithm alg) =>
alg -> ba -> Digest alg
hashWith Keccak_256
Keccak_256 ba
unsigned)