package libp2pwebrtc import ( "crypto" "crypto/x509" "errors" ma "github.com/multiformats/go-multiaddr" "github.com/multiformats/go-multibase" mh "github.com/multiformats/go-multihash" "github.com/pion/webrtc/v3" ) // parseFingerprint is forked from pion to avoid bytes to string alloc, // and to avoid the entire hex interspersing when we do not need it anyway var errHashUnavailable = errors.New("fingerprint: hash algorithm is not linked into the binary") // parseFingerprint creates a fingerprint for a certificate using the specified hash algorithm func parseFingerprint(cert *x509.Certificate, algo crypto.Hash) ([]byte, error) { if !algo.Available() { return nil, errHashUnavailable } h := algo.New() // Hash.Writer is specified to be never returning an error. // https://golang.org/pkg/hash/#Hash h.Write(cert.Raw) return h.Sum(nil), nil } func decodeRemoteFingerprint(maddr ma.Multiaddr) (*mh.DecodedMultihash, error) { remoteFingerprintMultibase, err := maddr.ValueForProtocol(ma.P_CERTHASH) if err != nil { return nil, err } _, data, err := multibase.Decode(remoteFingerprintMultibase) if err != nil { return nil, err } return mh.Decode(data) } func encodeDTLSFingerprint(fp webrtc.DTLSFingerprint) (string, error) { digest, err := decodeInterspersedHexFromASCIIString(fp.Value) if err != nil { return "", err } encoded, err := mh.Encode(digest, mh.SHA2_256) if err != nil { return "", err } return multibase.Encode(multibase.Base64url, encoded) }