phish

package module
v0.0.0-...-b27a91a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 19, 2025 License: MIT Imports: 3 Imported by: 0

README

Phish

simple prototype of web-of-trust petnames

In contrast to many P2P and DID systems, this implementation has non-global aliases, and is loosely coupled to keys. Meaning is instead derived from your friends.

I frequently got too distracted by other details, or making it to complicated. This is the bare bones of the protocol.

It allows me to study the durability and phishing attacks on the protocol.

You can pin identities or proofs, similar to keyoxide.

When a friend adds you (e.g. as "alice") they can resolve friends-of-friends using your record as a starting point.

Your top-level alias's records ({something}.alice.phish) are up to you to set.

Usage

go install codeberg.org/risottobias/phish/phish-cli@latest

# make your identity/site
phish-cli keys gen
phish-cli alias update "yourhandle"
phish-cli carrier gen

# after that completes, you'll have an address.
phish-cli hello send {someone}.onion # say hello to a friend

# they can receive it:
phish-cli hello check
phish-cli hello contact {nickname} {fingerprint}
phish-cli chat send {nickname} "{message}"

# if you trust this person:
phish-cli delegate hurdle 1 # set the threshold of DNS servers
phish-cli delegate add {nickname} 1

# if you want to help a friend:
phish-cli hello check
phish-cli nameserver accept {peer}

# say you have your keys:
phish-cli keys upgrade

# say you lose your keys:
phish-cli keys reset

# say the peer looses their keys, you can update them after you validate their id:
phish-cli nameserver update {peer}

to study

  • timing / out of order attacks
    • flaws in incrementing counters?
  • hijacked onions (e.g., knowing the halo passphrase)
  • discovery of far-off peers
  • sockpuppets
  • confused generals
  • local data integrity
  • spamming with invite requests

extras/distractions

  • halo based onion site recovery? - could also try to make predictable Age and minisign keys?
  • yubikey/cross signing
  • keychain saving (e.g. to prevent repeated password entry)

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AgeGenerate

func AgeGenerate(password string)

func CarrierUpdateAuto

func CarrierUpdateAuto()

func CarrierUpdateEval

func CarrierUpdateEval()

func CarrierUpdateWizard

func CarrierUpdateWizard()

func CheckHello

func CheckHello(c Carrier) (bool, error)

func Fsck

func Fsck(t StoreType) error

Fsck validates storage.

func Get

func Get(url string) ([]byte, error)

func List

func List(t StoreType) ([]any, error)

func Load

func Load(t StoreType, key string) (any, error)

func LookupWebfinger

func LookupWebfinger(domain, username, post string)

Lookup a proof post (or bio) given a URL

func Marshall

func Marshall(MarshallMessage, recipient Alias) ([]byte, error)

marshall and optionally encrypt

func MinisignGenerate

func MinisignGenerate(password string)

func MinisignLoad

func MinisignLoad(password string)

Read your minisign identity

func NewCarrierAuto

func NewCarrierAuto()

func NewCarrierEval

func NewCarrierEval()

func NewCarrierWizard

func NewCarrierWizard()

func Print

func Print(s string, w io.Writer)

safely print to the output

func RecordFind

func RecordFind(record string, threshhold int, nopinning bool, world bool)

find a record, with at least threshold, optionally verifying pins, optionally searching world

func RecordReverse

func RecordReverse(record string, world bool)

check what everybody else calls something

func RecordSave

func RecordSave(alias string, resolution string, replace bool) error

saves a record as an alias, unless it's taken

func Rescue

func Rescue(t StoreType) (bool, error)

Rescue cleans storage. return true if fixed

func SendHello

func SendHello(addr string) (bool, error)

func Store

func Store(t StoreType, key string, obj any) error

marshall correctly for signing and storage, ascii armored...

func WebmentionEncode

func WebmentionEncode(m MarshallMessage) []byte

write message for sending

func WebmentionSend

func WebmentionSend(m MarshallMessage, addr string) (bool, error)

mention send returns if successfully sent

Types

type Age

type Age struct {
}

age wrapper

func AgeLoad

func AgeLoad(password string) Age

Read your age identity

func (*Age) Decrypt

func (a *Age) Decrypt(c []byte) []byte

func (*Age) Encrypt

