github.com/pion/dtls/v2@v2.2.12/pkg/crypto/fingerprint/fingerprint.go (about)

     1  // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
     2  // SPDX-License-Identifier: MIT
     3  
     4  // Package fingerprint provides a helper to create fingerprint string from certificate
     5  package fingerprint
     6  
     7  import (
     8  	"crypto"
     9  	"crypto/x509"
    10  	"errors"
    11  	"fmt"
    12  )
    13  
    14  var (
    15  	errHashUnavailable          = errors.New("fingerprint: hash algorithm is not linked into the binary")
    16  	errInvalidFingerprintLength = errors.New("fingerprint: invalid fingerprint length")
    17  )
    18  
    19  // Fingerprint creates a fingerprint for a certificate using the specified hash algorithm
    20  func Fingerprint(cert *x509.Certificate, algo crypto.Hash) (string, error) {
    21  	if !algo.Available() {
    22  		return "", errHashUnavailable
    23  	}
    24  	h := algo.New()
    25  	for i := 0; i < len(cert.Raw); {
    26  		n, _ := h.Write(cert.Raw[i:])
    27  		// Hash.Writer is specified to be never returning an error.
    28  		// https://golang.org/pkg/hash/#Hash
    29  		i += n
    30  	}
    31  	digest := []byte(fmt.Sprintf("%x", h.Sum(nil)))
    32  
    33  	digestlen := len(digest)
    34  	if digestlen == 0 {
    35  		return "", nil
    36  	}
    37  	if digestlen%2 != 0 {
    38  		return "", errInvalidFingerprintLength
    39  	}
    40  	res := make([]byte, digestlen>>1+digestlen-1)
    41  
    42  	pos := 0
    43  	for i, c := range digest {
    44  		res[pos] = c
    45  		pos++
    46  		if (i)%2 != 0 && i < digestlen-1 {
    47  			res[pos] = byte(':')
    48  			pos++
    49  		}
    50  	}
    51  
    52  	return string(res), nil
    53  }