package sm9

import (
	"crypto"
	"io"
)

var _ crypto.Signer = &Signer{}
var _ crypto.Decrypter = &Decrypter{}

type Signer struct {
	Id                []byte
	Priv              *UserSignKey
	MastSignPublicKey *MastSignPublicKey
}

// Sign signs digest with priv, reading randomness from rand. The opts argument
// is not currently used but, in keeping with the crypto.Signer interface,
// should be the hash function used to digest the message.
func (s *Signer) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) {
	signature, err := Sign(digest, s.Priv, s.MastSignPublicKey, rand)
	if err != nil {
		return nil, err
	}

	return signature.MarshalASN1(false)
}
func VerifyASN1(id []byte, hash, sig []byte, pub *MastSignPublicKey) bool {
	var signature Signature
	_, err := signature.UnmarshalASN1(sig)
	if err != nil {
		return false
	}
	return Verify(&signature, id, hash, pub)
}

type Decrypter struct {
	Id               []byte
	Priv             *UserEncKey
	MastEncPublicKey *MastEncPublicKey
}

func (s *Signer) Public() crypto.PublicKey {
	return s.Id
}

// Decrypt implements crypto.Decrypter.
func (d *Decrypter) Decrypt(rand io.Reader, msg []byte, opts crypto.DecrypterOpts) (plaintext []byte, err error) {
	var cipher Cipher
	_, err = cipher.UnmarshalASN1(msg)
	if err != nil {
		return nil, err
	}
	return Decrypt(d.Id, &cipher, d.Priv)
}

func (d *Decrypter) Public() crypto.PublicKey {
	return d.Id
}
