package crypto

import (
	
	
	

	pb 
	

	
	
)

// Secp256k1PrivateKey is a Secp256k1 private key
type Secp256k1PrivateKey secp256k1.PrivateKey

// Secp256k1PublicKey is a Secp256k1 public key
type Secp256k1PublicKey secp256k1.PublicKey

// GenerateSecp256k1Key generates a new Secp256k1 private and public key pair
func ( io.Reader) (PrivKey, PubKey, error) {
	,  := secp256k1.GeneratePrivateKey()
	if  != nil {
		return nil, nil, 
	}

	 := (*Secp256k1PrivateKey)()
	return , .GetPublic(), nil
}

// UnmarshalSecp256k1PrivateKey returns a private key from bytes
func ( []byte) ( PrivKey,  error) {
	if len() != secp256k1.PrivKeyBytesLen {
		return nil, fmt.Errorf("expected secp256k1 data size to be %d", secp256k1.PrivKeyBytesLen)
	}
	defer func() { catch.HandlePanic(recover(), &, "secp256k1 private-key unmarshal") }()

	 := secp256k1.PrivKeyFromBytes()
	return (*Secp256k1PrivateKey)(), nil
}

// UnmarshalSecp256k1PublicKey returns a public key from bytes
func ( []byte) ( PubKey,  error) {
	defer func() { catch.HandlePanic(recover(), &, "secp256k1 public-key unmarshal") }()
	,  := secp256k1.ParsePubKey()
	if  != nil {
		return nil, 
	}

	return (*Secp256k1PublicKey)(), nil
}

// Type returns the private key type
func ( *Secp256k1PrivateKey) () pb.KeyType {
	return pb.KeyType_Secp256k1
}

// Raw returns the bytes of the key
func ( *Secp256k1PrivateKey) () ([]byte, error) {
	return (*secp256k1.PrivateKey)().Serialize(), nil
}

// Equals compares two private keys
func ( *Secp256k1PrivateKey) ( Key) bool {
	,  := .(*Secp256k1PrivateKey)
	if ! {
		return basicEquals(, )
	}

	return .GetPublic().Equals(.GetPublic())
}

// Sign returns a signature from input data
func ( *Secp256k1PrivateKey) ( []byte) ( []byte,  error) {
	defer func() { catch.HandlePanic(recover(), &, "secp256k1 signing") }()
	 := (*secp256k1.PrivateKey)()
	 := sha256.Sum256()
	 := ecdsa.Sign(, [:])

	return .Serialize(), nil
}

// GetPublic returns a public key
func ( *Secp256k1PrivateKey) () PubKey {
	return (*Secp256k1PublicKey)((*secp256k1.PrivateKey)().PubKey())
}

// Type returns the public key type
func ( *Secp256k1PublicKey) () pb.KeyType {
	return pb.KeyType_Secp256k1
}

// Raw returns the bytes of the key
func ( *Secp256k1PublicKey) () ( []byte,  error) {
	defer func() { catch.HandlePanic(recover(), &, "secp256k1 public key marshaling") }()
	return (*secp256k1.PublicKey)().SerializeCompressed(), nil
}

// Equals compares two public keys
func ( *Secp256k1PublicKey) ( Key) bool {
	,  := .(*Secp256k1PublicKey)
	if ! {
		return basicEquals(, )
	}

	return (*secp256k1.PublicKey)().IsEqual((*secp256k1.PublicKey)())
}

// Verify compares a signature against the input data
func ( *Secp256k1PublicKey) ( []byte,  []byte) ( bool,  error) {
	defer func() {
		catch.HandlePanic(recover(), &, "secp256k1 signature verification")

		// To be extra safe.
		if  != nil {
			 = false
		}
	}()
	,  := ecdsa.ParseDERSignature()
	if  != nil {
		return false, 
	}

	 := sha256.Sum256()
	return .Verify([:], (*secp256k1.PublicKey)()), nil
}