module Tezos.Crypto.P256
(
PublicKey (..)
, SecretKey
, Signature (..)
, detSecretKey
, toPublic
, publicKeyToBytes
, mkPublicKey
, publicKeyLengthBytes
, signatureToBytes
, mkSignature
, signatureLengthBytes
, formatPublicKey
, mformatPublicKey
, parsePublicKey
, formatSignature
, mformatSignature
, parseSignature
, checkSignature
) where
import Crypto.Random (getRandomBytes)
import Data.ByteArray (ByteArray, ByteArrayAccess)
import qualified Data.ByteArray as BA
import qualified Data.ByteString as BS
import Fmt (Buildable, build)
import Test.QuickCheck (Arbitrary(..), vector)
import Michelson.Text
import Tezos.Crypto.Util
newtype PublicKey = PublicKey
{ unPublicKey :: ByteString
} deriving stock (Show, Eq)
instance Arbitrary PublicKey where
arbitrary = toPublic <$> arbitrary
newtype SecretKey = SecretKey
{ unSecretKey :: ByteString
} deriving stock (Show, Eq)
detSecretKey :: ByteString -> SecretKey
detSecretKey seed =
SecretKey $ deterministic seed $ getRandomBytes publicKeyLengthBytes
instance Arbitrary SecretKey where
arbitrary = detSecretKey . BS.pack <$> vector 32
toPublic :: SecretKey -> PublicKey
toPublic = PublicKey . unSecretKey
newtype Signature = Signature
{ unSignature :: ByteString
} deriving stock (Show, Eq)
instance Arbitrary Signature where
arbitrary = Signature . BS.pack <$> replicateM signatureLengthBytes arbitrary
publicKeyToBytes :: forall ba. ByteArray ba => PublicKey -> ba
publicKeyToBytes = BA.convert . unPublicKey
mkPublicKey :: ByteArrayAccess ba => ba -> Either CryptoParseError PublicKey
mkPublicKey ba
| l == publicKeyLengthBytes =
Right $ PublicKey (BA.convert ba)
| otherwise =
Left $ CryptoParseUnexpectedLength "public key" l
where
l = BA.length ba
publicKeyLengthBytes :: Integral n => n
publicKeyLengthBytes = 33
signatureToBytes :: ByteArray ba => Signature -> ba
signatureToBytes = BA.convert . unSignature
mkSignature :: ByteArray ba => ba -> Either CryptoParseError Signature
mkSignature ba
| l == signatureLengthBytes =
Right $ Signature (BA.convert ba)
| otherwise =
Left $ CryptoParseUnexpectedLength "signature" l
where
l = BA.length ba
signatureLengthBytes :: Integral n => n
signatureLengthBytes = 64
publicKeyTag :: ByteString
publicKeyTag = "\003\178\139\127"
signatureTag :: ByteString
signatureTag = "\054\240\044\052"
formatPublicKey :: PublicKey -> Text
formatPublicKey = formatImpl @ByteString publicKeyTag . publicKeyToBytes
mformatPublicKey :: PublicKey -> MText
mformatPublicKey = mkMTextUnsafe . formatPublicKey
instance Buildable PublicKey where
build = build . formatPublicKey
parsePublicKey :: Text -> Either CryptoParseError PublicKey
parsePublicKey = parseImpl publicKeyTag mkPublicKey
formatSignature :: Signature -> Text
formatSignature = formatImpl @ByteString signatureTag . signatureToBytes
mformatSignature :: Signature -> MText
mformatSignature = mkMTextUnsafe . formatSignature
instance Buildable Signature where
build = build . formatSignature
parseSignature :: Text -> Either CryptoParseError Signature
parseSignature = parseImpl signatureTag mkSignature
checkSignature :: PublicKey -> Signature -> ByteString -> Bool
checkSignature _ _ _ = False