rootCA.go 2.79 KB
Newer Older
1
package authority
Caro Axel's avatar
Caro Axel committed
2 3 4 5 6

import (
	"crypto/rsa"
	"crypto/x509"
	"io/ioutil"
7
	"os"
Caro Axel's avatar
Caro Axel committed
8
	"path/filepath"
9 10

	"dfss/auth"
Caro Axel's avatar
Caro Axel committed
11 12 13
)

const (
14
	// PkeyFileName is the private key file default name
15
	PkeyFileName = "dfssp_pkey.pem"
16
	// RootCAFileName is the root certificate file default name
17
	RootCAFileName = "dfssp_rootCA.pem"
Caro Axel's avatar
Caro Axel committed
18 19
)

20
// PlatformID contains platform private key and root certificate
Caro Axel's avatar
Caro Axel committed
21
type PlatformID struct {
22 23
	Pkey   *rsa.PrivateKey
	RootCA *x509.Certificate
Caro Axel's avatar
Caro Axel committed
24 25
}

26 27 28 29 30 31
// Initialize creates and saves the platform's private key and root certificate to a PEM format.
// If ca and rKey are not nil, they will be used as the root certificate and root private key instead of creating a ones.
// The files are saved at the specified path.
func Initialize(bits, days int, country, organization, unit, cn, path string, ca *x509.Certificate, rKey *rsa.PrivateKey) error {
	// Generate the private key.
	key, err := auth.GeneratePrivateKey(bits)
Caro Axel's avatar
Caro Axel committed
32 33

	if err != nil {
34
		return err
Caro Axel's avatar
Caro Axel committed
35 36
	}

37 38 39
	var cert []byte
	certPath := filepath.Join(path, RootCAFileName)
	keyPath := filepath.Join(path, PkeyFileName)
Caro Axel's avatar
Caro Axel committed
40

41 42 43 44 45 46 47 48 49 50 51
	if ca == nil {
		// Generate the root certificate, using the private key.
		cert, err = auth.GetSelfSignedCertificate(days, auth.GenerateUID(), country, organization, unit, cn, key)
	} else {
		csr, _ := auth.GetCertificateRequest(country, organization, unit, cn, key)
		request, _ := auth.PEMToCertificateRequest(csr)
		cert, err = auth.GetCertificate(days, auth.GenerateUID(), request, ca, rKey)
		// Override default path values
		certPath = filepath.Join(path, "cert.pem")
		keyPath = filepath.Join(path, "key.pem")
	}
Caro Axel's avatar
Caro Axel committed
52 53 54 55 56

	if err != nil {
		return err
	}

57 58
	// Create missing folders, if needed
	err = os.MkdirAll(path, os.ModeDir|0700)
Caro Axel's avatar
Caro Axel committed
59 60 61 62
	if err != nil {
		return err
	}

63
	// Convert the private key to a PEM format, and save it.
Caro Axel's avatar
Caro Axel committed
64 65 66 67 68 69
	keyPem := auth.PrivateKeyToPEM(key)
	err = ioutil.WriteFile(keyPath, keyPem, 0600)
	if err != nil {
		return err
	}

70
	// Save the root certificate.
71
	return ioutil.WriteFile(certPath, cert, 0600)
Caro Axel's avatar
Caro Axel committed
72 73
}

74
// Start fetches the platform's private rsa key and root certificate, and create a PlatformID accordingly.
Caro Axel's avatar
Caro Axel committed
75 76 77 78 79 80 81 82
//
// The specified path should not end by a separator.
//
// The files are fetched using their default name.
func Start(path string) (*PlatformID, error) {
	keyPath := filepath.Join(path, PkeyFileName)
	certPath := filepath.Join(path, RootCAFileName)

83
	// Recover the private rsa key from file.
Caro Axel's avatar
Caro Axel committed
84 85 86 87 88 89 90 91 92 93
	keyBytes, err := ioutil.ReadFile(keyPath)
	if err != nil {
		return nil, err
	}

	key, err := auth.PEMToPrivateKey(keyBytes)
	if err != nil {
		return nil, err
	}

94
	// Recover the root certificate from file.
Caro Axel's avatar
Caro Axel committed
95 96 97 98 99 100 101 102 103 104 105
	certBytes, err := ioutil.ReadFile(certPath)
	if err != nil {
		return nil, err
	}

	cert, err := auth.PEMToCertificate(certBytes)
	if err != nil {
		return nil, err
	}

	res := &PlatformID{
106 107 108
		Pkey:   key,
		RootCA: cert,
	}
Caro Axel's avatar
Caro Axel committed
109 110 111

	return res, nil
}