func SplitSANs(sans []string) (dnsNames []string, ips []net.IP, emails []string, uris []*url.URL) {
	dnsNames = []string{}
	ips = []net.IP{}
	emails = []string{}
	uris = []*url.URL{}
	if sans == nil {
		return
	}
	for _, san := range sans {
		if ip := net.ParseIP(san); ip != nil {
			ips = append(ips, ip)
		} else if u, err := url.Parse(san); err == nil && u.Scheme != "" {
			uris = append(uris, u)
		} else if strings.Contains(san, "@") {
			emails = append(emails, san)
		} else {
			dnsNames = append(dnsNames, san)
		}
	}
	return
}
SplitSANs splits a slice of Subject Alternative Names into slices of
IP Addresses and DNS Names. If an element is not an IP address, then it
is bucketed as a DNS Name.
package x509util
import (
	"crypto/sha256"
	"crypto/x509"
	"encoding/base64"
	"encoding/hex"
	"encoding/pem"
	"io/ioutil"
	"net"
	"net/url"
	"os"
	"path/filepath"
	"strings"
	"github.com/pkg/errors"
	"github.com/smallstep/cli/errs"
)
func Fingerprint(cert *x509.Certificate) string {
	return EncodedFingerprint(cert, HexFingerprint)
}
type FingerprintEncoding int
const (
	HexFingerprint FingerprintEncoding = iota
	Base64Fingerprint
	Base64URLFingerprint
)
func EncodedFingerprint(cert *x509.Certificate, encoding FingerprintEncoding) string {
	sum := sha256.Sum256(cert.Raw)
	if encoding == HexFingerprint {
		return strings.ToLower(hex.EncodeToString(sum[:]))
	}
	src := make([]byte, len(sum))
	for i, b := range sum {
		src[i] = b
	}
	switch encoding {
	case Base64Fingerprint:
		return base64.StdEncoding.EncodeToString(src)
	case Base64URLFingerprint:
		return base64.URLEncoding.EncodeToString(src)
	}
	return ""
}