Commit Graph

4945 Commits

Author SHA1 Message Date
Dave Collins
277e4e4574
schnorr: Rename error codes to better match reality.
This renames some error codes to more closely match the failure as
follows:

- ErrBadInputSize -> ErrInvalidHashLen
- ErrInputValue -> ErrPrivateKeyIsZero
- ErrPointNotOnCurve -> ErrPubKeyNotOnCurve
- ErrBadSigRYValue -> ErrSigRYIsOdd
- ErrBadSigRNotOnCurve -> ErrSigRNotOnCurve
2020-04-08 04:08:49 -05:00
Dave Collins
0cd04a0b0c
schnorr: Remove unused error codes.
This removes the following unused error codes:

- ErrRegenSig
- ErrRegenerateRPoint
- ErrBadNonce
- ErrNonmatchingR
2020-04-08 04:08:49 -05:00
Dave Collins
bba36ac56e
schnorr: Use specialized types in signature type.
This updates the internal implementation of the Signature type to use
the ModNScalar and FieldVal types instead of big.Ints and modifies
NewSignature to accept the types accordingly.

Signature parsing and signing operations are now completely free of
big.Ints.  Verification still relies on them due to their use in public
keys.

It also removes the now unused primitives.go file.
2020-04-08 04:03:34 -05:00
Dave Collins
300fa12fdb
schnorr: Optimize sig verify with specialized types.
This modifies the signature verification function use the
ModNScalar and FieldVal types instead of big ints.

This is work towards eventually using the specialized types throughout.

The following benchmark shows a before and after comparison of typical
signature verification:

benchmark            old ns/op    new ns/op    delta
------------------------------------------------------
BenchmarkSigVerify   203206       182142       -10.37%

benchmark            old allocs   new allocs   delta
------------------------------------------------------
BenchmarkSigVerify   45           21           -53.33%

benchmark            old bytes    new bytes    delta
------------------------------------------------------
BenchmarkSigVerify   2066         1041         -49.61%
2020-04-08 03:58:20 -05:00
Dave Collins
4fa0208d32
schnorr: Use specialized types when signing.
This modifies the function that produces signatures to use the
ModNScalar and FieldVal types instead of big ints and also fleshes out
the comments to include a reference to the signing algorithm specified
in README.md.

This is work towards eventually using the specialized types throughout.

While the primary focus of this change is not optimization since signing
happens infrequently enough that it is not in a performance hot path, as
can be seen from the benchmark below, it does have the effect of making
signing a bit faster.

The following benchmark shows a before and after comparison of producing
a typical signature:

benchmark       old ns/op    new ns/op    delta
-------------------------------------------------
BenchmarkSign   54270        52622        -3.04%

benchmark       old allocs   new allocs   delta
-------------------------------------------------
BenchmarkSign   34           20           -41.18%

benchmark       old bytes    new bytes    delta
-------------------------------------------------
BenchmarkSign   1809         1088         -39.86%
2020-04-06 16:37:39 -05:00
Dave Collins
522fbd20be
schnorr: Add doc.go.
This adds doc.go to provide package documentation via godoc.
2020-04-06 16:33:50 -05:00
Dave Collins
3260979691
schnorr: Add README.md.
This adds a README.md file for the package which includes the custom
EC-Schnorr-DCRv0 specification along with the design details and
rationale for why its various characteristics were chosen.
2020-04-06 16:33:50 -05:00
Dave Collins
796e8c663c
schnorr: Remove unused copyBytes func. 2020-04-06 16:31:07 -05:00
Dave Collins
f812519df0
schnorr: Rework signature parsing.
This reworks the Schnorr signature parsing code to be more consistent
with the ecdsa parsing code and pave the way for eventually being able
to remove the reliance on big ints.

It also adds a full set of signature parsing tests that include 100%
coverage of all branches in the parsing code and test for the explicit
reason for the failure to ensure that each test is actually testing the
intended condition.

In particular, the parsing code has been changed as follows:

- Reject signatures that have the r and/or s components out of
  the allowed ranges for their respective type
- Make use of the specialized mod N scalar and field val types
- Introduce new error codes for signature errors and return them
2020-04-06 16:31:06 -05:00
Dave Collins
8c6b52d574
secp256k1: Add overflow check to field val set.
This modifies the SetBytes and SetByteSlice methods of the FieldVal type
to return whether or not the provided value was greater than or equal to
the field prime and adds tests to ensure  it works as expected.