func (a *Age) Encrypt(m []byte) []byte

type Alias

type Alias struct {
	Nick              string // set to the current name
	Prefered          string // set to the last ack'd prefered name
	Onion             string // their onion addr
	Age               string // their age key
	Minisign          string // their minisign key
	PublishOkay       bool
	WorldDiscoverOkay bool // whether they're okay being on /world/
}

func LoadAlias

func LoadAlias(name string) Alias

func NewAlias

func NewAlias(name string) Alias

type Carrier

type Carrier struct {
	// basic options
	Nickname     string
	Configured   bool // default to false
	InstallTor   bool // whether they want us to install Tor
	InstallCaddy bool // whether they want us to install caddy

	// helper modes
	Wizard bool // guide user step by step with input prompts
	Eval   bool // print out the commands to be run e.g. > bash $(phish-cli carrier upgrade --eval)
	Auto   bool // whether we do it ourselves

	// host specific values
	Remote   bool // whether it's this machine
	Host     string
	Username string // if we need to become someone else

	// static site
	Publisher bool // whether we can send files here
	Path      string

	// site with logs
	Webmention bool   // whether we can read webmentions here
	LogReadCmd string // our log read command
}

type Chat

type Chat struct {
	// contains filtered or unexported fields
}

func LoadChat

func LoadChat(a Alias) Chat

func (*Chat) Read

func (c *Chat) Read() (string, error)

func (*Chat) Remove

func (c *Chat) Remove() error

func (*Chat) Send

func (c *Chat) Send(message string)

type Contact

type Contact struct {
	Alias Alias
}

contact methods

- a contact is subtly different from alias

func BoostrapContact

func BoostrapContact(nick string, dns string, onion string, web string, age string, minisign string, crossign string) (Contact, error)

allow you to manually define a contact given any amount of bootstrap information.

func NewContact

func NewContact(a Alias, nick string) (Contact, error)

func (Contact) Pin

func (c Contact) Pin(dns string, website string, activitypub string, crosssign string)

pin an identity to a specific external proof

func (Contact) Remove

func (c Contact) Remove() error

func (Contact) Rename

func (c Contact) Rename(nick string) error

func (Contact) Save

func (c Contact) Save() error

func (Contact) Unpin

func (c Contact) Unpin(dns string, website string, activitypub string, crossign string)

revert pinning decision

func (Contact) Update

func (c Contact) Update(replacement Contact) error

type Delegation

type Delegation struct {
}

func (*Delegation) Add

func (d *Delegation) Add(a Alias, weight int)

func (*Delegation) Remove

func (d *Delegation) Remove(a Alias)

type Hello

type Hello struct {
	Onion          string
	Age            string
	Minisign       string
	PreferredAlias string
	// contains filtered or unexported fields
}

type Letter

type Letter struct {
	// contains filtered or unexported fields
}

chat functionalities

type MarshallFamily

type MarshallFamily int

message marshalling of structured data e.g. ensure ordering/correctness?

- when decrypting a message from age: - first byte: message family (starts 0x01) - second byte: message type (starts 0x01) - final header byte: message length (3 bytes, max length 2048kb)

  • used to catch liars? meh.

- next each section is prefixed with its field type (from the message type table, starting at 0x01) - fixed length items go first

  • e.g., keys, sigs, onion addrs,

- variable length short items (length below 255)

  • e.g., nicknames, short DNS entries,

- variable length long items (length below 65536)

  • signatures, cross-records,

0x00 family - undefined 0x01 family - private / do not publish (e.g., keys, notes, configs) 0x02 family - fingerprint / alias (known identities) 0x03 family - requests / acks (incomplete states) 0x04 family - Delegate SOA record (authorization to be a NS) 0x05 family - NS record (recent update by peer) 0x06 family - cross-sign record (external e.g. yubikey, proof of site,)

const (
	MarshallHello MarshallFamily
	MarshallAlias
	MarshallContact
	MarshallDelegate
	MarshallNameserver
	MarshallChat
)

type MarshallField

type MarshallField int
const (
	FieldInt8     MarshallField
	FieldByte32   // fixed item
	FieldOnion    // e.g. onion server
	FieldSmallStr // less than 255
	FieldLargeStr // less than 66535
)

