Use base64 to encode fingerprints
This commit is contained in:
parent
ab1db34f02
commit
7ee0ea8b7f
@ -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")
|
||||||
|
32
tofu.go
32
tofu.go
@ -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 {
|
||||||
|
Raw []byte // raw fingerprint data
|
||||||
Algorithm string // fingerprint algorithm e.g. SHA-512
|
Algorithm string // fingerprint algorithm e.g. SHA-512
|
||||||
Hex string // fingerprint in hexadecimal, with ':' between each octet
|
Expires time.Time // unix time of the fingerprint expiration date
|
||||||
Expires int64 // 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(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user