home

How We Lost at The Delphi Oracle Challenge

Because the method — some messing around with the tezos-crypto library — could be useful to others.
Also, some code annotated in SVG.

Not that we (friends and I) put that much effort into this but the “how” can be useful to others: basically some quick and dirty use of the tezos-crypto OCaml library. We didn't get even close to the right solution, but this was also a good occasion to do some experiments with code annotated in SVG (!).

Checkout the challenge in the blog post by @chainofinsight: The Oracle of Delphi, a Tezos Puzzle. And, what most people got drawn to: the list of oracular statements from Delphi around 480 BC on Wikipedia.

Friends found the phrase “Pray to the Winds. They will prove to be mighty allies of Greece.” and had tried SmartPy's sp.test_account and Flextesa's deterministic key-pairs:

docker run --rm  tqtezos/flextesa:20200925 flextesa key-of-name "Pray to the Winds"

We thought we needed to find 32 bytes to create an Ed25519 private key — because of the 1 in tz1…… — cf. the implementation.

Myself had too much zoom-fatigue and too many preemptive slackterruptions to be able to read through “Greek mythology wikipedia” or to stare at an image, so did not notice any Bip39 word. But I was OK with spending a little time here and there hammering at the problem with some OCaml. So here it is.

I use dune utop src/lib_crypto/ in the Tezos repository to start utop and then use #use to load and run the script because I happen to always have those things available. But it should just work with opam install tezos-crypto; let me know if it doesn't.

The SVG experiment went like this:

highlight delphi-oracle.ml --src-lang=ocaml --inline-css -O html -o delphi-oracle.html

Then the HTML output was cleaned-up with libreoffice and exported to a PDF which was then imported into an Inkscape project. The build system of the blog then keeps calling inkscape with --export-plain-svg and we get:

