Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Schnorr signature support #258

Merged
merged 17 commits into from
Mar 2, 2022
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
226 changes: 112 additions & 114 deletions cardano-crypto-class/cardano-crypto-class.cabal
Original file line number Diff line number Diff line change
@@ -1,129 +1,127 @@
cabal-version: 2.2
cabal-version: 2.2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would have been better to leave the formatting style intact; reformatting file like this when you're only making minor changes produces "diff noise", makes code harder to merge / rebase, and makes it more difficult to spot the actual changes. Improving formatting is great, but I'd recommend (for the future) to do it in a separate commit.

name: cardano-crypto-class
version: 2.0.0
synopsis:
Type classes abstracting over cryptography primitives for Cardano

name: cardano-crypto-class
version: 2.0.0
synopsis: Type classes abstracting over cryptography primitives for Cardano
description: Type classes abstracting over cryptography primitives for Cardano
license: Apache-2.0
description:
Type classes abstracting over cryptography primitives for Cardano

license: Apache-2.0
license-files:
LICENSE
NOTICE
author: IOHK
maintainer: [email protected]
copyright: 2019-2021 IOHK
category: Currency
build-type: Simple
extra-source-files: README.md

author: IOHK
maintainer: [email protected]
copyright: 2019-2021 IOHK
category: Currency
build-type: Simple
extra-source-files: README.md

flag development
description: Disable `-Werror`
default: False
manual: True
description: Disable `-Werror`
default: False
manual: True

common base { build-depends: base >= 4.14 && < 4.15 }
common base
build-depends: base ^>=4.14

common project-config
default-language: Haskell2010
default-language: Haskell2010
ghc-options:
-Wall -Wcompat -Wincomplete-record-updates
-Wincomplete-uni-patterns -Wpartial-fields -Wredundant-constraints
-Wunused-packages

ghc-options: -Wall
-Wcompat
-Wincomplete-record-updates
-Wincomplete-uni-patterns
-Wpartial-fields
-Wredundant-constraints
-Wunused-packages

if (!flag(development))
ghc-options: -Werror
if !flag(development)
ghc-options: -Werror

library
import: base, project-config
hs-source-dirs: src
import: base, project-config
hs-source-dirs: src
exposed-modules:
Cardano.Crypto.DSIGN
Cardano.Crypto.Hash
Cardano.Crypto.KES
Cardano.Crypto.VRF

Cardano.Crypto.DSIGN.Class
Cardano.Crypto.DSIGN.Ed25519
Cardano.Crypto.DSIGN.Ed448
Cardano.Crypto.DSIGN.Mock
Cardano.Crypto.DSIGN.NeverUsed
Cardano.Crypto.DSIGN.SECP256k1

Cardano.Crypto.Hash.Blake2b
Cardano.Crypto.Hash.Class
Cardano.Crypto.Hash.NeverUsed
Cardano.Crypto.Hash.SHA256
Cardano.Crypto.Hash.SHA3_256
Cardano.Crypto.Hash.Short
Cardano.Crypto.Hash.Keccak256

Cardano.Crypto.KES.Class
Cardano.Crypto.KES.Mock
Cardano.Crypto.KES.NeverUsed
Cardano.Crypto.KES.Simple
Cardano.Crypto.KES.Single
Cardano.Crypto.KES.Sum
Cardano.Crypto.KES.CompactSingle
Cardano.Crypto.KES.CompactSum

Cardano.Crypto.PinnedSizedBytes
Cardano.Crypto.Seed
Cardano.Crypto.Util

Cardano.Crypto.VRF.Class
Cardano.Crypto.VRF.Mock
Cardano.Crypto.VRF.NeverUsed
Cardano.Crypto.VRF.Simple

Cardano.Crypto.Libsodium
Cardano.Crypto.Libsodium.C
Cardano.Crypto.Libsodium.Constants
Cardano.Crypto.Libsodium.Hash
Cardano.Crypto.Libsodium.Init
Cardano.Crypto.Libsodium.Memory
Cardano.Crypto.Libsodium.Memory.Internal
Cardano.Crypto.Libsodium.MLockedBytes
Cardano.Crypto.Libsodium.MLockedBytes.Internal
Cardano.Crypto.Libsodium.UnsafeC

