#!/usr/bin/python3 from dreamtown_config import * import sys import os import json import sqlite3 import time import hashlib import random # # Bassed off https://github.com/MrBlinky/Tamagotchi-friends-code-generator # # MIT License # # Copyright (c) 2021 Mr.Blinky # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. passwordchars1 = "0123456789ABCDEF" passwordchars2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0" namechars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ " namechars_xor = [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xA0] checksum_xor = [0x11, 0x32, 0x53, 0x74, 0x15, 0x36, 0x58, 0x77, 0x29, 0x4F, 0x6E, 0x0D, 0x2C, 0x4B, 0x6A, 0x7F] step3count_xor = [0x57, 0x3A] nameorder = [6, 8, 10, 7, 9, 13, 11, 12] #digit order of name characters step13count_add = [[1, 2, 3, 4, 5, 6, 7, 8], [2, 3, 4, 5, 6, 7, 8, 1], [3, 4, 5, 6, 7, 8, 1, 2], [4, 5, 6, 7, 8, 1, 2, 3], [5, 6, 7, 8, 1, 2, 3, 4], [6, 7, 8, 1, 2, 3, 4, 5], [7, 2, 1, 2, 3, 4, 5, 6], [8, 1, 2, 3, 4, 5, 6, 7]] print("Content-Type: application/json") print("") content_len = int(os.environ["CONTENT_LENGTH"]) post = sys.stdin.read(content_len) jsonData = json.loads(post) result = {"status":SUCCESS} method = os.environ["REQUEST_METHOD"] if method != "POST": print("Expected POST") os._exit() def GetTamaName(tama_id): if tama_id >= len(tamagotchi) or tama_id < 0: return "Unknown #"+str(tama_id) tamaName = tamagotchi[tama_id] if tamaName == "": tamaName = "Unknown #"+str(tama_id) return tamaName def InputValidation(password): if len(password) != 14: return False for i in range(0,6): if passwordchars1.find(password[i]) == -1: return False for i in range(6,14): if passwordchars2.find(password[i]) == -1: return False return True def GetItem(special): #check item input if not special: itemType = random.randrange(0, 2) else: itemType = random.randrange(2, 6) itemId = random.randrange(0, 30) if itemType == 0: pass if itemType == 1: itemId += 30; else: if itemId > 14: itemId = 14; itemId += (itemType-2) * 15; itemType = 2; return [itemId, itemType] def GetName(password, stepCount): name = ''; for i in range(0,8): #get user name c = passwordchars2.find(password[nameorder[i]]) - step13count_add[stepCount][i]; if c < 0: c += 0x1B; name += namechars[c]; return name def TryGet(): authToken = jsonData['authToken'] c = db.cursor() cur = c.execute('SELECT COUNT(1) from users WHERE LastSession=?',(authToken,)) rows = cur.fetchone() count = rows[0] if count == 0: result['status'] = USER_DOES_NOT_EXIST return 0 #validate loginPassword = jsonData["code"].upper() ticketNumber = jsonData['ticketNumber'] if not InputValidation(loginPassword): result['status'] = 2 # code invalid return 0 #decode checksum = passwordchars1.find(loginPassword[0]) step13count = passwordchars1.find(loginPassword[1]) >> 1 step3count = passwordchars1.find(loginPassword[1]) & 1 name = GetName(loginPassword, step13count) #login data for decoding and checksum verifying logindata = [ (passwordchars1.find(loginPassword[4]) << 4) | passwordchars1.find(loginPassword[5]), (passwordchars1.find(loginPassword[2]) << 4) | passwordchars1.find(loginPassword[3]), ((namechars.find(name[1]) & 0x3) << 6) | namechars.find(name[0]), ((namechars.find(name[2]) & 0xF) << 4) | (namechars.find(name[1]) >> 2), (namechars.find(name[3]) << 2) | (namechars.find(name[2]) >> 4), ((namechars.find(name[5]) & 0x3) << 6) | namechars.find(name[4]), ((namechars.find(name[6]) & 0xF) << 4) | (namechars.find(name[5]) >> 2), (namechars.find(name[7]) << 2) | (namechars.find(name[6]) >> 4), (passwordchars1.find(loginPassword[0]) << 4) | passwordchars1.find(loginPassword[1]) ] # step 3 counter xoring logindata[0] ^= step3count_xor[step3count] logindata[1] ^= step3count_xor[step3count] #name xor logindata[0] ^= namechars_xor[namechars.find(name[1])]; logindata[1] ^= namechars_xor[namechars.find(name[3])]; #checksum xor logindata[0] ^= checksum_xor[checksum]; logindata[1] ^= checksum_xor[checksum]; # Check checksum c = 0; for i in range(0, 17): if (i & 1) == 1: c -= (logindata[i >> 1] >> 4); else: c -= (logindata[i >> 1] & 0xF); if (c & 0xF) != checksum: result['status'] = 2 # code invalid return 0 tama_id = logindata[0] & 0x3F step7count = logindata[1] >> 4; device_id = (logindata[0] >> 6) | ((logindata[1] & 0xF) << 2); special = False if ticketNumber > 1: special = True itemResult = GetItem(special) itemId = itemResult[0] itemType = itemResult[1] #create logout data logoutdata = [ logindata[0], logindata[1] | 0x80, itemId, (step3count << 3) | itemType ] checksum = (0 - (logoutdata[1] >> 4) - (logoutdata[1] & 0xF) - (logoutdata[0] >> 4) - (logoutdata[0] & 0xF) - (logoutdata[2] >> 4) - (logoutdata[2] & 0xF) - (logoutdata[3] & 0xF)) & 0XF; #xor checksum for i in range(0,3): logoutdata[i] ^= checksum_xor[checksum]; #player name xoring logoutdata[0] ^= namechars_xor[namechars.find(name[1])]; logoutdata[1] ^= namechars_xor[namechars.find(name[3])]; logoutdata[2] ^= namechars_xor[namechars.find(name[5])]; #step 3 counter xoring for i in range(0,3): logoutdata[i] ^= step3count_xor[step3count]; logoutPassword = '%X%X%X%X%X%X%X%X' % ( logoutdata[1] >> 4, logoutdata[1] & 0xF, logoutdata[0] >> 4, logoutdata[0] & 0xF, checksum , logoutdata[3] & 0xF, logoutdata[2] >> 4, logoutdata[2] & 0xF) result["code"] = logoutPassword try: db = sqlite3.connect(SQLLITE_DB_PATH) TryGet() db.commit() db.close() except Exception as e: print(e) os._exit() print(json.dumps(result))