Skip to content

Commit 7247d5f

Browse files
committed
cmd/dkim-keygen: new utility
1 parent 4ac38eb commit 7247d5f

File tree

1 file changed

+90
-0
lines changed

1 file changed

+90
-0
lines changed

cmd/dkim-keygen/main.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package main
2+
3+
import (
4+
"crypto"
5+
"crypto/ed25519"
6+
"crypto/rand"
7+
"crypto/rsa"
8+
"crypto/x509"
9+
"encoding/base64"
10+
"encoding/pem"
11+
"flag"
12+
"fmt"
13+
"log"
14+
"os"
15+
"strings"
16+
)
17+
18+
var (
19+
keyType string
20+
nBits int
21+
filename string
22+
)
23+
24+
func init() {
25+
flag.StringVar(&keyType, "t", "rsa", "key type (rsa, ed25519)")
26+
flag.IntVar(&nBits, "b", 3072, "number of bits in the key (only for RSA)")
27+
flag.StringVar(&filename, "f", "dkim.priv", "private key filename")
28+
flag.Parse()
29+
}
30+
31+
func main() {
32+
var (
33+
privKey crypto.Signer
34+
err error
35+
)
36+
switch keyType {
37+
case "rsa":
38+
log.Printf("Generating a %v-bit RSA key", nBits)
39+
privKey, err = rsa.GenerateKey(rand.Reader, nBits)
40+
case "ed25519":
41+
log.Printf("Generating an Ed25519 key")
42+
_, privKey, err = ed25519.GenerateKey(rand.Reader)
43+
default:
44+
log.Fatalf("Unsupported key type %q", keyType)
45+
}
46+
if err != nil {
47+
log.Fatalf("Failed to generate key: %v", err)
48+
}
49+
50+
privBytes, err := x509.MarshalPKCS8PrivateKey(privKey)
51+
if err != nil {
52+
log.Fatalf("Failed to marshal private key: %v", err)
53+
}
54+
55+
f, err := os.Create(filename)
56+
if err != nil {
57+
log.Fatalf("Failed to create key file: %v", err)
58+
}
59+
defer f.Close()
60+
61+
privBlock := pem.Block{
62+
Type: "PRIVATE KEY",
63+
Bytes: privBytes,
64+
}
65+
if err := pem.Encode(f, &privBlock); err != nil {
66+
log.Fatalf("Failed to write key PEM block: %v", err)
67+
}
68+
if err := f.Close(); err != nil {
69+
log.Fatalf("Failed to close key file: %v", err)
70+
}
71+
log.Printf("Private key written to %q", filename)
72+
73+
var pubBytes []byte
74+
switch pubKey := privKey.Public().(type) {
75+
case *rsa.PublicKey:
76+
pubBytes = x509.MarshalPKCS1PublicKey(pubKey)
77+
case ed25519.PublicKey:
78+
pubBytes = pubKey
79+
default:
80+
panic("unreachable")
81+
}
82+
83+
params := []string{
84+
"v=DKIM1",
85+
"k=" + keyType,
86+
"p=" + base64.StdEncoding.EncodeToString(pubBytes),
87+
}
88+
log.Println("Public key, to be stored in the TXT record \"<selector>._domainkey\":")
89+
fmt.Println(strings.Join(params, "; "))
90+
}

0 commit comments

Comments
 (0)