• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* Copyright (c) 2020, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15// make_basic_constraints.go generates self-signed certificates with the basic
16// constraints extension.
17package main
18
19import (
20	"crypto/ecdsa"
21	"crypto/rand"
22	"crypto/x509"
23	"crypto/x509/pkix"
24	"encoding/pem"
25	"fmt"
26	"io/ioutil"
27	"math/big"
28	"time"
29)
30
31func main() {
32	key := ecdsaKeyFromPEMOrPanic(keyPEM)
33
34	notBefore, err := time.Parse(time.RFC3339, "2000-01-01T00:00:00Z")
35	if err != nil {
36		panic(err)
37	}
38	notAfter, err := time.Parse(time.RFC3339, "2100-01-01T00:00:00Z")
39	if err != nil {
40		panic(err)
41	}
42
43	baseTemplate := x509.Certificate{
44		SerialNumber:       new(big.Int).SetInt64(1),
45		Subject:            pkix.Name{CommonName: "Basic Constraints"},
46		NotBefore:          notBefore,
47		NotAfter:           notAfter,
48		SignatureAlgorithm: x509.ECDSAWithSHA256,
49	}
50
51	certs := []struct {
52		name                  string
53		basicConstraintsValid bool
54		isCA                  bool
55		maxPathLen            int
56		maxPathLenZero        bool
57	}{
58		{name: "none"},
59		{name: "leaf", basicConstraintsValid: true},
60		{name: "ca", basicConstraintsValid: true, isCA: true},
61		{name: "ca_pathlen_0", basicConstraintsValid: true, isCA: true, maxPathLenZero: true},
62		{name: "ca_pathlen_1", basicConstraintsValid: true, isCA: true, maxPathLen: 1},
63		{name: "ca_pathlen_10", basicConstraintsValid: true, isCA: true, maxPathLen: 10},
64	}
65	for _, cert := range certs {
66		template := baseTemplate
67		template.BasicConstraintsValid = cert.basicConstraintsValid
68		template.IsCA = cert.isCA
69		template.MaxPathLen = cert.maxPathLen
70		template.MaxPathLenZero = cert.maxPathLenZero
71
72		certBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &key.PublicKey, key)
73		if err != nil {
74			panic(err)
75		}
76
77		certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certBytes})
78		if err := ioutil.WriteFile(fmt.Sprintf("basic_constraints_%s.pem", cert.name), certPEM, 0666); err != nil {
79			panic(err)
80		}
81	}
82}
83
84const keyPEM = `-----BEGIN PRIVATE KEY-----
85MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgoPUXNXuH9mgiS/nk
86024SYxryxMa3CyGJldiHymLxSquhRANCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5
87w8u3SSwm7HZREvmcBCJBjVIREacRqI0umhzR2V5NLzBBP9yPD/A+Ch5X
88-----END PRIVATE KEY-----`
89
90func ecdsaKeyFromPEMOrPanic(in string) *ecdsa.PrivateKey {
91	keyBlock, _ := pem.Decode([]byte(in))
92	if keyBlock == nil || keyBlock.Type != "PRIVATE KEY" {
93		panic("could not decode private key")
94	}
95	key, err := x509.ParsePKCS8PrivateKey(keyBlock.Bytes)
96	if err != nil {
97		panic(err)
98	}
99	return key.(*ecdsa.PrivateKey)
100}
101