// Copyright 2021 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package ellipticimport// CurveParams contains the parameters of an elliptic curve and also provides// a generic, non-constant time implementation of [Curve].//// The generic Curve implementation is deprecated, and using custom curves// (those not returned by [P224], [P256], [P384], and [P521]) is not guaranteed// to provide any security property.typeCurveParamsstruct { P *big.Int// the order of the underlying field N *big.Int// the order of the base point B *big.Int// the constant of the curve equation Gx, Gy *big.Int// (x,y) of the base point BitSize int// the size of the underlying field Name string// the canonical name of the curve}func ( *CurveParams) () *CurveParams {return}// CurveParams operates, internally, on Jacobian coordinates. For a given// (x, y) position on the curve, the Jacobian coordinates are (x1, y1, z1)// where x = x1/z1² and y = y1/z1³. The greatest speedups come when the whole// calculation can be performed within the transform (as in ScalarMult and// ScalarBaseMult). But even for Add and Double, it's faster to apply and// reverse the transform than to operate in affine coordinates.// polynomial returns x³ - 3x + b.func ( *CurveParams) ( *big.Int) *big.Int { := new(big.Int).Mul(, ) .Mul(, ) := new(big.Int).Lsh(, 1) .Add(, ) .Sub(, ) .Add(, .B) .Mod(, .P)return}// IsOnCurve implements [Curve.IsOnCurve].//// Deprecated: the [CurveParams] methods are deprecated and are not guaranteed to// provide any security property. For ECDH, use the [crypto/ecdh] package.// For ECDSA, use the [crypto/ecdsa] package with a [Curve] value returned directly// from [P224], [P256], [P384], or [P521].func ( *CurveParams) (, *big.Int) bool {// If there is a dedicated constant-time implementation for this curve operation, // use that instead of the generic one.if , := matchesSpecificCurve(); {return .IsOnCurve(, ) }if .Sign() < 0 || .Cmp(.P) >= 0 || .Sign() < 0 || .Cmp(.P) >= 0 {returnfalse }// y² = x³ - 3x + b := new(big.Int).Mul(, ) .Mod(, .P)return .polynomial().Cmp() == 0}// zForAffine returns a Jacobian Z value for the affine point (x, y). If x and// y are zero, it assumes that they represent the point at infinity because (0,// 0) is not on the any of the curves handled here.func zForAffine(, *big.Int) *big.Int { := new(big.Int)if .Sign() != 0 || .Sign() != 0 { .SetInt64(1) }return}// affineFromJacobian reverses the Jacobian transform. See the comment at the// top of the file. If the point is ∞ it returns 0, 0.func ( *CurveParams) (, , *big.Int) (, *big.Int) {if .Sign() == 0 {returnnew(big.Int), new(big.Int) } := new(big.Int).ModInverse(, .P) := new(big.Int).Mul(, ) = new(big.Int).Mul(, ) .Mod(, .P) .Mul(, ) = new(big.Int).Mul(, ) .Mod(, .P)return}// Add implements [Curve.Add].//// Deprecated: the [CurveParams] methods are deprecated and are not guaranteed to// provide any security property. For ECDH, use the [crypto/ecdh] package.// For ECDSA, use the [crypto/ecdsa] package with a [Curve] value returned directly// from [P224], [P256], [P384], or [P521].func ( *CurveParams) (, , , *big.Int) (*big.Int, *big.Int) {// If there is a dedicated constant-time implementation for this curve operation, // use that instead of the generic one.if , := matchesSpecificCurve(); {return .Add(, , , ) }panicIfNotOnCurve(, , )panicIfNotOnCurve(, , ) := zForAffine(, ) := zForAffine(, )return .affineFromJacobian(.addJacobian(, , , , , ))}// addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and// (x2, y2, z2) and returns their sum, also in Jacobian form.func ( *CurveParams) (, , , , , *big.Int) (*big.Int, *big.Int, *big.Int) {// See https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl , , := new(big.Int), new(big.Int), new(big.Int)if .Sign() == 0 { .Set() .Set() .Set()return , , }if .Sign() == 0 { .Set() .Set() .Set()return , , } := new(big.Int).Mul(, ) .Mod(, .P) := new(big.Int).Mul(, ) .Mod(, .P) := new(big.Int).Mul(, ) .Mod(, .P) := new(big.Int).Mul(, ) .Mod(, .P) := new(big.Int).Sub(, ) := .Sign() == 0if .Sign() == -1 { .Add(, .P) } := new(big.Int).Lsh(, 1) .Mul(, ) := new(big.Int).Mul(, ) := new(big.Int).Mul(, ) .Mul(, ) .Mod(, .P) := new(big.Int).Mul(, ) .Mul(, ) .Mod(, .P) := new(big.Int).Sub(, )if .Sign() == -1 { .Add(, .P) } := .Sign() == 0if && {return .doubleJacobian(, , ) } .Lsh(, 1) := new(big.Int).Mul(, ) .Set() .Mul(, ) .Sub(, ) .Sub(, ) .Sub(, ) .Mod(, .P) .Set() .Sub(, ) .Mul(, ) .Mul(, ) .Lsh(, 1) .Sub(, ) .Mod(, .P) .Add(, ) .Mul(, ) .Sub(, ) .Sub(, ) .Mul(, ) .Mod(, .P)return , , }// Double implements [Curve.Double].//// Deprecated: the [CurveParams] methods are deprecated and are not guaranteed to// provide any security property. For ECDH, use the [crypto/ecdh] package.// For ECDSA, use the [crypto/ecdsa] package with a [Curve] value returned directly// from [P224], [P256], [P384], or [P521].func ( *CurveParams) (, *big.Int) (*big.Int, *big.Int) {// If there is a dedicated constant-time implementation for this curve operation, // use that instead of the generic one.if , := matchesSpecificCurve(); {return .Double(, ) }panicIfNotOnCurve(, , ) := zForAffine(, )return .affineFromJacobian(.doubleJacobian(, , ))}// doubleJacobian takes a point in Jacobian coordinates, (x, y, z), and// returns its double, also in Jacobian form.func ( *CurveParams) (, , *big.Int) (*big.Int, *big.Int, *big.Int) {// See https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b := new(big.Int).Mul(, ) .Mod(, .P) := new(big.Int).Mul(, ) .Mod(, .P) := new(big.Int).Sub(, )if .Sign() == -1 { .Add(, .P) } := new(big.Int).Add(, ) .Mul(, ) .Set() .Lsh(, 1) .Add(, ) := .Mul(, ) := new(big.Int).Mul(, ) := new(big.Int).Lsh(, 3) .Mod(, .P) .Sub(, )if .Sign() == -1 { .Add(, .P) } .Mod(, .P) := new(big.Int).Add(, ) .Mul(, ) .Sub(, )if .Sign() == -1 { .Add(, .P) } .Sub(, )if .Sign() == -1 { .Add(, .P) } .Mod(, .P) .Lsh(, 2) .Sub(, )if .Sign() == -1 { .Add(, .P) } := .Mul(, ) .Mul(, ) .Lsh(, 3) .Mod(, .P) .Sub(, )if .Sign() == -1 { .Add(, .P) } .Mod(, .P)return , , }// ScalarMult implements [Curve.ScalarMult].//// Deprecated: the [CurveParams] methods are deprecated and are not guaranteed to// provide any security property. For ECDH, use the [crypto/ecdh] package.// For ECDSA, use the [crypto/ecdsa] package with a [Curve] value returned directly// from [P224], [P256], [P384], or [P521].func ( *CurveParams) (, *big.Int, []byte) (*big.Int, *big.Int) {// If there is a dedicated constant-time implementation for this curve operation, // use that instead of the generic one.if , := matchesSpecificCurve(); {return .ScalarMult(, , ) }panicIfNotOnCurve(, , ) := new(big.Int).SetInt64(1) , , := new(big.Int), new(big.Int), new(big.Int)for , := range {for := 0; < 8; ++ { , , = .doubleJacobian(, , )if &0x80 == 0x80 { , , = .addJacobian(, , , , , ) } <<= 1 } }return .affineFromJacobian(, , )}// ScalarBaseMult implements [Curve.ScalarBaseMult].//// Deprecated: the [CurveParams] methods are deprecated and are not guaranteed to// provide any security property. For ECDH, use the [crypto/ecdh] package.// For ECDSA, use the [crypto/ecdsa] package with a [Curve] value returned directly// from [P224], [P256], [P384], or [P521].func ( *CurveParams) ( []byte) (*big.Int, *big.Int) {// If there is a dedicated constant-time implementation for this curve operation, // use that instead of the generic one.if , := matchesSpecificCurve(); {return .ScalarBaseMult() }return .ScalarMult(.Gx, .Gy, )}func matchesSpecificCurve( *CurveParams) (Curve, bool) {for , := range []Curve{p224, p256, p384, p521} {if == .Params() {return , true } }returnnil, false}
The pages are generated with Goldsv0.7.0-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.