/* Copyright (c) 2020, Google Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ // make_basic_constraints.go generates self-signed certificates with the basic // constraints extension. package main import ( "crypto/ecdsa" "crypto/rand" "crypto/x509" "crypto/x509/pkix" "encoding/pem" "fmt" "io/ioutil" "math/big" "time" ) func main() { key := ecdsaKeyFromPEMOrPanic(keyPEM) notBefore, err := time.Parse(time.RFC3339, "2000-01-01T00:00:00Z") if err != nil { panic(err) } notAfter, err := time.Parse(time.RFC3339, "2100-01-01T00:00:00Z") if err != nil { panic(err) } baseTemplate := x509.Certificate{ SerialNumber: new(big.Int).SetInt64(1), Subject: pkix.Name{CommonName: "Basic Constraints"}, NotBefore: notBefore, NotAfter: notAfter, SignatureAlgorithm: x509.ECDSAWithSHA256, } certs := []struct { name string basicConstraintsValid bool isCA bool maxPathLen int maxPathLenZero bool }{ {name: "none"}, {name: "leaf", basicConstraintsValid: true}, {name: "ca", basicConstraintsValid: true, isCA: true}, {name: "ca_pathlen_0", basicConstraintsValid: true, isCA: true, maxPathLenZero: true}, {name: "ca_pathlen_1", basicConstraintsValid: true, isCA: true, maxPathLen: 1}, {name: "ca_pathlen_10", basicConstraintsValid: true, isCA: true, maxPathLen: 10}, } for _, cert := range certs { template := baseTemplate template.BasicConstraintsValid = cert.basicConstraintsValid template.IsCA = cert.isCA template.MaxPathLen = cert.maxPathLen template.MaxPathLenZero = cert.maxPathLenZero certBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &key.PublicKey, key) if err != nil { panic(err) } certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certBytes}) if err := ioutil.WriteFile(fmt.Sprintf("basic_constraints_%s.pem", cert.name), certPEM, 0666); err != nil { panic(err) } } } const keyPEM = `-----BEGIN PRIVATE KEY----- MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgoPUXNXuH9mgiS/nk 024SYxryxMa3CyGJldiHymLxSquhRANCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5 w8u3SSwm7HZREvmcBCJBjVIREacRqI0umhzR2V5NLzBBP9yPD/A+Ch5X -----END PRIVATE KEY-----` func ecdsaKeyFromPEMOrPanic(in string) *ecdsa.PrivateKey { keyBlock, _ := pem.Decode([]byte(in)) if keyBlock == nil || keyBlock.Type != "PRIVATE KEY" { panic("could not decode private key") } key, err := x509.ParsePKCS8PrivateKey(keyBlock.Bytes) if err != nil { panic(err) } return key.(*ecdsa.PrivateKey) }