Skip to content
This repository has been archived by the owner on Dec 15, 2018. It is now read-only.

Commit

Permalink
Merge pull request #142 from ZeChrales/master
Browse files Browse the repository at this point in the history
Incoming break-fix. API 0.43.3.
  • Loading branch information
keyphact authored Nov 6, 2016
2 parents 3a02e74 + cf0db6a commit 1a11287
Show file tree
Hide file tree
Showing 17 changed files with 192 additions and 74 deletions.
5 changes: 2 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ __pycache__/
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
Expand All @@ -15,7 +14,6 @@ dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
Expand Down Expand Up @@ -89,4 +87,5 @@ ENV/
.ropeproject

# Personal load details
config.json
config.json
/.idea
Binary file added pgoapi/lib/encrypt32.dll
Binary file not shown.
Binary file added pgoapi/lib/encrypt64.dll
Binary file not shown.
11 changes: 11 additions & 0 deletions pgoapi/lib/howto_compile.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
: https://github.com/laverdet/pcrypt-c
Thanks a lot to @marcel
use "make all"


https://gist.github.com/ZeChrales/28373120d41829d8e4cd3bdc959cb275
Thanks a lot to @Waryas
Linux :
cc -fPIC -shared -o libnhash.so libnhash.c
Windows :
oh plz !
Binary file added pgoapi/lib/libencrypt-freebsd-64.so
Binary file not shown.
Binary file added pgoapi/lib/libencrypt-linux-x86-64.so
Binary file not shown.
Binary file added pgoapi/lib/libencrypt-osx-64.so
Binary file not shown.
Binary file added pgoapi/lib/libniantichash-freebsd-64.so
Binary file not shown.
Binary file added pgoapi/lib/libniantichash-linux-x86-64.so
Binary file not shown.
Binary file added pgoapi/lib/libniantichash-osx-64.so
Binary file not shown.
Binary file added pgoapi/lib/niantichash32.dll
Binary file not shown.
Binary file added pgoapi/lib/niantichash64.dll
Binary file not shown.
30 changes: 24 additions & 6 deletions pgoapi/pgoapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
from pgoapi.rpc_api import RpcApi
from pgoapi.auth_ptc import AuthPtc
from pgoapi.auth_google import AuthGoogle
from pgoapi.utilities import parse_api_endpoint
from pgoapi.utilities import parse_api_endpoint, get_encryption_lib_paths
from pgoapi.exceptions import AuthException, NotLoggedInException, ServerBusyOrOfflineException, NoPlayerPositionSetException, EmptySubrequestChainException, AuthTokenExpiredException, ServerApiEndpointRedirectException, UnexpectedResponseException

from . import protos
Expand All @@ -60,6 +60,7 @@ def __init__(self, provider=None, oauth2_refresh_token=None, username=None, pass
self._position_alt = position_alt

self._signature_lib = None
self._hash_lib = None

self._session = requests.session()
self._session.headers.update({'User-Agent': 'Niantic App'})
Expand Down Expand Up @@ -126,12 +127,25 @@ def create_request(self):
self._position_alt, self.device_info)
return request

def activate_signature(self, lib_path):
self._signature_lib = lib_path
def activate_signature(self, signature_lib_path=None, hash_lib_path=None):
raise Exception("activate_signature is deprecated, binaries compatible with 0.41 API are now required." +
"\r\n Comment out all calls to activate_signature to let them be autodetected. " +
"\r\n Use set_signature_lib and set_hash_lib to override if needed.")
# if signature_lib_path: self.set_signature_lib(signature_lib_path)
# if hash_lib_path: self.set_hash_lib(hash_lib_path)

def set_signature_lib(self, signature_lib_path):
self._signature_lib = signature_lib_path

def set_hash_lib(self, hash_lib_path):
self._hash_lib = hash_lib_path

def get_signature_lib(self):
return self._signature_lib

def get_hash_lib(self):
return self._hash_lib

def __getattr__(self, func):
def function(**kwargs):
request = self.create_request()
Expand Down Expand Up @@ -227,9 +241,13 @@ def call(self):
request = RpcApi(self._auth_provider, self.device_info)
request._session = self.__parent__._session

lib_path = self.__parent__.get_signature_lib()
if lib_path is not None:
request.activate_signature(lib_path)
signature_lib_path = self.__parent__.get_signature_lib()
hash_lib_path = self.__parent__.get_hash_lib()
if signature_lib_path is None or hash_lib_path is None:
default_libraries = get_encryption_lib_paths()
if not signature_lib_path: signature_lib_path = default_libraries[0]
if not hash_lib_path: hash_lib_path = default_libraries[1]
request.activate_signature(signature_lib_path, hash_lib_path)

self.log.info('Execution of RPC')
response = None
Expand Down
47 changes: 23 additions & 24 deletions pgoapi/rpc_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,17 @@
import requests
import subprocess
import six
import binascii
import ctypes

from google.protobuf import message

from importlib import import_module


import ctypes

from pgoapi.protobuf_to_dict import protobuf_to_dict
from pgoapi.exceptions import NotLoggedInException, ServerBusyOrOfflineException, ServerSideRequestThrottlingException, ServerSideAccessForbiddenException, UnexpectedResponseException, AuthTokenExpiredException, ServerApiEndpointRedirectException
from pgoapi.utilities import to_camel_case, get_time, get_format_time_diff, Rand48, long_to_bytes, generate_location_hash_by_seed, generate_location_hash, generate_request_hash, f2i
from pgoapi.utilities import to_camel_case, get_time, get_format_time_diff, Rand48, long_to_bytes, f2i, \
HashGenerator

