Skip to content
Switch branches/tags
Go to file
Cannot retrieve contributors at this time
# This source file is part of mc3p, the Minecraft Protocol Parsing Proxy.
# This program is free software. It comes without any warranty, to
# the extent permitted by applicable law. You can redistribute it
# and/or modify it under the terms of the Do What The Fuck You Want
# To Public License, Version 2, as published by Sam Hocevar. See
# for more details
import requests
import sys
import os
from time import time
from hashlib import sha1
from struct import unpack
from encryption import encode_public_key, PBEWithMD5AndDES
class Authenticator(object):
VERSION = 1337
def __init__(self, username, password):
self.user = username
self.password = password
self._session = None
self._login_time = 0
def check(self):
"""Checks if the credentials are valid"""
return self._get_session_id() is not None
def join_server(self, server_id, shared_secret, public_key):
r = requests.get(self.SESSION_URL,
params={'user': self.player_name(),
'sessionId': self._get_session_id(),
'serverId': self.login_hash(server_id,
def player_name(self):
if self._get_session() is None:
return None
return self._get_session()[2]
def _get_session(self):
"""Authenticates a player"""
if self._session is None or self._login_time < time() - 50:
r =,
data={'user': self.user,
'password': self.password,
'version': self.VERSION})
if r.ok and len(r.content.split(":")) >= 4:
self._session = r.content.split(":")
self._login_time = time()
return self._session
def _get_session_id(self):
if self._get_session() is None:
return None
return self._get_session()[3].strip()
def check_player(cls, username, server_id, shared_secret, public_key):
"""Checks if a user is allowed to join the server."""
return cls._check_player(username, cls.login_hash(server_id,
def _check_player(cls, username, session_hash):
r = requests.get(cls.CHECK_SESSION_URL,
params={'user': username, 'serverId': session_hash})
return r.ok and r.content.strip() == "YES"
def login_hash(server_id, shared_secret, public_key):
"""Returns the server id which is then used for joining a server"""
digest = sha1()
d = long(digest.hexdigest(), 16)
if d >> 39 * 4 & 0x8:
return "-%x" % ((-d) & (2 ** (40 * 4) - 1))
return "%x" % d
def minecraft_credentials():
path = os.path.join(_minecraft_folder(), "lastlogin")
with open(path) as f:
ciphertext =
except IOError:
return None
plaintext = PBEWithMD5AndDES('passwordfile').decrypt(ciphertext)
user_size = unpack(">h", plaintext[:2])[0]
user = plaintext[2:user_size + 2]
password_size = unpack(">h", plaintext[2 + user_size:4 + user_size])[0]
password = plaintext[4 + user_size:]
return user, password
def _minecraft_folder():
"""Finds the folder minecraft stores the account credentials in.
Copyright (c) 2010 David Rio Vierra
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
if sys.platform == "win32":
import win32com.client
objShell = win32com.client.Dispatch("WScript.Shell")
appDataDir = objShell.SpecialFolders("AppData")
except Exception, e:
from import shell, shellcon
appDataDir = shell.SHGetPathFromIDListEx(
shell.SHGetSpecialFolderLocation(0, shellcon.CSIDL_APPDATA)
except Exception, e:
appDataDir = os.environ['APPDATA'].decode(
minecraftDir = os.path.join(appDataDir, u".minecraft")
elif sys.platform == "darwin":
appDataDir = os.path.expanduser(u"~/Library/Application Support")
minecraftDir = os.path.join(appDataDir, u"minecraft")
appDataDir = os.path.expanduser(u"~")
minecraftDir = os.path.expanduser(u"~/.minecraft")
return minecraftDir
if __name__ == "__main__":
print minecraft_credentials()