package crypto

import (
	
	
	
	
	
	
	
	
	
	
)

type ecdsaSignature struct {
	R, S *big.Int
}

// ECDSAKey takes the given elliptic curve, and private key (d) byte slice
// and returns the private ECDSA key.
func ( elliptic.Curve,  []byte) *ecdsa.PrivateKey {
	return ECDSAKeyFromPoint(, (&big.Int{}).SetBytes())
}

// ECDSAKeyFromPoint takes the given elliptic curve and point and returns the
// private and public keypair
func ( elliptic.Curve,  *big.Int) *ecdsa.PrivateKey {
	,  := .ScalarBaseMult(.Bytes())

	 := &ecdsa.PrivateKey{
		PublicKey: ecdsa.PublicKey{
			Curve: ,
			X:     ,
			Y:     ,
		},
		D: ,
	}

	return 
}

// ECDSAPublicKey takes the provide curve and (x, y) coordinates and returns
// *ecdsa.PublicKey. Returns an error if the given points are not on the curve.
func ( elliptic.Curve, ,  []byte) (*ecdsa.PublicKey, error) {
	 := (&big.Int{}).SetBytes()
	 := (&big.Int{}).SetBytes()

	if !.IsOnCurve(, ) {
		return nil, fmt.Errorf("point(%v, %v) is not on the given curve", .String(), .String())
	}

	return &ecdsa.PublicKey{
		Curve: ,
		X:     ,
		Y:     ,
	}, nil
}

// VerifySignature takes the provided public key, hash, and asn1 encoded signature and returns
// whether the given signature is valid.
func ( *ecdsa.PublicKey,  []byte,  []byte) (bool, error) {
	var  ecdsaSignature

	,  := asn1.Unmarshal(, &)
	if  != nil {
		return false, 
	}

	return ecdsa.Verify(, , .R, .S), nil
}

// HMACKeyDerivation provides an implementation of a NIST-800-108 of a KDF (Key Derivation Function) in Counter Mode.
// For the purposes of this implantation HMAC is used as the PRF (Pseudorandom function), where the value of
// `r` is defined as a 4 byte counter.
func ( func() hash.Hash,  int,  []byte, ,  []byte) ([]byte, error) {
	// verify that we won't overflow the counter
	 := int64(math.Ceil((float64() / 8) / float64(().Size())))
	if  > 0x7FFFFFFF {
		return nil, fmt.Errorf("unable to derive key of size %d using 32-bit counter", )
	}

	// verify the requested bit length is not larger then the length encoding size
	if int64() > 0x7FFFFFFF {
		return nil, fmt.Errorf("bitLen is greater than 32-bits")
	}

	 := bytes.NewBuffer(nil)
	.Write()
	.WriteByte(0x00)
	.Write()
	if  := binary.Write(, binary.BigEndian, int32());  != nil {
		return nil, fmt.Errorf("failed to write bit length to fixed input string: %v", )
	}

	var  []byte

	 := hmac.New(, )

	for  := int64(1);  <= ; ++ {
		.Reset()
		if  := binary.Write(, binary.BigEndian, int32());  != nil {
			return nil, 
		}
		,  := .Write(.Bytes())
		if  != nil {
			return nil, 
		}
		 = append(, .Sum(nil)...)
	}

	return [:/8], nil
}