(keyPath, newKeyAlgo string)
| 96 | } |
| 97 | |
| 98 | func (m *Modifier) generateAndWrite(keyPath, newKeyAlgo string) (crypto.Signer, error) { |
| 99 | wrapErr := func(err error) error { |
| 100 | return fmt.Errorf("modify.dkim: generate %s: %w", keyPath, err) |
| 101 | } |
| 102 | |
| 103 | m.log.Printf("generating a new %s keypair...", newKeyAlgo) |
| 104 | |
| 105 | var ( |
| 106 | pkey crypto.Signer |
| 107 | dkimName = newKeyAlgo |
| 108 | err error |
| 109 | ) |
| 110 | switch newKeyAlgo { |
| 111 | case "rsa4096": |
| 112 | dkimName = "rsa" |
| 113 | pkey, err = rsa.GenerateKey(rand.Reader, 4096) |
| 114 | case "rsa2048": |
| 115 | dkimName = "rsa" |
| 116 | pkey, err = rsa.GenerateKey(rand.Reader, 2048) |
| 117 | case "ed25519": |
| 118 | _, pkey, err = ed25519.GenerateKey(rand.Reader) |
| 119 | default: |
| 120 | err = fmt.Errorf("unknown key algorithm: %s", newKeyAlgo) |
| 121 | } |
| 122 | if err != nil { |
| 123 | return nil, wrapErr(err) |
| 124 | } |
| 125 | |
| 126 | keyBlob, err := x509.MarshalPKCS8PrivateKey(pkey) |
| 127 | if err != nil { |
| 128 | return nil, wrapErr(err) |
| 129 | } |
| 130 | |
| 131 | // 0777 because we have public keys in here too and they don't |
| 132 | // need protection. Individual private key files have 0600 perms. |
| 133 | if err := os.MkdirAll(filepath.Dir(keyPath), 0o777); err != nil { |
| 134 | return nil, wrapErr(err) |
| 135 | } |
| 136 | |
| 137 | _, err = writeDNSRecord(keyPath, dkimName, pkey) |
| 138 | if err != nil { |
| 139 | return nil, wrapErr(err) |
| 140 | } |
| 141 | |
| 142 | f, err := os.OpenFile(keyPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o600) |
| 143 | if err != nil { |
| 144 | return nil, wrapErr(err) |
| 145 | } |
| 146 | |
| 147 | if err := pem.Encode(f, &pem.Block{ |
| 148 | Type: "PRIVATE KEY", |
| 149 | Bytes: keyBlob, |
| 150 | }); err != nil { |
| 151 | return nil, wrapErr(err) |
| 152 | } |
| 153 | |
| 154 | return pkey, nil |
| 155 | } |
no test coverage detected