You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
consul/agent/connect/generate.go

114 lines
2.8 KiB

// Copyright (c) HashiCorp, Inc.
[COMPLIANCE] License changes (#18443) * Adding explicit MPL license for sub-package This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Adding explicit MPL license for sub-package This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Updating the license from MPL to Business Source License Going forward, this project will be licensed under the Business Source License v1.1. Please see our blog post for more details at <Blog URL>, FAQ at www.hashicorp.com/licensing-faq, and details of the license at www.hashicorp.com/bsl. * add missing license headers * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 --------- Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com>
1 year ago
// SPDX-License-Identifier: BUSL-1.1
package connect
import (
"bytes"
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
"strings"
"time"
)
const (
DefaultPrivateKeyType = "ec"
DefaultPrivateKeyBits = 256
DefaultIntermediateCertTTL = 24 * 365 * time.Hour
// RSA specific settings.
PrivateKeyTypeRSA = "rsa"
MinPrivateKeyBitsRSA = 2048
DefaultPrivateKeyBitsRSA = 4096
)
func pemEncode(value []byte, blockType string) (string, error) {
var buf bytes.Buffer
if err := pem.Encode(&buf, &pem.Block{Type: blockType, Bytes: value}); err != nil {
return "", fmt.Errorf("error encoding value %v: %s", blockType, err)
}
return buf.String(), nil
}
func generateRSAKey(keyBits int) (crypto.Signer, string, error) {
var pk *rsa.PrivateKey
// Check for a secure key length.
if keyBits < MinPrivateKeyBitsRSA {
return nil, "", fmt.Errorf("error generating RSA private key: invalid key size %d, must be at least %d bits", keyBits, MinPrivateKeyBitsRSA)
}
pk, err := rsa.GenerateKey(rand.Reader, keyBits)
if err != nil {
return nil, "", fmt.Errorf("error generating RSA private key: %s", err)
}
bs := x509.MarshalPKCS1PrivateKey(pk)
pemBlock, err := pemEncode(bs, "RSA PRIVATE KEY")
if err != nil {
return nil, "", err
}
return pk, pemBlock, nil
}
func generateECDSAKey(keyBits int) (crypto.Signer, string, error) {
var pk *ecdsa.PrivateKey
var curve elliptic.Curve
switch keyBits {
case 224:
curve = elliptic.P224()
case 256:
curve = elliptic.P256()
case 384:
curve = elliptic.P384()
case 521:
curve = elliptic.P521()
default:
return nil, "", fmt.Errorf("error generating ECDSA private key: unknown curve length %d", keyBits)
}
pk, err := ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
return nil, "", fmt.Errorf("error generating ECDSA private key: %s", err)
}
bs, err := x509.MarshalECPrivateKey(pk)
if err != nil {
return nil, "", fmt.Errorf("error marshaling ECDSA private key: %s", err)
}
pemBlock, err := pemEncode(bs, "EC PRIVATE KEY")
if err != nil {
return nil, "", err
}
return pk, pemBlock, nil
}
// GeneratePrivateKey generates a new Private key
func GeneratePrivateKeyWithConfig(keyType string, keyBits int) (crypto.Signer, string, error) {
switch strings.ToLower(keyType) {
case PrivateKeyTypeRSA:
return generateRSAKey(keyBits)
case DefaultPrivateKeyType:
return generateECDSAKey(keyBits)
default:
return nil, "", fmt.Errorf("unknown private key type requested: %s", keyType)
}
}
func GeneratePrivateKey() (crypto.Signer, string, error) {
// TODO: find any calls to this func, replace with calls to GeneratePrivateKeyWithConfig()
// using prefs `private_key_type` and `private_key_bits`
return GeneratePrivateKeyWithConfig(DefaultPrivateKeyType, DefaultPrivateKeyBits)
}