Skip to content

CHK

CHK is a common parameter in requests, which is intended to improve security. CHK is sent in request often as chk.

CHK is generated like so:

  1. Take arbitrary amount of values.
  2. Combine them and add salt if there is one.
  3. Apply SHA-1 hashing to combined values and get its hexdigest.
  4. Apply XOR-Cipher to the hexdigest with desired key.
  5. Base64 encode the result.

CHK generator can be implemented like this:

Python

py
import base64
import hashlib  # sha1() lives there


def generate_chk(values: [int, str] = [], key: str = "", salt: str = "") -> str:
    values.append(salt)

    string = ("").join(map(str, values))  # assure "str" type and connect values

    hashed = hashlib.sha1(string.encode()).hexdigest()
    xored = xor_cipher(hashed, key)  # we discuss this one in encryption/xor
    final = base64.urlsafe_b64encode(xored.encode()).decode()

    return final

XOR keys can be found here.

Here is a list of CHK values and explanations on their generation:

Download level

Upload level

  • seed2

seed2 is generated from level data:

Pseudocode

plain
seed2 = ""
space = length of levelString / 50

for i in range 50:
    seed2 += levelString[space * i]
   
seed2 += "xI25fpAapCQg"
sha1 encode seed2
xor encrypt seed2 with key 41274

Python

py
def generate_upload_seed(data: str, chars: int = 50) -> str:
    # GD currently uses 50 characters for level upload seed
    if len(data) < chars:
        return data  # not enough data to generate
    step = len(data) // chars
    return data[::step][:chars]

Upload list

  • seed

Seed is generated by taking the listLevel and obtaining 50 characters the same way as for uploading a level (see above), then appending your account ID to it, then taking a SHA-1 hash of that, then XOR encrypting with the randomly generated seed2 value and Base64 URL-Safe encoding it.

Comment

  • Username
  • Comment Content
  • LevelID
  • Percentage
  • Comment Type (0 = Level, 1 = User).

Challenges

  • Random Number

Random number consisting of 5 digits.

Rewards

  • Random Number

Random number consisting of 5 digits.

Like

  • Special (0 = Level, LevelID = Level Comment, CommentID = Other Comment)
  • ItemID
  • Like (0 = dislike, 1 = like)
  • Type (1 = Level, 2 = Level Comment, 3 = Other Comment)
  • RS
  • AccountID
  • UDID
  • "UUID" (player/user ID, different from the account ID)

Rate

  • LevelID
  • Stars
  • RS
  • AccountID
  • UDID
  • "UUID" (player/user ID, different from the account ID)

User Profile

  • AccountID
  • UserCoins
  • Demons
  • Stars
  • Coins
  • IconType
  • Icon
  • Diamonds
  • CubeID
  • ShipID
  • BallID
  • UFOID
  • WaveID
  • RobotID
  • Glow (0 = disabled, 1 = enabled)
  • SpiderID
  • ExplosionID
  • Length of dinfo
  • dinfow
  • dinfog
  • sinfo
  • sinfod
  • sinfog

Level Leaderboard

  • AccountID
  • LevelID
  • Percentage
  • Jumps
  • Attempts
  • Seed

Seed for classic levels can be generated like this:

Python

py
def generate_classic_leaderboard_seed(
    jumps: int, percentage: int, seconds: int, has_played: bool = True
) -> int:

    return (
        1482 * (has_played + 1)
        + (jumps + 3991) * (percentage + 8354)
        + ((seconds + 4085) ** 2) - 50028039
    )

For platformer levels:

Python

py
def generatePlatformerHash(bestTime, bestPoints):
  number = (((bestTime + 7890) % 34567) * 601 + ((abs(bestPoints) + 3456) % 78901) * 967 + 94819) % 94433
  return ((number ^ number >> 16) * 829) % 77849
  • Best Differences

For example, 0% - 13% - 100% -> (13 - 0), (100 - 13) -> 13,87

  • Unknown (always 1)

  • Coins

  • TimelyID

  • RS

Upload Multiplayer Comment

  • AccountID
  • Comment
  • GameID
  • Extra

Salts

ValueType
xI25fpAapCQgLevel
xPT6iUrtws0JComment
ysg6pUrtjn0JLike or Rate
xI35fsAapCRgUser Profile
yPg6pUrtWn0JLevel Leaderboard