Ejemplo n.º 1
0
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)
	}
}
Ejemplo n.º 2
0
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)
	}
}
Ejemplo n.º 3
0
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)
	}
}
Ejemplo n.º 4
0
// 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
}
Ejemplo n.º 5
0
Archivo: jwt.go Proyecto: knq/jwt
// 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
}
Ejemplo n.º 6
0
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
}
Ejemplo n.º 7
0
// 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
}
Ejemplo n.º 8
0
// 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)
}
Ejemplo n.º 9
0
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)
}
Ejemplo n.º 10
0
// 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
}
Ejemplo n.º 11
0
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
}
Ejemplo n.º 12
0
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
}
Ejemplo n.º 13
0
// 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
}
Ejemplo n.º 14
0
// 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
}
Ejemplo n.º 15
0
// 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))
	}
}
Ejemplo n.º 16
0
// 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
}
Ejemplo n.º 17
0
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
}
Ejemplo n.º 18
0
// 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
}
Ejemplo n.º 19
0
// 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
}
Ejemplo n.º 20
0
// 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
}
Ejemplo n.º 21
0
Archivo: ecc.go Proyecto: knq/jwt
// 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
	}
}
Ejemplo n.º 22
0
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
}
Ejemplo n.º 23
0
// 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
}
Ejemplo n.º 24
0
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
}
Ejemplo n.º 25
0
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
}
Ejemplo n.º 26
0
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
}
Ejemplo n.º 27
0
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
}
Ejemplo n.º 28
0
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
}
Ejemplo n.º 29
0
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
}
Ejemplo n.º 30
0
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
}