import hashlib import json import os import sys from collections import OrderedDict from subprocess import check_call, check_output # WARNING: changing those affects reproducibility GO_ROOT = '/tmp/go' GO_PATH = '/tmp/go-path' NDK_DIR = 'android-ndk' def get_version(): if len(sys.argv) > 2: fail("Usage: %s [version tag]" % sys.argv[0]) return sys.argv[1] if len(sys.argv) > 1 else None def get_version_and_tool(): if len(sys.argv) < 2 or len(sys.argv) > 3: fail("Usage: %s tool [version tag]" % sys.argv[0]) tool = sys.argv[1] command_line_version = sys.argv[2] if len(sys.argv) > 2 else None return tool, command_line_version def get_build_versions(tool, tag): # load versions and their dependencies with open('versions.json', 'r') as f: versions = json.load(f, object_pairs_hook=OrderedDict) if tag is None: # take top-most version tag = next(iter(versions[tool])) return tag, versions[tool][tag] def check_go_version(versions): # Check if proper Go version is installed (trailing space, because 'go1.10' in 'go1.10.1') if versions['go']['version'] + ' ' not in check_output(['go', 'version']).decode("UTF-8"): fail("You need Go version %s to reproduce this binary" % versions['go']['version']) def ex(args, env=None, cwd=None): print("+ %s" % " ".join(args)) check_call(args, env=env, cwd=cwd) def fail(msg=""): sys.stderr.write("Error: %s\n" % msg) sys.exit(1) def get_sha256(filename, block_size=65536): sha256 = hashlib.sha256() with open(filename, 'rb') as f: for block in iter(lambda: f.read(block_size), b''): sha256.update(block) return sha256.hexdigest() def reset_time(file_name): check_call(['touch', '--no-dereference', '-t', '197001010000.00', file_name]) def zip_files(files, zip_name): for file_name in files: reset_time(file_name) # use deterministic permissions to prevent differences in zip files os.chmod(file_name, 0o755) sha256hash = get_sha256(file_name) print("Hash before zipping %s: %s" % (file_name, sha256hash)) ex(['zip', '-D', '-X', zip_name] + files) def get_obfs4_version(versions): version = versions['revision'] if '-' in version: return version.split('-')[1] return version def get_file_suffix(versions, android=False): version = get_obfs4_version(versions) return "%s-%s" % ("android", version) if android else version def get_final_file_name(versions, android=False): return 'obfs4proxy-%s.zip' % get_file_suffix(versions, android) def get_sources_file_name(versions, android=False): return 'obfs4proxy-%s-sources.jar' % get_file_suffix(versions, android) def get_pom_file_name(versions, android=False): return 'obfs4proxy-%s.pom' % get_file_suffix(versions, android)