dkim.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package parsemail
  2. import (
  3. "bytes"
  4. "crypto"
  5. "crypto/x509"
  6. "encoding/pem"
  7. "fmt"
  8. "github.com/Jinnrry/pmail/config"
  9. "github.com/Jinnrry/pmail/utils/consts"
  10. "github.com/emersion/go-msgauth/dkim"
  11. log "github.com/sirupsen/logrus"
  12. "golang.org/x/crypto/ed25519"
  13. "io"
  14. "os"
  15. "strings"
  16. )
  17. type Dkim struct {
  18. privateKey crypto.Signer
  19. }
  20. var instance *Dkim
  21. func Init() {
  22. privateKey, err := loadPrivateKey(config.Instance.DkimPrivateKeyPath)
  23. if err != nil {
  24. panic(config.Instance.DkimPrivateKeyPath +
  25. " DKIM load fail! Please set dkim! dkim私钥加载失败!请先设置dkim秘钥" +
  26. err.Error())
  27. }
  28. instance = &Dkim{
  29. privateKey: privateKey,
  30. }
  31. }
  32. func loadPrivateKey(path string) (crypto.Signer, error) {
  33. b, err := os.ReadFile(path)
  34. if err != nil {
  35. return nil, err
  36. }
  37. block, _ := pem.Decode(b)
  38. if block == nil {
  39. return nil, fmt.Errorf("no PEM data found")
  40. }
  41. switch strings.ToUpper(block.Type) {
  42. case "PRIVATE KEY":
  43. k, err := x509.ParsePKCS8PrivateKey(block.Bytes)
  44. if err != nil {
  45. return nil, err
  46. }
  47. return k.(crypto.Signer), nil
  48. case "RSA PRIVATE KEY":
  49. return x509.ParsePKCS1PrivateKey(block.Bytes)
  50. case "EDDSA PRIVATE KEY":
  51. if len(block.Bytes) != ed25519.PrivateKeySize {
  52. return nil, fmt.Errorf("invalid Ed25519 private key size")
  53. }
  54. return ed25519.PrivateKey(block.Bytes), nil
  55. default:
  56. return nil, fmt.Errorf("unknown private key type: '%v'", block.Type)
  57. }
  58. }
  59. func (p *Dkim) Sign(msgData string) []byte {
  60. var b bytes.Buffer
  61. r := strings.NewReader(msgData)
  62. options := &dkim.SignOptions{
  63. Domain: config.Instance.Domain,
  64. Selector: "default",
  65. Signer: p.privateKey,
  66. }
  67. if err := dkim.Sign(&b, r, options); err != nil {
  68. log.Errorf("%+v", err)
  69. return []byte(msgData)
  70. }
  71. return b.Bytes()
  72. }
  73. func Check(mail io.Reader) bool {
  74. verifications, err := dkim.Verify(mail)
  75. if err != nil {
  76. log.Println(err)
  77. }
  78. for _, v := range verifications {
  79. if v.Domain == consts.TEST_DOMAIN {
  80. return true
  81. }
  82. if v.Err == nil {
  83. log.Println("Valid signature for:", v.Domain)
  84. } else {
  85. log.Println("Invalid signature for:", v.Domain, v.Err)
  86. return false
  87. }
  88. }
  89. return true
  90. }