func benchDouble(curve elliptic.Curve, n int) { x := curve.Params().Gx y := curve.Params().Gy for i := 0; i < n; i++ { curve.Double(x, y) } }
func benchScalarMult(curve elliptic.Curve, k []byte, n int) { x := curve.Params().Gx y := curve.Params().Gy for i := 0; i < n; i++ { curve.ScalarMult(x, y, k) } }
func benchAdd(curve elliptic.Curve, n int) { x := curve.Params().Gx y := curve.Params().Gy for i := 0; i < n; i++ { curve.Add(x, y, x, y) } }
// parseECPrivateKey parses an ASN.1 Elliptic Curve Private Key Structure. // The OID for the named curve may be provided from another source (such as // the PKCS8 container) - if it is provided then use this instead of the OID // that may exist in the EC private key structure. func parseECPrivateKey(namedCurveOID *asn1.ObjectIdentifier, der []byte) (key *ecdsa.PrivateKey, err error) { var privKey ecPrivateKey if _, err := asn1.Unmarshal(der, &privKey); err != nil { return nil, errors.New("x509: failed to parse EC private key: " + err.Error()) } if privKey.Version != ecPrivKeyVersion { return nil, fmt.Errorf("x509: unknown EC private key version %d", privKey.Version) } var curve elliptic.Curve if namedCurveOID != nil { curve = namedCurveFromOID(*namedCurveOID) } else { curve = namedCurveFromOID(privKey.NamedCurveOID) } if curve == nil { return nil, errors.New("x509: unknown elliptic curve") } k := new(big.Int).SetBytes(privKey.PrivateKey) if k.Cmp(curve.Params().N) >= 0 { return nil, errors.New("x509: invalid elliptic curve private key value") } priv := new(ecdsa.PrivateKey) priv.Curve = curve priv.D = k priv.X, priv.Y = curve.ScalarBaseMult(privKey.PrivateKey) return priv, nil }
// getSuitableAlgFromCurve inspects the key length in curve, and determines the // corresponding jwt.Algorithm. func getSuitableAlgFromCurve(curve elliptic.Curve) (jwt.Algorithm, error) { curveBitSize := curve.Params().BitSize // compute curve key len keyLen := curveBitSize / 8 if curveBitSize%8 > 0 { keyLen++ } // determine alg var alg jwt.Algorithm switch 2 * keyLen { case 64: alg = jwt.ES256 case 96: alg = jwt.ES384 case 132: alg = jwt.ES512 default: return jwt.NONE, fmt.Errorf("invalid key length %d", keyLen) } return alg, nil }
func UnmarshalBallot(c elliptic.Curve, bytes []byte) (*Ballot, error) { if len(bytes) < 4 { return nil, errors.New("Not long enough!") } numballots := int(bytes[0])<<24 + int(bytes[1])<<16 + int(bytes[2])<<8 + int(bytes[3]) ret := new(Ballot) ret.boxes = make([]*Checkbox, numballots, numballots) bytesize := (c.Params().BitSize + 7) >> 3 ballotlen := 2 + 8*bytesize if len(bytes) != 4+numballots*ballotlen+2*bytesize { return nil, errors.New("Wrong length!") } for i := 0; i < numballots; i++ { ret.boxes[i] = UnmarshalCheckbox(c, bytes[i*ballotlen+4:(i+1)*ballotlen+4]) if ret.boxes[i] == nil { return nil, errors.New("Incorrect serialization") } } ret.c = new(big.Int) ret.c.SetBytes(bytes[numballots*ballotlen+4 : numballots*ballotlen+ 4+bytesize]) ret.r = new(big.Int) ret.r.SetBytes(bytes[numballots*ballotlen+4+bytesize : numballots*ballotlen+4+2*bytesize]) return ret, nil }
// validateECPublicKey checks that the point is a valid public key for // the given curve. See [SEC1], 3.2.2 func validateECPublicKey(curve elliptic.Curve, x, y *big.Int) bool { if x.Sign() == 0 && y.Sign() == 0 { return false } if x.Cmp(curve.Params().P) >= 0 { return false } if y.Cmp(curve.Params().P) >= 0 { return false } if !curve.IsOnCurve(x, y) { return false } // We don't check if N * PubKey == 0, since // // - the NIST curves have cofactor = 1, so this is implicit. // (We don't foresee an implementation that supports non NIST // curves) // // - for ephemeral keys, we don't need to worry about small // subgroup attacks. return true }
// https://tools.ietf.org/html/rfc6979#section-2.3.4 func bits2octets(in []byte, curve elliptic.Curve, rolen int) []byte { z1 := hashToInt(in, curve) z2 := new(big.Int).Sub(z1, curve.Params().N) if z2.Sign() < 0 { return int2octets(z1, rolen) } return int2octets(z2, rolen) }
func DecryptMark(c elliptic.Curve, m *Mark, priv []byte) (int, error) { tx, ty := c.ScalarMult(m.ax, m.ay, priv) tm := big.NewInt(0) tm.Sub(c.Params().P, ty) tm.Mod(tm, c.Params().P) px, py := c.Add(m.bx, m.by, tx, tm) return DiscreteLog(px, py, c, 1<<10) }
// ecHash returns the hash to match the given elliptic curve, see RFC // 5656, section 6.2.1 func ecHash(curve elliptic.Curve) crypto.Hash { bitSize := curve.Params().BitSize switch { case bitSize <= 256: return crypto.SHA256 case bitSize <= 384: return crypto.SHA384 } return crypto.SHA512 }
func UnmarshalMark(c elliptic.Curve, bytes []byte) *Mark { bytelen := (c.Params().BitSize + 7) >> 3 pointlen := 1 + 2*bytelen if len(bytes) != 2*pointlen { return nil } ret := new(Mark) ret.ax, ret.ay = elliptic.Unmarshal(c, bytes[:pointlen]) ret.bx, ret.by = elliptic.Unmarshal(c, bytes[pointlen:2*pointlen]) return ret }
func MarshalMark(c elliptic.Curve, m *Mark) []byte { bytelen := (c.Params().BitSize + 7) >> 3 pointlen := 1 + 2*bytelen outlen := 2 * pointlen ret := make([]byte, outlen, outlen) abytes := elliptic.Marshal(c, m.ax, m.ay) copy(ret, abytes) bbytes := elliptic.Marshal(c, m.bx, m.by) copy(ret[pointlen:], bbytes) return ret }
// Marshal encodes a ECC Point into it's compressed representation func Marshal(curve elliptic.Curve, x, y *big.Int) []byte { byteLen := (curve.Params().BitSize + 7) >> 3 ret := make([]byte, 1+byteLen) ret[0] = 2 + byte(y.Bit(0)) xBytes := x.Bytes() copy(ret[1+byteLen-len(xBytes):], xBytes) return ret }
// Get size of curve in bytes func curveSize(crv elliptic.Curve) int { bits := crv.Params().BitSize div := bits / 8 mod := bits % 8 if mod == 0 { return div } return div + 1 }
// GoodCurve determines if an elliptic curve meets our requirements. func (policy *KeyPolicy) goodCurve(c elliptic.Curve) (err error) { // Simply use a whitelist for now. params := c.Params() switch { case policy.AllowECDSANISTP256 && params == elliptic.P256().Params(): return nil case policy.AllowECDSANISTP384 && params == elliptic.P384().Params(): return nil default: return core.MalformedRequestError(fmt.Sprintf("ECDSA curve %v not allowed", params.Name)) } }
// Unmarshal converts a point, serialized by Marshal, into an x, y pair. // It is an error if the point is not on the curve. On error, x = nil. func Unmarshal(curve elliptic.Curve, data []byte) (x, y *big.Int) { byteLen := (curve.Params().BitSize + 7) >> 3 if len(data) != 1+2*byteLen { return } if data[0] != 4 { // uncompressed form return } x = new(big.Int).SetBytes(data[1 : 1+byteLen]) y = new(big.Int).SetBytes(data[1+byteLen:]) return }
func parseECCoordinate(cB64Url string, curve elliptic.Curve) (*big.Int, error) { curveByteLen := (curve.Params().BitSize + 7) >> 3 cBytes, err := joseBase64UrlDecode(cB64Url) if err != nil { return nil, fmt.Errorf("invalid base64 URL encoding: %s", err) } cByteLength := len(cBytes) if cByteLength != curveByteLen { return nil, fmt.Errorf("invalid number of octets: got %d, should be %d", cByteLength, curveByteLen) } return new(big.Int).SetBytes(cBytes), nil }
// hashToInt converts a hash value to an integer. There is some disagreement // about how this is done. [NSA] suggests that this is done in the obvious // manner, but [SECG] truncates the hash to the bit-length of the curve order // first. We follow [SECG] because that's what OpenSSL does. Additionally, // OpenSSL right shifts excess bits from the number if the hash is too large // and we mirror that too. func hashToInt(hash []byte, c elliptic.Curve) *big.Int { orderBits := c.Params().N.BitLen() orderBytes := (orderBits + 7) / 8 if len(hash) > orderBytes { hash = hash[:orderBytes] } ret := new(big.Int).SetBytes(hash) excess := len(hash)*8 - orderBits if excess > 0 { ret.Rsh(ret, uint(excess)) } return ret }
// randFieldElement returns a random element of the field underlying the given // curve using the procedure given in [NSA] A.2.1. func randFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error) { params := c.Params() b := make([]byte, params.BitSize/8+8) _, err = io.ReadFull(rand, b) if err != nil { return } k = new(big.Int).SetBytes(b) n := new(big.Int).Sub(params.N, one) k.Mod(k, n) k.Add(k, one) return }
// Generates an ephemeral public key and returns a function that will compute // the shared secret key. Used in the identify module. // // Focuses only on ECDH now, but can be made more general in the future. func GenerateEKeyPair(curveName string) ([]byte, GenSharedKey, error) { var curve elliptic.Curve switch curveName { case "P-224": curve = elliptic.P224() case "P-256": curve = elliptic.P256() case "P-384": curve = elliptic.P384() case "P-521": curve = elliptic.P521() } priv, x, y, err := elliptic.GenerateKey(curve, rand.Reader) if err != nil { return nil, nil, err } var pubKey bytes.Buffer pubKey.Write(x.Bytes()) pubKey.Write(y.Bytes()) done := func(theirPub []byte) ([]byte, error) { // Verify and unpack node's public key. curveSize := curve.Params().BitSize if len(theirPub) != (curveSize / 4) { return nil, errors.New("Malformed public key.") } bound := (curveSize / 8) x := big.NewInt(0) y := big.NewInt(0) x.SetBytes(theirPub[0:bound]) y.SetBytes(theirPub[bound : bound*2]) if !curve.IsOnCurve(x, y) { return nil, errors.New("Invalid public key.") } // Generate shared secret. secret, _ := curve.ScalarMult(x, y, priv) return secret.Bytes(), nil } return pubKey.Bytes(), done, nil }
// NewEllipticSigner creates an Elliptic Curve Signer for the specified curve. func NewEllipticSigner(alg Algorithm, curve elliptic.Curve) func(pemutil.Store, crypto.Hash) (Signer, error) { curveBitSize := curve.Params().BitSize // precompute curve key len keyLen := curveBitSize / 8 if curveBitSize%8 > 0 { keyLen++ } return func(store pemutil.Store, hash crypto.Hash) (Signer, error) { var ok bool var privRaw, pubRaw interface{} var priv *ecdsa.PrivateKey var pub *ecdsa.PublicKey // check private key if privRaw, ok = store[pemutil.ECPrivateKey]; ok { if priv, ok = privRaw.(*ecdsa.PrivateKey); !ok { return nil, errors.New("NewEllipticSigner: private key must be a *ecdsa.PrivateKey") } // check curve type matches private key curve type if curveBitSize != priv.Curve.Params().BitSize { return nil, fmt.Errorf("NewEllipticSigner: private key have bit size %d", curve.Params().BitSize) } } // check public key if pubRaw, ok = store[pemutil.PublicKey]; ok { if pub, ok = pubRaw.(*ecdsa.PublicKey); !ok { return nil, errors.New("NewEllipticSigner: public key must be a *ecdsa.PublicKey") } } // check that either a private or public key has been provided if priv == nil && pub == nil { return nil, errors.New("NewEllipticSigner: either a private key or a public key must be provided") } return &eccSigner{ alg: alg, curve: curve, hash: hash, priv: priv, pub: pub, keyLen: keyLen, }, nil } }
func MarshalReckoning(c elliptic.Curve, r *Reckoning) []byte { num := len(r.marks) bytesize := (c.Params().BitSize + 7) >> 3 marklen := 2 + 4*bytesize totsize := 4 + marklen*num ret := make([]byte, totsize, totsize) ret[0] = byte((num >> 24) & 0xff) ret[1] = byte((num >> 16) & 0xff) ret[2] = byte((num >> 8) & 0xff) ret[3] = byte((num) & 0xff) for i := 0; i < num; i++ { copy(ret[i*marklen+4:(i+1)*marklen+4], MarshalMark(c, r.marks[i])) } return ret }
// parseECPrivateKey parses an ASN.1 Elliptic Curve Private Key Structure. // The OID for the named curve may be provided from another source (such as // the PKCS8 container) - if it is provided then use this instead of the OID // that may exist in the EC private key structure. func parseECPrivateKey(namedCurveOID *asn1.ObjectIdentifier, der []byte) (key *ecdsa.PrivateKey, err error) { var privKey ecPrivateKey if _, err := asn1.Unmarshal(der, &privKey); err != nil { return nil, errors.New("x509: failed to parse EC private key: " + err.Error()) } if privKey.Version != ecPrivKeyVersion { return nil, fmt.Errorf("x509: unknown EC private key version %d", privKey.Version) } var curve elliptic.Curve if namedCurveOID != nil { curve = namedCurveFromOID(*namedCurveOID) } else { curve = namedCurveFromOID(privKey.NamedCurveOID) } if curve == nil { return nil, errors.New("x509: unknown elliptic curve") } k := new(big.Int).SetBytes(privKey.PrivateKey) curveOrder := curve.Params().N if k.Cmp(curveOrder) >= 0 { return nil, errors.New("x509: invalid elliptic curve private key value") } priv := new(ecdsa.PrivateKey) priv.Curve = curve priv.D = k privateKey := make([]byte, (curveOrder.BitLen()+7)/8) // Some private keys have leading zero padding. This is invalid // according to [SEC1], but this code will ignore it. for len(privKey.PrivateKey) > len(privateKey) { if privKey.PrivateKey[0] != 0 { return nil, errors.New("x509: invalid private key length") } privKey.PrivateKey = privKey.PrivateKey[1:] } // Some private keys remove all leading zeros, this is also invalid // according to [SEC1] but since OpenSSL used to do this, we ignore // this too. copy(privateKey[len(privateKey)-len(privKey.PrivateKey):], privKey.PrivateKey) priv.X, priv.Y = curve.ScalarBaseMult(privateKey) return priv, nil }
func UnmarshalReckoning(c elliptic.Curve, bytes []byte) (*Reckoning, error) { if len(bytes) < 4 { return nil, errors.New("Insufficient length") } num := int(bytes[0])<<24 + int(bytes[1])<<16 + int(bytes[2])<<8 + int(bytes[3]) bytesize := (c.Params().BitSize + 7) >> 3 marklen := 2 + 4*bytesize if len(bytes) != marklen*num+4 { return nil, errors.New("Incorrect length") } ret := new(Reckoning) ret.marks = make([]*Mark, num, num) for i := 0; i < num; i++ { ret.marks[i] = UnmarshalMark(c, bytes[i*marklen+4:(i+1)*marklen+4]) } return ret, nil }
func MarshalCheckbox(c elliptic.Curve, b *Checkbox) []byte { bytelen := (c.Params().BitSize + 7) >> 3 pointlen := 1 + 2*bytelen scalarlen := bytelen outlen := 2*pointlen + 4*scalarlen ret := make([]byte, outlen, outlen) abytes := elliptic.Marshal(c, b.ax, b.ay) copy(ret, abytes) bbytes := elliptic.Marshal(c, b.bx, b.by) copy(ret[pointlen:], bbytes) c1bytes := b.c1.Bytes() copy(ret[2*pointlen+scalarlen-len(c1bytes):], c1bytes) c2bytes := b.c2.Bytes() copy(ret[2*pointlen+2*scalarlen-len(c2bytes):], c2bytes) r1bytes := b.r1.Bytes() copy(ret[2*pointlen+3*scalarlen-len(r1bytes):], r1bytes) r2bytes := b.r2.Bytes() copy(ret[2*pointlen+4*scalarlen-len(r2bytes):], r2bytes) return ret }
func UnmarshalCheckbox(c elliptic.Curve, bytes []byte) *Checkbox { bytelen := (c.Params().BitSize + 7) >> 3 pointlen := 1 + 2*bytelen scalarlen := bytelen if len(bytes) != 2*pointlen+4*scalarlen { return nil } ret := new(Checkbox) ret.ax, ret.ay = elliptic.Unmarshal(c, bytes[:pointlen]) ret.bx, ret.by = elliptic.Unmarshal(c, bytes[pointlen:2*pointlen]) ret.c1 = new(big.Int) ret.c2 = new(big.Int) ret.r1 = new(big.Int) ret.r2 = new(big.Int) ret.c1.SetBytes(bytes[2*pointlen : 2*pointlen+scalarlen]) ret.c2.SetBytes(bytes[2*pointlen+scalarlen : 2*pointlen+2*scalarlen]) ret.r1.SetBytes(bytes[2*pointlen+2*scalarlen : 2*pointlen+3*scalarlen]) ret.r2.SetBytes(bytes[2*pointlen+3*scalarlen : 2*pointlen+4*scalarlen]) return ret }
func newrcurve(twisted elliptic.Curve, gx, gy, z *big.Int) *rcurve { var curve rcurve curve.twisted = twisted curve.params = *twisted.Params() curve.params.B = nil // FIXME: crypto/elliptic assumes A=-3 curve.params.Gx = gx curve.params.Gy = gy two := big.NewInt(2) three := big.NewInt(3) curve.z = z curve.zinv = new(big.Int).ModInverse(z, curve.params.P) curve.z2 = new(big.Int).Exp(curve.z, two, curve.params.P) curve.z3 = new(big.Int).Exp(curve.z, three, curve.params.P) curve.zinv2 = new(big.Int).Exp(curve.zinv, two, curve.params.P) curve.zinv3 = new(big.Int).Exp(curve.zinv, three, curve.params.P) return &curve }
func FillBallot(c elliptic.Curve, px *big.Int, py *big.Int, entry int, size int) *Ballot { b := new(Ballot) b.boxes = make([]*Checkbox, size, size) for i := 0; i < size; i++ { if i == entry { b.boxes[i] = VoteOne(c, px, py) } else { b.boxes[i] = VoteZero(c, px, py) } } //TODO: add validation //Let A be the sum of all the A, B the sum of all the B //Then we want log_g(A)=log_h(B-g) ax := big.NewInt(0) ay := big.NewInt(0) bx := big.NewInt(0) by := big.NewInt(0) s := big.NewInt(0) for i := 0; i < size; i++ { ax, ay = c.Add(ax, ay, b.boxes[i].ax, b.boxes[i].ay) bx, by = c.Add(bx, by, b.boxes[i].bx, b.boxes[i].by) s.Add(s, b.boxes[i].s) } s.Mod(s, c.Params().N) k, err := rand.Int(rand.Reader, c.Params().N) if err != nil { panic("Not here, not now") } v1x, v1y := c.ScalarBaseMult(k.Bytes()) v2x, v2y := c.ScalarMult(px, py, k.Bytes()) var commit [4][]byte commit[0] = elliptic.Marshal(c, ax, ay) commit[1] = elliptic.Marshal(c, bx, by) commit[2] = elliptic.Marshal(c, v1x, v1y) commit[3] = elliptic.Marshal(c, v2x, v2y) cb := bytes.Join(commit[:], []byte{}) cbytes := sha256.Sum256(cb[:]) b.c = big.NewInt(0) b.c.SetBytes(cbytes[:]) b.c.Mod(b.c, c.Params().N) b.r = big.NewInt(0) //r=k-c*s b.r.Mul(b.c, s) b.r.Sub(k, b.r) b.r.Mod(b.r, c.Params().N) return b }
func MarshalBallot(c elliptic.Curve, b *Ballot) []byte { /* The format is very simple: first 4 bytes are length of ballot Then that many serialized checkboxes, one after the other lastly, (c, r) */ numballots := len(b.boxes) bytelen := (c.Params().BitSize + 7) >> 3 ballotlen := 2 + 8*bytelen //Result of not compressing size := 4 + numballots*ballotlen + 2*bytelen ret := make([]byte, size, size) ret[0] = byte((numballots >> 24) & 0xff) ret[1] = byte((numballots >> 16) & 0xff) ret[2] = byte((numballots >> 8) & 0xff) ret[3] = byte(numballots & 0xff) for i := 0; i < numballots; i++ { copy(ret[i*ballotlen+4:(i+1)*ballotlen+4], MarshalCheckbox(c, b.boxes[i])) } cbytes := b.c.Bytes() copy(ret[numballots*ballotlen+4+bytelen-len(cbytes):], cbytes) rbytes := b.r.Bytes() copy(ret[numballots*ballotlen+4+2*bytelen-len(rbytes):], rbytes) return ret }
func parseECPrivateParam(dB64Url string, curve elliptic.Curve) (*big.Int, error) { dBytes, err := joseBase64UrlDecode(dB64Url) if err != nil { return nil, fmt.Errorf("invalid base64 URL encoding: %s", err) } // The length of this octet string MUST be ceiling(log-base-2(n)/8) // octets (where n is the order of the curve). This is because the private // key d must be in the interval [1, n-1] so the bitlength of d should be // no larger than the bitlength of n-1. The easiest way to find the octet // length is to take bitlength(n-1), add 7 to force a carry, and shift this // bit sequence right by 3, which is essentially dividing by 8 and adding // 1 if there is any remainder. Thus, the private key value d should be // output to (bitlength(n-1)+7)>>3 octets. n := curve.Params().N octetLength := (new(big.Int).Sub(n, big.NewInt(1)).BitLen() + 7) >> 3 dByteLength := len(dBytes) if dByteLength != octetLength { return nil, fmt.Errorf("invalid number of octets: got %d, should be %d", dByteLength, octetLength) } return new(big.Int).SetBytes(dBytes), nil }