@@ -25,6 +25,7 @@ module Crypto.Secp256k1 (
25
25
KeyPair ,
26
26
Signature ,
27
27
RecoverableSignature ,
28
+ SchnorrSignature ,
28
29
Tweak ,
29
30
30
31
-- * Parsing and Serialization
@@ -40,6 +41,8 @@ module Crypto.Secp256k1 (
40
41
exportSignatureDer ,
41
42
importRecoverableSignature ,
42
43
exportRecoverableSignature ,
44
+ importSchnorrSignature ,
45
+ exportSchnorrSignature ,
43
46
importTweak ,
44
47
45
48
-- * ECDSA Operations
@@ -283,6 +286,28 @@ instance NFData Signature where
283
286
rnf Signature {.. } = seq signatureFPtr ()
284
287
285
288
289
+ -- | Structure containing Schnorr Signature
290
+ newtype SchnorrSignature = SchnorrSignature { schnorrSignatureFPtr :: ForeignPtr Prim. Sig64}
291
+
292
+
293
+ instance Show SchnorrSignature where
294
+ show sig = (B8. unpack . encodeBase16) (exportSchnorrSignature sig)
295
+ instance Read SchnorrSignature where
296
+ readsPrec i cs = case decodeBase16 $ B8. pack token of
297
+ Left e -> []
298
+ Right a -> maybeToList $ (,rest) <$> importSchnorrSignature a
299
+ where
300
+ trimmed = dropWhile isSpace cs
301
+ (token, rest) = span isAlphaNum trimmed
302
+ instance Eq SchnorrSignature where
303
+ sig == sig' = unsafePerformIO . evalContT $ do
304
+ sigp <- ContT $ withForeignPtr (schnorrSignatureFPtr sig)
305
+ sigp' <- ContT $ withForeignPtr (schnorrSignatureFPtr sig')
306
+ (EQ == ) <$> lift (memCompare (castPtr sigp) (castPtr sigp') 64 )
307
+ instance NFData SchnorrSignature where
308
+ rnf SchnorrSignature {.. } = seq schnorrSignatureFPtr ()
309
+
310
+
286
311
-- | Structure containing Signature AND recovery ID
287
312
newtype RecoverableSignature = RecoverableSignature { recoverableSignatureFPtr :: ForeignPtr Prim. RecSig65}
288
313
@@ -493,6 +518,23 @@ exportRecoverableSignature RecoverableSignature{..} = unsafePerformIO . evalCont
493
518
unsafePackByteString (outBuf, 65 )
494
519
495
520
521
+ -- | Parses 'SchnorrSignature' from Schnorr (64 byte) representation
522
+ importSchnorrSignature :: ByteString -> Maybe SchnorrSignature
523
+ importSchnorrSignature bs
524
+ | BS. length bs /= 64 = Nothing
525
+ | otherwise = unsafePerformIO $ do
526
+ outBuf <- mallocBytes 64
527
+ unsafeUseByteString bs $ \ (ptr, _) -> do
528
+ memcpy outBuf ptr 64
529
+ Just . SchnorrSignature <$> newForeignPtr finalizerFree outBuf
530
+
531
+
532
+ -- | Serializes 'SchnorrSignature' to Schnorr (64 byte) representation
533
+ exportSchnorrSignature :: SchnorrSignature -> ByteString
534
+ exportSchnorrSignature (SchnorrSignature fptr) = unsafePerformIO $
535
+ withForeignPtr fptr $ \ ptr -> BS. packCStringLen (castPtr ptr, 64 )
536
+
537
+
496
538
-- | Parses 'Tweak' from 32 byte @ByteString@. If the @ByteString@ is an invalid 'SecKey' then this will yield @Nothing@
497
539
importTweak :: ByteString -> Maybe Tweak
498
540
importTweak = fmap (Tweak . castForeignPtr . secKeyFPtr) . importSecKey
@@ -702,7 +744,7 @@ keyPairPubKeyXOTweakAdd KeyPair{..} Tweak{..} = unsafePerformIO . evalContT $ do
702
744
703
745
-- | Compute a schnorr signature using a 'KeyPair'. The @ByteString@ must be 32 bytes long to get a @Just@ out of this
704
746
-- function
705
- schnorrSign :: KeyPair -> ByteString -> Maybe Signature
747
+ schnorrSign :: KeyPair -> ByteString -> Maybe SchnorrSignature
706
748
schnorrSign KeyPair {.. } bs
707
749
| BS. length bs /= 32 = Nothing
708
750
| otherwise = unsafePerformIO . evalContT $ do
@@ -713,17 +755,17 @@ schnorrSign KeyPair{..} bs
713
755
-- TODO: provide randomness here instead of supplying a null pointer
714
756
ret <- Prim. schnorrsigSign ctx sigBuf msgHashPtr keyPairPtr nullPtr
715
757
if isSuccess ret
716
- then Just . Signature <$> newForeignPtr finalizerFree sigBuf
758
+ then Just . SchnorrSignature <$> newForeignPtr finalizerFree sigBuf
717
759
else free sigBuf $> Nothing
718
760
719
761
720
762
-- | Verify the authenticity of a schnorr signature. @True@ means the 'Signature' is correct.
721
- schnorrVerify :: PubKeyXO -> ByteString -> Signature -> Bool
722
- schnorrVerify PubKeyXO {.. } bs Signature {.. } = unsafePerformIO . evalContT $ do
763
+ schnorrVerify :: PubKeyXO -> ByteString -> SchnorrSignature -> Bool
764
+ schnorrVerify PubKeyXO {.. } bs SchnorrSignature {.. } = unsafePerformIO . evalContT $ do
723
765
pubKeyPtr <- ContT (withForeignPtr pubKeyXOFPtr)
724
- signaturePtr <- ContT (withForeignPtr signatureFPtr )
766
+ schnorrSignaturePtr <- ContT (withForeignPtr schnorrSignatureFPtr )
725
767
(msgPtr, msgLen) <- ContT (unsafeUseByteString bs)
726
- lift $ isSuccess <$> Prim. schnorrsigSignVerify ctx signaturePtr msgPtr msgLen pubKeyPtr
768
+ lift $ isSuccess <$> Prim. schnorrsigSignVerify ctx schnorrSignaturePtr msgPtr msgLen pubKeyPtr
727
769
728
770
729
771
-- | Generate a tagged sha256 digest as specified in BIP340
0 commit comments