func (sig *Signature) set(t *tag) (err error) {
	if t == nil {
		return
	}
	var l uint64
	switch t.key {
	case tagVersion:
		if len(t.value) != 1 || t.value[0] != '1' {
			return fmt.Errorf("dkim: invalid version: '%s'", t.value)
		}
		sig.Version = t.value
	case tagAlg:
		for k, name := range signAlgNames {
			if bytes.Equal(t.value, name) {
				k := k
				sig.Alg = &k
				return nil
			}
		}
		return fmt.Errorf("dkim: unknown algorithm: '%s'", t.value)
	case tagSDID:
		if len(t.value) == 0 {
			return errEmptySDID
		}
		sig.SDID = t.value
	case tagHeaders:
		if len(t.value) == 0 {
			return errEmptyHeader
		}
		headers := bytes.Split(t.value, sepColon)
		for x := 0; x < len(headers); x++ {
			headers[x] = bytes.ToLower(bytes.TrimSpace(headers[x]))
			sig.Headers = append(sig.Headers, headers[x])
		}
		err = sig.validateHeaders()
	case tagSelector:
		if len(t.value) == 0 {
			return errEmptySelector
		}
		sig.Selector = t.value
	case tagBodyHash:
		if len(t.value) == 0 {
			return errEmptyBodyHash
		}
		sig.BodyHash = t.value
	case tagSignature:
		if len(t.value) == 0 {
			return errEmptySignature
		}
		sig.Value = t.value
	case tagCreatedAt:
		sig.CreatedAt, err = strconv.ParseUint(string(t.value), 10, 64)
		if err != nil {
			return errors.New("dkim: t=: " + err.Error())
		}
		err = sig.validateTime()
	case tagExpiredAt:
		sig.ExpiredAt, err = strconv.ParseUint(string(t.value), 10, 64)
		if err != nil {
			return errors.New("dkim: x=: " + err.Error())
		}
		err = sig.validateTime()
	case tagCanon:
		sig.CanonHeader, sig.CanonBody, err = unpackCanons(t.value)
	case tagPresentHeaders:
		z := bytes.Split(t.value, sepVBar)
		for x := 0; x < len(z); x++ {
			z[x] = bytes.TrimSpace(z[x])
			sig.PresentHeaders = append(sig.PresentHeaders, z[x])
		}
	case tagAUID:
		sig.AUID = t.value
		err = sig.validateAUID()
	case tagBodyLength:
		l, err = strconv.ParseUint(string(t.value), 10, 64)
		if err == nil {
			sig.BodyLength = &l
		}
	case tagQueryMethod:
		sig.setQueryMethods(t.value)
	}
	return err
}
set the signature field value with value from tag.
package dkim
import (
	"bytes"
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha1"
	"crypto/sha256"
	"encoding/base64"
	"errors"
	"fmt"
	"strconv"
	"time"
)
type Signature struct {
	Version []byte
	Alg *SignAlg
	SDID []byte
	Selector []byte
	Headers [][]byte
	BodyHash []byte
	Value []byte
	CreatedAt uint64
	ExpiredAt uint64
	CanonHeader *Canon
	CanonBody *Canon
	PresentHeaders [][]byte
	AUID []byte
	BodyLength *uint64
	QMethod *QueryMethod
	raw []byte
}
func Parse(value []byte) (sig *Signature, err error) {
	if len(value) == 0 {
		return nil, nil
	}
	l := len(value)
	if value[l-2] != '\r' && value[l-1] != '\n' {
		return nil, errors.New("dkim: value must end with CRLF")
	}
	p := newParser(value)
	sig = &Signature{}
	for {
		tag, err := p.fetchTag()
		if err != nil {
			return sig, err
		}
		if tag == nil {
			break
		}
		if tag.key == tagUnknown {
			continue
		}
		err = sig.set(tag)
		if err != nil {
			return sig, err
		}
	}
	sig.raw = value
	return sig, nil
}
func NewSignature(sdid, selector []byte) (sig *Signature) {
	sig = &Signature{
		SDID:     sdid,
		Selector: selector,
	}
	sig.SetDefault()
	return sig
}
func (sig *Signature) Hash(in []byte) (h, h64 []byte) {
	if sig.Alg == nil || *sig.Alg == SignAlgRS256 {
		h256 := sha256.Sum256(in)
		h = h256[:]
	} else {
		h1 := sha1.Sum(in)
		h = h1[:]
	}
	h64 = make([]byte, base64.StdEncoding.EncodedLen(len(h)))
	base64.StdEncoding.Encode(h64, h)
	return
}
func (sig *Signature) Pack(simple bool) []byte {
	bb := new(bytes.Buffer)
	var sigAlg = signAlgNames[SignAlgRS256]
	if sig.Alg != nil {
		sigAlg = signAlgNames[*sig.Alg]
	}
	_, _ = fmt.Fprintf(bb, "v=%s; a=%s; d=%s; s=%s;",
		sig.Version, sigAlg, sig.SDID, sig.Selector)
	wrap(bb, simple)
	_, _ = fmt.Fprintf(bb, "h=%s;", bytes.Join(sig.Headers, sepColon))
	wrap(bb, simple)
	_, _ = fmt.Fprintf(bb, "bh=%s;", sig.BodyHash)
	wrap(bb, simple)
	_, _ = fmt.Fprintf(bb, "b=%s;", sig.Value)
	wrap(bb, simple)
	if sig.CreatedAt > 0 {
		_, _ = fmt.Fprintf(bb, "t=%d; ", sig.CreatedAt)
	}
	if sig.ExpiredAt > 0 {
		_, _ = fmt.Fprintf(bb, "x=%d; ", sig.ExpiredAt)
	}
	if sig.CanonHeader != nil {
		_, _ = fmt.Fprintf(bb, "c=%s", canonNames[*sig.CanonHeader])
		if sig.CanonBody != nil {
			_, _ = fmt.Fprintf(bb, "/%s;", canonNames[*sig.CanonBody])
		} else {
			bb.WriteByte(';')
		}
		wrap(bb, simple)
	}
	if len(sig.PresentHeaders) > 0 {
		bb.WriteString("z=")
		for x := 0; x < len(sig.PresentHeaders); x++ {
			if x > 0 {
				bb.WriteByte('|')
				wrap(bb, simple)
			}
			bb.Write(sig.PresentHeaders[x])
		}
		bb.WriteByte(';')
		wrap(bb, simple)
	}
	if len(sig.AUID) > 0 {
		_, _ = fmt.Fprintf(bb, "i=%s; ", sig.AUID)
	}
	if sig.BodyLength != nil {
		_, _ = fmt.Fprintf(bb, "l=%d; ", *sig.BodyLength)
	}
	if sig.QMethod != nil {
		_, _ = fmt.Fprintf(bb, "q=%s/%s",
			queryTypeNames[sig.QMethod.Type],
			queryOptionNames[sig.QMethod.Option])
	}
	bb.WriteByte('\r')
	bb.WriteByte('\n')
	return bb.Bytes()
}
func wrap(bb *bytes.Buffer, simple bool) {
	if simple {
		bb.WriteByte('\r')
		bb.WriteByte('\n')
	}
	bb.WriteByte(' ')
}
func (sig *Signature) SetDefault() {
	if len(sig.Version) == 0 {
		sig.Version = append(sig.Version, '1')
	}
	if sig.Alg == nil {
		signAlg := SignAlgRS256
		sig.Alg = &signAlg
	}
	if sig.CanonHeader == nil {
		canonHeader := CanonRelaxed
		sig.CanonHeader = &canonHeader
	}
	if sig.CanonBody == nil {
		canonBody := CanonRelaxed
		sig.CanonBody = &canonBody
	}
}
func (sig *Signature) Sign(pk *rsa.PrivateKey, hashHeader []byte) (err error) {
	if pk == nil {
		return fmt.Errorf("email/dkim: empty private key for signing")
	}
	cryptoHash := crypto.SHA256
	if sig.Alg != nil && *sig.Alg == SignAlgRS1 {
		cryptoHash = crypto.SHA1
	}
	rng := rand.Reader
	b, err := rsa.SignPKCS1v15(rng, pk, cryptoHash, hashHeader)
	if err != nil {
		err = fmt.Errorf("email/dkim: failed to sign message: %w", err)
		return err
	}
	sig.Value = make([]byte, base64.StdEncoding.EncodedLen(len(b)))
	base64.StdEncoding.Encode(sig.Value, b)
	return nil
}
func (sig *Signature) Relaxed() []byte {
	return sig.Pack(false)
}
func (sig *Signature) Simple() []byte {
	if len(sig.raw) == 0 {
		return sig.Pack(true)
	}
	return sig.raw
}
func (sig *Signature) Validate() (err error) {
	if len(sig.Version) == 0 || sig.Version[0] != '1' {
		return fmt.Errorf("dkim: invalid version: '%s'", sig.Version)
	}
	if sig.Alg == nil {
		return errEmptySignAlg
	}
	if len(sig.SDID) == 0 {
		return errEmptySDID
	}
	if len(sig.Selector) == 0 {
		return errEmptySelector
	}
	if len(sig.Headers) == 0 {
		return errEmptyHeader
	}
	err = sig.validateHeaders()
	if err != nil {
		return err
	}
	if len(sig.BodyHash) == 0 {
		return errEmptyBodyHash
	}
	if len(sig.Value) == 0 {
		return errEmptySignature
	}
	err = sig.validateTime()
	if err != nil {
		return err
	}
	err = sig.validateAUID()
	return err
}
func (sig *Signature) Verify(key *Key, headerHash []byte) (err error) {
	if key == nil {
		return fmt.Errorf("email/dkim: key record is empty")
	}
	if key.RSA == nil {
		return fmt.Errorf("email/dkim: public key is empty")
	}
	sigValue := make([]byte, base64.StdEncoding.DecodedLen(len(sig.Value)))
	n, err := base64.StdEncoding.Decode(sigValue, sig.Value)
	if err != nil {
		return fmt.Errorf("email/dkim: failed to decode signature: %w", err)
	}
	sigValue = sigValue[:n]
	cryptoHash := crypto.SHA256
	if sig.Alg != nil && *sig.Alg == SignAlgRS1 {
		cryptoHash = crypto.SHA1
	}
	err = rsa.VerifyPKCS1v15(key.RSA, cryptoHash, headerHash, sigValue)
	if err != nil {
		err = fmt.Errorf("email/dkim: verification failed: %w", err)
	}
	return err
}