func main() {
	key := []byte("key")
	msg := []byte("The quick brown fox jumps over the lazy dog")
	s := util.HMacSha1(key, msg)
	expected, _ := hex.DecodeString("de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9")
	if bytes.Compare(s, expected) != 0 {
		log.Fatalf("expected %x, got %x sign", expected, s)
	}

	sign := make([]byte, 20)
	_, averageTime := getStatus(sign)
	succTime := 0.0
	for i := 0; i < len(sign); i++ {
		expected := float64(i+1) * succTime * 0.95
		fmt.Println("expected:", expected)
		for b := byte(0); b <= 255; b++ {
			sign[i] = b
			status, elapsed := getStatus(sign)
			fmt.Printf("%d %x %f %f\n", status, sign, elapsed, averageTime)
			if succTime == 0.0 {
				if elapsed > averageTime*4 {
					succTime = elapsed
					fmt.Println("delay for success byte:", succTime)
					break
				}
				averageTime = (elapsed + averageTime) / 2
			} else {
				if elapsed > expected {
					break
				}
			}
		}
	}
}
func response(w http.ResponseWriter, r *http.Request) {
	q := r.URL.Query()
	fmt.Println(r.URL.Path, q)
	file, ok := q["file"]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		io.WriteString(w, "file parameter is missing")
		return
	}
	sign, ok := q["signature"]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		io.WriteString(w, "signature parameter is missing")
		return
	}
	// fmt.Println(file[0], sign[0])
	clientSign, err := hex.DecodeString(sign[0])
	if err != nil {
		io.WriteString(w, "sign is not hex encoded!")
		return
	}
	serverSign := util.HMacSha1(key, []byte(file[0]))
	same := insecureSame(clientSign, serverSign)
	if same {
		w.WriteHeader(http.StatusOK)
	} else {
		w.WriteHeader(http.StatusInternalServerError)
	}
	// fmt.Printf("%x %x -> %t\n", clientSign, serverSign, same)
}
func main() {
	key := []byte("key")
	msg := []byte("The quick brown fox jumps over the lazy dog")
	s := util.HMacSha1(key, msg)
	expected, _ := hex.DecodeString("de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9")
	if bytes.Compare(s, expected) != 0 {
		log.Fatalf("expected %x, got %x sign", expected, s)
	}

	sign := make([]byte, 20)

	avg := average(sign, 100)
	fmt.Println("avg:", avg)

	succTime := 0.0
	for i := 0; i < len(sign); i++ {
		expected := float64(i+1) * (succTime - avg)
		found := false
		fmt.Printf("%d bytes expected: %f\n", i+1, expected)
		var max float64
		var ch byte
		for b := 0; b < 256; b++ {
			sign[i] = byte(b)
			status, elapsed := getStatus(sign)
			//fmt.Printf("%d %x %f\n", status, sign, elapsed)
			if elapsed > max {
				max = elapsed
				ch = byte(b)
			}
			if succTime == 0.0 {
				if elapsed > avg*2 {
					elapsed := average(sign, 5)
					fmt.Printf("%d %x took %f\n", status, sign, elapsed)
					succTime = elapsed
					fmt.Printf("delay for success byte: %f\n\n", succTime)
					found = true
					break
				}
			} else {
				if elapsed > expected {
					prev := elapsed
					elapsed := average(sign, 5)
					if elapsed > expected {
						fmt.Printf("%d %x took %f\n", status, sign, elapsed)
						succTime = (elapsed/float64(i+1) + succTime) / 2
						fmt.Printf("delay for success byte: %f\n\n", succTime)
						found = true
						break
					} else {
						fmt.Printf("... false positive %x: %f -> %f\n", b, prev, elapsed)
						continue
					}
				}
			}
		}
		if !found {
			// let's try the best char in position i so far
			fmt.Printf("resorting to the best char %x: %f...\n", ch, max)
			sign[i] = ch
			status, _ := getStatus(sign)
			elapsed := average(sign, 10)
			fmt.Printf("%d %x took %f\n", status, sign, elapsed)
			succTime = (elapsed/float64(i+1) + succTime) / 2
			fmt.Printf("delay for success byte: %f\n\n", succTime)
		}
	}
}