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:
- Take arbitrary amount of values.
- Combine them and add salt if there is one.
- Apply SHA-1 hashing to combined values and get its hexdigest.
- Apply XOR-Cipher to the hexdigest with desired key.
- Base64 encode the result.
CHK generator can be implemented like this:
Python
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 finalXOR 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
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 41274Python
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
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
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
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
Upload Multiplayer Comment
- AccountID
- Comment
- GameID
- Extra
Salts
| Value | Type |
|---|---|
| xI25fpAapCQg | Level |
| xPT6iUrtws0J | Comment |
| ysg6pUrtjn0J | Like or Rate |
| xI35fsAapCRg | User Profile |
| yPg6pUrtWn0J | Level Leaderboard |
