@ -100,10 +100,6 @@ const (
// fieldPrimeWordOne is word one of the secp256k1 prime in the
// internal field representation. It is used during negation.
fieldPrimeWordOne = 0x3ffffbf
// primeLowBits is the lower 2*fieldBase bits of the secp256k1 prime in
// its standard normalized form. It is used during modular reduction.
primeLowBits = 0xffffefffffc2f
)
// fieldVal implements optimized fixed-precision arithmetic over the
@ -250,39 +246,15 @@ func (f *fieldVal) SetHex(hexString string) *fieldVal {
// performs fast modular reduction over the secp256k1 prime by making use of the
// special form of the prime.
func ( f * fieldVal ) Normalize ( ) * fieldVal {
// The field representation leaves 6 bits of overflow in each
// word so intermediate calculations can be performed without needing
// to propagate the carry to each higher word during the calculations.
// In order to normalize, first we need to "compact" the full 256-bit
// value to the right and treat the additional 64 leftmost bits as
// the magnitude.
m := f . n [ 0 ]
t0 := m & fieldBaseMask
m = ( m >> fieldBase ) + f . n [ 1 ]
t1 := m & fieldBaseMask
m = ( m >> fieldBase ) + f . n [ 2 ]
t2 := m & fieldBaseMask
m = ( m >> fieldBase ) + f . n [ 3 ]
t3 := m & fieldBaseMask
m = ( m >> fieldBase ) + f . n [ 4 ]
t4 := m & fieldBaseMask
m = ( m >> fieldBase ) + f . n [ 5 ]
t5 := m & fieldBaseMask
m = ( m >> fieldBase ) + f . n [ 6 ]
t6 := m & fieldBaseMask
m = ( m >> fieldBase ) + f . n [ 7 ]
t7 := m & fieldBaseMask
m = ( m >> fieldBase ) + f . n [ 8 ]
t8 := m & fieldBaseMask
m = ( m >> fieldBase ) + f . n [ 9 ]
t9 := m & fieldMSBMask
m = m >> fieldMSBBits
// At this point, if the magnitude is greater than 0, the overall value
// is greater than the max possible 256-bit value. In particular, it is
// "how many times larger" than the max value it is. Since this field
// is doing arithmetic modulo the secp256k1 prime, we need to perform
// modular reduction over the prime.
// The field representation leaves 6 bits of overflow in each word so
// intermediate calculations can be performed without needing to
// propagate the carry to each higher word during the calculations. In
// order to normalize, we need to "compact" the full 256-bit value to
// the right while propagating any carries through to the high order
// word.
//
// Since this field is doing arithmetic modulo the secp256k1 prime, we
// also need to perform modular reduction over the prime.
//
// Per [HAC] section 14.3.4: Reduction method of moduli of special form,
// when the modulus is of the special form m = b^t - c, highly efficient
@ -298,98 +270,87 @@ func (f *fieldVal) Normalize() *fieldVal {
//
// The algorithm presented in the referenced section typically repeats
// until the quotient is zero. However, due to our field representation
// we already know at least how many times we would need to repeat as
// it's the value currently in m. Thus we can simply multiply the
// magnitude by the field representation of the prime and do a single
// iteration. Notice that nothing will be changed when the magnitude is
// zero, so we could skip this in that case, however always running
// regardless allows it to run in constant time.
r := t0 + m * 977
t0 = r & fieldBaseMask
r = ( r >> fieldBase ) + t1 + m * 64
t1 = r & fieldBaseMask
r = ( r >> fieldBase ) + t2
t2 = r & fieldBaseMask
r = ( r >> fieldBase ) + t3
t3 = r & fieldBaseMask
r = ( r >> fieldBase ) + t4
t4 = r & fieldBaseMask
r = ( r >> fieldBase ) + t5
t5 = r & fieldBaseMask
r = ( r >> fieldBase ) + t6
t6 = r & fieldBaseMask
r = ( r >> fieldBase ) + t7
t7 = r & fieldBaseMask
r = ( r >> fieldBase ) + t8
t8 = r & fieldBaseMask
r = ( r >> fieldBase ) + t9
t9 = r & fieldMSBMask
// At this point, the result will be in the range 0 <= result <=
// prime + (2^64 - c). Therefore, one more subtraction of the prime
// might be needed if the current result is greater than or equal to the
// prime. The following does the final reduction in constant time.
// Note that the if/else here intentionally does the bitwise OR with
// zero even though it won't change the value to ensure constant time
// between the branches.
var mask int32
lowBits := uint64 ( t1 ) << fieldBase | uint64 ( t0 )
if lowBits < primeLowBits {
mask |= - 1
} else {
mask |= 0
}
if t2 < fieldBaseMask {
mask |= - 1
} else {
mask |= 0
}
if t3 < fieldBaseMask {
mask |= - 1
} else {
mask |= 0
}
if t4 < fieldBaseMask {
mask |= - 1
} else {
mask |= 0
}
if t5 < fieldBaseMask {
mask |= - 1
} else {
mask |= 0
}
if t6 < fieldBaseMask {
mask |= - 1
// we already know to within one reduction how many times we would need
// to repeat as it's the uppermost bits of the high order word. Thus we
// can simply multiply the magnitude by the field representation of the
// prime and do a single iteration. After this step there might be an
// additional carry to bit 256 (bit 22 of the high order word).
t9 := f . n [ 9 ]
m := t9 >> fieldMSBBits
t9 = t9 & fieldMSBMask
t0 := f . n [ 0 ] + m * 977
t1 := ( t0 >> fieldBase ) + f . n [ 1 ] + ( m << 6 )
t0 = t0 & fieldBaseMask
t2 := ( t1 >> fieldBase ) + f . n [ 2 ]
t1 = t1 & fieldBaseMask
t3 := ( t2 >> fieldBase ) + f . n [ 3 ]
t2 = t2 & fieldBaseMask
t4 := ( t3 >> fieldBase ) + f . n [ 4 ]
t3 = t3 & fieldBaseMask
t5 := ( t4 >> fieldBase ) + f . n [ 5 ]
t4 = t4 & fieldBaseMask
t6 := ( t5 >> fieldBase ) + f . n [ 6 ]
t5 = t5 & fieldBaseMask
t7 := ( t6 >> fieldBase ) + f . n [ 7 ]
t6 = t6 & fieldBaseMask
t8 := ( t7 >> fieldBase ) + f . n [ 8 ]
t7 = t7 & fieldBaseMask
t9 = ( t8 >> fieldBase ) + t9
t8 = t8 & fieldBaseMask
// At this point, the magnitude is guaranteed to be one, however, the
// value could still be greater than the prime if there was either a
// carry through to bit 256 (bit 22 of the higher order word) or the
// value is greater than or equal to the field characteristic. The
// following determines if either or these conditions are true and does
// the final reduction in constant time.
//
// Note that the if/else statements here intentionally do the bitwise
// operators even when it won't change the value to ensure constant time
// between the branches. Also note that 'm' will be zero when neither
// of the aforementioned conditions are true and the value will not be
// changed when 'm' is zero.
m = 1
if t9 == fieldMSBMask {
m &= 1
} else {
mask | = 0
m &= 0
}
if t7 < fieldBaseMask {
mask |= - 1
if t2 & t3 & t4 & t5 & t6 & t7 & t8 == fieldBaseMask {
m &= 1
} else {
mask | = 0
m &= 0
}
if t8 < fieldBaseMask {
mask |= - 1
if ( ( t0 + 977 ) >> fieldBase + t1 + 64 ) > fieldBaseMask {
m &= 1
} else {
mask | = 0
m &= 0
}
if t9 < fieldMSBMask {
mask |= - 1
if t9 >> fieldMSBBits != 0 {
m |= 1
} else {
mask |= 0
m |= 0
}
lowBits -= ^ uint64 ( mask ) & primeLowBits
t0 = uint32 ( lowBits & fieldBaseMask )
t1 = uint32 ( ( lowBits >> fieldBase ) & fieldBaseMask )
t2 = t2 & uint32 ( mask )
t3 = t3 & uint32 ( mask )
t4 = t4 & uint32 ( mask )
t5 = t5 & uint32 ( mask )
t6 = t6 & uint32 ( mask )
t7 = t7 & uint32 ( mask )
t8 = t8 & uint32 ( mask )
t9 = t9 & uint32 ( mask )
t0 = t0 + m * 977
t1 = ( t0 >> fieldBase ) + t1 + ( m << 6 )
t0 = t0 & fieldBaseMask
t2 = ( t1 >> fieldBase ) + t2
t1 = t1 & fieldBaseMask
t3 = ( t2 >> fieldBase ) + t3
t2 = t2 & fieldBaseMask
t4 = ( t3 >> fieldBase ) + t4
t3 = t3 & fieldBaseMask
t5 = ( t4 >> fieldBase ) + t5
t4 = t4 & fieldBaseMask
t6 = ( t5 >> fieldBase ) + t6
t5 = t5 & fieldBaseMask
t7 = ( t6 >> fieldBase ) + t7
t6 = t6 & fieldBaseMask
t8 = ( t7 >> fieldBase ) + t8
t7 = t7 & fieldBaseMask
t9 = ( t8 >> fieldBase ) + t9
t8 = t8 & fieldBaseMask
t9 = t9 & fieldMSBMask // Remove potential multiple of 2^256.
// Finally, set the normalized and reduced words.
f . n [ 0 ] = t0