secp256k1: Expose IsZeroBit on mod n scalar type.
This exposes a new function on the ModNScalar 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.
This commit is contained in:
parent
67b4d3dbf7
commit
d5cfa73a2f
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2020 The Decred developers
|
||||
// Copyright (c) 2020-2022 The Decred developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -100,7 +100,7 @@ var (
|
||||
// arithmetic over the secp256k1 group order. This means all arithmetic is
|
||||
// performed modulo:
|
||||
//
|
||||
// 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
|
||||
// 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
|
||||
//
|
||||
// It only implements the arithmetic needed for elliptic curve operations,
|
||||
// however, the operations that are not implemented can typically be worked
|
||||
@ -174,6 +174,19 @@ func (s *ModNScalar) Zero() {
|
||||
s.n[7] = 0
|
||||
}
|
||||
|
||||
// IsZeroBit returns 1 when the scalar is equal to zero or 0 otherwise in
|
||||
// constant time.
|
||||
//
|
||||
// Note that a bool is not used here 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. See IsZero for the version that returns
|
||||
// a bool.
|
||||
func (s *ModNScalar) IsZeroBit() uint32 {
|
||||
// The scalar can only be zero if no bits are set in any of the words.
|
||||
bits := s.n[0] | s.n[1] | s.n[2] | s.n[3] | s.n[4] | s.n[5] | s.n[6] | s.n[7]
|
||||
return constantTimeEq(bits, 0)
|
||||
}
|
||||
|
||||
// IsZero returns whether or not the scalar is equal to zero in constant time.
|
||||
func (s *ModNScalar) IsZero() bool {
|
||||
// The scalar can only be zero if no bits are set in any of the words.
|
||||
|
||||
@ -80,28 +80,40 @@ func TestModNScalarZero(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestModNScalarIsZero ensures that checking if a scalar is zero works as
|
||||
// expected.
|
||||
// TestModNScalarIsZero ensures that checking if a scalar is zero via IsZero and
|
||||
// IsZeroBit works as expected.
|
||||
func TestModNScalarIsZero(t *testing.T) {
|
||||
var s ModNScalar
|
||||
if !s.IsZero() {
|
||||
t.Errorf("new scalar is not zero - got %v (rawints %x)", s, s.n)
|
||||
}
|
||||
if s.IsZeroBit() != 1 {
|
||||
t.Errorf("new scalar is not zero - got %v (rawints %x)", s, s.n)
|
||||
}
|
||||
|
||||
s.SetInt(1)
|
||||
if s.IsZero() {
|
||||
t.Errorf("claims zero for nonzero scalar - got %v (rawints %x)", s, s.n)
|
||||
}
|
||||
if s.IsZeroBit() == 1 {
|
||||
t.Errorf("claims zero for nonzero scalar - got %v (rawints %x)", s, s.n)
|
||||
}
|
||||
|
||||
s.SetInt(0)
|
||||
if !s.IsZero() {
|
||||
t.Errorf("claims nonzero for zero scalar - got %v (rawints %x)", s, s.n)
|
||||
}
|
||||
if s.IsZeroBit() != 1 {
|
||||
t.Errorf("claims nonzero for zero scalar - got %v (rawints %x)", s, s.n)
|
||||
}
|
||||
|
||||
s.SetInt(1)
|
||||
s.Zero()
|
||||
if !s.IsZero() {
|
||||
t.Errorf("claims zero for nonzero scalar - got %v (rawints %x)", s, s.n)
|
||||
t.Errorf("claims nonzero for zero scalar - got %v (rawints %x)", s, s.n)
|
||||
}
|
||||
if s.IsZeroBit() != 1 {
|
||||
t.Errorf("claims nonzero for zero scalar - got %v (rawints %x)", s, s.n)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user