// Copyright 2012 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 x509

import (
	
	
	
	
	
	
	
)

const ecPrivKeyVersion = 1

// ecPrivateKey reflects an ASN.1 Elliptic Curve Private Key Structure.
// References:
//
//	RFC 5915
//	SEC1 - http://www.secg.org/sec1-v2.pdf
//
// Per RFC 5915 the NamedCurveOID is marked as ASN.1 OPTIONAL, however in
// most cases it is not.
type ecPrivateKey struct {
	Version       int
	PrivateKey    []byte
	NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"`
	PublicKey     asn1.BitString        `asn1:"optional,explicit,tag:1"`
}

// ParseECPrivateKey parses an EC private key in SEC 1, ASN.1 DER form.
//
// This kind of key is commonly encoded in PEM blocks of type "EC PRIVATE KEY".
func ( []byte) (*ecdsa.PrivateKey, error) {
	return parseECPrivateKey(nil, )
}

// MarshalECPrivateKey converts an EC private key to SEC 1, ASN.1 DER form.
//
// This kind of key is commonly encoded in PEM blocks of type "EC PRIVATE KEY".
// For a more flexible key format which is not EC specific, use
// MarshalPKCS8PrivateKey.
func ( *ecdsa.PrivateKey) ([]byte, error) {
	,  := oidFromNamedCurve(.Curve)
	if ! {
		return nil, errors.New("x509: unknown elliptic curve")
	}

	return marshalECPrivateKeyWithOID(, )
}

// marshalECPrivateKeyWithOID marshals an EC private key into ASN.1, DER format and
// sets the curve ID to the given OID, or omits it if OID is nil.
func ( *ecdsa.PrivateKey,  asn1.ObjectIdentifier) ([]byte, error) {
	if !.Curve.IsOnCurve(.X, .Y) {
		return nil, errors.New("invalid elliptic key public key")
	}
	 := make([]byte, (.Curve.Params().N.BitLen()+7)/8)
	return asn1.Marshal(ecPrivateKey{
		Version:       1,
		PrivateKey:    .D.FillBytes(),
		NamedCurveOID: ,
		PublicKey:     asn1.BitString{Bytes: elliptic.Marshal(.Curve, .X, .Y)},
	})
}

// marshalECDHPrivateKey marshals an EC private key into ASN.1, DER format
// suitable for NIST curves.
func ( *ecdh.PrivateKey) ([]byte, error) {
	return asn1.Marshal(ecPrivateKey{
		Version:    1,
		PrivateKey: .Bytes(),
		PublicKey:  asn1.BitString{Bytes: .PublicKey().Bytes()},
	})
}

// 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 ( *asn1.ObjectIdentifier,  []byte) ( *ecdsa.PrivateKey,  error) {
	var  ecPrivateKey
	if ,  := asn1.Unmarshal(, &);  != nil {
		if ,  := asn1.Unmarshal(, &pkcs8{});  == nil {
			return nil, errors.New("x509: failed to parse private key (use ParsePKCS8PrivateKey instead for this key format)")
		}
		if ,  := asn1.Unmarshal(, &pkcs1PrivateKey{});  == nil {
			return nil, errors.New("x509: failed to parse private key (use ParsePKCS1PrivateKey instead for this key format)")
		}
		return nil, errors.New("x509: failed to parse EC private key: " + .Error())
	}
	if .Version != ecPrivKeyVersion {
		return nil, fmt.Errorf("x509: unknown EC private key version %d", .Version)
	}

	var  elliptic.Curve
	if  != nil {
		 = namedCurveFromOID(*)
	} else {
		 = namedCurveFromOID(.NamedCurveOID)
	}
	if  == nil {
		return nil, errors.New("x509: unknown elliptic curve")
	}

	 := new(big.Int).SetBytes(.PrivateKey)
	 := .Params().N
	if .Cmp() >= 0 {
		return nil, errors.New("x509: invalid elliptic curve private key value")
	}
	 := new(ecdsa.PrivateKey)
	.Curve = 
	.D = 

	 := make([]byte, (.BitLen()+7)/8)

	// Some private keys have leading zero padding. This is invalid
	// according to [SEC1], but this code will ignore it.
	for len(.PrivateKey) > len() {
		if .PrivateKey[0] != 0 {
			return nil, errors.New("x509: invalid private key length")
		}
		.PrivateKey = .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([len()-len(.PrivateKey):], .PrivateKey)
	.X, .Y = .ScalarBaseMult()

	return , nil
}