Cardano.Foreign

other-modules: Cardano.Crypto.PackedBytes

build-depends: aeson
, base
, base16-bytestring >= 1
, bytestring
, cardano-binary
, cardano-prelude
, cereal
, cryptonite
, deepseq
, integer-gmp
, ghc-prim
, memory
, nothunks
, primitive
, serialise
, secp256k1-haskell
, text
, transformers
, vector

pkgconfig-depends: libsodium
Cardano.Crypto.DSIGN
Cardano.Crypto.DSIGN.Class
Cardano.Crypto.DSIGN.EcdsaSecp256k1
Cardano.Crypto.DSIGN.Ed25519
Cardano.Crypto.DSIGN.Ed448
Cardano.Crypto.DSIGN.Mock
Cardano.Crypto.DSIGN.NeverUsed
Cardano.Crypto.DSIGN.SchnorrSecp256k1
Cardano.Crypto.Hash
Cardano.Crypto.Hash.Blake2b
Cardano.Crypto.Hash.Class
Cardano.Crypto.Hash.Keccak256
Cardano.Crypto.Hash.NeverUsed
Cardano.Crypto.Hash.SHA256
Cardano.Crypto.Hash.SHA3_256
Cardano.Crypto.Hash.Short
Cardano.Crypto.KES
Cardano.Crypto.KES.Class
Cardano.Crypto.KES.CompactSingle
Cardano.Crypto.KES.CompactSum
Cardano.Crypto.KES.Mock
Cardano.Crypto.KES.NeverUsed
Cardano.Crypto.KES.Simple
Cardano.Crypto.KES.Single
Cardano.Crypto.KES.Sum
Cardano.Crypto.Libsodium
Cardano.Crypto.Libsodium.C
Cardano.Crypto.Libsodium.Constants
Cardano.Crypto.Libsodium.Hash
Cardano.Crypto.Libsodium.Init
Cardano.Crypto.Libsodium.Memory
Cardano.Crypto.Libsodium.Memory.Internal
Cardano.Crypto.Libsodium.MLockedBytes
Cardano.Crypto.Libsodium.MLockedBytes.Internal
Cardano.Crypto.Libsodium.UnsafeC
Cardano.Crypto.PinnedSizedBytes
Cardano.Crypto.Seed
Cardano.Crypto.Util
Cardano.Crypto.VRF
Cardano.Crypto.VRF.Class
Cardano.Crypto.VRF.Mock
Cardano.Crypto.VRF.NeverUsed
Cardano.Crypto.VRF.Simple
Cardano.Foreign

other-modules:
Cardano.Crypto.PackedBytes
Cardano.Crypto.Schnorr

build-depends:
, aeson
, base
, base16-bytestring >=1
, bytestring
, cardano-binary
, cardano-prelude
, cereal
, cryptonite
, deepseq
, ghc-prim
, integer-gmp
, memory
, nothunks
, primitive
, secp256k1-haskell
, serialise
, text
, transformers
, vector

pkgconfig-depends: libsodium -any, libsecp256k1 -any

test-suite test-memory-example
import: base, project-config
type: exitcode-stdio-1.0
hs-source-dirs: memory-example
main-is: Main.hs

build-depends: base
, bytestring
, cardano-crypto-class

if os(linux) || os(osx)
build-depends: unix
import: base, project-config
type: exitcode-stdio-1.0
hs-source-dirs: memory-example
main-is: Main.hs
build-depends:
, base
, bytestring
, cardano-crypto-class

