package pki import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "crypto/x509" "encoding/pem" "errors" "fmt" "os" ) // NewKey generates a secure ecdsa private key, // or panics if it can't. func NewKey() *ecdsa.PrivateKey { key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { panic(fmt.Errorf("Generating key: %w", err)) } return key } // MarshalKeyToPEM returns the bytes of a single encoded PEM block containing // the given private key. Panics if it can't encode the key. func MarshalKeyToPEM(key *ecdsa.PrivateKey) []byte { der, err := x509.MarshalPKCS8PrivateKey(key) if err != nil { panic(fmt.Errorf("Encoding key: %w", err)) } return pem.EncodeToMemory(&pem.Block{ Type: PEMTypePrivateKey, Bytes: der, }) } // ParseKeyFromFile retrieves a private key stored in PEM format from a file. func ParseKeyFromFile(fn string) (*ecdsa.PrivateKey, error) { pemBytes, err := os.ReadFile(fn) if err != nil { return nil, err } keyBlock, _ := pem.Decode(pemBytes) if keyBlock == nil || keyBlock.Type != PEMTypePrivateKey { return nil, fmt.Errorf("file was not PEM or first block wasn't %s", PEMTypePrivateKey) } rawKey, err := x509.ParsePKCS8PrivateKey(keyBlock.Bytes) if err != nil { return nil, err } var key *ecdsa.PrivateKey var ok bool key, ok = rawKey.(*ecdsa.PrivateKey) if !ok { return nil, errors.New("key was not ecdsa") } return key, nil }