package main
import (
"fmt"
"math/big"
)
func main() {
c := Curves()
par := c.Params()
three := new(big.Int).SetUint64(3)
p4 := new(big.Int).Sub(par.P, new(big.Int).SetUint64(4))
p1 := new(big.Int).Sub(par.P, new(big.Int).SetUint64(1))
var d3, dp4, dsum, dsub [9]uint32
p256FromBig(&dp4, p4)
p256FromBig(&d3, three)
p256Sum(&dsum, &d3, &dp4)
du := p256ToBig(&dsum)
p256Diff(&dsub, &dsum, &dp4)
i3 := p256ToBig(&dsub)
fmt.Println(i3.Cmp(three))
fmt.Println(i3.Sign())
fmt.Println(du.Cmp(p1))
}
package main
// This file contains a constant-time, 32-bit implementation of P256.
import (
"crypto/elliptic"
"fmt"
"math/big"
)
type p256Curve struct {
*elliptic.CurveParams
}
var (
p256Params *elliptic.CurveParams
// RInverse contains 1/R mod p - the inverse of the Montgomery constant
// (2**257).
p256RInverse *big.Int
)
func initP256() {
// See FIPS 186-3, section D.2.3
p256Params = &elliptic.CurveParams{Name: "P-256"}
p256Params.P, _ = new(big.Int).SetString("115792089210356248762697446949407573530086143415290314195533631308867097853951", 10)
p256Params.N, _ = new(big.Int).SetString("115792089210356248762697446949407573529996955224135760342422259061068512044369", 10)
p256Params.B, _ = new(big.Int).SetString("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16)
p256Params.Gx, _ = new(big.Int).SetString("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16)
p256Params.Gy, _ = new(big.Int).SetString("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16)
p256Params.BitSize = 256
p256RInverse, _ = new(big.Int).SetString("7fffffff00000001fffffffe8000000100000000ffffffff0000000180000000", 16)
// Arch-specific initialization, i.e. let a platform dynamically pick a P256 implementation
}
func Curves()p256Curve {
initP256()
return p256Curve{p256Params}
}
func (curve p256Curve) Params() *elliptic.CurveParams {
return curve.CurveParams
}
// p256GetScalar endian-swaps the big-endian scalar value from in and writes it
// to out. If the scalar is equal or greater than the order of the group, it's
// reduced modulo that order.
func p256GetScalar(out *[32]byte, in []byte) {
n := new(big.Int).SetBytes(in)
var scalarBytes []byte
if n.Cmp(p256Params.N) >= 0 {
n.Mod(n, p256Params.N)
scalarBytes = n.Bytes()
} else {
scalarBytes = in
}
for i, v := range scalarBytes {
out[len(scalarBytes)-(1+i)] = v
}
}
func (p256Curve) ScalarBaseMult(scalar []byte) (x, y *big.Int) {
var scalarReversed [32]byte
p256GetScalar(&scalarReversed, scalar)
var x1, y1, z1 [p256Limbs]uint32
p256ScalarBaseMult(&x1, &y1, &z1, &scalarReversed)
return p256ToAffine(&x1, &y1, &z1)
}
func (p256Curve) ScalarMult(bigX, bigY *big.Int, scalar []byte) (x, y *big.Int) {
var scalarReversed [32]byte
p256GetScalar(&scalarReversed, scalar)
var px, py, x1, y1, z1 [p256Limbs]uint32
p256FromBig(&px, bigX)
p256FromBig(&py, bigY)
p256ScalarMult(&x1, &y1, &z1, &px, &py, &scalarReversed)
return p256ToAffine(&x1, &y1, &z1)
}
// Field elements are represented as nine, unsigned 32-bit words.
//
// The value of a field element is:
// x[0] + (x[1] * 2**29) + (x[2] * 2**57) + ... + (x[8] * 2**228)
//
// That is, each limb is alternately 29 or 28-bits wide in little-endian
// order.
//
// This means that a field element hits 2**257, rather than 2**256 as we would
// like. A 28, 29, ... pattern would cause us to hit 2**256, but that causes
// problems when multiplying as terms end up one bit short of a limb which
// would require much bit-shifting to correct.
//
// Finally, the values stored in a field element are in Montgomery form. So the
// value |y| is stored as (y*R) mod p, where p is the P-256 prime and R is
// 2**257.
const (
p256Limbs = 9
bottom29Bits = 0x1fffffff
)
var (
// p256One is the number 1 as a field element.
p256One = [p256Limbs]uint32{2, 0, 0, 0xffff800, 0x1fffffff, 0xfffffff, 0x1fbfffff, 0x1ffffff, 0}
p256Zero = [p256Limbs]uint32{0, 0, 0, 0, 0, 0, 0, 0, 0}
// p256P is the prime modulus as a field element.
p256P = [p256Limbs]uint32{0x1fffffff, 0xfffffff, 0x1fffffff, 0x3ff, 0, 0, 0x200000, 0xf000000, 0xfffffff}
// p2562P is the twice prime modulus as a field element.
p2562P = [p256Limbs]uint32{0x1ffffffe, 0xfffffff, 0x1fffffff, 0x7ff, 0, 0, 0x400000, 0xe000000, 0x1fffffff}
)
// p256Precomputed contains precomputed values to aid the calculation of scalar
// multiples of the base point, G. It's actually two, equal length, tables
// concatenated.
//
// The first table contains (x,y) field element pairs for 16 multiples of the
// base point, G.
//
// Index | Index (binary) | Value
// 0 | 0000 | 0G (all zeros, omitted)
// 1 | 0001 | G
// 2 | 0010 | 2**64G
// 3 | 0011 | 2**64G + G
// 4 | 0100 | 2**128G
// 5 | 0101 | 2**128G + G
// 6 | 0110 | 2**128G + 2**64G
// 7 | 0111 | 2**128G + 2**64G + G
// 8 | 1000 | 2**192G
// 9 | 1001 | 2**192G + G
// 10 | 1010 | 2**192G + 2**64G
// 11 | 1011 | 2**192G + 2**64G + G
// 12 | 1100 | 2**192G + 2**128G
// 13 | 1101 | 2**192G + 2**128G + G
// 14 | 1110 | 2**192G + 2**128G + 2**64G
// 15 | 1111 | 2**192G + 2**128G + 2**64G + G
//
// The second table follows the same style, but the terms are 2**32G,
// 2**96G, 2**160G, 2**224G.
//
// This is ~2KB of data.
var p256Precomputed = [p256Limbs * 2 * 15 * 2]uint32{
0x11522878, 0xe730d41, 0xdb60179, 0x4afe2ff, 0x12883add, 0xcaddd88, 0x119e7edc, 0xd4a6eab, 0x3120bee,
0x1d2aac15, 0xf25357c, 0x19e45cdd, 0x5c721d0, 0x1992c5a5, 0xa237487, 0x154ba21, 0x14b10bb, 0xae3fe3,
0xd41a576, 0x922fc51, 0x234994f, 0x60b60d3, 0x164586ae, 0xce95f18, 0x1fe49073, 0x3fa36cc, 0x5ebcd2c,
0xb402f2f, 0x15c70bf, 0x1561925c, 0x5a26704, 0xda91e90, 0xcdc1c7f, 0x1ea12446, 0xe1ade1e, 0xec91f22,
0x26f7778, 0x566847e, 0xa0bec9e, 0x234f453, 0x1a31f21a, 0xd85e75c, 0x56c7109, 0xa267a00, 0xb57c050,
0x98fb57, 0xaa837cc, 0x60c0792, 0xcfa5e19, 0x61bab9e, 0x589e39b, 0xa324c5, 0x7d6dee7, 0x2976e4b,
0x1fc4124a, 0xa8c244b, 0x1ce86762, 0xcd61c7e, 0x1831c8e0, 0x75774e1, 0x1d96a5a9, 0x843a649, 0xc3ab0fa,
0x6e2e7d5, 0x7673a2a, 0x178b65e8, 0x4003e9b, 0x1a1f11c2, 0x7816ea, 0xf643e11, 0x58c43df, 0xf423fc2,
0x19633ffa, 0x891f2b2, 0x123c231c, 0x46add8c, 0x54700dd, 0x59e2b17, 0x172db40f, 0x83e277d, 0xb0dd609,
0xfd1da12, 0x35c6e52, 0x19ede20c, 0xd19e0c0, 0x97d0f40,