Skip to content

Commit aa3658f

Browse files
committed
break up importSignature since DER sigs can be any length, even if unlikely
1 parent 36c48c9 commit aa3658f

File tree

3 files changed

+31
-18
lines changed

3 files changed

+31
-18
lines changed

src/Crypto/Secp256k1.hs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ module Crypto.Secp256k1 (
3535
exportPubKeyXY,
3636
importPubKeyXO,
3737
exportPubKeyXO,
38-
importSignature,
38+
importSignatureCompact,
39+
importSignatureDer,
3940
exportSignatureCompact,
4041
exportSignatureDer,
4142
importRecoverableSignature,
@@ -80,6 +81,7 @@ module Crypto.Secp256k1 (
8081
ecdh,
8182
) where
8283

84+
import Control.Applicative (Alternative (..))
8385
import Control.DeepSeq (NFData (..))
8486
import Control.Monad (replicateM, unless, (<=<))
8587
import Control.Monad.Trans.Class (lift)
@@ -269,7 +271,7 @@ instance Show Signature where
269271
instance Read Signature where
270272
readsPrec i cs = case decodeBase16 $ B8.pack token of
271273
Left e -> []
272-
Right a -> maybeToList $ (,rest) <$> importSignature a
274+
Right a -> maybeToList $ (,rest) <$> (importSignatureCompact a <|> importSignatureDer a)
273275
where
274276
trimmed = dropWhile isSpace cs
275277
(token, rest) = span isAlphaNum trimmed
@@ -414,24 +416,33 @@ exportPubKeyXO (PubKeyXO pkFPtr) = unsafePerformIO $ do
414416
unsafePackByteString (outBuf, 32)
415417

416418

417-
-- | Parses 'Signature' from DER (71 | 72 | 73 bytes) or Compact (64 bytes) representations.
418-
importSignature :: ByteString -> Maybe Signature
419-
importSignature bs = unsafePerformIO $
419+
-- | Parses 'Signature' from Compact (64 bytes) representation.
420+
importSignatureCompact :: ByteString -> Maybe Signature
421+
importSignatureCompact bs = unsafePerformIO $
420422
unsafeUseByteString bs $ \(inBuf, len) -> do
421423
outBuf <- mallocBytes 64
422424
ret <-
423-
if
425+
if len == 64
424426
-- compact
425-
| len == 64 -> Prim.ecdsaSignatureParseCompact ctx outBuf inBuf
426-
-- der
427-
| len >= 69 && len <= 73 -> Prim.ecdsaSignatureParseDer ctx outBuf inBuf len
427+
then Prim.ecdsaSignatureParseCompact ctx outBuf inBuf
428428
-- invalid
429-
| otherwise -> pure 0
429+
else pure 0
430430
if isSuccess ret
431431
then Just . Signature <$> newForeignPtr finalizerFree outBuf
432432
else free outBuf $> Nothing
433433

434434

435+
-- | Parses 'Signature' from DER representation.
436+
importSignatureDer :: ByteString -> Maybe Signature
437+
importSignatureDer bs = unsafePerformIO $
438+
unsafeUseByteString bs $ \(inBuf, len) -> do
439+
outBuf <- mallocBytes 64
440+
ret <- Prim.ecdsaSignatureParseDer ctx outBuf inBuf len
441+
if isSuccess ret
442+
then Just . Signature <$> newForeignPtr finalizerFree outBuf
443+
else pure Nothing
444+
445+
435446
-- | Serializes 'Signature' to Compact (64 byte) representation
436447
exportSignatureCompact :: Signature -> ByteString
437448
exportSignatureCompact (Signature fptr) = unsafePerformIO $ do

test/Crypto/Secp256k1Prop.hs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ prop_signatureParseInvertsSerialize = property $ do
123123
let serialized = export sig
124124
annotateShow serialized
125125
annotateShow (BS.length serialized)
126-
case importSignature serialized of
126+
let parse = if exportDer then importSignatureDer else importSignatureCompact
127+
case parse serialized of
127128
Nothing -> failure
128129
Just x -> x === sig
129130

@@ -185,12 +186,12 @@ prop_ecdsaSignatureValidityPreservedOverSerialization = property $ do
185186
msg <- forAll $ bytes (singleton 32)
186187
sig <- maybe failure pure $ ecdsaSign sk msg
187188
useDer <- forAll enumBounded
188-
let export =
189+
let (serialize, parse) =
189190
if useDer
190-
then exportSignatureDer
191-
else exportSignatureCompact
192-
let serialized = export sig
193-
let parsed = fromJust (importSignature serialized)
191+
then (exportSignatureDer, importSignatureDer)
192+
else (exportSignatureCompact, importSignatureCompact)
193+
let serialized = serialize sig
194+
let parsed = fromJust (parse serialized)
194195
assert $ ecdsaVerify msg (derivePubKey sk) parsed
195196

196197

test/Crypto/Secp256k1Spec.hs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module Crypto.Secp256k1Spec (spec) where
33
import Control.Monad.Par qualified as P
44
import Crypto.Secp256k1
55
import Crypto.Secp256k1.Internal
6+
import Data.ByteArray.Encoding (Base (Base16), convertFromBase)
67
import Data.ByteString qualified as BS
78
import Data.ByteString.Char8 qualified as B8
89
import Data.Either (fromRight)
@@ -69,7 +70,7 @@ parSerializePubKeyTest ps = P.runPar $ do
6970

7071
serializeSigTest :: (BS.ByteString, SecKey) -> Bool
7172
serializeSigTest (fm, fk) =
72-
(fg >>= importSignature . exportSignatureDer) == fg && isJust fg
73+
(fg >>= importSignatureDer . exportSignatureDer) == fg && isJust fg
7374
where
7475
fg = ecdsaSign fk fm
7576

@@ -82,7 +83,7 @@ parSerializeSigTest ms = P.runPar $ do
8283

8384
serializeCompactSigTest :: (BS.ByteString, SecKey) -> Bool
8485
serializeCompactSigTest (fm, fk) =
85-
(fg >>= importSignature . exportSignatureCompact) == fg && isJust fg
86+
(fg >>= importSignatureCompact . exportSignatureCompact) == fg && isJust fg
8687
where
8788
fg = ecdsaSign fk fm
8889

0 commit comments

Comments
 (0)