package cerberus import ( "context" "errors" "fmt" "io" "log" "net" "net/http" "net/http/cookiejar" "strings" "testing" "golang.org/x/net/proxy" ) const _TEST_HOST = "kiwifarms.st" const _TEST_ONION = "kiwifarmsaaf4t2h7gc3dfc5ojhmqruw2nit3uejrpiagrxeuxiyxcyd.onion" type errBadZeroCheck struct { Diff uint32 Hash []byte } func (e *errBadZeroCheck) Error() string { return fmt.Sprintf("Zero check failed. Diff: %d, Hash: %+v\n", e.Diff, e.Hash) } func solveTest(ctx context.Context, hc http.Client, host string) error { connType := "clearnet" if strings.HasSuffix(host, ".onion") { connType = "tor" } log.Printf("Fetching new %s challenge...", connType) c, err := NewChallenge(ctx, hc, host) if err != nil { return err } log.Printf("Challenge: %s, Difficulty: %d, Steps: %d\n", c.Salt, c.Diff, c.Steps) s, err := Solve(ctx, c) if err != nil { return err } log.Printf("Solution hash: %x, nonce: %d\n", s.Hash, s.Nonce) resp, err := Submit(ctx, hc, s, "") if err != nil { return err } defer resp.Body.Close() cookies := resp.Cookies() for _, ck := range cookies { log.Printf("Cookie: %s\n", ck.String()) } log.Print("Response: ") io.CopyN(log.Writer(), resp.Body, 128) fmt.Print("\n...\n") return nil } func newProxyTransport() *http.Transport { pcd := proxy.FromEnvironment().(proxy.ContextDialer) tr := http.DefaultTransport.(*http.Transport).Clone() tr.DialContext = pcd.DialContext return tr } func TestSolve(t *testing.T) { ctx := t.Context() jar, err := cookiejar.New(nil) if err != nil { t.Error(err) return } err = solveTest(ctx, http.Client{Jar: jar}, _TEST_HOST) if err != nil { t.Error(err) return } } func TestOnionSolve(t *testing.T) { ctx := t.Context() jar, err := cookiejar.New(nil) if err != nil { t.Error(err) return } err = solveTest(ctx, http.Client{ Jar: jar, Transport: newProxyTransport(), }, _TEST_ONION) if err != nil { if _, ok := errors.AsType[*net.DNSError](err); ok { log.Println("Unable to resolve .onion domain. Make sure ALL_PROXY is set and tor is running.") log.Println("Skipping...") return } t.Error(err) } } func TestCheckZeros(t *testing.T) { d, h := uint32(17), []byte{0, 0, 64, 128, 42} if !checkZeros(d, h) { t.Error(errBadZeroCheck{d, h}) } // This should fail (i.e. be false). d, h = uint32(3), []byte{33, 130, 222, 88} if checkZeros(d, h) { t.Error(errBadZeroCheck{d, h}) } }