This allows callers to easily check if a given uint256 value will fit
within the field element without modular reduction and makes it more
consistent with the ModNScalar type.

Finally, it updates all of the callers in the repository accordingly.
2020-04-06 16:24:30 -05:00
Dave Collins
79fa2f0c12
hdkeychain: Use secp256k1 privkey to pubkey method.
This makes use of the PubKey method on secp256k1.PrivateKey to convert a
private key to a public key instead of manually performing the
conversion.

This is desirable since secp256k1 provides the method specifically for
this purpose and it also has the benefit of allowing secp256k1 to
perform the task without round tripping through big integers which
results in slightly faster derivation.

The following benchmarks show a before and after comparison of the
affected operations:

benchmark                 old ns/op    new ns/op    delta
----------------------------------------------------------
BenchmarkDeriveHardened   3702         3671         -0.84%
BenchmarkDeriveNormal     4053         3999         -1.33%

benchmark                 old allocs   new allocs   delta
----------------------------------------------------------
BenchmarkDeriveHardened   14           14           +0.00%
BenchmarkDeriveNormal     15           15           +0.00%

benchmark                 old bytes    new bytes    delta
----------------------------------------------------------
BenchmarkDeriveHardened   1360         1360         +0.00%
BenchmarkDeriveNormal     1409         1409         +0.00%
2020-04-06 15:38:41 -05:00
Dave Collins
c8468e90b9
hdkeychain: Add child key with leading zeros test.
This adds a modification of a new test vector added to BIP32 which tests
for the case of a child key with leading zeros.  It was modified to
ensure it tests the intended condition with the new hash function Decred
uses.
2020-04-06 14:21:44 -05:00
Dave Collins
2f2a729db6
schnorr: Add negative tests for sig verification.
This adds several tests to help ensure the signature verification code
works as intended with invalid signatures by crafting signatures that
are specifically designed to hit the various failure cases and checking
the verification failed for that explicit reason.
2020-04-04 23:19:52 -05:00
Dave Collins
09f57f235f
schnorr: Add error support for errors.Is/As.
This updates the Error and ErrorCode types to provide support for
errors.Is and errors.As and adds a full set of tests for the error
infrastructure so the error handling is more consistent with the rest of
the secp256k1 module.

While here, it removes the unused ErrPubKeyOffCurve error and renames
the error creation func to signatureError to be more consistent.
2020-04-04 23:19:49 -05:00
David Hill
3c04174f55 txscript: use errors api; require go 1.13+ 2020-04-04 07:12:01 -05:00
David Hill
2c39d3b692 rpcclient: use NewRequestWithContext 2020-04-04 07:07:40 -05:00
David Hill
877b527200 rpcclient: use errors api; require go 1.13+ 2020-04-04 07:07:40 -05:00
David Hill
0142883ef3 mempool: use errors api; require go 1.13+ 2020-04-04 07:03:05 -05:00
David Hill
e1e11efd0e dcrutil: use errors api; require go 1.13+ 2020-04-04 06:59:54 -05:00
Dave Collins
bcc1a227a6
schnorr: Use extra data for RFC6979 nonces.
This modifies the signing code to use extra data that specifically
identifies the custom schnorr signature scheme used when generating
RFC6979 nonces to ensure the same nonce is not generated for the same
message and key as for other signing algorithms such as ECDSA.

While nobody realistically should ever be signing the same message with
the same private key with both Schnorr and ECDSA at the same time, it's
safer to ensure that even if they do, the same nonce value isn't used
since that could lead to revealing the private key.

It also updates the relevant tests to use the new deterministic nonces
and signatures which have been independently verified with the Sage
computer algebra system.
2020-03-31 15:52:24 -05:00
Dave Collins
4fcea17b28
chaincfg: Remove unused modules.
This updates the go.mod and go.sum files to remove modules that are no
longer needed since the removal of chainec.
2020-03-31 14:03:59 -05:00
Dave Collins
76a18d1716
secp256k1/ecdsa: Decouple ECDSA from secp256k1.
Currently, the secp256k1 package is rather tightly bound to ECDSA
signatures which makes them the only real first-class citizen in the
code.  In an effort to make it clear the ECDSA is only one possible
digital signature algorithms and to enable Schnorr signatures to also be
made first class citizens, this decouples all code related to producing
and parsing ECDSA signatures into a separate package under secp256k1
named ecdsa.

This is a fairly large change in terms of the number of lines changed,
however, the vast majority of the changes are mechanical to deal with
the package name changes and moved code.  The only real new code is
documentation for the new package.

