...

Source file src/github.com/letsencrypt/boulder/test/certs.go

Documentation: github.com/letsencrypt/boulder/test

     1  package test
     2  
     3  import (
     4  	"crypto"
     5  	"crypto/ecdsa"
     6  	"crypto/rand"
     7  	"crypto/rsa"
     8  	"crypto/x509"
     9  	"encoding/hex"
    10  	"encoding/pem"
    11  	"errors"
    12  	"fmt"
    13  	"math/big"
    14  	"os"
    15  	"testing"
    16  )
    17  
    18  // LoadSigner loads a PEM private key specified by filename or returns an error.
    19  // Can be paired with issuance.LoadCertificate to get both a CA cert and its
    20  // associated private key for use in signing throwaway test certs.
    21  func LoadSigner(filename string) (crypto.Signer, error) {
    22  	keyBytes, err := os.ReadFile(filename)
    23  	if err != nil {
    24  		return nil, err
    25  	}
    26  
    27  	// pem.Decode does not return an error as its 2nd arg, but instead the "rest"
    28  	// that was leftover from parsing the PEM block. We only care if the decoded
    29  	// PEM block was empty for this test function.
    30  	block, _ := pem.Decode(keyBytes)
    31  	if block == nil {
    32  		return nil, errors.New("Unable to decode private key PEM bytes")
    33  	}
    34  
    35  	// Try decoding as an RSA private key
    36  	if rsaKey, err := x509.ParsePKCS1PrivateKey(block.Bytes); err == nil {
    37  		return rsaKey, nil
    38  	}
    39  
    40  	// Try decoding as a PKCS8 private key
    41  	if key, err := x509.ParsePKCS8PrivateKey(block.Bytes); err == nil {
    42  		// Determine the key's true type and return it as a crypto.Signer
    43  		switch k := key.(type) {
    44  		case *rsa.PrivateKey:
    45  			return k, nil
    46  		case *ecdsa.PrivateKey:
    47  			return k, nil
    48  		}
    49  	}
    50  
    51  	// Try as an ECDSA private key
    52  	if ecdsaKey, err := x509.ParseECPrivateKey(block.Bytes); err == nil {
    53  		return ecdsaKey, nil
    54  	}
    55  
    56  	// Nothing worked! Fail hard.
    57  	return nil, errors.New("Unable to decode private key PEM bytes")
    58  }
    59  
    60  // ThrowAwayCert is a small test helper function that creates a self-signed
    61  // certificate for nameCount random example.com subdomains and returns the
    62  // parsed certificate  and the random serial in string form or aborts the test.
    63  // The certificate returned from this function is the bare minimum needed for
    64  // most tests and isn't a robust example of a complete end entity certificate.
    65  func ThrowAwayCert(t *testing.T, nameCount int) (string, *x509.Certificate) {
    66  	var serialBytes [16]byte
    67  	_, _ = rand.Read(serialBytes[:])
    68  	sn := big.NewInt(0).SetBytes(serialBytes[:])
    69  
    70  	return ThrowAwayCertWithSerial(t, nameCount, sn, nil)
    71  }
    72  
    73  // ThrowAwayCertWithSerial is a small test helper function that creates a
    74  // certificate for nameCount random example.com subdomains and returns the
    75  // parsed certificate and the serial in string form or aborts the test.
    76  // The new throwaway certificate is always self-signed (with a random key),
    77  // but will appear to be issued from issuer if provided.
    78  // The certificate returned from this function is the bare minimum needed for
    79  // most tests and isn't a robust example of a complete end entity certificate.
    80  func ThrowAwayCertWithSerial(t *testing.T, nameCount int, sn *big.Int, issuer *x509.Certificate) (string, *x509.Certificate) {
    81  	k, err := rsa.GenerateKey(rand.Reader, 512)
    82  	AssertNotError(t, err, "rsa.GenerateKey failed")
    83  
    84  	var names []string
    85  	for i := 0; i < nameCount; i++ {
    86  		var nameBytes [3]byte
    87  		_, _ = rand.Read(nameBytes[:])
    88  		names = append(names, fmt.Sprintf("%s.example.com", hex.EncodeToString(nameBytes[:])))
    89  	}
    90  
    91  	template := &x509.Certificate{
    92  		SerialNumber:          sn,
    93  		DNSNames:              names,
    94  		IssuingCertificateURL: []string{"http://localhost:4001/acme/issuer-cert/1234"},
    95  	}
    96  
    97  	if issuer == nil {
    98  		issuer = template
    99  	}
   100  
   101  	testCertDER, err := x509.CreateCertificate(rand.Reader, template, issuer, &k.PublicKey, k)
   102  	AssertNotError(t, err, "x509.CreateCertificate failed")
   103  	testCert, err := x509.ParseCertificate(testCertDER)
   104  	AssertNotError(t, err, "failed to parse self-signed cert DER")
   105  	return fmt.Sprintf("%036x", sn), testCert
   106  }
   107  

View as plain text