| 34 | ) |
| 35 | |
| 36 | func (m *Modifier) loadOrGenerateKey(keyPath, newKeyAlgo string) (pkey crypto.Signer, newKey bool, err error) { |
| 37 | f, err := os.Open(keyPath) |
| 38 | if err != nil { |
| 39 | if os.IsNotExist(err) { |
| 40 | pkey, err = m.generateAndWrite(keyPath, newKeyAlgo) |
| 41 | return pkey, true, err |
| 42 | } |
| 43 | return nil, false, err |
| 44 | } |
| 45 | defer func() { |
| 46 | if err := f.Close(); err != nil { |
| 47 | m.log.Error("failed to close key file", err) |
| 48 | } |
| 49 | }() |
| 50 | |
| 51 | pemBlob, err := io.ReadAll(f) |
| 52 | if err != nil { |
| 53 | return nil, false, err |
| 54 | } |
| 55 | |
| 56 | block, _ := pem.Decode(pemBlob) |
| 57 | if block == nil { |
| 58 | return nil, false, fmt.Errorf("modify.dkim: %s: invalid PEM block", keyPath) |
| 59 | } |
| 60 | |
| 61 | var key interface{} |
| 62 | switch block.Type { |
| 63 | case "PRIVATE KEY": // RFC 5208 aka PKCS #8 |
| 64 | key, err = x509.ParsePKCS8PrivateKey(block.Bytes) |
| 65 | if err != nil { |
| 66 | return nil, false, fmt.Errorf("modify.dkim: %s: %w", keyPath, err) |
| 67 | } |
| 68 | case "RSA PRIVATE KEY": // RFC 3447 aka PKCS #1 |
| 69 | key, err = x509.ParsePKCS1PrivateKey(block.Bytes) |
| 70 | if err != nil { |
| 71 | return nil, false, fmt.Errorf("modify.dkim: %s: %w", keyPath, err) |
| 72 | } |
| 73 | case "EC PRIVATE KEY": // RFC 5915 |
| 74 | key, err = x509.ParseECPrivateKey(block.Bytes) |
| 75 | if err != nil { |
| 76 | return nil, false, fmt.Errorf("modify.dkim: %s: %w", keyPath, err) |
| 77 | } |
| 78 | default: |
| 79 | return nil, false, fmt.Errorf("modify.dkim: %s: not a private key or unsupported format", keyPath) |
| 80 | } |
| 81 | |
| 82 | switch key := key.(type) { |
| 83 | case *rsa.PrivateKey: |
| 84 | if err := key.Validate(); err != nil { |
| 85 | return nil, false, err |
| 86 | } |
| 87 | key.Precompute() |
| 88 | return key, false, nil |
| 89 | case ed25519.PrivateKey: |
| 90 | return key, false, nil |
| 91 | case *ecdsa.PublicKey: |
| 92 | return nil, false, fmt.Errorf("modify.dkim: %s: ECDSA keys are not supported", keyPath) |
| 93 | default: |