The following is a high level overview of the changes:

- Rename signature.go to ecdsa/signature.go
- Rename signature_test.go to ecdsa/signature_test.go
- Rename sigerror.go to ecdsa/error.go
  - Rename SignatureErrorCode type to ErrorCode
  - Rename SignatureError type to Error
- Rename sigerror_test.go to ecdsa/error_test.go
- Rename signature_bench_test.go to ecdsa/bench_test.go
- Move signing-related examples from example_test.go to
  ecdsa/example_test.go
- Update all moved code to reference secp256k1 types and funcs
- Remove Sign from the secp256k1.PrivateKey type in favor of ecdsa.Sign
- Add ecdsa/README.md to describe the new package
- Add ecdsa/doc.go to provide package documentation via godoc
- Move signing examples from README.md to new ecdsa/README.md
- Update txscript and rpcserver to use the new package methods
2020-03-28 13:32:04 -05:00
Dave Collins
dcadf8fb9c
secp256k1: Split nonce code into separate files.
This moves the code for generating an RFC6979 nonce and the related
tests into separate files named nonce.go and nonce_test.go,
respectively.  The nonce is not specific to ecdsa and therefore it is
being split out so it remains accessible to multiple signing algorithms.
2020-03-28 13:32:03 -05:00
Dave Collins
a183a4a9ba
secp256k1: Export scalar from PrivateKey.
This exports the internal scalar that is used to house the private key
so that it can be used by external callers without having to round trip
through serializing the bytes.
2020-03-28 13:32:03 -05:00
Dave Collins
990076ec2e
secp256k1: Add AsJacobian method to pubkey.
This add a new method to the PublicKey type named AsJacobian which
converts the public key into a Jacobian point with Z=1.  This allows the
public key to be treated a Jacobian point in the secp256k1 group in
calculations.

It also adds an associated test to ensure proper functionality.
2020-03-28 13:32:03 -05:00
Dave Collins
b9695b4828
secp256k1: Export DecompressY.
This exports the decompressY func as DecompressY in order to allow
external callers to perform optimized elliptic curve point decompression
for a given X coordinate when possible.

It also moves the function and related tests from pubkey.go and
pubkey_test.go to curve.go and curve_test.go, respectively, since it
more correctly belongs there given it is not specific to public keys.

This is part of exposing the ec group operations so callers are not
forced to round trip through big ints.
2020-03-28 13:32:02 -05:00
Dave Collins
0dca15f1d7
secp256k1: Export ScalarBaseMultNonConst.
This exports the scalarBaseMultJacobian func as ScalarBaseMultNonConst
in order to allow external callers to perform optimized elliptic curve
point multiplication of the group base point with a scalar in Jacobian
project coordinates in addition to more clearly indentifying that the
function is not constant time.

This is part of exposing the ec group operations so callers are not
forced to round trip through big ints in affine space.
2020-03-28 13:32:02 -05:00
Dave Collins
88a2c01958
secp256k1: Export SclarMultNonConst.
This exports the scalarMultJacobian func as SclarMultNonConst in order
to allow external callers to perform optimized elliptic curve point
multiplication with a scalar in Jacobian project coordinates in addition
to more clearly indentifying that the function is not constant time.

This is part of exposing the ec group operations so callers are not
forced to round trip through big ints in affine space.
2020-03-28 13:32:02 -05:00
Dave Collins
5ee5073693
secp256k1: Export DoubleNonConst.
This exports the doubleJacobian func as DoubleNonConst in order to allow
external callers to perform optimized elliptic curve point doubling in
Jacobian project coordinates in addition to more clearly indentifying
that the function is not constant time.

This is part of exposing the ec group operations so callers are not
forced to round trip through big ints in affine space.
2020-03-28 13:32:01 -05:00
Dave Collins
ba2de1aa06
secp256k1: Export AddNonConst.
This exports the addJacobian func as AddNonConst in order to allow
external callers to perform optimized elliptic curve point addition in
Jacobian project coordinates in addition to more clearly indentifying
that the function is not constant time.

This is part of exposing the ec group operations so callers are not
forced to round trip through big ints in affine space.
2020-03-28 13:32:01 -05:00
Dave Collins
a71a206371
secp256k1: Export JacobianPoint type.
This exports the jacobianPoint type as JacobianPoint in order to allow
external callers to perform optimized elliptic curve math in Jacobian
projective coordinates.

