github.com/hoffie/larasync@v0.0.0-20151025221940-0384d2bddcef/helpers/x509/fingerprint.go (about)

     1  package x509
     2  
     3  import (
     4  	"crypto/sha512"
     5  	"crypto/x509"
     6  	"encoding/hex"
     7  	"encoding/pem"
     8  	"errors"
     9  	"io/ioutil"
    10  )
    11  
    12  // CertificateFingerprint returns the SHA-512 fingerprint of the given certificate
    13  // as a hex-encoded string.
    14  //
    15  // Note that this algorithm is *not* compatible with the one used in browsers.
    16  // This is for two reasons:
    17  // Firstly, currentl (2015) browsers do not show sha512 fingerprints anway
    18  // (sha256 and sha1 only).
    19  // Secondly, we do not care about the certificate at all (it contains standardized
    20  // field contents only). Instead we want to verify the public key. This is what
    21  // we do here.
    22  //
    23  // The algorithm is taken from
    24  // http://tools.ietf.org/html/draft-ietf-websec-key-pinning-01#ref-why-pin-key
    25  // but uses sha512 instead of sha1.
    26  func CertificateFingerprint(cert *x509.Certificate) string {
    27  	h := sha512.New()
    28  	h.Write(cert.RawSubjectPublicKeyInfo)
    29  	sum := h.Sum(nil)
    30  	return hex.EncodeToString(sum)
    31  }
    32  
    33  // CertificateFingerprintFromBytes parses the given certificate bytes and returns its
    34  // fingerprint.
    35  func CertificateFingerprintFromBytes(cert []byte) (string, error) {
    36  	parsed, err := x509.ParseCertificate(cert)
    37  	if err != nil {
    38  		return "", err
    39  	}
    40  	return CertificateFingerprint(parsed), nil
    41  }
    42  
    43  // CertificateFingerprintFromPEMFile loads the given PEM file and returns its
    44  // fingerprint.
    45  func CertificateFingerprintFromPEMFile(path string) (string, error) {
    46  	pemBytes, err := ioutil.ReadFile(path)
    47  	if err != nil {
    48  		return "", err
    49  	}
    50  	block, _ := pem.Decode(pemBytes)
    51  	if block == nil {
    52  		return "", errors.New("unable to parse PEM block")
    53  	}
    54  	return CertificateFingerprintFromBytes(block.Bytes)
    55  }