ripple-0.1: Ripple/Sign.hs
module Ripple.Sign (signTransaction) where
import Data.Word (Word32)
import Control.Applicative ((<$>))
import Control.Arrow (first)
import Data.Binary (encode)
import qualified Data.Serialize as Serialize
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as LZ
import Crypto.Hash.CryptoAPI (SHA512, Hash(..), hash)
import Crypto.Types.PubKey.ECDSA (PrivateKey(..))
import Crypto.Random (CryptoRandomGen, GenError)
import ECDSA (sign, publicToBytes, publicFromPrivate, signatureEncodeDER)
import Ripple.Transaction
signTransaction :: (CryptoRandomGen g) =>
Transaction -> PrivateKey -> g -> Either GenError (Transaction, g)
signTransaction (Transaction fs) private g =
first (addSig . signatureEncodeDER) <$> sign private hash g
where
addSig s = Transaction ((TransactionSignature $ LZ.fromChunks [s]) : fs')
hash = signing_hash (Transaction fs')
fs' = SigningPublicKey publicKey : filter (not.isSPK) fs
publicKey = LZ.fromChunks [publicToBytes $ publicFromPrivate private]
isSPK :: Field -> Bool
isSPK (SigningPublicKey {}) = True
isSPK _ = False
hash_sign :: Word32
hash_sign = 0x53545800
compute_hash :: (Hash ctx d) => Transaction -> d
compute_hash t = hash (encode hash_sign `LZ.append` encode t)
signing_hash :: Transaction -> BS.ByteString
signing_hash t = BS.take 32 $ Serialize.encode sha512
where
sha512 = compute_hash t :: SHA512