This is part of exposing the ec group operations so callers are not
forced to round trip through big ints in affine space.
2020-03-28 13:32:00 -05:00
Dave Collins
8429504b5d
schnorr: Remove internal verify func bool ret.
This removes the bool return from the internal schnorrVerify function
since it is entirely unnecessary given an error is already returned if
the signature fails to verify.  It is also more consistent with the rest
of the code.
2020-03-28 13:27:56 -05:00
Dave Collins
e90328637d
secp256k1: Expose IsZeroBit on field val type.
This exposes a new function on the FieldVal type named IsZeroBit which
operates similarly to IsZero except it returns a 0 or 1.

This is being provided because it is not possible in Go to convert from
a bool to numeric value in constant time and many constant-time
operations require a numeric value.

Since the type is now exported for external use, consumers would
otherwise have no way to perform the conversion.
2020-03-28 13:20:42 -05:00
Dave Collins
5034f3fafb
secp256k1: Expose IsOneBit on field val type.
This exposes a new function on the FieldVal type named IsOneBit which
operates similarly to IsOne except it returns a 0 or 1.

This is being provided because it is not possible in Go to convert from
a bool to numeric value in constant time and many constant-time
operations require a numeric value.

Since the type is now exported for external use, consumers would
otherwise have no way to perform the conversion.
2020-03-28 13:20:42 -05:00
Dave Collins
05cc323f2a
secp256k1: Expose IsOddBit on field val type.
This exposes a new function on the FieldVal type named IsOddBit which
operates similarly to IsOdd except it returns a 0 or 1.

This is being provided because it is not possible in Go to convert from
a bool to numeric value in constant time and many constant-time
operations require a numeric value.

Since the type is now exported for external use, consumers would
otherwise have no way to perform the conversion.
2020-03-28 13:20:38 -05:00
David Hill
be680db523 multi: remove superfluous fmt.Sprintf
build: bump golangci-lint to 1.24.0
2020-03-27 16:05:30 -05:00
Dave Collins
52d2d2db29
secp256k1: Export field value type.
This exports the fieldVal type as FieldVal in order to allow external
callers to perform optimized field math.  The intent is ultimately to
expose the group operations as well so callers are not forced to round
trip through big ints.
2020-03-24 11:47:54 -05:00
Dave Collins
a7355bc913
secp256k1: Update field val docs to public facing.
This updates the documentation for the field value type in preparation
for exporting the type as follows:

- Add a primer to the main field value type which warns loudly about the
  requirements for the caller to ensure proper preconditions and
  explains the concepts of normalization and magnitude accordingly
- Update all methods to explicitly call out their preconditions
- Update all methods to explicitly call out the resulting normalization
  and magnitude
- Update all methods that are constant time to explicitly state it
2020-03-24 11:47:53 -05:00
Dave Collins
c5580bc531
secp256k1: Move field val set hex to test file.
This moves the SetHex method on the field value type to the associated
test file so it is only avilable during the tests which is its intended
purpose.  It is not constant time and therefore shouldn't be available
to callers.  This is in preparation for exporting the type.
2020-03-24 11:47:53 -05:00
Dave Collins
3d9cda1d25
secp256k1: Make field set byte slice const time.
This makes the SetByteSlice method on the field value type constant time
in preparation for exporting the type.
2020-03-24 11:47:53 -05:00
Dave Collins
e80c805540
secp256k1: Make field value mul int take uint8.
This modifies the MulInt method on a field value to take a uint8 instead
of a uint in order to make it harder to misuse it since it has a
precondition which requires to the caller to ensure internal overflows
are avoided.   In practice, the code currently only ever calls it with a
max value of 8, but in order to prepare for exporting the type, it's
nicer to make it harder to misuse.
2020-03-24 11:47:52 -05:00
Dave Collins
ebb25a7009
secp256k1: Make field value add int take uint16.
This modifies the AddInt method on a field value to take a uint16
instead of a uint in order to make it impossible to misuse it since it
has a precondition of a max value of 2^26 - 1.  In practice, the code
currently only ever calls it with 7, but in order to prepare for
exporting the type, it's nicer to prevent the potential misuse.
2020-03-24 11:47:52 -05:00
Dave Collins
92feebd272
secp256k1: Make field value set int take uint16.
This modifies the SetInt method on a field value to take a uint16
instead of a uint in order to make it impossible to misuse it since it
has a precondition of a max value of 2^26 - 1.  In practice, the code
currently only ever calls it with 0 and 1, but in order to prepare for
exporting the type, it's nicer to prevent the potential misuse.
2020-03-24 11:47:51 -05:00
Dave Collins
418e5eba2d
secp256k1: Make field value tests more consistent.
This updates all of the field value tests to be more consistent with the
rest of the code in preparation for exporting the type.
2020-03-24 11:47:51 -05:00
Dave Collins
ee025a39ca
secp256k1: Improve exported curve params.
This modifies the CurveParams struct that is exported to independently
define the params instead of directly embedding elliptic.CurveParams and
updates KoblitzCurve to directly embed elliptic.CurveParams instead to
prevent possible misuse.

