mirror of https://github.com/bjdgyc/anylink.git
51 lines
1.2 KiB
Go
51 lines
1.2 KiB
Go
// Package fingerprint provides a helper to create fingerprint string from certificate
|
|
package fingerprint
|
|
|
|
import (
|
|
"crypto"
|
|
"crypto/x509"
|
|
"errors"
|
|
"fmt"
|
|
)
|
|
|
|
var (
|
|
errHashUnavailable = errors.New("fingerprint: hash algorithm is not linked into the binary")
|
|
errInvalidFingerprintLength = errors.New("fingerprint: invalid fingerprint length")
|
|
)
|
|
|
|
// Fingerprint creates a fingerprint for a certificate using the specified hash algorithm
|
|
func Fingerprint(cert *x509.Certificate, algo crypto.Hash) (string, error) {
|
|
if !algo.Available() {
|
|
return "", errHashUnavailable
|
|
}
|
|
h := algo.New()
|
|
for i := 0; i < len(cert.Raw); {
|
|
n, _ := h.Write(cert.Raw[i:])
|
|
// Hash.Writer is specified to be never returning an error.
|
|
// https://golang.org/pkg/hash/#Hash
|
|
i += n
|
|
}
|
|
digest := []byte(fmt.Sprintf("%x", h.Sum(nil)))
|
|
|
|
digestlen := len(digest)
|
|
if digestlen == 0 {
|
|
return "", nil
|
|
}
|
|
if digestlen%2 != 0 {
|
|
return "", errInvalidFingerprintLength
|
|
}
|
|
res := make([]byte, digestlen>>1+digestlen-1)
|
|
|
|
pos := 0
|
|
for i, c := range digest {
|
|
res[pos] = c
|
|
pos++
|
|
if (i)%2 != 0 && i < digestlen-1 {
|
|
res[pos] = byte(':')
|
|
pos++
|
|
}
|
|
}
|
|
|
|
return string(res), nil
|
|
}
|