You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
DateKeys/profile/registry.go

82 lines
2.2 KiB

package profile
import (
"encoding/hex"
"fmt"
datekeys "g.activething.com/go/DateKeys"
)
// Registry resolves a profile_id to a locally trusted Provider Profile. The
// client MUST NOT accept a profile or key supplied by the endpoint that
// delivers the release (spec §13); a Registry is built by the caller from
// pinned data only.
type Registry interface {
// Lookup returns a copy of the pinned profile for id.
Lookup(id string) (*Profile, bool)
}
// Pin is a profile together with the profile_hash the caller expects it to
// have (spec §13: the profile hash is known in advance).
type Pin struct {
Profile *Profile
Hash [32]byte
}
type pinned struct {
profile *Profile
hash [32]byte
}
type registry struct {
m map[string]pinned
}
// NewRegistry validates every profile, checks it against its expected
// profile_hash and returns an immutable registry holding private copies.
func NewRegistry(pins ...Pin) (Registry, error) {
r := &registry{m: make(map[string]pinned, len(pins))}
for _, pin := range pins {
if pin.Profile == nil {
return nil, fmt.Errorf("profile: nil profile in registry: %w", datekeys.ErrUnknownProfile)
}
p := pin.Profile.Clone()
if err := p.Validate(); err != nil {
return nil, err
}
h, err := p.Hash()
if err != nil {
return nil, err
}
if h != pin.Hash {
return nil, fmt.Errorf("profile %s: profile_hash %x does not match the pinned %x: %w",
p.ID, h, pin.Hash, datekeys.ErrProfileMismatch)
}
if _, dup := r.m[p.ID]; dup {
return nil, fmt.Errorf("profile %s: pinned twice", p.ID)
}
r.m[p.ID] = pinned{profile: p, hash: h}
}
return r, nil
}
func (r *registry) Lookup(id string) (*Profile, bool) {
e, ok := r.m[id]
if !ok {
return nil, false
}
return e.profile.Clone(), true
}
// Default returns the default registry, which contains only the Quicknet
// profile checked against QuicknetProfileHash.
func Default() (Registry, error) {
var h [32]byte
b, err := hex.DecodeString(QuicknetProfileHash)
if err != nil || len(b) != len(h) {
return nil, fmt.Errorf("profile: invalid pinned Quicknet profile hash: %w", datekeys.ErrProfileMismatch)
}
copy(h[:], b)
return NewRegistry(Pin{Profile: Quicknet(), Hash: h})
}

Powered by TurnKey Linux.