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
|
||||
pubKey, err := newPubKeyFromDnsTxt(dkimHeader.Selector, dkimHeader.Domain)
|
||||
pubKey, verifyOutputOnError, err := newPubKeyFromDnsTxt(dkimHeader.Selector, dkimHeader.Domain)
|
||||
if err != nil {
|
||||
return verifyOutputOnError, err
|
||||
}
|
||||
println(pubKey)
|
||||
|
||||
return SUCCESS, nil
|
||||
|
||||
23
errors.go
23
errors.go
@@ -53,9 +53,30 @@ var (
|
||||
// Version not supported
|
||||
ErrDkimVersionNotsupported = errors.New("incompatible version")
|
||||
|
||||
// Query method unsopported
|
||||
// Query method unsupported
|
||||
errQueryMethodNotsupported = errors.New("query method not supported")
|
||||
|
||||
// ErrVerifyBodyHash when body hash doesn't 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 (
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// pubKeyRep represents a parsed version of public key record
|
||||
@@ -18,9 +21,84 @@ type pubKeyRep struct {
|
||||
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)
|
||||
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)
|
||||
|
||||
return nil, nil
|
||||
return nil, SUCCESS, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user