Use base64 to encode fingerprints

This commit is contained in:
Adnan Maolood 2020-11-25 14:16:51 -05:00
parent ab1db34f02
commit 7ee0ea8b7f
2 changed files with 20 additions and 19 deletions

View File

@ -2,6 +2,7 @@ package gemini
import ( import (
"bufio" "bufio"
"bytes"
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
"errors" "errors"
@ -221,7 +222,7 @@ func (c *Client) verifyConnection(req *Request, cs tls.ConnectionState) error {
// Check the known hosts // Check the known hosts
knownHost, ok := c.KnownHosts.Lookup(hostname) knownHost, ok := c.KnownHosts.Lookup(hostname)
if !ok || time.Now().Unix() >= knownHost.Expires { if !ok || !time.Now().Before(knownHost.Expires) {
// See if the client trusts the certificate // See if the client trusts the certificate
if c.TrustCertificate != nil { if c.TrustCertificate != nil {
switch c.TrustCertificate(hostname, cert) { switch c.TrustCertificate(hostname, cert) {
@ -240,7 +241,7 @@ func (c *Client) verifyConnection(req *Request, cs tls.ConnectionState) error {
} }
fingerprint := NewFingerprint(cert.Raw, cert.NotAfter) fingerprint := NewFingerprint(cert.Raw, cert.NotAfter)
if knownHost.Hex == fingerprint.Hex { if !bytes.Equal(knownHost.Raw, fingerprint.Raw) {
return nil return nil
} }
return errors.New("gemini: fingerprint does not match") return errors.New("gemini: fingerprint does not match")

34
tofu.go
View File

@ -3,6 +3,7 @@ package gemini
import ( import (
"bufio" "bufio"
"crypto/sha512" "crypto/sha512"
"encoding/base64"
"fmt" "fmt"
"io" "io"
"os" "os"
@ -20,7 +21,7 @@ const (
TrustAlways // The certificate is trusted always. TrustAlways // The certificate is trusted always.
) )
// KnownHosts represents a list of known hosts. // KnownHosts maps hosts to fingerprints.
type KnownHosts map[string]Fingerprint type KnownHosts map[string]Fingerprint
// KnownHostsFile represents a list of known hosts optionally loaded from a file. // KnownHostsFile represents a list of known hosts optionally loaded from a file.
@ -69,7 +70,8 @@ func (k *KnownHostsFile) WriteAll(w io.Writer) error {
// writeKnownHost writes a known host to the provided io.Writer. // writeKnownHost writes a known host to the provided io.Writer.
func (k *KnownHostsFile) writeKnownHost(w io.Writer, hostname string, f Fingerprint) (int, error) { func (k *KnownHostsFile) writeKnownHost(w io.Writer, hostname string, f Fingerprint) (int, error) {
return fmt.Fprintf(w, "%s %s %s %d\n", hostname, f.Algorithm, f.Hex, f.Expires) s := base64.StdEncoding.EncodeToString([]byte(f.Raw))
return fmt.Fprintf(w, "%s %s %s %d\n", hostname, f.Algorithm, s, f.Expires)
} }
// Load loads the known hosts from the provided path. // Load loads the known hosts from the provided path.
@ -111,15 +113,20 @@ func (k *KnownHostsFile) Parse(r io.Reader) {
continue continue
} }
fingerprint := parts[2] fingerprint := parts[2]
raw, err := base64.StdEncoding.DecodeString(fingerprint)
expires, err := strconv.ParseInt(parts[3], 10, 0)
if err != nil { if err != nil {
continue continue
} }
unix, err := strconv.ParseInt(parts[3], 10, 0)
if err != nil {
continue
}
expires := time.Unix(unix, 0)
k.KnownHosts[hostname] = Fingerprint{ k.KnownHosts[hostname] = Fingerprint{
Raw: raw,
Algorithm: algorithm, Algorithm: algorithm,
Hex: fingerprint,
Expires: expires, Expires: expires,
} }
} }
@ -127,24 +134,17 @@ func (k *KnownHostsFile) Parse(r io.Reader) {
// Fingerprint represents a fingerprint using a certain algorithm. // Fingerprint represents a fingerprint using a certain algorithm.
type Fingerprint struct { type Fingerprint struct {
Algorithm string // fingerprint algorithm e.g. SHA-512 Raw []byte // raw fingerprint data
Hex string // fingerprint in hexadecimal, with ':' between each octet Algorithm string // fingerprint algorithm e.g. SHA-512
Expires int64 // unix time of the fingerprint expiration date Expires time.Time // unix time of the fingerprint expiration date
} }
// NewFingerprint returns the SHA-512 fingerprint of the provided raw data. // NewFingerprint returns the SHA-512 fingerprint of the provided raw data.
func NewFingerprint(raw []byte, expires time.Time) Fingerprint { func NewFingerprint(raw []byte, expires time.Time) Fingerprint {
sum512 := sha512.Sum512(raw) sum512 := sha512.Sum512(raw)
var b strings.Builder
for i, f := range sum512 {
if i > 0 {
b.WriteByte(':')
}
fmt.Fprintf(&b, "%02X", f)
}
return Fingerprint{ return Fingerprint{
Raw: sum512[:],
Algorithm: "SHA-512", Algorithm: "SHA-512",
Hex: b.String(), Expires: expires,
Expires: expires.Unix(),
} }
} }