these are the global field families:

type MarshallMessage

type MarshallMessage struct {
}

func DNSCheck

func DNSCheck(s string) (MarshallMessage, error)

privately validate DNS without revealing client

func Unmarshall

func Unmarshall([]byte) (MarshallMessage, error)

func WebmentionReadLog

func WebmentionReadLog(path string) ([]MarshallMessage, error)

type MarshallSubfamily

type MarshallSubfamily int

type Minisign

type Minisign struct {
}

func (*Minisign) Sign

func (a *Minisign) Sign()

func (*Minisign) Verify

func (a *Minisign) Verify()

type Nameserver

type Nameserver struct {
	Patron Alias
	// contains filtered or unexported fields
}

nameserver (responsible) functions

func (*Nameserver) Accept

func (n *Nameserver) Accept(a Alias)

func (*Nameserver) Check

func (n *Nameserver) Check() (bool, error)

check for duties

func (*Nameserver) Remove

func (n *Nameserver) Remove()

func (*Nameserver) Update

func (n *Nameserver) Update(replacement Alias)

type PrivateAlias

type PrivateAlias struct {
	MyNick            string
	MyOnion           string
	MyAge             string
	MyMinisign        string
	PublishOkay       bool // whether you're okay being published
	WorldDiscoverOkay bool // whether you want to be crawlable
}

for private keys see keys.go

type PrivateKeys

type PrivateKeys struct {
	Age      age.X25519Identity
	Minisign minisign.PrivateKey
}

func (PrivateKeys) GenerateKeys

func (p PrivateKeys) GenerateKeys() (PrivateKeys, MarshallMessage, error)

func (PrivateKeys) LoadKeys

func (p PrivateKeys) LoadKeys(password string, keyring bool) (PrivateKeys, error)

load keys, optionally store password in keyring

func (PrivateKeys) ResetKeys

func (p PrivateKeys) ResetKeys() (PrivateKeys, MarshallMessage, error)

func (PrivateKeys) UpgradeKeys

func (p PrivateKeys) UpgradeKeys() (PrivateKeys, MarshallMessage, error)

type Publish

type Publish struct {
	// contains filtered or unexported fields
}

func (Publish) REmoveWorld

func (p Publish) REmoveWorld(a Alias)

func (Publish) UploadWorld

func (p Publish) UploadWorld(a Alias)

type SearchResult

type SearchResult struct {
	// contains filtered or unexported fields
}

func Discover

func Discover(depth, max int, hello, world, save bool) ([]SearchResult, []error)
func Search(q string, checkproofs bool, depth int, world bool, hello bool) ([]SearchResult, []error)

search, sometimes among friends, sometimes among world

func (SearchResult) Canonize

func (s SearchResult) Canonize(alias string, pin bool)

cannonize a found alias

type StoreType

type StoreType int

functions for correctly interacting with storage

- text file based operations? avoids gob, sqlite, etc

- private storage: (these filenames leak metadata...)

  • /keys/{age,minisign,onion}
  • /contacts/
  • /contacts.txt.age.minisign - private/unlisted contacts
  • /alice.phish.pub.age.minisign
  • /messages/
  • /alice.{inbox.age.minisign,outbox.age.minisign} - messages
  • /world/
  • /fingertable.age.minisign
  • /{fingerprint}.age.minisign - historical known combos of keys we discovered

- publish: (these file names are dirbustable...)

  • /onionsite.minisign - my onion site, signed, for reference
  • /phish.minisign - my keys
  • /delegate.minisign - NS delegation document - places where you can find me
  • /contacts/
  • /contacts.minisign - publicly listed contacts
  • /alice.phish.minisign
  • /dns/
  • /alice.phish.minisign - latest alice record signed by me
  • /alice.{delegate,revoke}.minisign - ticket from alice authorizing me to delegate
  • /messages/
  • /alice.inbox.age.minisign - my message to alice
  • /world/
  • /fingertable.minisign
  • /{fingerprint}.minisign - known fingerprints
const (
	AliasStore StoreType
	ContactStore
	WorldStore
	CarrierStore
	// key storage:
	KeyStore
	AgeStore
	MinisignStore
	// chats
	ChatStore
	// delegation
	DelegateStore
	NameserverStore
)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL