mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-27 04:36:19 +08:00
internal/bigmod: sync bigmod change between 30/Nov 2024 to 3/Dec 2024 #282
This commit is contained in:
parent
a599819ef8
commit
d009f7ebef
@ -114,6 +114,11 @@ func (x *Nat) resetToBytes(b []byte) *Nat {
|
|||||||
if err := x.setBytes(b); err != nil {
|
if err := x.setBytes(b); err != nil {
|
||||||
panic("bigmod: internal error: bad arithmetic")
|
panic("bigmod: internal error: bad arithmetic")
|
||||||
}
|
}
|
||||||
|
return x.trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
// trim reduces the size of x to match its value.
|
||||||
|
func (x *Nat) trim() *Nat {
|
||||||
// Trim most significant (trailing in little-endian) zero limbs.
|
// Trim most significant (trailing in little-endian) zero limbs.
|
||||||
// We assume comparison with zero (but not the branch) is constant time.
|
// We assume comparison with zero (but not the branch) is constant time.
|
||||||
for i := len(x.limbs) - 1; i >= 0; i-- {
|
for i := len(x.limbs) - 1; i >= 0; i-- {
|
||||||
@ -135,7 +140,7 @@ func (x *Nat) Set(y *Nat) *Nat {
|
|||||||
// Bytes returns x as a zero-extended big-endian byte slice. The size of the
|
// Bytes returns x as a zero-extended big-endian byte slice. The size of the
|
||||||
// slice will match the size of m.
|
// slice will match the size of m.
|
||||||
//
|
//
|
||||||
// x must have the same size as m and it must be reduced modulo m.
|
// x must have the same size as m and it must be less than or equal to m.
|
||||||
func (x *Nat) Bytes(m *Modulus) []byte {
|
func (x *Nat) Bytes(m *Modulus) []byte {
|
||||||
i := m.Size()
|
i := m.Size()
|
||||||
bytes := make([]byte, i)
|
bytes := make([]byte, i)
|
||||||
@ -180,8 +185,10 @@ func (x *Nat) SetOverflowingBytes(b []byte, m *Modulus) (*Nat, error) {
|
|||||||
if err := x.setBytes(b); err != nil {
|
if err := x.setBytes(b); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
leading := _W - bitLen(x.limbs[len(x.limbs)-1])
|
// setBytes would have returned an error if the input overflowed the limb
|
||||||
if leading < m.leading {
|
// size of the modulus, so now we only need to check if the most significant
|
||||||
|
// limb of x has more bits than the most significant limb of the modulus.
|
||||||
|
if bitLen(x.limbs[len(x.limbs)-1]) > bitLen(m.nat.limbs[len(m.nat.limbs)-1]) {
|
||||||
return nil, errors.New("input overflows the modulus size")
|
return nil, errors.New("input overflows the modulus size")
|
||||||
}
|
}
|
||||||
x.maybeSubtractModulus(no, m)
|
x.maybeSubtractModulus(no, m)
|
||||||
@ -228,17 +235,13 @@ func (x *Nat) setBytes(b []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetUint assigns x = y, and returns an error if y >= m.
|
// SetUint assigns x = y.
|
||||||
//
|
//
|
||||||
// The output will be resized to the size of m and overwritten.
|
// The output will be resized to the size of m and overwritten.
|
||||||
func (x *Nat) SetUint(y uint, m *Modulus) (*Nat, error) {
|
func (x *Nat) SetUint(y uint, m *Modulus) *Nat {
|
||||||
x.resetFor(m)
|
x.resetFor(m)
|
||||||
// Modulus is never zero, so always at least one limb.
|
|
||||||
x.limbs[0] = y
|
x.limbs[0] = y
|
||||||
if x.CmpGeq(m.nat) == yes {
|
return x
|
||||||
return nil, errors.New("input overflows the modulus")
|
|
||||||
}
|
|
||||||
return x, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equal returns 1 if x == y, and 0 otherwise.
|
// Equal returns 1 if x == y, and 0 otherwise.
|
||||||
@ -270,6 +273,56 @@ func (x *Nat) IsZero() choice {
|
|||||||
return zero
|
return zero
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsOne returns 1 if x == 1, and 0 otherwise.
|
||||||
|
func (x *Nat) IsOne() choice {
|
||||||
|
// Eliminate bounds checks in the loop.
|
||||||
|
size := len(x.limbs)
|
||||||
|
xLimbs := x.limbs[:size]
|
||||||
|
|
||||||
|
if len(xLimbs) == 0 {
|
||||||
|
return no
|
||||||
|
}
|
||||||
|
|
||||||
|
one := ctEq(xLimbs[0], 1)
|
||||||
|
for i := 1; i < size; i++ {
|
||||||
|
one &= ctEq(xLimbs[i], 0)
|
||||||
|
}
|
||||||
|
return one
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMinusOne returns 1 if x == -1 mod m, and 0 otherwise.
|
||||||
|
//
|
||||||
|
// The length of x must be the same as the modulus. x must already be reduced
|
||||||
|
// modulo m.
|
||||||
|
func (x *Nat) IsMinusOne(m *Modulus) choice {
|
||||||
|
minusOne := m.Nat()
|
||||||
|
minusOne.SubOne(m)
|
||||||
|
return x.Equal(minusOne)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsOdd returns 1 if x is odd, and 0 otherwise.
|
||||||
|
func (x *Nat) IsOdd() choice {
|
||||||
|
if len(x.limbs) == 0 {
|
||||||
|
return no
|
||||||
|
}
|
||||||
|
return choice(x.limbs[0] & 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TrailingZeroBitsVarTime returns the number of trailing zero bits in x.
|
||||||
|
func (x *Nat) TrailingZeroBitsVarTime() uint {
|
||||||
|
var t uint
|
||||||
|
limbs := x.limbs
|
||||||
|
for _, l := range limbs {
|
||||||
|
if l == 0 {
|
||||||
|
t += _W
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t += uint(bits.TrailingZeros(l))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
// CmpGeq returns 1 if x >= y, and 0 otherwise.
|
// CmpGeq returns 1 if x >= y, and 0 otherwise.
|
||||||
//
|
//
|
||||||
// Both operands must have the same announced length.
|
// Both operands must have the same announced length.
|
||||||
@ -334,6 +387,68 @@ func (x *Nat) sub(y *Nat) (c uint) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ShiftRightVarTime sets x = x >> n.
|
||||||
|
//
|
||||||
|
// The announced length of x is unchanged.
|
||||||
|
func (x *Nat) ShiftRightVarTime(n uint) *Nat {
|
||||||
|
// Eliminate bounds checks in the loop.
|
||||||
|
size := len(x.limbs)
|
||||||
|
xLimbs := x.limbs[:size]
|
||||||
|
|
||||||
|
shift := int(n % _W)
|
||||||
|
shiftLimbs := int(n / _W)
|
||||||
|
|
||||||
|
var shiftedLimbs []uint
|
||||||
|
if shiftLimbs < size {
|
||||||
|
shiftedLimbs = xLimbs[shiftLimbs:]
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range xLimbs {
|
||||||
|
if i >= len(shiftedLimbs) {
|
||||||
|
xLimbs[i] = 0
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
xLimbs[i] = shiftedLimbs[i] >> shift
|
||||||
|
if i+1 < len(shiftedLimbs) {
|
||||||
|
xLimbs[i] |= shiftedLimbs[i+1] << (_W - shift)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
// BitLenVarTime returns the actual size of x in bits.
|
||||||
|
//
|
||||||
|
// The actual size of x (but nothing more) leaks through timing side-channels.
|
||||||
|
// Note that this is ordinarily secret, as opposed to the announced size of x.
|
||||||
|
func (x *Nat) BitLenVarTime() int {
|
||||||
|
// Eliminate bounds checks in the loop.
|
||||||
|
size := len(x.limbs)
|
||||||
|
xLimbs := x.limbs[:size]
|
||||||
|
|
||||||
|
for i := size - 1; i >= 0; i-- {
|
||||||
|
if xLimbs[i] != 0 {
|
||||||
|
return i*_W + bitLen(xLimbs[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// bitLen is a version of bits.Len that only leaks the bit length of n, but not
|
||||||
|
// its value. bits.Len and bits.LeadingZeros use a lookup table for the
|
||||||
|
// low-order bits on some architectures.
|
||||||
|
func bitLen(n uint) int {
|
||||||
|
len := 0
|
||||||
|
// We assume, here and elsewhere, that comparison to zero is constant time
|
||||||
|
// with respect to different non-zero values.
|
||||||
|
for n != 0 {
|
||||||
|
len++
|
||||||
|
n >>= 1
|
||||||
|
}
|
||||||
|
return len
|
||||||
|
}
|
||||||
|
|
||||||
// Modulus is used for modular arithmetic, precomputing relevant constants.
|
// Modulus is used for modular arithmetic, precomputing relevant constants.
|
||||||
//
|
//
|
||||||
// A Modulus can leak the exact number of bits needed to store its value
|
// A Modulus can leak the exact number of bits needed to store its value
|
||||||
@ -344,7 +459,6 @@ type Modulus struct {
|
|||||||
// This will be stored without any padding, and shouldn't alias with any
|
// This will be stored without any padding, and shouldn't alias with any
|
||||||
// other natural number being used.
|
// other natural number being used.
|
||||||
nat *Nat
|
nat *Nat
|
||||||
leading int // number of leading zeros in the modulus
|
|
||||||
|
|
||||||
// If m is even, the following fields are not set.
|
// If m is even, the following fields are not set.
|
||||||
odd bool
|
odd bool
|
||||||
@ -418,18 +532,34 @@ func minusInverseModW(x uint) uint {
|
|||||||
return -y
|
return -y
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewModulus creates a new Modulus from a slice of big-endian bytes.
|
// NewModulus creates a new Modulus from a slice of big-endian bytes. The
|
||||||
|
// modulus must be greater than one.
|
||||||
//
|
//
|
||||||
// The number of significant bits and whether the modulus is even is leaked
|
// The number of significant bits and whether the modulus is even is leaked
|
||||||
// through timing side-channels.
|
// through timing side-channels.
|
||||||
func NewModulus(b []byte) (*Modulus, error) {
|
func NewModulus(b []byte) (*Modulus, error) {
|
||||||
m := &Modulus{}
|
n := NewNat().resetToBytes(b)
|
||||||
m.nat = NewNat().resetToBytes(b)
|
return newModulus(n)
|
||||||
if len(m.nat.limbs) == 0 {
|
|
||||||
return nil, errors.New("modulus must be > 0")
|
|
||||||
}
|
}
|
||||||
m.leading = _W - bitLen(m.nat.limbs[len(m.nat.limbs)-1])
|
|
||||||
if m.nat.limbs[0]&1 == 1 {
|
// NewModulusProduct creates a new Modulus from the product of two numbers
|
||||||
|
// represented as big-endian byte slices. The result must be greater than one.
|
||||||
|
func NewModulusProduct(a, b []byte) (*Modulus, error) {
|
||||||
|
x := NewNat().resetToBytes(a)
|
||||||
|
y := NewNat().resetToBytes(b)
|
||||||
|
n := NewNat().reset(len(x.limbs) + len(y.limbs))
|
||||||
|
for i := range y.limbs {
|
||||||
|
n.limbs[i+len(x.limbs)] = addMulVVW(n.limbs[i:i+len(x.limbs)], x.limbs, y.limbs[i])
|
||||||
|
}
|
||||||
|
return newModulus(n.trim())
|
||||||
|
}
|
||||||
|
|
||||||
|
func newModulus(n *Nat) (*Modulus, error) {
|
||||||
|
m := &Modulus{nat: n}
|
||||||
|
if m.nat.IsZero() == yes || m.nat.IsOne() == yes {
|
||||||
|
return nil, errors.New("modulus must be > 1")
|
||||||
|
}
|
||||||
|
if m.nat.IsOdd() == 1 {
|
||||||
m.odd = true
|
m.odd = true
|
||||||
m.m0inv = minusInverseModW(m.nat.limbs[0])
|
m.m0inv = minusInverseModW(m.nat.limbs[0])
|
||||||
m.rr = rr(m)
|
m.rr = rr(m)
|
||||||
@ -437,20 +567,6 @@ func NewModulus(b []byte) (*Modulus, error) {
|
|||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// bitLen is a version of bits.Len that only leaks the bit length of n, but not
|
|
||||||
// its value. bits.Len and bits.LeadingZeros use a lookup table for the
|
|
||||||
// low-order bits on some architectures.
|
|
||||||
func bitLen(n uint) int {
|
|
||||||
var len int
|
|
||||||
// We assume, here and elsewhere, that comparison to zero is constant time
|
|
||||||
// with respect to different non-zero values.
|
|
||||||
for n != 0 {
|
|
||||||
len++
|
|
||||||
n >>= 1
|
|
||||||
}
|
|
||||||
return len
|
|
||||||
}
|
|
||||||
|
|
||||||
// Size returns the size of m in bytes.
|
// Size returns the size of m in bytes.
|
||||||
func (m *Modulus) Size() int {
|
func (m *Modulus) Size() int {
|
||||||
return (m.BitLen() + 7) / 8
|
return (m.BitLen() + 7) / 8
|
||||||
@ -458,12 +574,16 @@ func (m *Modulus) Size() int {
|
|||||||
|
|
||||||
// BitLen returns the size of m in bits.
|
// BitLen returns the size of m in bits.
|
||||||
func (m *Modulus) BitLen() int {
|
func (m *Modulus) BitLen() int {
|
||||||
return len(m.nat.limbs)*_W - int(m.leading)
|
return m.nat.BitLenVarTime()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nat returns m as a Nat. The return value must not be written to.
|
// Nat returns m as a Nat.
|
||||||
func (m *Modulus) Nat() *Nat {
|
func (m *Modulus) Nat() *Nat {
|
||||||
return m.nat
|
// Make a copy so that the caller can't modify m.nat or alias it with
|
||||||
|
// another Nat in a modulus operation.
|
||||||
|
n := NewNat()
|
||||||
|
n.Set(m.nat)
|
||||||
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// shiftIn calculates x = x << _W + y mod m.
|
// shiftIn calculates x = x << _W + y mod m.
|
||||||
@ -595,6 +715,17 @@ func (x *Nat) Sub(y *Nat, m *Modulus) *Nat {
|
|||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SubOne computes x = x - 1 mod m.
|
||||||
|
//
|
||||||
|
// The length of x must be the same as the modulus.
|
||||||
|
func (x *Nat) SubOne(m *Modulus) *Nat {
|
||||||
|
one := NewNat().ExpandFor(m)
|
||||||
|
one.limbs[0] = 1
|
||||||
|
// Sub asks for x to be reduced modulo m, while SubOne doesn't, but when
|
||||||
|
// y = 1, it works, and this is an internal use.
|
||||||
|
return x.Sub(one, m)
|
||||||
|
}
|
||||||
|
|
||||||
// Add computes x = x + y mod m.
|
// Add computes x = x + y mod m.
|
||||||
//
|
//
|
||||||
// The length of both operands must be the same as the modulus. Both operands
|
// The length of both operands must be the same as the modulus. Both operands
|
||||||
@ -918,7 +1049,7 @@ func (out *Nat) ExpShortVarTime(x *Nat, e uint, m *Modulus) *Nat {
|
|||||||
// chain, skipping the initial run of zeroes.
|
// chain, skipping the initial run of zeroes.
|
||||||
xR := NewNat().Set(x).montgomeryRepresentation(m)
|
xR := NewNat().Set(x).montgomeryRepresentation(m)
|
||||||
out.Set(xR)
|
out.Set(xR)
|
||||||
for i := bits.UintSize - bitLen(e) + 1; i < bits.UintSize; i++ {
|
for i := bits.UintSize - bits.Len(e) + 1; i < bits.UintSize; i++ {
|
||||||
out.montgomeryMul(out, out, m)
|
out.montgomeryMul(out, out, m)
|
||||||
if k := (e >> (bits.UintSize - i - 1)) & 1; k != 0 {
|
if k := (e >> (bits.UintSize - i - 1)) & 1; k != 0 {
|
||||||
out.montgomeryMul(out, xR, m)
|
out.montgomeryMul(out, xR, m)
|
||||||
@ -926,3 +1057,129 @@ func (out *Nat) ExpShortVarTime(x *Nat, e uint, m *Modulus) *Nat {
|
|||||||
}
|
}
|
||||||
return out.montgomeryReduction(m)
|
return out.montgomeryReduction(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InverseVarTime calculates x = a⁻¹ mod m and returns (x, true) if a is
|
||||||
|
// invertible. Otherwise, InverseVarTime returns (x, false) and x is not
|
||||||
|
// modified.
|
||||||
|
//
|
||||||
|
// a must be reduced modulo m, but doesn't need to have the same size. The
|
||||||
|
// output will be resized to the size of m and overwritten.
|
||||||
|
func (x *Nat) InverseVarTime(a *Nat, m *Modulus) (*Nat, bool) {
|
||||||
|
// This is the extended binary GCD algorithm described in the Handbook of
|
||||||
|
// Applied Cryptography, Algorithm 14.61, adapted by BoringSSL to bound
|
||||||
|
// coefficients and avoid negative numbers. For more details and proof of
|
||||||
|
// correctness, see https://github.com/mit-plv/fiat-crypto/pull/333/files.
|
||||||
|
//
|
||||||
|
// Following the proof linked in the PR above, the changes are:
|
||||||
|
//
|
||||||
|
// 1. Negate [B] and [C] so they are positive. The invariant now involves a
|
||||||
|
// subtraction.
|
||||||
|
// 2. If step 2 (both [x] and [y] are even) runs, abort immediately. This
|
||||||
|
// algorithm only cares about [x] and [y] relatively prime.
|
||||||
|
// 3. Subtract copies of [x] and [y] as needed in step 6 (both [u] and [v]
|
||||||
|
// are odd) so coefficients stay in bounds.
|
||||||
|
// 4. Replace the [u >= v] check with [u > v]. This changes the end
|
||||||
|
// condition to [v = 0] rather than [u = 0]. This saves an extra
|
||||||
|
// subtraction due to which coefficients were negated.
|
||||||
|
// 5. Rename x and y to a and n, to capture that one is a modulus.
|
||||||
|
// 6. Rearrange steps 4 through 6 slightly. Merge the loops in steps 4 and
|
||||||
|
// 5 into the main loop (step 7's goto), and move step 6 to the start of
|
||||||
|
// the loop iteration, ensuring each loop iteration halves at least one
|
||||||
|
// value.
|
||||||
|
//
|
||||||
|
// Note this algorithm does not handle either input being zero.
|
||||||
|
|
||||||
|
if a.IsZero() == yes {
|
||||||
|
return x, false
|
||||||
|
}
|
||||||
|
if a.IsOdd() == no && !m.odd {
|
||||||
|
// a and m are not coprime, as they are both even.
|
||||||
|
return x, false
|
||||||
|
}
|
||||||
|
|
||||||
|
u := NewNat().Set(a).ExpandFor(m)
|
||||||
|
v := m.Nat()
|
||||||
|
|
||||||
|
A := NewNat().reset(len(m.nat.limbs))
|
||||||
|
A.limbs[0] = 1
|
||||||
|
B := NewNat().reset(len(a.limbs))
|
||||||
|
C := NewNat().reset(len(m.nat.limbs))
|
||||||
|
D := NewNat().reset(len(a.limbs))
|
||||||
|
D.limbs[0] = 1
|
||||||
|
|
||||||
|
// Before and after each loop iteration, the following hold:
|
||||||
|
//
|
||||||
|
// u = A*a - B*m
|
||||||
|
// v = D*m - C*a
|
||||||
|
// 0 < u <= a
|
||||||
|
// 0 <= v <= m
|
||||||
|
// 0 <= A < m
|
||||||
|
// 0 <= B <= a
|
||||||
|
// 0 <= C < m
|
||||||
|
// 0 <= D <= a
|
||||||
|
//
|
||||||
|
// After each loop iteration, u and v only get smaller, and at least one of
|
||||||
|
// them shrinks by at least a factor of two.
|
||||||
|
for {
|
||||||
|
// If both u and v are odd, subtract the smaller from the larger.
|
||||||
|
// If u = v, we need to subtract from v to hit the modified exit condition.
|
||||||
|
if u.IsOdd() == yes && v.IsOdd() == yes {
|
||||||
|
if v.CmpGeq(u) == no {
|
||||||
|
u.sub(v)
|
||||||
|
A.Add(C, m)
|
||||||
|
B.Add(D, &Modulus{nat: a})
|
||||||
|
} else {
|
||||||
|
v.sub(u)
|
||||||
|
C.Add(A, m)
|
||||||
|
D.Add(B, &Modulus{nat: a})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exactly one of u and v is now even.
|
||||||
|
if u.IsOdd() == v.IsOdd() {
|
||||||
|
panic("bigmod: internal error: u and v are not in the expected state")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Halve the even one and adjust the corresponding coefficient.
|
||||||
|
if u.IsOdd() == no {
|
||||||
|
rshift1(u, 0)
|
||||||
|
if A.IsOdd() == yes || B.IsOdd() == yes {
|
||||||
|
rshift1(A, A.add(m.nat))
|
||||||
|
rshift1(B, B.add(a))
|
||||||
|
} else {
|
||||||
|
rshift1(A, 0)
|
||||||
|
rshift1(B, 0)
|
||||||
|
}
|
||||||
|
} else { // v.IsOdd() == no
|
||||||
|
rshift1(v, 0)
|
||||||
|
if C.IsOdd() == yes || D.IsOdd() == yes {
|
||||||
|
rshift1(C, C.add(m.nat))
|
||||||
|
rshift1(D, D.add(a))
|
||||||
|
} else {
|
||||||
|
rshift1(C, 0)
|
||||||
|
rshift1(D, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.IsZero() == yes {
|
||||||
|
if u.IsOne() == no {
|
||||||
|
return x, false
|
||||||
|
}
|
||||||
|
return x.Set(A), true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func rshift1(a *Nat, carry uint) {
|
||||||
|
size := len(a.limbs)
|
||||||
|
aLimbs := a.limbs[:size]
|
||||||
|
|
||||||
|
for i := 0; i < size; i++ {
|
||||||
|
aLimbs[i] >>= 1
|
||||||
|
if i+1 < size {
|
||||||
|
aLimbs[i] |= aLimbs[i+1] << (_W - 1)
|
||||||
|
} else {
|
||||||
|
aLimbs[i] |= carry << (_W - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
package bigmod
|
package bigmod
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
cryptorand "crypto/rand"
|
cryptorand "crypto/rand"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
@ -12,6 +13,7 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"math/bits"
|
"math/bits"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@ -31,6 +33,14 @@ func (x *Nat) setBig(n *big.Int) *Nat {
|
|||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *Nat) asBig() *big.Int {
|
||||||
|
bits := make([]big.Word, len(n.limbs))
|
||||||
|
for i := range n.limbs {
|
||||||
|
bits[i] = big.Word(n.limbs[i])
|
||||||
|
}
|
||||||
|
return new(big.Int).SetBits(bits)
|
||||||
|
}
|
||||||
|
|
||||||
func (n *Nat) String() string {
|
func (n *Nat) String() string {
|
||||||
var limbs []string
|
var limbs []string
|
||||||
for i := range n.limbs {
|
for i := range n.limbs {
|
||||||
@ -400,6 +410,98 @@ func testMul(t *testing.T, n int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIs(t *testing.T) {
|
||||||
|
checkYes := func(c choice, err string) {
|
||||||
|
t.Helper()
|
||||||
|
if c != yes {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkNot := func(c choice, err string) {
|
||||||
|
t.Helper()
|
||||||
|
if c != no {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mFour := modulusFromBytes([]byte{4})
|
||||||
|
n, err := NewNat().SetBytes([]byte{3}, mFour)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
checkYes(n.IsMinusOne(mFour), "3 is not -1 mod 4")
|
||||||
|
checkNot(n.IsZero(), "3 is zero")
|
||||||
|
checkNot(n.IsOne(), "3 is one")
|
||||||
|
checkYes(n.IsOdd(), "3 is not odd")
|
||||||
|
n.SubOne(mFour)
|
||||||
|
checkNot(n.IsMinusOne(mFour), "2 is -1 mod 4")
|
||||||
|
checkNot(n.IsZero(), "2 is zero")
|
||||||
|
checkNot(n.IsOne(), "2 is one")
|
||||||
|
checkNot(n.IsOdd(), "2 is odd")
|
||||||
|
n.SubOne(mFour)
|
||||||
|
checkNot(n.IsMinusOne(mFour), "1 is -1 mod 4")
|
||||||
|
checkNot(n.IsZero(), "1 is zero")
|
||||||
|
checkYes(n.IsOne(), "1 is not one")
|
||||||
|
checkYes(n.IsOdd(), "1 is not odd")
|
||||||
|
n.SubOne(mFour)
|
||||||
|
checkNot(n.IsMinusOne(mFour), "0 is -1 mod 4")
|
||||||
|
checkYes(n.IsZero(), "0 is not zero")
|
||||||
|
checkNot(n.IsOne(), "0 is one")
|
||||||
|
checkNot(n.IsOdd(), "0 is odd")
|
||||||
|
n.SubOne(mFour)
|
||||||
|
checkYes(n.IsMinusOne(mFour), "-1 is not -1 mod 4")
|
||||||
|
checkNot(n.IsZero(), "-1 is zero")
|
||||||
|
checkNot(n.IsOne(), "-1 is one")
|
||||||
|
checkYes(n.IsOdd(), "-1 mod 4 is not odd")
|
||||||
|
|
||||||
|
mTwoLimbs := maxModulus(2)
|
||||||
|
n, err = NewNat().SetBytes([]byte{0x01}, mTwoLimbs)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if n.IsOne() != 1 {
|
||||||
|
t.Errorf("1 is not one")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTrailingZeroBits(t *testing.T) {
|
||||||
|
nb := new(big.Int).SetBytes([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e})
|
||||||
|
nb.Lsh(nb, 128)
|
||||||
|
expected := 129
|
||||||
|
for expected >= 0 {
|
||||||
|
n := NewNat().setBig(nb)
|
||||||
|
if n.TrailingZeroBitsVarTime() != uint(expected) {
|
||||||
|
t.Errorf("%d != %d", n.TrailingZeroBitsVarTime(), expected)
|
||||||
|
}
|
||||||
|
nb.Rsh(nb, 1)
|
||||||
|
expected--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRightShift(t *testing.T) {
|
||||||
|
nb, err := cryptorand.Int(cryptorand.Reader, new(big.Int).Lsh(big.NewInt(1), 1024))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for _, shift := range []uint{1, 32, 64, 128, 1024 - 128, 1024 - 64, 1024 - 32, 1024 - 1} {
|
||||||
|
testShift := func(t *testing.T, shift uint) {
|
||||||
|
n := NewNat().setBig(nb)
|
||||||
|
oldLen := len(n.limbs)
|
||||||
|
n.ShiftRightVarTime(shift)
|
||||||
|
if len(n.limbs) != oldLen {
|
||||||
|
t.Errorf("len(n.limbs) = %d, want %d", len(n.limbs), oldLen)
|
||||||
|
}
|
||||||
|
exp := new(big.Int).Rsh(nb, shift)
|
||||||
|
if n.asBig().Cmp(exp) != 0 {
|
||||||
|
t.Errorf("%v != %v", n.asBig(), exp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.Run(fmt.Sprint(shift-1), func(t *testing.T) { testShift(t, shift-1) })
|
||||||
|
t.Run(fmt.Sprint(shift), func(t *testing.T) { testShift(t, shift) })
|
||||||
|
t.Run(fmt.Sprint(shift+1), func(t *testing.T) { testShift(t, shift+1) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func natBytes(n *Nat) []byte {
|
func natBytes(n *Nat) []byte {
|
||||||
return n.Bytes(maxModulus(uint(len(n.limbs))))
|
return n.Bytes(maxModulus(uint(len(n.limbs))))
|
||||||
}
|
}
|
||||||
@ -546,7 +648,7 @@ func BenchmarkExp(b *testing.B) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNewModulus(t *testing.T) {
|
func TestNewModulus(t *testing.T) {
|
||||||
expected := "modulus must be > 0"
|
expected := "modulus must be > 1"
|
||||||
_, err := NewModulus([]byte{})
|
_, err := NewModulus([]byte{})
|
||||||
if err == nil || err.Error() != expected {
|
if err == nil || err.Error() != expected {
|
||||||
t.Errorf("NewModulus(0) got %q, want %q", err, expected)
|
t.Errorf("NewModulus(0) got %q, want %q", err, expected)
|
||||||
@ -559,6 +661,14 @@ func TestNewModulus(t *testing.T) {
|
|||||||
if err == nil || err.Error() != expected {
|
if err == nil || err.Error() != expected {
|
||||||
t.Errorf("NewModulus(0) got %q, want %q", err, expected)
|
t.Errorf("NewModulus(0) got %q, want %q", err, expected)
|
||||||
}
|
}
|
||||||
|
_, err = NewModulus([]byte{1})
|
||||||
|
if err == nil || err.Error() != expected {
|
||||||
|
t.Errorf("NewModulus(1) got %q, want %q", err, expected)
|
||||||
|
}
|
||||||
|
_, err = NewModulus([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1})
|
||||||
|
if err == nil || err.Error() != expected {
|
||||||
|
t.Errorf("NewModulus(1) got %q, want %q", err, expected)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOverflowedBytes(t *testing.T) {
|
func TestOverflowedBytes(t *testing.T) {
|
||||||
@ -594,3 +704,121 @@ func TestOverflowedBytes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeTestValue(nbits int) []uint {
|
||||||
|
n := nbits / _W
|
||||||
|
x := make([]uint, n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
x[i]--
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func slicesEqual(a, b []uint) bool {
|
||||||
|
if len(a) != len(b) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := range a {
|
||||||
|
if a[i] != b[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddMulVVWSized(t *testing.T) {
|
||||||
|
// Sized addMulVVW have architecture-specific implementations on
|
||||||
|
// a number of architectures. Test that they match the generic
|
||||||
|
// implementation.
|
||||||
|
tests := []struct {
|
||||||
|
n int
|
||||||
|
f func(z, x *uint, y uint) uint
|
||||||
|
}{
|
||||||
|
{256, addMulVVW256},
|
||||||
|
{1024, addMulVVW1024},
|
||||||
|
{1536, addMulVVW1536},
|
||||||
|
{2048, addMulVVW2048},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(fmt.Sprint(test.n), func(t *testing.T) {
|
||||||
|
x := makeTestValue(test.n)
|
||||||
|
z := makeTestValue(test.n)
|
||||||
|
z2 := makeTestValue(test.n)
|
||||||
|
var y uint
|
||||||
|
y--
|
||||||
|
c := addMulVVW(z, x, y)
|
||||||
|
c2 := test.f(&z2[0], &x[0], y)
|
||||||
|
if !slicesEqual(z, z2) || c != c2 {
|
||||||
|
t.Errorf("%016X, %016X != %016X, %016X", z, c, z2, c2)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInverse(t *testing.T) {
|
||||||
|
f, err := os.Open("testdata/mod_inv_tests.txt")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var ModInv, A, M string
|
||||||
|
var lineNum int
|
||||||
|
scanner := bufio.NewScanner(f)
|
||||||
|
for scanner.Scan() {
|
||||||
|
lineNum++
|
||||||
|
line := scanner.Text()
|
||||||
|
if len(line) == 0 || line[0] == '#' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
k, v, _ := strings.Cut(line, " = ")
|
||||||
|
switch k {
|
||||||
|
case "ModInv":
|
||||||
|
ModInv = v
|
||||||
|
case "A":
|
||||||
|
A = v
|
||||||
|
case "M":
|
||||||
|
M = v
|
||||||
|
|
||||||
|
t.Run(fmt.Sprintf("line %d", lineNum), func(t *testing.T) {
|
||||||
|
m, err := NewModulus(decodeHex(t, M))
|
||||||
|
if err != nil {
|
||||||
|
t.Skip("modulus <= 1")
|
||||||
|
}
|
||||||
|
a, err := NewNat().SetBytes(decodeHex(t, A), m)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
got, ok := NewNat().InverseVarTime(a, m)
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("not invertible")
|
||||||
|
}
|
||||||
|
exp, err := NewNat().SetBytes(decodeHex(t, ModInv), m)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if got.Equal(exp) != 1 {
|
||||||
|
t.Errorf("%v != %v", got, exp)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
default:
|
||||||
|
t.Fatalf("unknown key %q on line %d", k, lineNum)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeHex(t *testing.T, s string) []byte {
|
||||||
|
t.Helper()
|
||||||
|
if len(s)%2 != 0 {
|
||||||
|
s = "0" + s
|
||||||
|
}
|
||||||
|
b, err := hex.DecodeString(s)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to decode hex %q: %v", s, err)
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
115
internal/bigmod/testdata/mod_inv_tests.txt
vendored
Normal file
115
internal/bigmod/testdata/mod_inv_tests.txt
vendored
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
# ModInv tests.
|
||||||
|
#
|
||||||
|
# These test vectors satisfy ModInv * A = 1 (mod M) and 0 <= ModInv < M.
|
||||||
|
|
||||||
|
ModInv = 00
|
||||||
|
A = 00
|
||||||
|
M = 01
|
||||||
|
|
||||||
|
ModInv = 00
|
||||||
|
A = 01
|
||||||
|
M = 01
|
||||||
|
|
||||||
|
ModInv = 00
|
||||||
|
A = 02
|
||||||
|
M = 01
|
||||||
|
|
||||||
|
ModInv = 00
|
||||||
|
A = 03
|
||||||
|
M = 01
|
||||||
|
|
||||||
|
ModInv = 64
|
||||||
|
A = 54
|
||||||
|
M = e3
|
||||||
|
|
||||||
|
ModInv = 13
|
||||||
|
A = 2b
|
||||||
|
M = 30
|
||||||
|
|
||||||
|
ModInv = 2f
|
||||||
|
A = 30
|
||||||
|
M = 37
|
||||||
|
|
||||||
|
ModInv = 4
|
||||||
|
A = 13
|
||||||
|
M = 4b
|
||||||
|
|
||||||
|
ModInv = 1c47
|
||||||
|
A = cd4
|
||||||
|
M = 6a21
|
||||||
|
|
||||||
|
ModInv = 2b97
|
||||||
|
A = 8e7
|
||||||
|
M = 49c0
|
||||||
|
|
||||||
|
ModInv = 29b9
|
||||||
|
A = fcb
|
||||||
|
M = 3092
|
||||||
|
|
||||||
|
ModInv = a83
|
||||||
|
A = 14bf
|
||||||
|
M = 41ae
|
||||||
|
|
||||||
|
ModInv = 18f15fe1
|
||||||
|
A = 11b5d53e
|
||||||
|
M = 322e92a1
|
||||||
|
|
||||||
|
ModInv = 32f9453b
|
||||||
|
A = 8af6df6
|
||||||
|
M = 33d45eb7
|
||||||
|
|
||||||
|
ModInv = d696369
|
||||||
|
A = c5f89dd5
|
||||||
|
M = fc09c17c
|
||||||
|
|
||||||
|
ModInv = 622839d8
|
||||||
|
A = 60c2526
|
||||||
|
M = 74200493
|
||||||
|
|
||||||
|
ModInv = fb5a8aee7bbc4ef
|
||||||
|
A = 24ebd835a70be4e2
|
||||||
|
M = 9c7256574e0c5e93
|
||||||
|
|
||||||
|
ModInv = 846bc225402419c
|
||||||
|
A = 23026003ab1fbdb
|
||||||
|
M = 1683cbe32779c59b
|
||||||
|
|
||||||
|
ModInv = 5ff84f63a78982f9
|
||||||
|
A = 4a2420dc733e1a0f
|
||||||
|
M = a73c6bfabefa09e6
|
||||||
|
|
||||||
|
ModInv = 133e74d28ef42b43
|
||||||
|
A = 2e9511ae29cdd41
|
||||||
|
M = 15234df99f19fcda
|
||||||
|
|
||||||
|
ModInv = 46ae1fabe9521e4b99b198fc8439609023aa69be2247c0d1e27c2a0ea332f9c5
|
||||||
|
A = 6331fec5f01014046788c919ed50dc86ac7a80c085f1b6f645dd179c0f0dc9cd
|
||||||
|
M = 8ef409de82318259a8655a39293b1e762fa2cc7e0aeb4c59713a1e1fff6af640
|
||||||
|
|
||||||
|
ModInv = 444ccea3a7b21677dd294d34de53cc8a5b51e69b37782310a00fc6bcc975709b
|
||||||
|
A = 679280bd880994c08322143a4ea8a0825d0466fda1bb6b3eb86fc8e90747512b
|
||||||
|
M = e4fecab84b365c63a0dab4244ce3f921a9c87ec64d69a2031939f55782e99a2e
|
||||||
|
|
||||||
|
ModInv = 1ac7d7a03ceec5f690f567c9d61bf3469c078285bcc5cf00ac944596e887ca17
|
||||||
|
A = 1593ef32d9c784f5091bdff952f5c5f592a3aed6ba8ea865efa6d7df87be1805
|
||||||
|
M = 1e276882f90c95e0c1976eb079f97af075445b1361c02018d6bd7191162e67b2
|
||||||
|
|
||||||
|
ModInv = 639108b90dfe946f498be21303058413bbb0e59d0bd6a6115788705abd0666d6
|
||||||
|
A = 9258d6238e4923d120b2d1033573ffcac691526ad0842a3b174dccdbb79887bd
|
||||||
|
M = ce62909c39371d463aaba3d4b72ea6da49cb9b529e39e1972ef3ccd9a66fe08f
|
||||||
|
|
||||||
|
ModInv = aebde7654cb17833a106231c4b9e2f519140e85faee1bfb4192830f03f385e773c0f4767e93e874ffdc3b7a6b7e6a710e5619901c739ee8760a26128e8c91ef8cf761d0e505d8b28ae078d17e6071c372893bb7b72538e518ebc57efa70b7615e406756c49729b7c6e74f84aed7a316b6fa748ff4b9f143129d29dad1bff98bb
|
||||||
|
A = a29dacaf5487d354280fdd2745b9ace4cd50f2bde41d0ee529bf26a1913244f708085452ff32feab19a7418897990da46a0633f7c8375d583367319091bbbe069b0052c5e48a7daac9fb650db5af768cd2508ec3e2cda7456d4b9ce1c39459627a8b77e038b826cd7e326d0685b0cd0cb50f026f18300dae9f5fd42aa150ee8b
|
||||||
|
M = d686f9b86697313251685e995c09b9f1e337ddfaa050bd2df15bf4ca1dc46c5565021314765299c434ea1a6ec42bf92a29a7d1ffff599f4e50b79a82243fb24813060580c770d4c1140aeb2ab2685007e948b6f1f62e8001a0545619477d498132c907774479f6d95899e6251e7136f79ab6d3b7c82e4aca421e7d22fe7db19c
|
||||||
|
|
||||||
|
ModInv = 1ec872f4f20439e203597ca4de9d1296743f95781b2fe85d5def808558bbadef02a46b8955f47c83e1625f8bb40228eab09cad2a35c9ad62ab77a30e3932872959c5898674162da244a0ec1f68c0ed89f4b0f3572bfdc658ad15bf1b1c6e1176b0784c9935bd3ff1f49bb43753eacee1d8ca1c0b652d39ec727da83984fe3a0f
|
||||||
|
A = 2e527b0a1dc32460b2dd94ec446c692989f7b3c7451a5cbeebf69fc0ea9c4871fbe78682d5dc5b66689f7ed889b52161cd9830b589a93d21ab26dbede6c33959f5a0f0d107169e2daaac78bac8cf2d41a1eb1369cb6dc9e865e73bb2e51b886f4e896082db199175e3dde0c4ed826468f238a77bd894245d0918efc9ca84f945
|
||||||
|
M = b13133a9ebe0645f987d170c077eea2aa44e85c9ab10386d02867419a590cb182d9826a882306c212dbe75225adde23f80f5b37ca75ed09df20fc277cc7fbbfac8d9ef37a50f6b68ea158f5447283618e64e1426406d26ea85232afb22bf546c75018c1c55cb84c374d58d9d44c0a13ba88ac2e387765cb4c3269e3a983250fa
|
||||||
|
|
||||||
|
ModInv = 30ffa1876313a69de1e4e6ee132ea1d3a3da32f3b56f5cfb11402b0ad517dce605cf8e91d69fa375dd887fa8507bd8a28b2d5ce745799126e86f416047709f93f07fbd88918a047f13100ea71b1d48f6fc6d12e5c917646df3041b302187af641eaedf4908abc36f12c204e1526a7d80e96e302fb0779c28d7da607243732f26
|
||||||
|
A = 31157208bde6b85ebecaa63735947b3b36fa351b5c47e9e1c40c947339b78bf96066e5dbe21bb42629e6fcdb81f5f88db590bfdd5f4c0a6a0c3fc6377e5c1fd8235e46e291c688b6d6ecfb36604891c2a7c9cbcc58c26e44b43beecb9c5044b58bb58e35de3cf1128f3c116534fe4e421a33f83603c3df1ae36ec88092f67f2a
|
||||||
|
M = 53408b23d6cb733e6c9bc3d1e2ea2286a5c83cc4e3e7470f8af3a1d9f28727f5b1f8ae348c1678f5d1105dc3edf2de64e65b9c99545c47e64b770b17c8b4ef5cf194b43a0538053e87a6b95ade1439cebf3d34c6aa72a11c1497f58f76011e16c5be087936d88aba7a740113120e939e27bd3ddcb6580c2841aa406566e33c35
|
||||||
|
|
||||||
|
ModInv = 87355002f305c81ba0dc97ca2234a2bc02528cefde38b94ac5bd95efc7bf4c140899107fff47f0df9e3c6aa70017ebc90610a750f112cd4f475b9c76b204a953444b4e7196ccf17e93fdaed160b7345ca9b397eddf9446e8ea8ee3676102ce70eaafbe9038a34639789e6f2f1e3f352638f2e8a8f5fc56aaea7ec705ee068dd5
|
||||||
|
A = 42a25d0bc96f71750f5ac8a51a1605a41b506cca51c9a7ecf80cad713e56f70f1b4b6fa51cbb101f55fd74f318adefb3af04e0c8a7e281055d5a40dd40913c0e1211767c5be915972c73886106dc49325df6c2df49e9eea4536f0343a8e7d332c6159e4f5bdb20d89f90e67597c4a2a632c31b2ef2534080a9ac61f52303990d
|
||||||
|
M = d3d3f95d50570351528a76ab1e806bae1968bd420899bdb3d87c823fac439a4354c31f6c888c939784f18fe10a95e6d203b1901caa18937ba6f8be033af10c35fc869cf3d16bef479f280f53b3499e645d0387554623207ca4989e5de00bfeaa5e9ab56474fc60dd4967b100e0832eaaf2fcb2ef82a181567057b880b3afef62
|
@ -604,7 +604,7 @@ func (priv *PrivateKey) inverseOfPrivateKeyPlus1(c *sm2Curve) (*bigmod.Nat, erro
|
|||||||
dp1Bytes []byte
|
dp1Bytes []byte
|
||||||
)
|
)
|
||||||
priv.inverseOfKeyPlus1Once.Do(func() {
|
priv.inverseOfKeyPlus1Once.Do(func() {
|
||||||
oneNat, _ = bigmod.NewNat().SetUint(1, c.N)
|
oneNat = bigmod.NewNat().SetUint(1, c.N)
|
||||||
dp1Inv, err = bigmod.NewNat().SetBytes(priv.D.Bytes(), c.N)
|
dp1Inv, err = bigmod.NewNat().SetBytes(priv.D.Bytes(), c.N)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
dp1Inv.Add(oneNat, c.N)
|
dp1Inv.Add(oneNat, c.N)
|
||||||
@ -1070,8 +1070,8 @@ func precomputeParams(c *sm2Curve, curve elliptic.Curve) {
|
|||||||
c.curve = curve
|
c.curve = curve
|
||||||
c.N, _ = bigmod.NewModulus(params.N.Bytes())
|
c.N, _ = bigmod.NewModulus(params.N.Bytes())
|
||||||
c.P, _ = bigmod.NewModulus(params.P.Bytes())
|
c.P, _ = bigmod.NewModulus(params.P.Bytes())
|
||||||
c.nMinus2 = new(big.Int).Sub(params.N, big.NewInt(2)).Bytes()
|
c.nMinus1 = c.N.Nat().SubOne(c.N)
|
||||||
c.nMinus1, _ = bigmod.NewNat().SetBytes(new(big.Int).Sub(params.N, big.NewInt(1)).Bytes(), c.N)
|
c.nMinus2 = new(bigmod.Nat).Set(c.nMinus1).SubOne(c.N).Bytes(c.N)
|
||||||
}
|
}
|
||||||
|
|
||||||
var errInvalidPrivateKey = errors.New("sm2: invalid private key")
|
var errInvalidPrivateKey = errors.New("sm2: invalid private key")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user