github.com/smoorpal/witchcraft-go-server@v1.12.0/integration/testdata/generator.go (about)

     1  // Copyright (c) 2018 Palantir Technologies. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  //go:generate go run $GOFILE
    16  
    17  // package main writes the crypto material used by unit tests. Run using "go generate".
    18  package main
    19  
    20  import (
    21  	"bytes"
    22  	"crypto/rand"
    23  	"crypto/rsa"
    24  	"crypto/x509"
    25  	"crypto/x509/pkix"
    26  	"encoding/pem"
    27  	"io/ioutil"
    28  	"math/big"
    29  	"net"
    30  	"os"
    31  	"time"
    32  )
    33  
    34  const (
    35  	caCertFile     = "ca-cert.pem"
    36  	caKeyFile      = "ca-key.pem"
    37  	serverCertFile = "server-cert.pem"
    38  	serverKeyFile  = "server-key.pem"
    39  	clientCertFile = "client-cert.pem"
    40  	clientKeyFile  = "client-key.pem"
    41  )
    42  
    43  var (
    44  	serverTemplate = x509.Certificate{
    45  		NotBefore:             time.Now(),
    46  		NotAfter:              time.Now().Add(10 * 365 * 24 * time.Hour),
    47  		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
    48  		BasicConstraintsValid: true,
    49  		DNSNames:              []string{"localhost"},
    50  		IPAddresses:           []net.IP{net.IPv4(127, 0, 0, 1)},
    51  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
    52  	}
    53  	clientTemplate = x509.Certificate{
    54  		NotBefore:             time.Now(),
    55  		NotAfter:              time.Now().Add(10 * 365 * 24 * time.Hour),
    56  		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
    57  		BasicConstraintsValid: true,
    58  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
    59  	}
    60  )
    61  
    62  func main() {
    63  	caCertStr, caKeyStr := newCAKeyPair(1, "Root CA")
    64  	block, _ := pem.Decode([]byte(caCertStr))
    65  	if block == nil {
    66  		panic("failed to parse certificate PEM")
    67  	}
    68  	caCert, err := x509.ParseCertificate(block.Bytes)
    69  	if err != nil {
    70  		panic(err)
    71  	}
    72  
    73  	serverCertStr, serverKeyStr := newSignedKeyPair(2, "Test Org", "localhost", &serverTemplate, caCert, caKeyStr)
    74  	clientCertStr, clientKeyStr := newSignedKeyPair(3, "Test Org", "client", &clientTemplate, caCert, caKeyStr)
    75  
    76  	mustWriteFile(caCertFile, []byte(caCertStr), 0644)
    77  	mustWriteFile(caKeyFile, []byte(caKeyStr), 0644)
    78  
    79  	mustWriteFile(serverCertFile, []byte(serverCertStr), 0644)
    80  	mustWriteFile(serverKeyFile, []byte(serverKeyStr), 0644)
    81  
    82  	mustWriteFile(clientCertFile, []byte(clientCertStr), 0644)
    83  	mustWriteFile(clientKeyFile, []byte(clientKeyStr), 0644)
    84  }
    85  
    86  func mustWriteFile(filename string, data []byte, perm os.FileMode) {
    87  	if err := ioutil.WriteFile(filename, data, perm); err != nil {
    88  		panic(err)
    89  	}
    90  }
    91  
    92  func newCAKeyPair(serial int64, org string) (string, string) {
    93  	caTemplate := &x509.Certificate{
    94  		SerialNumber: big.NewInt(serial),
    95  		Subject: pkix.Name{
    96  			Organization: []string{org},
    97  		},
    98  		NotBefore:             time.Now(),
    99  		NotAfter:              time.Now().Add(10 * 365 * 24 * time.Hour),
   100  		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
   101  		BasicConstraintsValid: true,
   102  		IsCA:                  true,
   103  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageAny},
   104  	}
   105  	privKey, err := rsa.GenerateKey(rand.Reader, 2048)
   106  	if err != nil {
   107  		panic(err)
   108  	}
   109  	certDERBytes, err := x509.CreateCertificate(rand.Reader, caTemplate, caTemplate, &privKey.PublicKey, privKey)
   110  	if err != nil {
   111  		panic(err)
   112  	}
   113  	keyDERBytes := x509.MarshalPKCS1PrivateKey(privKey)
   114  	return derBytesToStrings(certDERBytes, keyDERBytes)
   115  }
   116  
   117  func newSignedKeyPair(serial int64, org, cn string, template, caCert *x509.Certificate, caPrivKey string) (string, string) {
   118  	block, _ := pem.Decode([]byte(caPrivKey))
   119  	if block == nil {
   120  		panic("failed to parse certificate PEM")
   121  	}
   122  	signingPrivKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
   123  	if err != nil {
   124  		panic(err)
   125  	}
   126  
   127  	privKey, err := rsa.GenerateKey(rand.Reader, 2048)
   128  	if err != nil {
   129  		panic(err)
   130  	}
   131  
   132  	tmplCopy := *template
   133  	tmplCopy.SerialNumber = big.NewInt(serial)
   134  	tmplCopy.Subject = pkix.Name{
   135  		Organization: []string{org},
   136  		CommonName:   cn,
   137  	}
   138  
   139  	certDERBytes, err := x509.CreateCertificate(rand.Reader, &tmplCopy, caCert, &privKey.PublicKey, signingPrivKey)
   140  	if err != nil {
   141  		panic(err)
   142  	}
   143  
   144  	return derBytesToStrings(certDERBytes, x509.MarshalPKCS1PrivateKey(privKey))
   145  }
   146  
   147  func derBytesToStrings(certDERBytes, keyDERBytes []byte) (string, string) {
   148  	var certBuf bytes.Buffer
   149  	if err := pem.Encode(&certBuf, &pem.Block{Type: "CERTIFICATE", Bytes: certDERBytes}); err != nil {
   150  		panic(err)
   151  	}
   152  	var keyBuf bytes.Buffer
   153  	if err := pem.Encode(&keyBuf, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: keyDERBytes}); err != nil {
   154  		panic(err)
   155  	}
   156  	return certBuf.String(), keyBuf.String()
   157  }