image/svg+xml ;; #require "fmt" ;; #require "base" open Base let make metaseed = let of_seed seed = try let pkh , pk, sk = Tezos_crypto . Ed25519 .generate_key ~seed:( Bytes .of_string seed) () in Some ( seed, Tezos_crypto . Ed25519 . Public_key_hash .to_b58check pkh , Tezos_crypto . Ed25519 . Secret_key .to_b58check sk ) with _ -> None in let all = let clean = String .filter ~f:( function .’ | ‘ ‘ -> false | _ -> true ) in let odd s = let x = ref 0 in String .filter ~f:( function | _ when ! x % 2 = 1 -> Caml .incr x ; true | _ -> Caml .incr x ; false ) s in let even s = let x = ref 0 in String .filter ~f:( function | _ when ! x % 2 = 0 -> Caml .incr x ; true | _ -> Caml .incr x ; false ) s in let blake2b s = Tezos_crypto . Blake2B .hash_string [ s ] |> Tezos_crypto . Blake2B .to_string in let sha256 s = Tezos_crypto . Hacl . Hash . SHA256 .digest ( Bytes .of_string s) |> Bytes .to_string in let mirror s = s ^ String .rev s in List .filter_map ~f: of_seed [ metaseed; String .lowercase metaseed; String .uppercase metaseed; clean metaseed; String .lowercase ( clean metaseed); String .uppercase ( clean metaseed); odd metaseed; odd ( String .lowercase metaseed); even metaseed; even ( String .lowercase metaseed); blake2b metaseed; blake2b ( String .lowercase metaseed); blake2b ( String .uppercase metaseed); sha256 metaseed; sha256 ( String .lowercase metaseed); sha256 ( String .uppercase metaseed); String .rev metaseed; String .rev ( String .lowercase metaseed); String .rev ( String .uppercase metaseed); mirror metaseed; mirror ( String .lowercase metaseed); mirror ( String .uppercase metaseed); ] in let truth = "tz1V7rDn1uhSnGPnfj3ebuHS5nqjYEBU3QGF" in Fmt .pr "Metaseed: %S \n " metaseed; List .iter all ~f:( fun (seed, pkh , sk) -> Fmt .pr " %s %s ( %S , %d ) %s \n %!" pkh sk seed ( String .length seed) ( if String .equal truth pkh then failwith seed else "" )) let () = make "Pray to the Winds. They will prove to be mighty allies of Greece." ; make "Pray to the Winds. \n They will prove to be mighty allies of Greece." ; make "Pray to the Winds." ; make ": Pray to the Winds. They will prove to be mighty allies of Greece." ; make "They will prove to be mighty allies of Greece." ; () ;; #require "fmt" ;; #require "base" open Base let make metaseed = let of_seed seed = try let pkh , pk, sk = Tezos_crypto . Ed25519 .generate_key ~seed:( Bytes .of_string seed) () in Some ( seed, Tezos_crypto . Ed25519 . Public_key_hash .to_b58check pkh , Tezos_crypto . Ed25519 . Secret_key .to_b58check sk ) with _ -> None in let all = let clean = String .filter ~f:( function '.' | ' ' -> false | _ -> true ) in let odd s = let x = ref 0 in String .filter ~f:( function | _ when ! x % 2 = 1 -> Caml .incr x ; true | _ -> Caml .incr x ; false ) s in let even s = let x = ref 0 in String .filter ~f:( function | _ when ! x % 2 = 0 -> Caml .incr x ; true | _ -> Caml .incr x ; false ) s in let blake2b s = Tezos_crypto . Blake2B .hash_string [ s ] |> Tezos_crypto . Blake2B .to_string in let sha256 s = Tezos_crypto . Hacl . Hash . SHA256 .digest ( Bytes .of_string s) |> Bytes .to_string in let mirror s = s ^ String .rev s in List .filter_map ~f: of_seed [ metaseed; String .lowercase metaseed; String .uppercase metaseed; clean metaseed; String .lowercase ( clean metaseed); String .uppercase ( clean metaseed); odd metaseed; odd ( String .lowercase metaseed); even metaseed; even ( String .lowercase metaseed); blake2b metaseed; blake2b ( String .lowercase metaseed); blake2b ( String .uppercase metaseed); sha256 metaseed; sha256 ( String .lowercase metaseed); sha256 ( String .uppercase metaseed); String .rev metaseed; String .rev ( String .lowercase metaseed); String .rev ( String .uppercase metaseed); mirror metaseed; mirror ( String .lowercase metaseed); mirror ( String .uppercase metaseed); ] in let truth = "tz1V7rDn1uhSnGPnfj3ebuHS5nqjYEBU3QGF" in Fmt .pr "Metaseed: %S \n " metaseed; List .iter all ~f:( fun (seed, pkh , sk) -> Fmt .pr " %s %s ( %S , %d ) %s \n %!" pkh sk seed ( String .length seed) ( if String .equal truth pkh then failwith seed else "" )) let () = make "Pray to the Winds. They will prove to be mighty allies of Greece." ; make "Pray to the Winds. \n They will prove to be mighty allies of Greece." ; make "Pray to the Winds." ; make ": Pray to the Winds. They will prove to be mighty allies of Greece." ; make "They will prove to be mighty allies of Greece." ; () ;; #require "fmt" ;; #require "base" open Base let make metaseed = let of_seed seed = try let pkh , pk, sk = Tezos_crypto . Ed25519 .generate_key ~seed:( Bytes .of_string seed) () in Some ( seed, Tezos_crypto . Ed25519 . Public_key_hash .to_b58check pkh , Tezos_crypto . Ed25519 . Secret_key .to_b58check sk ) with _ -> None in let all = let clean = String .filter ~f:( function .’ | ‘ ‘ -> false | _ -> true ) in let odd s = let x = ref 0 in String .filter ~f:( function | _ when ! x % 2 = 1 -> Caml .incr x ; true | _ -> Caml .incr x ; false ) s in let even s = let x = ref 0 in String .filter ~f:( function | _ when ! x % 2 = 0 -> Caml .incr x ; true | _ -> Caml .incr x ; false ) s in let blake2b s = Tezos_crypto . Blake2B .hash_string [ s ] |> Tezos_crypto . Blake2B .to_string in let sha256 s = Tezos_crypto . Hacl . Hash . SHA256 .digest ( Bytes .of_string s) |> Bytes .to_string in let mirror s = s ^ String .rev s in List .filter_map ~f: of_seed [ metaseed; String .lowercase metaseed; String .uppercase metaseed; clean metaseed; String .lowercase ( clean metaseed); String .uppercase ( clean metaseed); odd metaseed; odd ( String .lowercase metaseed); even metaseed; even ( String .lowercase metaseed); blake2b metaseed; blake2b ( String .lowercase metaseed); blake2b ( String .uppercase metaseed); sha256 metaseed; sha256 ( String .lowercase metaseed); sha256 ( String .uppercase metaseed); String .rev metaseed; String .rev ( String .lowercase metaseed); String .rev ( String .uppercase metaseed); mirror metaseed; mirror ( String .lowercase metaseed); mirror ( String .uppercase metaseed); ] in let truth = "tz1V7rDn1uhSnGPnfj3ebuHS5nqjYEBU3QGF" in Fmt .pr "Metaseed: %S \n " metaseed; List .iter all ~f:( fun (seed, pkh , sk) -> Fmt .pr " %s %s ( %S , %d ) %s \n %!" pkh sk seed ( String .length seed) ( if String .equal truth pkh then failwith seed else "" )) let () = make "Pray to the Winds. They will prove to be mighty allies of Greece." ; make "Pray to the Winds. \n They will prove to be mighty allies of Greece." ; make "Pray to the Winds." ; make ": Pray to the Winds. They will prove to be mighty allies of Greece." ; make "They will prove to be mighty allies of Greece." ; () My standard imports, on top oftezos-crypto. The metaseed is the input “phrase” — See the `let ()` at the end. We care about a public-key-hash (tz1..)and a secret-key compatible with tezos-client;both using a base58check encoding. We are looking for a tz1 address, hence Ed25519. Create a key-pair in the most obviousway for a given seed string.It only uses the first 32 bytes, butfails with less of them. We build the list of “all” seed candidates from the metaseed.Then follows a list of functions making seeds out of strings … Dumbest quick-and-dirty “take the odd/even characters”implementations. Hash functions like Blake2B or SHA256 seemed nice because theybring the size of the seed to a constant; moreover that soundedlike something some wallet software could have done to get a keyfrom a passphrase … Shoot out to formally verified crypto-primitives! A list of seeds & the function string → account option. The address we were looking for. We interrupt the search on success. A few of the phrases that we tried, in vain :) Those to_string functions are not for human-readable;it's just the OCaml string type, as a byte-array.

After 8 years of blograstination, this is post #10 of my attempt at using the #100DaysToOffload completely unrealistic “challenge” to remind me to write stuff once in a while … Let's see where this goes.