from . import protos
from POGOProtos.Networking.Envelopes.RequestEnvelope_pb2 import RequestEnvelope
Expand All @@ -68,6 +68,7 @@ def __init__(self, auth_provider, device_info):
# mystical unknown6 - resolved by PokemonGoDev
self._signal_agglom_gen = False
self._signature_lib = None
self._hash_engine = None

if RpcApi.START_TIME == 0:
RpcApi.START_TIME = get_time(ms=True)
Expand All @@ -79,10 +80,11 @@ def __init__(self, auth_provider, device_info):

self.device_info = device_info

def activate_signature(self, lib_path):
def activate_signature(self, signature_lib_path, hash_lib_path):
try:
self._signal_agglom_gen = True
self._signature_lib = ctypes.cdll.LoadLibrary(lib_path)
self._signature_lib = ctypes.cdll.LoadLibrary(signature_lib_path)
self._hash_engine = HashGenerator(hash_lib_path)
except:
raise

Expand Down Expand Up @@ -122,6 +124,7 @@ def _make_rpc(self, endpoint, request_proto_plain):
self.log.debug('Execution of RPC')

request_proto_serialized = request_proto_plain.SerializeToString()
#print binascii.hexlify(request_proto_serialized)
try:
http_response = self._session.post(endpoint, data=request_proto_serialized, timeout=30)
except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e:
Expand Down Expand Up @@ -208,11 +211,11 @@ def _build_main_request(self, subrequests, player_position=None):
if self._signal_agglom_gen:
sig = SignalAgglomUpdates()

sig.location_hash_by_token_seed = generate_location_hash_by_seed(ticket_serialized, request.latitude, request.longitude, request.accuracy)
sig.location_hash = generate_location_hash(request.latitude, request.longitude, request.accuracy)
sig.location_hash_by_token_seed = self._hash_engine.generate_location_hash_by_seed(ticket_serialized, request.latitude, request.longitude, request.accuracy)
sig.location_hash = self._hash_engine.generate_location_hash(request.latitude, request.longitude, request.accuracy)

for req in request.requests:
hash = generate_request_hash(ticket_serialized, req.SerializeToString())
hash = self._hash_engine.generate_request_hash(ticket_serialized, req.SerializeToString())
sig.request_hashes.append(hash)

sig.field22 = self.session_hash
Expand Down Expand Up @@ -275,7 +278,7 @@ def _build_main_request(self, subrequests, player_position=None):
sen.gravity_z = random.triangular(-1, .7, -0.8)
sen.status = 3

sig.field25 = 7363665268261373700
sig.field25 = ctypes.c_uint64(-8408506833887075802).value

if self.device_info:
for key in self.device_info:
Expand All @@ -288,7 +291,7 @@ def _build_main_request(self, subrequests, player_position=None):
signal_agglom_proto = sig.SerializeToString()

sig_request = SendEncryptedSignatureRequest()
sig_request.encrypted_signature = self._generate_signature(signal_agglom_proto)
sig_request.encrypted_signature = self._generate_signature(signal_agglom_proto, sig.timestamp_ms_since_start)
plat = request.platform_requests.add()
plat.type = 6
plat.request_message = sig_request.SerializeToString()
Expand All @@ -299,20 +302,16 @@ def _build_main_request(self, subrequests, player_position=None):

return request

def _generate_signature(self, signature_plain, lib_path="encrypt.so"):
if self._signature_lib is None:
self.activate_signature(lib_path)
self._signature_lib.argtypes = [ctypes.c_char_p, ctypes.c_size_t, ctypes.c_char_p, ctypes.c_size_t, ctypes.POINTER(ctypes.c_ubyte), ctypes.POINTER(ctypes.c_size_t)]
def _generate_signature(self, signature_plain, iv):
self._signature_lib.argtypes = [ctypes.c_char_p, ctypes.c_size_t, ctypes.c_char_p, ctypes.POINTER(ctypes.POINTER(ctypes.c_ubyte))]
self._signature_lib.restype = ctypes.c_int

iv = os.urandom(32)

output_size = ctypes.c_size_t()

self._signature_lib.encrypt(signature_plain, len(signature_plain), iv, 32, None, ctypes.byref(output_size))
output = (ctypes.c_ubyte * output_size.value)()
self._signature_lib.encrypt(signature_plain, len(signature_plain), iv, 32, ctypes.byref(output), ctypes.byref(output_size))
signature = b''.join(list(map(lambda x: six.int2byte(x), output)))
rounded_size = len(signature_plain) + (256 - (len(signature_plain) % 256));
total_size = rounded_size + 5;
output = ctypes.POINTER(ctypes.c_ubyte * total_size)()
#print binascii.hexlify(signature_plain)
output_size = self._signature_lib.encrypt(signature_plain, len(signature_plain), iv, ctypes.byref(output))
#print binascii.hexlify(output.contents)
signature = b''.join(list(map(lambda x: six.int2byte(x), output.contents)))
return signature

def _build_sub_requests(self, mainrequest, subrequest_list):
Expand Down
Loading

0 comments on commit 1a11287

Please sign in to comment.