func (c *CertInfo) Fingerprint() string {
	fingerprint, err := CertFingerprintStr(string(c.PublicKey()))
	if err != nil {
		panic("invalid public key material")
	}
	return fingerprint
}
Fingerprint returns the fingerprint of the public key.
package shared
import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"crypto/tls"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"fmt"
	"io/ioutil"
	"math/big"
	"net"
	"net/http"
	"os"
	"os/user"
	"path"
	"path/filepath"
	"time"
)
func KeyPairAndCA(dir, prefix string, kind CertKind) (*CertInfo, error) {
	certFilename := filepath.Join(dir, prefix+".crt")
	keyFilename := filepath.Join(dir, prefix+".key")
	err := FindOrGenCert(certFilename, keyFilename, kind == CertClient)
	if err != nil {
		return nil, err
	}
	keypair, err := tls.LoadX509KeyPair(certFilename, keyFilename)
	if err != nil {
		return nil, err
	}
	caFilename := filepath.Join(dir, prefix+".ca")
	var ca *x509.Certificate
	if PathExists(caFilename) {
		ca, err = ReadCert(caFilename)
		if err != nil {
			return nil, err
		}
	}
	info := &CertInfo{
		keypair: keypair,
		ca:      ca,
	}
	return info, nil
}
type CertInfo struct {
	keypair tls.Certificate
	ca      *x509.Certificate
}
func (c *CertInfo) KeyPair() tls.Certificate {
	return c.keypair
}
func (c *CertInfo) CA() *x509.Certificate {
	return c.ca
}
func (c *CertInfo) PublicKey() []byte {
	data := c.KeyPair().Certificate[0]
	return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: data})
}
func (c *CertInfo) PrivateKey() []byte {
	key, ok := c.KeyPair().PrivateKey.(*rsa.PrivateKey)
	if !ok {
		return nil
	}
	data := x509.MarshalPKCS1PrivateKey(key)
	return pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: data})
}