package main import ( "crypto" _ "crypto/sha1" "encoding/hex" "fmt" "math/rand" "time" ) func main() { g := Generator{ Difficulty: 26, } c := g.RandomChallenge() fmt.Println(c.String()) fmt.Println(c.Solve().String()) } type Challenge struct { Input [48]byte Date [20]byte Difficulty byte Solution int64 } type Generator struct { Difficulty byte } func (g *Generator) RandomChallenge() Challenge { bytes := make([]byte, 48) for i, _ := range bytes { bytes[i] = byte(rand.Int()) } today := time.Now().UTC() date := today.Format("2006-01-02") hash := crypto.SHA1.New().Sum([]byte(date)) return Challenge{ Input: [48]byte(bytes), Date: [20]byte(hash), Difficulty: g.Difficulty, } } // using a lookup table for this is super goofy but i'm lazy and it's 6am var prefixLookup = []int{ 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } func (c Challenge) Solve() Challenge { bytes := make([]byte, 76) bytes = append(bytes, c.Input[:]...) bytes = append(bytes, c.Date[:]...) for { for i := range 8 { bytes[75-i] = byte(c.Solution >> (i * 8)) } sum := make([]byte, 20) hash := crypto.SHA1.New() hash.Write(bytes) sum = hash.Sum(nil) count := 0 for _, c := range sum { p := prefixLookup[c] count += p if p != 8 { break } } if c.Solution%20000000 == 0 { println(c.Solution) } if count >= int(c.Difficulty) { println(c.Solution) break } c.Solution++ } return c } func (c Challenge) String() string { bytes := make([]byte, 0) bytes = append(bytes, c.Input[:]...) bytes = append(bytes, c.Date[:]...) bytes = append(bytes, make([]byte, 8)...) bytes[68] = c.Difficulty for i := range 7 { bytes[75-i] = byte(c.Solution >> (i * 8)) } return hex.EncodeToString(bytes) }