Files
PMail/server/dto/parsemail/dkim.go
T
Jinnrry 5af46b32f6 Feature/v2.8.0 (#231)
支持Imap协议
升级所有依赖
修复部分bug
2025-01-04 16:23:07 +08:00

105 lines
2.1 KiB
Go

package parsemail
import (
"bytes"
"crypto"
"crypto/x509"
"encoding/pem"
"fmt"
"github.com/Jinnrry/pmail/config"
"github.com/Jinnrry/pmail/utils/consts"
"github.com/emersion/go-msgauth/dkim"
log "github.com/sirupsen/logrus"
"golang.org/x/crypto/ed25519"
"io"
"os"
"strings"
)
type Dkim struct {
privateKey crypto.Signer
}
var instance *Dkim
func Init() {
privateKey, err := loadPrivateKey(config.Instance.DkimPrivateKeyPath)
if err != nil {
panic(config.Instance.DkimPrivateKeyPath +
" DKIM load fail! Please set dkim! dkim私钥加载失败!请先设置dkim秘钥" +
err.Error())
}
instance = &Dkim{
privateKey: privateKey,
}
}
func loadPrivateKey(path string) (crypto.Signer, error) {
b, err := os.ReadFile(path)
if err != nil {
return nil, err
}
block, _ := pem.Decode(b)
if block == nil {
return nil, fmt.Errorf("no PEM data found")
}
switch strings.ToUpper(block.Type) {
case "PRIVATE KEY":
k, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
return k.(crypto.Signer), nil
case "RSA PRIVATE KEY":
return x509.ParsePKCS1PrivateKey(block.Bytes)
case "EDDSA PRIVATE KEY":
if len(block.Bytes) != ed25519.PrivateKeySize {
return nil, fmt.Errorf("invalid Ed25519 private key size")
}
return ed25519.PrivateKey(block.Bytes), nil
default:
return nil, fmt.Errorf("unknown private key type: '%v'", block.Type)
}
}
func (p *Dkim) Sign(msgData string) []byte {
var b bytes.Buffer
r := strings.NewReader(msgData)
options := &dkim.SignOptions{
Domain: config.Instance.Domain,
Selector: "default",
Signer: p.privateKey,
}
if err := dkim.Sign(&b, r, options); err != nil {
log.Errorf("%+v", err)
return []byte(msgData)
}
return b.Bytes()
}
func Check(mail io.Reader) bool {
verifications, err := dkim.Verify(mail)
if err != nil {
log.Println(err)
}
for _, v := range verifications {
if v.Domain == consts.TEST_DOMAIN {
return true
}
if v.Err == nil {
log.Println("Valid signature for:", v.Domain)
} else {
log.Println("Invalid signature for:", v.Domain, v.Err)
return false
}
}
return true
}