func makeSigningKeyWithChain(rootKey libtrust.PrivateKey, depth int) (libtrust.PrivateKey, error) { if depth == 0 { // Don't need to build a chain. return rootKey, nil } var ( x5c = make([]string, depth) parentKey = rootKey key libtrust.PrivateKey cert *x509.Certificate err error ) for depth > 0 { if key, err = libtrust.GenerateECP256PrivateKey(); err != nil { return nil, err } if cert, err = libtrust.GenerateCACert(parentKey, key); err != nil { return nil, err } depth-- x5c[depth] = base64.StdEncoding.EncodeToString(cert.Raw) parentKey = key } key.AddExtendedField("x5c", x5c) return key, nil }
func makeRootCerts(rootKeys []libtrust.PrivateKey) ([]*x509.Certificate, error) { certs := make([]*x509.Certificate, 0, len(rootKeys)) for _, key := range rootKeys { cert, err := libtrust.GenerateCACert(key, key) if err != nil { return nil, err } certs = append(certs, cert) } return certs, nil }
func main() { key, err := libtrust.LoadKeyFile(clientPrivateKeyFilename) if err != nil { log.Fatal(err) } keyPEMBlock, err := key.PEMBlock() if err != nil { log.Fatal(err) } encodedPrivKey := pem.EncodeToMemory(keyPEMBlock) fmt.Printf("Client Key:\n\n%s\n", string(encodedPrivKey)) cert, err := libtrust.GenerateSelfSignedClientCert(key) if err != nil { log.Fatal(err) } encodedCert := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}) fmt.Printf("Client Cert:\n\n%s\n", string(encodedCert)) trustedServerKeys, err := libtrust.LoadKeySetFile(trustedHostsFilename) if err != nil { log.Fatal(err) } hostname, _, err := net.SplitHostPort(serverAddress) if err != nil { log.Fatal(err) } trustedServerKeys, err = libtrust.FilterByHosts(trustedServerKeys, hostname, false) if err != nil { log.Fatal(err) } caCert, err := libtrust.GenerateCACert(key, trustedServerKeys[0]) if err != nil { log.Fatal(err) } encodedCert = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: caCert.Raw}) fmt.Printf("CA Cert:\n\n%s\n", string(encodedCert)) }
// NewIdentityAuthTLSConfig creates a tls.Config for the client to use for // libtrust identity authentication func NewIdentityAuthTLSConfig(trustKey libtrust.PrivateKey, knownHostsPath, proto, addr string) (*tls.Config, error) { tlsConfig := createTLSConfig() // Load known hosts knownHosts, err := libtrust.LoadKeySetFile(knownHostsPath) if err != nil { return nil, fmt.Errorf("Could not load trusted hosts file: %s", err) } // Generate CA pool from known hosts allowedHosts, err := libtrust.FilterByHosts(knownHosts, addr, false) if err != nil { return nil, fmt.Errorf("Error filtering hosts: %s", err) } certPool, err := libtrust.GenerateCACertPool(trustKey, allowedHosts) if err != nil { return nil, fmt.Errorf("Could not create CA pool: %s", err) } tlsConfig.ServerName = "docker" tlsConfig.RootCAs = certPool // Generate client cert from trust key x509Cert, err := libtrust.GenerateSelfSignedClientCert(trustKey) if err != nil { return nil, fmt.Errorf("Certificate generation error: %s", err) } tlsConfig.Certificates = []tls.Certificate{{ Certificate: [][]byte{x509Cert.Raw}, PrivateKey: trustKey.CryptoPrivateKey(), Leaf: x509Cert, }} // Connect to server to see if it is a known host tlsConfig.InsecureSkipVerify = true testConn, err := tls.Dial(proto, addr, tlsConfig) if err != nil { return nil, fmt.Errorf("TLS Handshake error: %s", err) } opts := x509.VerifyOptions{ Roots: tlsConfig.RootCAs, CurrentTime: time.Now(), DNSName: tlsConfig.ServerName, Intermediates: x509.NewCertPool(), } certs := testConn.ConnectionState().PeerCertificates for i, cert := range certs { if i == 0 { continue } opts.Intermediates.AddCert(cert) } _, err = certs[0].Verify(opts) if err != nil { if _, ok := err.(x509.UnknownAuthorityError); ok { pubKey, err := libtrust.FromCryptoPublicKey(certs[0].PublicKey) if err != nil { return nil, fmt.Errorf("Error extracting public key from certificate: %s", err) } // If server is not a known host, prompt user to ask whether it should // be trusted and add to the known hosts file if promptUnknownKey(pubKey, addr) { pubKey.AddExtendedField("hosts", []string{addr}) err = libtrust.AddKeySetFile(knownHostsPath, pubKey) if err != nil { return nil, fmt.Errorf("Error saving updated host keys file: %s", err) } ca, err := libtrust.GenerateCACert(trustKey, pubKey) if err != nil { return nil, fmt.Errorf("Error generating CA: %s", err) } tlsConfig.RootCAs.AddCert(ca) } else { return nil, fmt.Errorf("Cancelling request due to invalid certificate") } } else { return nil, fmt.Errorf("TLS verification error: %s", err) } } testConn.Close() tlsConfig.InsecureSkipVerify = false return tlsConfig, nil }