// String values must be compared case insensitively.
typeSigstruct{
// Required fields.
Versionint// Version, 1. Field "v". Always the first field.
AlgorithmSignstring// "rsa" or "ed25519". Field "a".
AlgorithmHashstring// "sha256" or the deprecated "sha1" (deprecated). Field "a".
Signature[]byte// Field "b".
BodyHash[]byte// Field "bh".
Domaindns.Domain// Field "d".
SignedHeaders[]string// Duplicates are meaningful. Field "h".
Selectordns.Domain// Selector, for looking DNS TXT record at <s>._domainkey.<domain>. Field "s".
// Optional fields.
// Canonicalization is the transformation of header and/or body before hashing. The
// value is in original case, but must be compared case-insensitively. Normally two
// slash-separated values: header canonicalization and body canonicalization. But
// the "simple" means "simple/simple" and "relaxed" means "relaxed/simple". Field
// "c".
Canonicalizationstring
Lengthint64// Body length to verify, default -1 for whole body. Field "l".
Identity*Identity// AUID (agent/user id). If nil and an identity is needed, should be treated as an Identity without localpart and Domain from d= field. Field "i".
QueryMethods[]string// For public key, currently known value is "dns/txt" (should be compared case-insensitively). If empty, dns/txt must be assumed. Field "q".
SignTimeint64// Unix epoch. -1 if unset. Field "t".
ExpireTimeint64// Unix epoch. -1 if unset. Field "x".
CopiedHeaders[]string// Copied header fields. Field "z".
}
// Identity is used for the optional i= field in a DKIM-Signature header. It uses
// the syntax of an email address, but does not necessarily represent one.
typeIdentitystruct{
Localpart*smtp.Localpart// Optional.
Domaindns.Domain
}
// String returns a value for use in the i= DKIM-Signature field.
func(iIdentity)String()string{
s:="@"+i.Domain.ASCII
// We need localpart as pointer to indicate it is missing because localparts can be
// "" which we store (decoded) as empty string and we need to differentiate.
ifi.Localpart!=nil{
s=i.Localpart.String()+s
}
returns
}
funcnewSigWithDefaults()*Sig{
return&Sig{
Canonicalization:"simple/simple",
Length:-1,
SignTime:-1,
ExpireTime:-1,
}
}
// Algorithm returns an algorithm string for use in the "a" field. E.g.
// "ed25519-sha256".
func(sSig)Algorithm()string{
returns.AlgorithmSign+"-"+s.AlgorithmHash
}
// Header returns the DKIM-Signature header in string form, to be prepended to a
// message, including DKIM-Signature field name and trailing \r\n.
func(s*Sig)Header()(string,error){
// ../rfc/6376:1021
// todo: make a higher-level writer that accepts pairs, and only folds to next line when needed.
w:=&message.HeaderWriter{}
w.Addf("","DKIM-Signature: v=%d;",s.Version)
// Domain names must always be in ASCII. ../rfc/6376:1115 ../rfc/6376:1187 ../rfc/6376:1303
w.Addf(" ","d=%s;",s.Domain.ASCII)
w.Addf(" ","s=%s;",s.Selector.ASCII)
ifs.Identity!=nil{
w.Addf(" ","i=%s;",s.Identity.String())// todo: Is utf-8 ok here?