pub key representation parsing 2/..
This commit is contained in:
5
dkim.go
5
dkim.go
@@ -243,7 +243,10 @@ func Verify(email *[]byte) (VerifyOutput, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// we do not set quesry method because if it's other validation failed earlier
|
// we do not set quesry method because if it's other validation failed earlier
|
||||||
pubKey, err := newPubKeyFromDnsTxt(dkimHeader.Selector, dkimHeader.Domain)
|
pubKey, verifyOutputOnError, err := newPubKeyFromDnsTxt(dkimHeader.Selector, dkimHeader.Domain)
|
||||||
|
if err != nil {
|
||||||
|
return verifyOutputOnError, err
|
||||||
|
}
|
||||||
println(pubKey)
|
println(pubKey)
|
||||||
|
|
||||||
return SUCCESS, nil
|
return SUCCESS, nil
|
||||||
|
|||||||
23
errors.go
23
errors.go
@@ -53,9 +53,30 @@ var (
|
|||||||
// Version not supported
|
// Version not supported
|
||||||
ErrDkimVersionNotsupported = errors.New("incompatible version")
|
ErrDkimVersionNotsupported = errors.New("incompatible version")
|
||||||
|
|
||||||
// Query method unsopported
|
// Query method unsupported
|
||||||
errQueryMethodNotsupported = errors.New("query method not supported")
|
errQueryMethodNotsupported = errors.New("query method not supported")
|
||||||
|
|
||||||
// ErrVerifyBodyHash when body hash doesn't verify
|
// ErrVerifyBodyHash when body hash doesn't verify
|
||||||
ErrVerifyBodyHash = errors.New("body hash did not verify")
|
ErrVerifyBodyHash = errors.New("body hash did not verify")
|
||||||
|
|
||||||
|
// ErrVerifyNoKeyForSignature
|
||||||
|
ErrVerifyNoKeyForSignature = errors.New("no key for verify")
|
||||||
|
|
||||||
|
// ErrVerifyKeyUnavailable when service (dns) is anavailable
|
||||||
|
ErrVerifyKeyUnavailable = errors.New("key unavailable")
|
||||||
|
|
||||||
|
// ErrVerifyTagVMustBeTheFirst if present the v tag must be the firts in the record
|
||||||
|
ErrVerifyTagVMustBeTheFirst = errors.New("pub key syntax error: v tag must be the first")
|
||||||
|
|
||||||
|
// ErrVerifyVersionMusBeDkim1 if présent flag v (version) must be DKIM1
|
||||||
|
ErrVerifyVersionMusBeDkim1 = errors.New("flag v must be set to DKIM1")
|
||||||
|
|
||||||
|
// ErrVerifyBadKeyType bad type for pub key (only rsa is accepted)
|
||||||
|
ErrVerifyBadKeyType = errors.New("bad type for key type")
|
||||||
|
|
||||||
|
// ErrVerifyRevokedKey key(s) for this selector is revoked (p is empty)
|
||||||
|
ErrVerifyRevokedKey = errors.New("revoked key")
|
||||||
|
|
||||||
|
// ErrVerifyBadKey when we can't parse pubkey
|
||||||
|
ErrVerifyBadKey = errors.New("unable to parse pub key")
|
||||||
)
|
)
|
||||||
|
|||||||
82
pubKeyRep.go
82
pubKeyRep.go
@@ -2,8 +2,11 @@ package dkim
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// pubKeyRep represents a parsed version of public key record
|
// pubKeyRep represents a parsed version of public key record
|
||||||
@@ -18,9 +21,84 @@ type pubKeyRep struct {
|
|||||||
FlagIMustBeD bool // flag i
|
FlagIMustBeD bool // flag i
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPubKeyFromDnsTxt(selector, domain string) (*pubKeyRep, error) {
|
func newPubKeyFromDnsTxt(selector, domain string) (*pubKeyRep, VerifyOutput, error) {
|
||||||
txt, err := net.LookupTXT(selector + "._domainkey." + domain)
|
txt, err := net.LookupTXT(selector + "._domainkey." + domain)
|
||||||
|
if err != nil {
|
||||||
|
if strings.HasSuffix(err.Error(), "no such host") {
|
||||||
|
return nil, PERMFAIL, ErrVerifyNoKeyForSignature
|
||||||
|
} else {
|
||||||
|
return nil, TEMPFAIL, ErrVerifyKeyUnavailable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// empty record
|
||||||
|
if len(txt) == 0 {
|
||||||
|
return nil, PERMFAIL, ErrVerifyNoKeyForSignature
|
||||||
|
}
|
||||||
|
|
||||||
|
pkr := new(pubKeyRep)
|
||||||
|
pkr.Version = "DKIM1"
|
||||||
|
pkr.HashAlgo = []string{"sha1", "sha256"}
|
||||||
|
pkr.KeyType = "rsa"
|
||||||
|
|
||||||
|
// parsing, we keep the first record
|
||||||
|
// TODO: if there is multiple record
|
||||||
|
|
||||||
|
p := strings.Split(txt[0], ";")
|
||||||
|
for i, data := range p {
|
||||||
|
keyVal := strings.SplitN(data, "=", 2)
|
||||||
|
switch strings.ToLower(strings.TrimSpace(keyVal[0])) {
|
||||||
|
case "v":
|
||||||
|
// RFC: is this tag is specified it MUST be the first in the record
|
||||||
|
if i != 0 {
|
||||||
|
return nil, PERMFAIL, ErrVerifyTagVMustBeTheFirst
|
||||||
|
}
|
||||||
|
pkr.Version = strings.TrimSpace(keyVal[1])
|
||||||
|
if pkr.Version != "DKIM1" {
|
||||||
|
return nil, PERMFAIL, ErrVerifyVersionMusBeDkim1
|
||||||
|
}
|
||||||
|
case "h":
|
||||||
|
p := strings.Split(strings.ToLower(keyVal[1]), ":")
|
||||||
|
pkr.HashAlgo = []string{}
|
||||||
|
for _, h := range p {
|
||||||
|
h = strings.TrimSpace(h)
|
||||||
|
if h == "sha1" || h == "sha256" {
|
||||||
|
pkr.HashAlgo = append(pkr.HashAlgo, h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if empty switch back to default
|
||||||
|
if len(pkr.HashAlgo) == 0 {
|
||||||
|
pkr.HashAlgo = []string{"sha1", "sha256"}
|
||||||
|
}
|
||||||
|
case "k":
|
||||||
|
if strings.ToLower(strings.TrimSpace(keyVal[1])) != "rsa" {
|
||||||
|
return nil, PERMFAIL, ErrVerifyBadKeyType
|
||||||
|
}
|
||||||
|
case "n":
|
||||||
|
pkr.Note = strings.TrimSpace(keyVal[1])
|
||||||
|
case "p":
|
||||||
|
rawkey := strings.TrimSpace(keyVal[1])
|
||||||
|
if rawkey == "" {
|
||||||
|
return nil, PERMFAIL, ErrVerifyRevokedKey
|
||||||
|
}
|
||||||
|
// x509.ParsePKIXPublicKey(Dkim.PublicKey.PublicKey)
|
||||||
|
un64, err := base64.StdEncoding.DecodeString(rawkey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, PERMFAIL, ErrVerifyBadKey
|
||||||
|
}
|
||||||
|
pk, err := x509.ParsePKIXPublicKey(un64)
|
||||||
|
pkr.PubKey = *pk.(*rsa.PublicKey)
|
||||||
|
// HERE
|
||||||
|
case "s":
|
||||||
|
case "t":
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: If no pubkey
|
||||||
|
|
||||||
fmt.Println(txt, err)
|
fmt.Println(txt, err)
|
||||||
|
|
||||||
return nil, nil
|
return nil, SUCCESS, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user