if (os(linux) || os(osx))
build-depends: unix
3 changes: 2 additions & 1 deletion cardano-crypto-class/src/Cardano/Crypto/DSIGN.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ import Cardano.Crypto.DSIGN.Ed25519 as X
import Cardano.Crypto.DSIGN.Ed448 as X
import Cardano.Crypto.DSIGN.Mock as X
import Cardano.Crypto.DSIGN.NeverUsed as X
import Cardano.Crypto.DSIGN.SECP256k1 as X
import Cardano.Crypto.DSIGN.EcdsaSecp256k1 as X
import Cardano.Crypto.DSIGN.SchnorrSecp256k1 as X
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@
{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_GHC -Wno-orphans #-} -- need NoThunks for secp256k1-haskell types

module Cardano.Crypto.DSIGN.SECP256k1 where
module Cardano.Crypto.DSIGN.EcdsaSecp256k1 (
EcdsaSecp256k1DSIGN,
VerKeyDSIGN (..),
SignKeyDSIGN (..),
SigDSIGN (..)
) where

import Cardano.Binary (FromCBOR (fromCBOR), ToCBOR (toCBOR, encodedSizeExpr))
import Data.ByteString (ByteString)
Expand Down Expand Up @@ -51,67 +56,75 @@ import Cardano.Crypto.DSIGN.Class (
decodeSigDSIGN
)

data SECP256k1DSIGN
data EcdsaSecp256k1DSIGN

instance NoThunks (VerKeyDSIGN SECP256k1DSIGN)
instance NoThunks (VerKeyDSIGN EcdsaSecp256k1DSIGN)

instance NoThunks (SignKeyDSIGN SECP256k1DSIGN)
instance NoThunks (SignKeyDSIGN EcdsaSecp256k1DSIGN)

instance NoThunks (SigDSIGN SECP256k1DSIGN)
instance NoThunks (SigDSIGN EcdsaSecp256k1DSIGN)

instance DSIGNAlgorithm SECP256k1DSIGN where
type SeedSizeDSIGN SECP256k1DSIGN = 32
type SizeSigDSIGN SECP256k1DSIGN = 64
type SizeSignKeyDSIGN SECP256k1DSIGN = 32
type SizeVerKeyDSIGN SECP256k1DSIGN = 64
type Signable SECP256k1DSIGN = ((~) SECP.Msg)
newtype VerKeyDSIGN SECP256k1DSIGN = VerKeySECP256k1 SECP.PubKey
instance DSIGNAlgorithm EcdsaSecp256k1DSIGN where
type SeedSizeDSIGN EcdsaSecp256k1DSIGN = 32
type SizeSigDSIGN EcdsaSecp256k1DSIGN = 64
type SizeSignKeyDSIGN EcdsaSecp256k1DSIGN = 32
type SizeVerKeyDSIGN EcdsaSecp256k1DSIGN = 64
type Signable EcdsaSecp256k1DSIGN = ((~) SECP.Msg)
newtype VerKeyDSIGN EcdsaSecp256k1DSIGN =
VerKeyEcdsaSecp256k1 SECP.PubKey
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SECP is still Crypto.Secp256k1. Are these SECP associated types and functions (e.g. SECP.PubKey, SECP.derivePubKey, SECP.signMsg) here and below still exclusively linked to ECDSA?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, they are. I could rename the import if that would be clearer, but I figured it wouldn't matter much.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem I see is that in the import

import qualified Crypto.Secp256k1 as SECP

there is no mention whatsoever to the actual signing algorithm. I would change the import to

import qualified Crypto.EcdsaSecp256k1 as SECP

or, if it is not possible, to

import qualified Crypto.Secp256k1 as ECDSA

deriving newtype (Eq, NFData)
deriving stock (Show, Generic)
newtype SignKeyDSIGN SECP256k1DSIGN = SignKeySECP256k1 SECP.SecKey
newtype SignKeyDSIGN EcdsaSecp256k1DSIGN =
SignKeyEcdsaSecp256k1 SECP.SecKey
deriving newtype (Eq, NFData)
deriving stock (Show, Generic)
newtype SigDSIGN SECP256k1DSIGN = SigSECP256k1 SECP.Sig
newtype SigDSIGN EcdsaSecp256k1DSIGN =
SigEcdsaSecp256k1 SECP.Sig
deriving newtype (Eq, NFData)
deriving stock (Show, Generic)
algorithmNameDSIGN _ = "secp256k1"
deriveVerKeyDSIGN (SignKeySECP256k1 sk) = VerKeySECP256k1 . SECP.derivePubKey $ sk
signDSIGN () msg (SignKeySECP256k1 k) = SigSECP256k1 . SECP.signMsg k $ msg
verifyDSIGN () (VerKeySECP256k1 pk) msg (SigSECP256k1 sig) =
algorithmNameDSIGN _ = "ecdsa-secp256k1"
deriveVerKeyDSIGN (SignKeyEcdsaSecp256k1 sk) =
VerKeyEcdsaSecp256k1 . SECP.derivePubKey $ sk
signDSIGN () msg (SignKeyEcdsaSecp256k1 k) =
SigEcdsaSecp256k1 . SECP.signMsg k $ msg
verifyDSIGN () (VerKeyEcdsaSecp256k1 pk) msg (SigEcdsaSecp256k1 sig) =
if SECP.verifySig pk sig msg
then pure ()
else Left "SECP256k1 signature not verified"
else Left "ECDSA-SECP256k1 signature not verified"
genKeyDSIGN seed = runMonadRandomWithSeed seed $ do
bs <- getRandomBytes 32
case SECP.secKey bs of
Nothing -> error "Failed to construct a SECP256k1 secret key unexpectedly"
Just sk -> pure . SignKeySECP256k1 $ sk
rawSerialiseSigDSIGN (SigSECP256k1 sig) = putting sig
rawSerialiseVerKeyDSIGN (VerKeySECP256k1 pk) = putting pk
rawSerialiseSignKeyDSIGN (SignKeySECP256k1 sk) = putting sk
rawDeserialiseVerKeyDSIGN bs = VerKeySECP256k1 <$> (eitherToMaybe . getting $ bs)
rawDeserialiseSignKeyDSIGN bs = SignKeySECP256k1 <$> (eitherToMaybe . getting $ bs)
rawDeserialiseSigDSIGN bs = SigSECP256k1 <$> (eitherToMaybe . getting $ bs)

instance ToCBOR (VerKeyDSIGN SECP256k1DSIGN) where
Nothing -> error "Failed to construct a ECDSA-SECP256k1 secret key unexpectedly"
Just sk -> pure . SignKeyEcdsaSecp256k1 $ sk
rawSerialiseSigDSIGN (SigEcdsaSecp256k1 sig) = putting sig
rawSerialiseVerKeyDSIGN (VerKeyEcdsaSecp256k1 pk) = putting pk
rawSerialiseSignKeyDSIGN (SignKeyEcdsaSecp256k1 sk) = putting sk
rawDeserialiseVerKeyDSIGN bs =
VerKeyEcdsaSecp256k1 <$> (eitherToMaybe . getting $ bs)
rawDeserialiseSignKeyDSIGN bs =
SignKeyEcdsaSecp256k1 <$> (eitherToMaybe . getting $ bs)
rawDeserialiseSigDSIGN bs =
SigEcdsaSecp256k1 <$> (eitherToMaybe . getting $ bs)

instance ToCBOR (VerKeyDSIGN EcdsaSecp256k1DSIGN) where
toCBOR = encodeVerKeyDSIGN
encodedSizeExpr _ = encodedVerKeyDSIGNSizeExpr

instance FromCBOR (VerKeyDSIGN SECP256k1DSIGN) where
instance FromCBOR (VerKeyDSIGN EcdsaSecp256k1DSIGN) where
fromCBOR = decodeVerKeyDSIGN

instance ToCBOR (SignKeyDSIGN SECP256k1DSIGN) where
instance ToCBOR (SignKeyDSIGN EcdsaSecp256k1DSIGN) where
toCBOR = encodeSignKeyDSIGN
encodedSizeExpr _ = encodedSignKeyDESIGNSizeExpr

instance FromCBOR (SignKeyDSIGN SECP256k1DSIGN) where
instance FromCBOR (SignKeyDSIGN EcdsaSecp256k1DSIGN) where
fromCBOR = decodeSignKeyDSIGN

instance ToCBOR (SigDSIGN SECP256k1DSIGN) where
instance ToCBOR (SigDSIGN EcdsaSecp256k1DSIGN) where
toCBOR = encodeSigDSIGN
encodedSizeExpr _ = encodedSigDSIGNSizeExpr

instance FromCBOR (SigDSIGN SECP256k1DSIGN) where
instance FromCBOR (SigDSIGN EcdsaSecp256k1DSIGN) where
fromCBOR = decodeSigDSIGN

-- Required orphans
Expand Down
Loading