waveterm/wavesrv/pkg/keygen/keygen.go
Evan Simkowitz e6186cd694
Fixing linting errors in unused keygen function (#135)
* Fixing missing parameter error in unused keygen function

* applying error formatting linter suggestions

* fixing more linting suggestions
2023-12-12 14:17:03 -08:00

116 lines
3.5 KiB
Go

// Copyright 2023, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
// Utility functions for generating and reading public/private keypairs.
package keygen
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/base64"
"encoding/pem"
"fmt"
"math/big"
"os"
"time"
)
const p384Params = "BgUrgQQAIg=="
// Creates a keypair with CN=[id], private key at keyFileName, and
// public key certificate at certFileName.
func CreateKeyPair(keyFileName string, certFileName string, id string) error {
privateKey, err := CreatePrivateKey(keyFileName)
if err != nil {
return err
}
err = CreateCertificate(certFileName, privateKey, id)
if err != nil {
return err
}
return nil
}
// Creates a private key at keyFileName (ECDSA, secp384r1 (P-384)), PEM format
func CreatePrivateKey(keyFileName string) (*ecdsa.PrivateKey, error) {
curve := elliptic.P384() // secp384r1
privateKey, err := ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
return nil, fmt.Errorf("error generating P-384 key err:%w", err)
}
keyFile, err := os.Create(keyFileName)
if err != nil {
return nil, fmt.Errorf("error opening file:%s err:%w", keyFileName, err)
}
defer keyFile.Close()
pkBytes, err := x509.MarshalPKCS8PrivateKey(privateKey)
if err != nil {
return nil, fmt.Errorf("error MarshalPKCS8PrivateKey err:%w", err)
}
paramsBytes, err := base64.StdEncoding.DecodeString(p384Params)
if err != nil {
return nil, fmt.Errorf("error decoding bytes for P-384 EC PARAMETERS err:%w", err)
}
var pemParamsBlock = &pem.Block{
Type: "EC PARAMETERS",
Bytes: paramsBytes,
}
err = pem.Encode(keyFile, pemParamsBlock)
if err != nil {
return nil, fmt.Errorf("error writing EC PARAMETERS pem block err:%w", err)
}
var pemPrivateBlock = &pem.Block{
Type: "EC PRIVATE KEY",
Bytes: pkBytes,
}
err = pem.Encode(keyFile, pemPrivateBlock)
if err != nil {
return nil, fmt.Errorf("error writing EC PRIVATE KEY pem block err:%w", err)
}
return privateKey, nil
}
// Creates a public key certificate at certFileName using privateKey with CN=[id].
func CreateCertificate(certFileName string, privateKey *ecdsa.PrivateKey, id string) error {
serialNumber, err := rand.Int(rand.Reader, big.NewInt(1000000000000))
if err != nil {
return fmt.Errorf("cannot generate serial number err:%w", err)
}
notBefore, err := time.Parse("Jan 2 15:04:05 2006", "Jan 1 00:00:00 2020")
if err != nil {
return fmt.Errorf("cannot Parse Date err:%w", err)
}
notAfter, err := time.Parse("Jan 2 15:04:05 2006", "Jan 1 00:00:00 2030")
if err != nil {
return fmt.Errorf("cannot Parse Date err:%w", err)
}
template := x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
CommonName: id,
},
NotBefore: notBefore,
NotAfter: notAfter,
KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
BasicConstraintsValid: true,
}
certBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey)
if err != nil {
return fmt.Errorf("error running x509.CreateCertificate err:%v", err)
}
certFile, err := os.Create(certFileName)
if err != nil {
return fmt.Errorf("error opening file:%s err:%w", certFileName, err)
}
defer certFile.Close()
err = pem.Encode(certFile, &pem.Block{Type: "CERTIFICATE", Bytes: certBytes})
if err != nil {
return fmt.Errorf("error writing CERTIFICATE pem block err:%w", err)
}
return nil
}