tofu: Use base64-encoded sha256 fingerprints
This commit is contained in:
parent
c639233ea1
commit
6e5c2473e7
@ -6,7 +6,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"errors"
|
"errors"
|
||||||
@ -64,7 +63,7 @@ func trustCertificate(hostname string, cert *x509.Certificate) error {
|
|||||||
knownHost, ok := hosts.Lookup(hostname)
|
knownHost, ok := hosts.Lookup(hostname)
|
||||||
if ok {
|
if ok {
|
||||||
// Check fingerprint
|
// Check fingerprint
|
||||||
if bytes.Equal(knownHost.Fingerprint, host.Fingerprint) {
|
if knownHost.Fingerprint != host.Fingerprint {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errors.New("error: fingerprint does not match!")
|
return errors.New("error: fingerprint does not match!")
|
||||||
|
82
tofu/tofu.go
82
tofu/tofu.go
@ -4,14 +4,14 @@ package tofu
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/sha512"
|
"crypto/sha256"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
|
"encoding/base64"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
@ -150,7 +150,7 @@ func (k *KnownHosts) TOFU(hostname string, cert *x509.Certificate) error {
|
|||||||
k.Add(host)
|
k.Add(host)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if !bytes.Equal(knownHost.Fingerprint, host.Fingerprint) {
|
if host.Fingerprint != knownHost.Fingerprint {
|
||||||
return fmt.Errorf("fingerprint for %q does not match", hostname)
|
return fmt.Errorf("fingerprint for %q does not match", hostname)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -267,7 +267,7 @@ func (p *PersistentHosts) TOFU(hostname string, cert *x509.Certificate) error {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return p.Add(host)
|
return p.Add(host)
|
||||||
}
|
}
|
||||||
if !bytes.Equal(knownHost.Fingerprint, host.Fingerprint) {
|
if host.Fingerprint != knownHost.Fingerprint {
|
||||||
return fmt.Errorf("fingerprint for %q does not match", hostname)
|
return fmt.Errorf("fingerprint for %q does not match", hostname)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -280,20 +280,20 @@ func (p *PersistentHosts) Close() error {
|
|||||||
|
|
||||||
// Host represents a host entry with a fingerprint using a certain algorithm.
|
// Host represents a host entry with a fingerprint using a certain algorithm.
|
||||||
type Host struct {
|
type Host struct {
|
||||||
Hostname string // hostname
|
Hostname string // hostname
|
||||||
Algorithm string // fingerprint algorithm e.g. SHA-512
|
Algorithm string // fingerprint algorithm e.g. sha256
|
||||||
Fingerprint Fingerprint // fingerprint
|
Fingerprint string // fingerprint
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHost returns a new host with a SHA-512 fingerprint of
|
// NewHost returns a new host with a SHA256 fingerprint of
|
||||||
// the provided raw data.
|
// the provided raw data.
|
||||||
func NewHost(hostname string, raw []byte) Host {
|
func NewHost(hostname string, raw []byte) Host {
|
||||||
sum := sha512.Sum512(raw)
|
sum := sha256.Sum256(raw)
|
||||||
|
|
||||||
return Host{
|
return Host{
|
||||||
Hostname: hostname,
|
Hostname: hostname,
|
||||||
Algorithm: "SHA-512",
|
Algorithm: "sha256",
|
||||||
Fingerprint: sum[:],
|
Fingerprint: base64.StdEncoding.EncodeToString(sum[:]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,7 +311,7 @@ func (h Host) String() string {
|
|||||||
b.WriteByte(' ')
|
b.WriteByte(' ')
|
||||||
b.WriteString(h.Algorithm)
|
b.WriteString(h.Algorithm)
|
||||||
b.WriteByte(' ')
|
b.WriteByte(' ')
|
||||||
b.WriteString(h.Fingerprint.String())
|
b.WriteString(h.Fingerprint)
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,66 +331,18 @@ func (h *Host) UnmarshalText(text []byte) error {
|
|||||||
h.Hostname = string(parts[0])
|
h.Hostname = string(parts[0])
|
||||||
|
|
||||||
algorithm := string(parts[1])
|
algorithm := string(parts[1])
|
||||||
if algorithm != "SHA-512" {
|
if algorithm != "sha256" {
|
||||||
return fmt.Errorf("unsupported algorithm %q", algorithm)
|
return fmt.Errorf("unsupported algorithm %q", algorithm)
|
||||||
}
|
}
|
||||||
|
|
||||||
h.Algorithm = algorithm
|
h.Algorithm = algorithm
|
||||||
|
|
||||||
fingerprint := make([]byte, 0, sha512.Size)
|
fingerprint, err := base64.StdEncoding.DecodeString(string(parts[2]))
|
||||||
scanner := bufio.NewScanner(bytes.NewReader(parts[2]))
|
if err != nil {
|
||||||
scanner.Split(scanFingerprint)
|
return err
|
||||||
|
|
||||||
for scanner.Scan() {
|
|
||||||
b, err := strconv.ParseUint(scanner.Text(), 16, 8)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to parse fingerprint hash: %w", err)
|
|
||||||
}
|
|
||||||
fingerprint = append(fingerprint, byte(b))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(fingerprint) != sha512.Size {
|
h.Fingerprint = string(fingerprint)
|
||||||
return fmt.Errorf("invalid fingerprint size %d, expected %d",
|
|
||||||
len(fingerprint), sha512.Size)
|
|
||||||
}
|
|
||||||
|
|
||||||
h.Fingerprint = fingerprint
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func scanFingerprint(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
|
||||||
if atEOF && len(data) == 0 {
|
|
||||||
return 0, nil, nil
|
|
||||||
}
|
|
||||||
if i := bytes.IndexByte(data, ':'); i >= 0 {
|
|
||||||
// We have a full newline-terminated line.
|
|
||||||
return i + 1, data[0:i], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're at EOF, we have a final, non-terminated hex byte
|
|
||||||
if atEOF {
|
|
||||||
return len(data), data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Request more data.
|
|
||||||
return 0, nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fingerprint represents a fingerprint.
|
|
||||||
type Fingerprint []byte
|
|
||||||
|
|
||||||
// String returns a string representation of the fingerprint.
|
|
||||||
func (f Fingerprint) String() string {
|
|
||||||
var sb strings.Builder
|
|
||||||
|
|
||||||
for i, b := range f {
|
|
||||||
if i > 0 {
|
|
||||||
sb.WriteByte(':')
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(&sb, "%02X", b)
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.String()
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user