add variable entropy readers to cert gen helpers [VAULT-1179] (#10653)
* move entropy augmentation in cert gen to oss * changelog * go mod vendor * updated helpers to allow custom entropy * comments * comments
This commit is contained in:
parent
77d27cb968
commit
f6bdda8c9c
|
@ -0,0 +1,3 @@
|
|||
```release-note:feature
|
||||
sdk: Private key generation in the certutil package now allows custom io.Readers to be used.
|
||||
```
|
|
@ -191,17 +191,34 @@ func ParsePEMBundle(pemBundle string) (*ParsedCertBundle, error) {
|
|||
return parsedBundle, nil
|
||||
}
|
||||
|
||||
// GeneratePrivateKey generates a private key with the specified type and key bits
|
||||
// GeneratePrivateKey generates a private key with the specified type and key bits.
|
||||
func GeneratePrivateKey(keyType string, keyBits int, container ParsedPrivateKeyContainer) error {
|
||||
return generatePrivateKey(keyType, keyBits, container, nil)
|
||||
}
|
||||
|
||||
// GeneratePrivateKeyWithRandomSource generates a private key with the specified type and key bits.
|
||||
// GeneratePrivateKeyWithRandomSource uses randomness from the entropyReader to generate the private key.
|
||||
func GeneratePrivateKeyWithRandomSource(keyType string, keyBits int, container ParsedPrivateKeyContainer, entropyReader io.Reader) error {
|
||||
return generatePrivateKey(keyType, keyBits, container, entropyReader)
|
||||
}
|
||||
|
||||
// generatePrivateKey generates a private key with the specified type and key bits.
|
||||
// generatePrivateKey uses randomness from the entropyReader to generate the private key.
|
||||
func generatePrivateKey(keyType string, keyBits int, container ParsedPrivateKeyContainer, entropyReader io.Reader) error {
|
||||
var err error
|
||||
var privateKeyType PrivateKeyType
|
||||
var privateKeyBytes []byte
|
||||
var privateKey crypto.Signer
|
||||
|
||||
var randReader io.Reader = rand.Reader
|
||||
if entropyReader != nil {
|
||||
randReader = entropyReader
|
||||
}
|
||||
|
||||
switch keyType {
|
||||
case "rsa":
|
||||
privateKeyType = RSAPrivateKey
|
||||
privateKey, err = rsa.GenerateKey(rand.Reader, keyBits)
|
||||
privateKey, err = rsa.GenerateKey(randReader, keyBits)
|
||||
if err != nil {
|
||||
return errutil.InternalError{Err: fmt.Sprintf("error generating RSA private key: %v", err)}
|
||||
}
|
||||
|
@ -221,7 +238,7 @@ func GeneratePrivateKey(keyType string, keyBits int, container ParsedPrivateKeyC
|
|||
default:
|
||||
return errutil.UserError{Err: fmt.Sprintf("unsupported bit length for EC key: %d", keyBits)}
|
||||
}
|
||||
privateKey, err = ecdsa.GenerateKey(curve, rand.Reader)
|
||||
privateKey, err = ecdsa.GenerateKey(curve, randReader)
|
||||
if err != nil {
|
||||
return errutil.InternalError{Err: fmt.Sprintf("error generating EC private key: %v", err)}
|
||||
}
|
||||
|
@ -239,7 +256,17 @@ func GeneratePrivateKey(keyType string, keyBits int, container ParsedPrivateKeyC
|
|||
|
||||
// GenerateSerialNumber generates a serial number suitable for a certificate
|
||||
func GenerateSerialNumber() (*big.Int, error) {
|
||||
serial, err := rand.Int(rand.Reader, (&big.Int{}).Exp(big.NewInt(2), big.NewInt(159), nil))
|
||||
return generateSerialNumber(rand.Reader)
|
||||
}
|
||||
|
||||
// GenerateSerialNumberWithRandomSource generates a serial number suitable
|
||||
// for a certificate with custom entropy.
|
||||
func GenerateSerialNumberWithRandomSource(randReader io.Reader) (*big.Int, error) {
|
||||
return generateSerialNumber(randReader)
|
||||
}
|
||||
|
||||
func generateSerialNumber(randReader io.Reader) (*big.Int, error) {
|
||||
serial, err := rand.Int(randReader, (&big.Int{}).Exp(big.NewInt(2), big.NewInt(159), nil))
|
||||
if err != nil {
|
||||
return nil, errutil.InternalError{Err: fmt.Sprintf("error generating serial number: %v", err)}
|
||||
}
|
||||
|
@ -491,9 +518,19 @@ func ValidateKeyTypeLength(keyType string, keyBits int) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Performs the heavy lifting of creating a certificate. Returns
|
||||
// a fully-filled-in ParsedCertBundle.
|
||||
// CreateCertificate uses CreationBundle and the default rand.Reader to
|
||||
// generate a cert/keypair.
|
||||
func CreateCertificate(data *CreationBundle) (*ParsedCertBundle, error) {
|
||||
return createCertificate(data, rand.Reader)
|
||||
}
|
||||
|
||||
// CreateCertificateWithRandomSource uses CreationBundle and a custom
|
||||
// io.Reader for randomness to generate a cert/keypair.
|
||||
func CreateCertificateWithRandomSource(data *CreationBundle, randReader io.Reader) (*ParsedCertBundle, error) {
|
||||
return createCertificate(data, randReader)
|
||||
}
|
||||
|
||||
func createCertificate(data *CreationBundle, randReader io.Reader) (*ParsedCertBundle, error) {
|
||||
var err error
|
||||
result := &ParsedCertBundle{}
|
||||
|
||||
|
@ -502,9 +539,9 @@ func CreateCertificate(data *CreationBundle) (*ParsedCertBundle, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if err := GeneratePrivateKey(data.Params.KeyType,
|
||||
if err := generatePrivateKey(data.Params.KeyType,
|
||||
data.Params.KeyBits,
|
||||
result); err != nil {
|
||||
result, randReader); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -569,7 +606,7 @@ func CreateCertificate(data *CreationBundle) (*ParsedCertBundle, error) {
|
|||
caCert := data.SigningBundle.Certificate
|
||||
certTemplate.AuthorityKeyId = caCert.SubjectKeyId
|
||||
|
||||
certBytes, err = x509.CreateCertificate(rand.Reader, certTemplate, caCert, result.PrivateKey.Public(), data.SigningBundle.PrivateKey)
|
||||
certBytes, err = x509.CreateCertificate(randReader, certTemplate, caCert, result.PrivateKey.Public(), data.SigningBundle.PrivateKey)
|
||||
} else {
|
||||
// Creating a self-signed root
|
||||
if data.Params.MaxPathLength == 0 {
|
||||
|
@ -588,7 +625,7 @@ func CreateCertificate(data *CreationBundle) (*ParsedCertBundle, error) {
|
|||
|
||||
certTemplate.AuthorityKeyId = subjKeyID
|
||||
certTemplate.BasicConstraintsValid = true
|
||||
certBytes, err = x509.CreateCertificate(rand.Reader, certTemplate, certTemplate, result.PrivateKey.Public(), result.PrivateKey)
|
||||
certBytes, err = x509.CreateCertificate(randReader, certTemplate, certTemplate, result.PrivateKey.Public(), result.PrivateKey)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
@ -620,15 +657,26 @@ func CreateCertificate(data *CreationBundle) (*ParsedCertBundle, error) {
|
|||
|
||||
var oidExtensionBasicConstraints = []int{2, 5, 29, 19}
|
||||
|
||||
// Creates a CSR. This is currently only meant for use when
|
||||
// generating an intermediate certificate.
|
||||
// CreateCSR creates a CSR with the default rand.Reader to
|
||||
// generate a cert/keypair. This is currently only meant
|
||||
// for use when generating an intermediate certificate.
|
||||
func CreateCSR(data *CreationBundle, addBasicConstraints bool) (*ParsedCSRBundle, error) {
|
||||
return createCSR(data, addBasicConstraints, rand.Reader)
|
||||
}
|
||||
|
||||
// CreateCSRWithRandomSource creates a CSR with a custom io.Reader
|
||||
// for randomness to generate a cert/keypair.
|
||||
func CreateCSRWithRandomSource(data *CreationBundle, addBasicConstraints bool, randReader io.Reader) (*ParsedCSRBundle, error) {
|
||||
return createCSR(data, addBasicConstraints, randReader)
|
||||
}
|
||||
|
||||
func createCSR(data *CreationBundle, addBasicConstraints bool, randReader io.Reader) (*ParsedCSRBundle, error) {
|
||||
var err error
|
||||
result := &ParsedCSRBundle{}
|
||||
|
||||
if err := GeneratePrivateKey(data.Params.KeyType,
|
||||
if err := generatePrivateKey(data.Params.KeyType,
|
||||
data.Params.KeyBits,
|
||||
result); err != nil {
|
||||
result, randReader); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -669,7 +717,7 @@ func CreateCSR(data *CreationBundle, addBasicConstraints bool) (*ParsedCSRBundle
|
|||
csrTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256
|
||||
}
|
||||
|
||||
csr, err := x509.CreateCertificateRequest(rand.Reader, csrTemplate, result.PrivateKey)
|
||||
csr, err := x509.CreateCertificateRequest(randReader, csrTemplate, result.PrivateKey)
|
||||
if err != nil {
|
||||
return nil, errutil.InternalError{Err: fmt.Sprintf("unable to create certificate: %s", err)}
|
||||
}
|
||||
|
@ -683,9 +731,21 @@ func CreateCSR(data *CreationBundle, addBasicConstraints bool) (*ParsedCSRBundle
|
|||
return result, nil
|
||||
}
|
||||
|
||||
// Performs the heavy lifting of generating a certificate from a CSR.
|
||||
// SignCertificate performs the heavy lifting
|
||||
// of generating a certificate from a CSR.
|
||||
// Returns a ParsedCertBundle sans private keys.
|
||||
func SignCertificate(data *CreationBundle) (*ParsedCertBundle, error) {
|
||||
return signCertificate(data, rand.Reader)
|
||||
}
|
||||
|
||||
// SignCertificateWithRandomSource generates a certificate
|
||||
// from a CSR, using custom randomness from the randReader.
|
||||
// Returns a ParsedCertBundle sans private keys.
|
||||
func SignCertificateWithRandomSource(data *CreationBundle, randReader io.Reader) (*ParsedCertBundle, error) {
|
||||
return signCertificate(data, randReader)
|
||||
}
|
||||
|
||||
func signCertificate(data *CreationBundle, randReader io.Reader) (*ParsedCertBundle, error) {
|
||||
switch {
|
||||
case data == nil:
|
||||
return nil, errutil.UserError{Err: "nil data bundle given to signCertificate"}
|
||||
|
@ -797,7 +857,7 @@ func SignCertificate(data *CreationBundle) (*ParsedCertBundle, error) {
|
|||
certTemplate.PermittedDNSDomainsCritical = true
|
||||
}
|
||||
|
||||
certBytes, err = x509.CreateCertificate(rand.Reader, certTemplate, caCert, data.CSR.PublicKey, data.SigningBundle.PrivateKey)
|
||||
certBytes, err = x509.CreateCertificate(randReader, certTemplate, caCert, data.CSR.PublicKey, data.SigningBundle.PrivateKey)
|
||||
|
||||
if err != nil {
|
||||
return nil, errutil.InternalError{Err: fmt.Sprintf("unable to create certificate: %s", err)}
|
||||
|
|
|
@ -191,17 +191,34 @@ func ParsePEMBundle(pemBundle string) (*ParsedCertBundle, error) {
|
|||
return parsedBundle, nil
|
||||
}
|
||||
|
||||
// GeneratePrivateKey generates a private key with the specified type and key bits
|
||||
// GeneratePrivateKey generates a private key with the specified type and key bits.
|
||||
func GeneratePrivateKey(keyType string, keyBits int, container ParsedPrivateKeyContainer) error {
|
||||
return generatePrivateKey(keyType, keyBits, container, nil)
|
||||
}
|
||||
|
||||
// GeneratePrivateKeyWithRandomSource generates a private key with the specified type and key bits.
|
||||
// GeneratePrivateKeyWithRandomSource uses randomness from the entropyReader to generate the private key.
|
||||
func GeneratePrivateKeyWithRandomSource(keyType string, keyBits int, container ParsedPrivateKeyContainer, entropyReader io.Reader) error {
|
||||
return generatePrivateKey(keyType, keyBits, container, entropyReader)
|
||||
}
|
||||
|
||||
// generatePrivateKey generates a private key with the specified type and key bits.
|
||||
// generatePrivateKey uses randomness from the entropyReader to generate the private key.
|
||||
func generatePrivateKey(keyType string, keyBits int, container ParsedPrivateKeyContainer, entropyReader io.Reader) error {
|
||||
var err error
|
||||
var privateKeyType PrivateKeyType
|
||||
var privateKeyBytes []byte
|
||||
var privateKey crypto.Signer
|
||||
|
||||
var randReader io.Reader = rand.Reader
|
||||
if entropyReader != nil {
|
||||
randReader = entropyReader
|
||||
}
|
||||
|
||||
switch keyType {
|
||||
case "rsa":
|
||||
privateKeyType = RSAPrivateKey
|
||||
privateKey, err = rsa.GenerateKey(rand.Reader, keyBits)
|
||||
privateKey, err = rsa.GenerateKey(randReader, keyBits)
|
||||
if err != nil {
|
||||
return errutil.InternalError{Err: fmt.Sprintf("error generating RSA private key: %v", err)}
|
||||
}
|
||||
|
@ -221,7 +238,7 @@ func GeneratePrivateKey(keyType string, keyBits int, container ParsedPrivateKeyC
|
|||
default:
|
||||
return errutil.UserError{Err: fmt.Sprintf("unsupported bit length for EC key: %d", keyBits)}
|
||||
}
|
||||
privateKey, err = ecdsa.GenerateKey(curve, rand.Reader)
|
||||
privateKey, err = ecdsa.GenerateKey(curve, randReader)
|
||||
if err != nil {
|
||||
return errutil.InternalError{Err: fmt.Sprintf("error generating EC private key: %v", err)}
|
||||
}
|
||||
|
@ -239,7 +256,17 @@ func GeneratePrivateKey(keyType string, keyBits int, container ParsedPrivateKeyC
|
|||
|
||||
// GenerateSerialNumber generates a serial number suitable for a certificate
|
||||
func GenerateSerialNumber() (*big.Int, error) {
|
||||
serial, err := rand.Int(rand.Reader, (&big.Int{}).Exp(big.NewInt(2), big.NewInt(159), nil))
|
||||
return generateSerialNumber(rand.Reader)
|
||||
}
|
||||
|
||||
// GenerateSerialNumberWithRandomSource generates a serial number suitable
|
||||
// for a certificate with custom entropy.
|
||||
func GenerateSerialNumberWithRandomSource(randReader io.Reader) (*big.Int, error) {
|
||||
return generateSerialNumber(randReader)
|
||||
}
|
||||
|
||||
func generateSerialNumber(randReader io.Reader) (*big.Int, error) {
|
||||
serial, err := rand.Int(randReader, (&big.Int{}).Exp(big.NewInt(2), big.NewInt(159), nil))
|
||||
if err != nil {
|
||||
return nil, errutil.InternalError{Err: fmt.Sprintf("error generating serial number: %v", err)}
|
||||
}
|
||||
|
@ -491,9 +518,19 @@ func ValidateKeyTypeLength(keyType string, keyBits int) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Performs the heavy lifting of creating a certificate. Returns
|
||||
// a fully-filled-in ParsedCertBundle.
|
||||
// CreateCertificate uses CreationBundle and the default rand.Reader to
|
||||
// generate a cert/keypair.
|
||||
func CreateCertificate(data *CreationBundle) (*ParsedCertBundle, error) {
|
||||
return createCertificate(data, rand.Reader)
|
||||
}
|
||||
|
||||
// CreateCertificateWithRandomSource uses CreationBundle and a custom
|
||||
// io.Reader for randomness to generate a cert/keypair.
|
||||
func CreateCertificateWithRandomSource(data *CreationBundle, randReader io.Reader) (*ParsedCertBundle, error) {
|
||||
return createCertificate(data, randReader)
|
||||
}
|
||||
|
||||
func createCertificate(data *CreationBundle, randReader io.Reader) (*ParsedCertBundle, error) {
|
||||
var err error
|
||||
result := &ParsedCertBundle{}
|
||||
|
||||
|
@ -502,9 +539,9 @@ func CreateCertificate(data *CreationBundle) (*ParsedCertBundle, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if err := GeneratePrivateKey(data.Params.KeyType,
|
||||
if err := generatePrivateKey(data.Params.KeyType,
|
||||
data.Params.KeyBits,
|
||||
result); err != nil {
|
||||
result, randReader); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -569,7 +606,7 @@ func CreateCertificate(data *CreationBundle) (*ParsedCertBundle, error) {
|
|||
caCert := data.SigningBundle.Certificate
|
||||
certTemplate.AuthorityKeyId = caCert.SubjectKeyId
|
||||
|
||||
certBytes, err = x509.CreateCertificate(rand.Reader, certTemplate, caCert, result.PrivateKey.Public(), data.SigningBundle.PrivateKey)
|
||||
certBytes, err = x509.CreateCertificate(randReader, certTemplate, caCert, result.PrivateKey.Public(), data.SigningBundle.PrivateKey)
|
||||
} else {
|
||||
// Creating a self-signed root
|
||||
if data.Params.MaxPathLength == 0 {
|
||||
|
@ -588,7 +625,7 @@ func CreateCertificate(data *CreationBundle) (*ParsedCertBundle, error) {
|
|||
|
||||
certTemplate.AuthorityKeyId = subjKeyID
|
||||
certTemplate.BasicConstraintsValid = true
|
||||
certBytes, err = x509.CreateCertificate(rand.Reader, certTemplate, certTemplate, result.PrivateKey.Public(), result.PrivateKey)
|
||||
certBytes, err = x509.CreateCertificate(randReader, certTemplate, certTemplate, result.PrivateKey.Public(), result.PrivateKey)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
@ -620,15 +657,26 @@ func CreateCertificate(data *CreationBundle) (*ParsedCertBundle, error) {
|
|||
|
||||
var oidExtensionBasicConstraints = []int{2, 5, 29, 19}
|
||||
|
||||
// Creates a CSR. This is currently only meant for use when
|
||||
// generating an intermediate certificate.
|
||||
// CreateCSR creates a CSR with the default rand.Reader to
|
||||
// generate a cert/keypair. This is currently only meant
|
||||
// for use when generating an intermediate certificate.
|
||||
func CreateCSR(data *CreationBundle, addBasicConstraints bool) (*ParsedCSRBundle, error) {
|
||||
return createCSR(data, addBasicConstraints, rand.Reader)
|
||||
}
|
||||
|
||||
// CreateCSRWithRandomSource creates a CSR with a custom io.Reader
|
||||
// for randomness to generate a cert/keypair.
|
||||
func CreateCSRWithRandomSource(data *CreationBundle, addBasicConstraints bool, randReader io.Reader) (*ParsedCSRBundle, error) {
|
||||
return createCSR(data, addBasicConstraints, randReader)
|
||||
}
|
||||
|
||||
func createCSR(data *CreationBundle, addBasicConstraints bool, randReader io.Reader) (*ParsedCSRBundle, error) {
|
||||
var err error
|
||||
result := &ParsedCSRBundle{}
|
||||
|
||||
if err := GeneratePrivateKey(data.Params.KeyType,
|
||||
if err := generatePrivateKey(data.Params.KeyType,
|
||||
data.Params.KeyBits,
|
||||
result); err != nil {
|
||||
result, randReader); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -669,7 +717,7 @@ func CreateCSR(data *CreationBundle, addBasicConstraints bool) (*ParsedCSRBundle
|
|||
csrTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256
|
||||
}
|
||||
|
||||
csr, err := x509.CreateCertificateRequest(rand.Reader, csrTemplate, result.PrivateKey)
|
||||
csr, err := x509.CreateCertificateRequest(randReader, csrTemplate, result.PrivateKey)
|
||||
if err != nil {
|
||||
return nil, errutil.InternalError{Err: fmt.Sprintf("unable to create certificate: %s", err)}
|
||||
}
|
||||
|
@ -683,9 +731,21 @@ func CreateCSR(data *CreationBundle, addBasicConstraints bool) (*ParsedCSRBundle
|
|||
return result, nil
|
||||
}
|
||||
|
||||
// Performs the heavy lifting of generating a certificate from a CSR.
|
||||
// SignCertificate performs the heavy lifting
|
||||
// of generating a certificate from a CSR.
|
||||
// Returns a ParsedCertBundle sans private keys.
|
||||
func SignCertificate(data *CreationBundle) (*ParsedCertBundle, error) {
|
||||
return signCertificate(data, rand.Reader)
|
||||
}
|
||||
|
||||
// SignCertificateWithRandomSource generates a certificate
|
||||
// from a CSR, using custom randomness from the randReader.
|
||||
// Returns a ParsedCertBundle sans private keys.
|
||||
func SignCertificateWithRandomSource(data *CreationBundle, randReader io.Reader) (*ParsedCertBundle, error) {
|
||||
return signCertificate(data, randReader)
|
||||
}
|
||||
|
||||
func signCertificate(data *CreationBundle, randReader io.Reader) (*ParsedCertBundle, error) {
|
||||
switch {
|
||||
case data == nil:
|
||||
return nil, errutil.UserError{Err: "nil data bundle given to signCertificate"}
|
||||
|
@ -797,7 +857,7 @@ func SignCertificate(data *CreationBundle) (*ParsedCertBundle, error) {
|
|||
certTemplate.PermittedDNSDomainsCritical = true
|
||||
}
|
||||
|
||||
certBytes, err = x509.CreateCertificate(rand.Reader, certTemplate, caCert, data.CSR.PublicKey, data.SigningBundle.PrivateKey)
|
||||
certBytes, err = x509.CreateCertificate(randReader, certTemplate, caCert, data.CSR.PublicKey, data.SigningBundle.PrivateKey)
|
||||
|
||||
if err != nil {
|
||||
return nil, errutil.InternalError{Err: fmt.Sprintf("unable to create certificate: %s", err)}
|
||||
|
|
Loading…
Reference in New Issue