What is this?

This is an annual "puzzle/ctf" contest that takes place at Thotcon. The winner of the Token.WTF challenge recieves a super fancy, inspirational, brag-worthy, and just plain-old-cool GOLD lifetime Thotcon badge.

This is not your typical puzzle contest. These challenges are hastily thrown together lovingly designed to take you outside of your comfort zone. There is no veneer cypher. You will not pop shells. There is no "jeopardy board" or bonus points for being first. Naught-Days will buy you nothing. APT is a package manager and CRYPTO means cryptography.

You will work with an API. You will hopefully end up writing some code or a script, if just to make things easier. You might scratch your head at some point and think to yourself: "Wait... What!?!" At the end of these techno-shenanigans, we hope you have enjoyed yourself and learned something new.

HEY! Hints and announcements will be made on twitter. Go follow @tokenwtf. There may be an meme.

How To Register

curl -vv -X POST \
  --header 'Content-Type: application/json' \
  -d '{"email": "user@example.com", "name": "Your name"}' \
  https://api.token.wtf/register

If successful, the token.wtf API will generate and return a set of API credentials. The response will look like the following:

{
    "credentials": {
        "admin": false,
        "api_key": "0e8de90abbfbc176",
        "api_secret": "f1a86f2be04ea46b2b667e7d"
    },
    "registration": {
        "email": "foo",
        "name": "bar"
    }
}

WARNING: This is the only time you will recieve this information. You will need the api_key and api_secret to participate in the challenges. Treat these two peices of information like a username and password. These identifiers are used to authenticate against the token.wtf API.

Making API Calls

As a user of the token.wtf services, you have two identifying peices of information; your api_key and your api_secret. Authenticated API requests require two HTTP headers to be present on every request: token-wtf-key and token-wtf-signature.

token-wtf-key is just your api_key. Example: token-wtf-key: 0e8de90abbfbc176

token-wtf-signature is a little more complicated, but not much so.

Building a canonical request

To build a canonical request take the following peices of information and join them with a newline.

  • host (lowercase)
  • URL (lowercase)
  • Your API key
  • request body

Example:

api.token.wtf
/foo/bar
0e8de90abbfbc176

Note: if there is no request body (because you are making a GET request) just use an empty string. You'll still need that last newline

Building a request signature

Once you have the canonical request, you need to generate the signature. psuedo-code: encode_as_hex(sha256_hmac($API_SECRET, $CANONICAL_REQUEST))

Create a SHA256 HMAC signature, using your api_secret as the key, and the canonical request as the contents. You should make sure the HMAC signature is encoded as hex, not binary.

Heres actual example Ruby code to generate a signature:

require 'openssl'
api_key = "ux71iiJKhRvYWJCc"
secret_key = "gLHsxBG4n2Ik8sdm1GJbP9L5WFrYAHy0"

url = "/foo/bar"
host = "api.token.wtf"
digest = OpenSSL::Digest.new('sha256')
req_body = ""
canonical_request = "#{host}
#{url}
#{api_key}
#{req_body}
"

signature = OpenSSL::HMAC.hexdigest(digest, secret_key, canonical_request)
puts "token-wtf-signature: #{signature}"

The API

Note When making POST requests to the token.wtf API, all contents must be supplied as JSON. Due to this, all requests containing a request body must correctly specify the content type as application/json.


💰claim a token

POST /token/:token_id/claim

auth required

Required data:

token_id
The token to claim. This is in the URL, not the JSON
api_key
The api_key you wish to award the token to

Example request body:

{
    "api_key": "ux71iiJKhRvYWJCc"
}

Example response body:

{
    "api_key": "ux71iiJKhRvYWJCc",
    "token_id": "8e1f2634-30cd-436d-98cb-2b37755a7006",
    "claimed_at": "timestamp"
}


🤔verify a token

GET /token/:token_id

auth required

Required data:

token_id
The token to claim. This is in the URL.

Example response body:

{
    "token": "8e1f2634-30cd-436d-98cb-2b37755a7006",
    "value": 5,
    "type": 0
}


📈check the score

GET /score

no auth required

Example response body:

????