~ knotless Search/
↑↓ move↵ open⇧↵ all results
0
0
main
87 lines · 2.2 KB Raw History
package market

import (
	"context"
	"crypto/sha256"
	"fmt"
	"sync"

	"github.com/mr-tron/base58"
)

func Base58BTCEncode(b []byte) string {
	return base58.Encode(b)
}

func BadgeBlueKeysRkey(did, keyID string) string {
	sum := sha256.Sum256([]byte(did + ":" + keyID))
	rkey := base58.Encode(sum[:24])
	if len(rkey) > 32 {
		rkey = rkey[:32]
	}
	return rkey
}

func KeyBoundByBadgeBlueKey(ctx context.Context, getter RecordGetter, did, key string) bool {
	if getter == nil {
		return false
	}
	rkey := BadgeBlueKeysRkey(did, key)
	rec, err := getter.GetRecord(ctx, did, BadgeBlueKeysNSID, rkey)
	if err != nil {
		return false
	}
	keyID, _ := rec.Value["keyId"].(string)
	challenge, _ := rec.Value["challenge"].(string)
	return keyID == key && challenge == did
}

type BadgeBlueKeyBinding struct {
	getter RecordGetter
	mu     sync.Mutex
	cache  map[string]bool
}

func NewBadgeBlueKeyBinding(getter RecordGetter) *BadgeBlueKeyBinding {
	return &BadgeBlueKeyBinding{getter: getter, cache: map[string]bool{}}
}

func (b *BadgeBlueKeyBinding) Check(ctx context.Context, did, key string) (bool, error) {
	cacheKey := did + "#" + key
	b.mu.Lock()
	cached, ok := b.cache[cacheKey]
	b.mu.Unlock()
	if ok {
		return cached, nil
	}
	bound := KeyBoundByBadgeBlueKey(ctx, b.getter, did, key)
	b.mu.Lock()
	b.cache[cacheKey] = bound
	b.mu.Unlock()
	return bound, nil
}

type BadgeBlueKeysRecordOptions struct {
	DID       string
	KeyID     string
	Service   string
	CreatedAt string
}

func BuildBadgeBlueKeysRecord(opts BadgeBlueKeysRecordOptions) BadgeBlueKeys {
	return BadgeBlueKeys{KeyID: opts.KeyID, Challenge: opts.DID, Service: opts.Service, CreatedAt: isoOrNow(opts.CreatedAt)}
}

func CreateBadgeBlueKeysRecord(ctx context.Context, w RecordWriter, opts BadgeBlueKeysRecordOptions) (StrongRef, error) {
	if w == nil {
		return StrongRef{}, fmt.Errorf("%w: nil writer", ErrInvalidRecord)
	}
	if opts.DID == "" || opts.KeyID == "" {
		return StrongRef{}, fmt.Errorf("%w: badgeBlueKeys needs did and keyId", ErrInvalidRecord)
	}
	record, err := EncodeRecord(BuildBadgeBlueKeysRecord(opts))
	if err != nil {
		return StrongRef{}, err
	}
	return w.PutRecord(ctx, opts.DID, BadgeBlueKeysNSID, BadgeBlueKeysRkey(opts.DID, opts.KeyID), record)
}