This is desirable because elliptic.CurveParams also defines methods
which provide a non-constant and generic implementation of the curve
based on big ints that does not work properly with the secp256k1 curve
due to its use of a different a value in the curve equation.  The
adaptor code works around that limitation by embedding the
elliptic.CurveParams and overriding the method implementations with the
correct calculations via the KoblitzCurve type.

In other words, prior to the change, the caller could have easily
misused the params to perform incorrect math by calling the
non-overridden methods on the type returned by the Params method instead
of the overridden version obtained via the S256 method.

That is no longer possible with this change since the Params method now
only contains the parameters and does not embed elliptic.CurveParams.
2020-03-24 11:42:53 -05:00
Dave Collins
c928dc451e
secp256k1: Remove unused q curve param.
This removes the q param from the curve params since it is no longer
used due to previous optimizations.
2020-03-24 11:39:11 -05:00
Dave Collins
791fcd166b
secp256k1: Reduce EC operation normalizes.
This modifies the various EC operations to reduce the overall number of
normalizations that are needed by requiring the caller to provide
normalized points instead of blindly normalizing the inputs.  It also
updates the operations to ensure the result is normalized along with
updating the comments to call out the new semantics and updating all of
the callers accordingly to ensure the new requirements are met.

This results in less overall normalizations because the caller has more
information about whether or not normalization is needed and can
therefore avoid it in many cases, particularly when it is using the
result that is already normalized as part of a chain of operations.

The following benchmarks show a before and after comparison of the
affected operations:

benchmark                         old ns/op   new ns/op   delta
-----------------------------------------------------------------
BenchmarkAddJacobian              569         442         -22.32%
BenchmarkAddJacobianNotZOne       1087        1080        -0.64%
BenchmarkScalarBaseMult           46966       46164       -1.71%
BenchmarkScalarBaseMultJacobian   34218       34165       -0.15%
BenchmarkScalarBaseMultLarge      47077       46819       -0.55%
BenchmarkScalarMult               155318      148019      -4.70%
BenchmarkSigVerify                176007      168422      -4.31%
BenchmarkSign                     57636       57561       -0.13%
BenchmarkSignCompact              57883       57653       -0.40%
BenchmarkRecoverCompact           206361      197419      -4.33%
2020-03-24 11:19:48 -05:00
Dave Collins
08498b8b24
secp256k1: Avoid inversion in sig verify.
This modifies signature verification to perform the final equality check
in Jacobian projective space to avoid an extra expensive field inversion
by taking advantage of the fact the R component of the signature can be
converted to Jacobian projective space and compared directly so long as
the two possible cases that arise from R being mod N and the original x
coordinate used to create it being mod P.

The following is a before and after comparison of verification of a
typical signature:

benchmark            old ns/op    new ns/op    delta
-----------------------------------------------------
BenchmarkSigVerify   189505       177147       -6.52%

benchmark            old allocs   new allocs   delta
-----------------------------------------------------
BenchmarkSigVerify   34           34           +0.00%

benchmark            old bytes    new bytes    delta
-----------------------------------------------------
BenchmarkSigVerify   1633         1633         +0.00%
2020-03-24 11:12:40 -05:00
Dave Collins
b11ae5cde4
mempool: Correct MaybeAcceptDependents mutex.
The MaybeAcceptDependents function was added as a part of the logic to
track tickets with non-approved inputs separately in a staging pool.
Given it modifies the contents of the mempool, it needs to hold a write
mutex as opposed to a read mutex as otherwise it can modify the mempool
out from under readers.

While here, comment the required locking semantics on the other
functions that were added as a part of the staging logic as well.
2020-03-21 19:10:28 -05:00
Dave Collins
1dcb1d1f55
schnorr: Remove unused GenerateKey.
This removes the GenerateKey function from the schnorr package since
nothing uses it and it is expected that the caller will use
secp256k1.GeneartePrivateKey instead since the package works with that
type as private keys.
2020-03-20 14:01:08 -05:00