From 5c6ce224aae4225401416afe131591251863067d Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 12 Mar 2019 00:32:49 +0100 Subject: [PATCH] Add support for Ed25519 --- go.mod | 1 + query.go | 31 ++++++++++++++++++++++++++++--- sign.go | 4 ++++ 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index eaf4c63..bbaa15b 100644 --- a/go.mod +++ b/go.mod @@ -5,4 +5,5 @@ go 1.12 require ( github.com/emersion/go-milter v0.0.0-20190311184326-c3095a41a6fe github.com/emersion/go-msgauth v0.0.0-20190307192406-8646172ce7a5 + golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 ) diff --git a/query.go b/query.go index 2a0cbd8..d47164e 100644 --- a/query.go +++ b/query.go @@ -5,9 +5,12 @@ import ( "crypto/rsa" "crypto/x509" "encoding/base64" + "errors" "fmt" "net" "strings" + + "golang.org/x/crypto/ed25519" ) type verifier interface { @@ -19,14 +22,29 @@ type rsaVerifier struct { *rsa.PublicKey } -func (v *rsaVerifier) Public() crypto.PublicKey { +func (v rsaVerifier) Public() crypto.PublicKey { return v.PublicKey } -func (v *rsaVerifier) Verify(hash crypto.Hash, hashed, sig []byte) error { +func (v rsaVerifier) Verify(hash crypto.Hash, hashed, sig []byte) error { return rsa.VerifyPKCS1v15(v.PublicKey, hash, hashed, sig) } +type ed25519Verifier struct { + ed25519.PublicKey +} + +func (v ed25519Verifier) Public() crypto.PublicKey { + return v.PublicKey +} + +func (v ed25519Verifier) Verify(hash crypto.Hash, hashed, sig []byte) error { + if !ed25519.Verify(v.PublicKey, hashed, sig) { + return errors.New("dkim: invalid Ed25519 signature") + } + return nil +} + type queryResult struct { Verifier verifier KeyAlgo string @@ -102,8 +120,15 @@ func parsePublicKey(s string) (*queryResult, error) { if rsaPub.Size() * 8 < 1024 { return nil, permFailError(fmt.Sprintf("key is too short: want 1024 bits, has %v bits", rsaPub.Size() * 8)) } - res.Verifier = &rsaVerifier{rsaPub} + res.Verifier = rsaVerifier{rsaPub} res.KeyAlgo = "rsa" + case "ed25519": + if len(b) != ed25519.PublicKeySize { + return nil, permFailError(fmt.Sprintf("invalid Ed25519 public key size: %v", len(b))) + } + ed25519Pub := ed25519.PublicKey(b) + res.Verifier = ed25519Verifier{ed25519Pub} + res.KeyAlgo = "ed25519" default: return nil, permFailError("unsupported key algorithm") } diff --git a/sign.go b/sign.go index 26ffa82..9064eaf 100644 --- a/sign.go +++ b/sign.go @@ -12,6 +12,8 @@ import ( "strconv" "strings" "time" + + "golang.org/x/crypto/ed25519" ) var randReader io.Reader = rand.Reader @@ -87,6 +89,8 @@ func Sign(w io.Writer, r io.Reader, options *SignOptions) error { switch options.Signer.Public().(type) { case *rsa.PublicKey: keyAlgo = "rsa" + case ed25519.PublicKey: + keyAlgo = "ed25519" default: return fmt.Errorf("dkim: unsupported key algorithm %T", options.Signer.Public()) }