diff --git a/README.md b/README.md
index 402a37ab92c74535e6a919493116cc003f732348..4ca040d27fdbb02f72faacb6e39f19285e4275ea 100644
--- a/README.md
+++ b/README.md
@@ -68,8 +68,12 @@ Note that this will not work if the issue is caused by an updated Debian package
 
 ### Historical changes
 
+Versions before 0.4.7.13-1 used a different format for the published artifacts.
+Please use the version of tor-reproducer tagged `0.4` to reproduce those.
+
 The Tor 0.3.x series had a different build system than the 0.4.x series.
-Please use a version of tor-reproducer that starts with 0.3 to reproduce those.
+Please use a version of tor-reproducer with a tag that starts with `0.3` to
+reproduce those.
 
 ### Only build Tor
 
diff --git a/build_tor_android.py b/build_tor_android.py
index 3fd75dae334c3c86bd0ebbcfe1815aff4d0aa158..8f16b245b9bf5d62ff865e1ab1f5fcbe2a8ab862 100755
--- a/build_tor_android.py
+++ b/build_tor_android.py
@@ -4,7 +4,7 @@ from shutil import rmtree, move, copy
 from subprocess import check_call
 
 import utils
-from utils import get_sha256, fail, BUILD_DIR, get_output_dir, reset_time
+from utils import get_sha256, fail, BUILD_DIR, get_output_dir, reset_time, pack, create_pom_file
 
 NDK_DIR = 'android-ndk'
 PLATFORM = "android"
@@ -61,57 +61,61 @@ def build_android(versions):
     os.environ.pop("PIEFLAGS", None)
 
     # build arm pie
+    app_abi = 'armeabi-v7a'
     env = os.environ.copy()
-    env['APP_ABI'] = "armeabi-v7a"
+    env['APP_ABI'] = app_abi
     env['NDK_PLATFORM_LEVEL'] = "16"  # first level supporting PIE
-    build_android_arch('tor_arm_pie.zip', env, versions)
+    build_android_arch(app_abi, env, versions)
 
     # build arm64 pie
+    app_abi = 'arm64-v8a'
     env = os.environ.copy()
-    env['APP_ABI'] = "arm64-v8a"
+    env['APP_ABI'] = app_abi
     env['NDK_PLATFORM_LEVEL'] = "21"  # first level supporting 64-bit
-    build_android_arch('tor_arm64_pie.zip', env, versions)
+    build_android_arch(app_abi, env, versions)
 
     # build x86 pie
+    app_abi = 'x86'
     env = os.environ.copy()
-    env['APP_ABI'] = "x86"
+    env['APP_ABI'] = app_abi
     env['NDK_PLATFORM_LEVEL'] = "16"  # first level supporting PIE
-    build_android_arch('tor_x86_pie.zip', env, versions)
+    build_android_arch(app_abi, env, versions)
 
     # build x86_64 pie
+    app_abi = 'x86_64'
     env = os.environ.copy()
-    env['APP_ABI'] = "x86_64"
+    env['APP_ABI'] = app_abi
     env['NDK_PLATFORM_LEVEL'] = "21"  # first level supporting 64-bit
-    build_android_arch('tor_x86_64_pie.zip', env, versions)
+    build_android_arch(app_abi, env, versions)
 
 
-def build_android_arch(name, env, versions):
-    print("Building %s" % name)
+def build_android_arch(app_abi, env, versions):
+    print("Building Tor for Android %s" % app_abi)
     output_dir = get_output_dir(PLATFORM)
     # TODO add extra flags to configure?
     #  '--enable-static-tor',
     #  '--enable-static-zlib',
     check_call(['make', 'clean', 'tor'], cwd=BUILD_DIR, env=env)
-    tor_path = os.path.join(output_dir, 'tor')
+    arch_dir = os.path.join(output_dir, app_abi)
+    os.mkdir(arch_dir)
+    tor_path = os.path.join(arch_dir, 'libtor.so')
     # note: stripping happens in makefile for now
     copy(os.path.join(BUILD_DIR, 'tor', 'src', 'app', 'tor'), tor_path)
     reset_time(tor_path, versions)
-    print("Sha256 hash of tor before zipping %s: %s" % (name, get_sha256(tor_path)))
-    check_call(['zip', '--no-dir-entries', '--junk-paths', '-X', name, 'tor'], cwd=output_dir)
-    os.remove(tor_path)
+    print("Sha256 hash of Tor for Android %s: %s" % (app_abi, get_sha256(tor_path)))
 
 
 def package_android(versions, jar_name):
     # zip binaries together
     output_dir = get_output_dir(PLATFORM)
     file_list = [
-        os.path.join(output_dir, 'tor_arm_pie.zip'),
-        os.path.join(output_dir, 'tor_arm64_pie.zip'),
-        os.path.join(output_dir, 'tor_x86_pie.zip'),
-        os.path.join(output_dir, 'tor_x86_64_pie.zip'),
+        os.path.join(output_dir, 'armeabi-v7a', 'libtor.so'),
+        os.path.join(output_dir, 'arm64-v8a', 'libtor.so'),
+        os.path.join(output_dir, 'x86', 'libtor.so'),
+        os.path.join(output_dir, 'x86_64', 'libtor.so'),
     ]
-    zip_name = utils.pack(versions, file_list, PLATFORM)
-    pom_name = utils.create_pom_file(versions, PLATFORM)
+    zip_name = pack(versions, file_list, PLATFORM)
+    pom_name = create_pom_file(versions, PLATFORM)
     print("%s:" % PLATFORM)
     for file in file_list + [zip_name, jar_name, pom_name]:
         sha256hash = get_sha256(file)
diff --git a/build_tor_linux.py b/build_tor_linux.py
index 23b8c09bb11325c3883b09f2197f0bf4ce51bbab..d99752e7896b47fbdd399aca9eaaea204e430a3b 100755
--- a/build_tor_linux.py
+++ b/build_tor_linux.py
@@ -25,8 +25,7 @@ def build_linux(versions):
 
 
 def build_linux_arch(arch, gcc_arch, cc_env, openssl_target, autogen_host, versions):
-    name = "tor_linux-%s.zip" % arch
-    print("Building %s" % name)
+    print("Building Tor for Linux %s" % arch)
     prefix_dir = os.path.abspath(os.path.join(BUILD_DIR, 'prefix'))
     lib_dir = os.path.join(prefix_dir, 'lib')
     include_dir = os.path.join(prefix_dir, 'include')
@@ -113,24 +112,24 @@ def build_linux_arch(arch, gcc_arch, cc_env, openssl_target, autogen_host, versi
                 ] + TOR_CONFIGURE_FLAGS, cwd=tor_dir, env=env)
     check_call(['make', '-j', str(os.cpu_count()), 'install'], cwd=tor_dir, env=env)
 
-    # copy and zip built Tor binary
+    # copy built Tor binary
     output_dir = get_output_dir(PLATFORM)
-    tor_path = os.path.join(output_dir, 'tor')
+    arch_dir = os.path.join(output_dir, arch)
+    os.mkdir(arch_dir)
+    tor_path = os.path.join(arch_dir, 'tor')
     copy(os.path.join(BUILD_DIR, 'tor', 'src', 'app', 'tor'), tor_path)
     check_call(['strip', '-D', tor_path])
     reset_time(tor_path, versions)
-    print("Sha256 hash of tor before zipping %s: %s" % (name, get_sha256(tor_path)))
-    check_call(['zip', '--no-dir-entries', '--junk-paths', '-X', name, 'tor'], cwd=output_dir)
-    os.remove(tor_path)
+    print("Sha256 hash of Tor for Linux %s: %s" % (arch, get_sha256(tor_path)))
 
 
 def package_linux(versions, jar_name):
     # zip binaries together
     output_dir = get_output_dir(PLATFORM)
     file_list = [
-        os.path.join(output_dir, 'tor_linux-aarch64.zip'),
-        os.path.join(output_dir, 'tor_linux-armhf.zip'),
-        os.path.join(output_dir, 'tor_linux-x86_64.zip'),
+        os.path.join(output_dir, 'aarch64', 'tor'),
+        os.path.join(output_dir, 'armhf', 'tor'),
+        os.path.join(output_dir, 'x86_64', 'tor'),
     ]
     zip_name = pack(versions, file_list, PLATFORM)
     pom_name = create_pom_file(versions, PLATFORM)
diff --git a/build_tor_windows.py b/build_tor_windows.py
index 20468824d50d45e032f6714df1ac14fa8a1e242c..9a2f219f6eaf610af38eede133d1c51285e6e559 100755
--- a/build_tor_windows.py
+++ b/build_tor_windows.py
@@ -5,7 +5,7 @@ from subprocess import check_call
 
 import utils
 from utils import BUILD_DIR, get_output_dir, TOR_CONFIGURE_FLAGS, OPENSSL_CONFIGURE_FLAGS, REPRODUCIBLE_GCC_CFLAGS, \
-    XZ_CONFIGURE_FLAGS, reset_time, get_sha256
+    XZ_CONFIGURE_FLAGS, reset_time, get_sha256, pack, create_pom_file
 
 PLATFORM = "windows"
 
@@ -23,8 +23,7 @@ def build_windows(versions):
 
 
 def build_windows_arch(arch, host, versions):
-    name = "tor_windows-%s.zip" % arch
-    print("Building %s" % name)
+    print("Building Tor for Windows %s" % arch)
     prefix_dir = os.path.abspath(os.path.join(BUILD_DIR, 'prefix'))
     lib_dir = os.path.join(prefix_dir, 'lib')
     include_dir = os.path.join(prefix_dir, 'include')
@@ -115,28 +114,28 @@ def build_windows_arch(arch, host, versions):
     check_call(['make', '-j', str(os.cpu_count())], cwd=tor_dir, env=env)
     check_call(['make', 'install'], cwd=tor_dir, env=env)
 
-    # copy and zip built Tor binary
+    # copy built Tor binary
     output_dir = get_output_dir(PLATFORM)
-    tor_path = os.path.join(output_dir, 'tor')
+    arch_dir = os.path.join(output_dir, arch)
+    os.mkdir(arch_dir)
+    tor_path = os.path.join(arch_dir, 'tor.exe')
     copy(os.path.join(prefix_dir, 'bin', 'tor.exe'), tor_path)
     check_call(['strip', '-D', tor_path])
     reset_time(tor_path, versions)
-    print("Sha256 hash of tor before zipping %s: %s" % (name, get_sha256(tor_path)))
-    check_call(['zip', '--no-dir-entries', '--junk-paths', '-X', name, 'tor'], cwd=output_dir)
-    os.remove(tor_path)
+    print("Sha256 hash of Tor for Windows %s: %s" % (arch, get_sha256(tor_path)))
 
 
 def package_windows(versions, jar_name):
     # zip binaries together
     output_dir = get_output_dir(PLATFORM)
     file_list = [
-        os.path.join(output_dir, 'tor_windows-x86_64.zip'),
+        os.path.join(output_dir, 'x86_64', 'tor.exe'),
     ]
-    zip_name = utils.pack(versions, file_list, PLATFORM)
-    pom_name = utils.create_pom_file(versions, PLATFORM)
+    zip_name = pack(versions, file_list, PLATFORM)
+    pom_name = create_pom_file(versions, PLATFORM)
     print("%s:" % PLATFORM)
     for file in file_list + [zip_name, jar_name, pom_name]:
-        sha256hash = utils.get_sha256(file)
+        sha256hash = get_sha256(file)
         print("%s: %s" % (file, sha256hash))
 
 
diff --git a/tor-versions.json b/tor-versions.json
index 0fff6e2d566b7bb5284df12410b26c19bf66145a..b7caac32c5a0db7720eab0b09329a7fe72148c74 100644
--- a/tor-versions.json
+++ b/tor-versions.json
@@ -1,4 +1,36 @@
 {
+  "0.4.7.13-1": {
+    "tor": {
+      "url": "https://gitlab.torproject.org/tpo/core/tor.git",
+      "commit": "tor-0.4.7.13"
+    },
+    "libevent": {
+      "url": "https://github.com/libevent/libevent.git",
+      "commit": "release-2.1.12-stable"
+    },
+    "openssl": {
+      "url": "https://github.com/openssl/openssl.git",
+      "commit": "OpenSSL_1_1_1s"
+    },
+    "xz": {
+      "url": "https://git.tukaani.org/xz.git",
+      "commit": "v5.2.10"
+    },
+    "zlib": {
+      "url": "https://github.com/madler/zlib.git",
+      "commit": "v1.2.12"
+    },
+    "zstd": {
+      "url": "https://github.com/facebook/zstd.git",
+      "commit": "v1.4.9"
+    },
+    "ndk": {
+      "url": "https://dl.google.com/android/repository/android-ndk-r21e-linux-x86_64.zip",
+      "revision": "21.4.7075529",
+      "sha256": "ad7ce5467e18d40050dc51b8e7affc3e635c85bd8c59be62de32352328ed467e"
+    },
+    "timestamp": "201001010000.00"
+  },
   "0.4.7.13": {
     "tor": {
       "url": "https://gitlab.torproject.org/tpo/core/tor.git",
diff --git a/utils.py b/utils.py
index 63315957aa38303eb97d4744899651a64afb8969..c0abdb8072308fbd4b97e23bd28bf2407f97832e 100644
--- a/utils.py
+++ b/utils.py
@@ -172,7 +172,10 @@ def pack(versions, file_list, platform):
     for filename in file_list:
         reset_time(filename, versions)
     zip_name = get_final_file_name(versions, platform)
-    check_call(['zip', '--no-dir-entries', '--junk-paths', '-X', zip_name] + file_list)
+    # use platform_dir as the root of the zip paths
+    platform_dir = get_output_dir(platform)
+    relative_file_list = [os.path.relpath(filename, start=platform_dir) for filename in file_list]
+    check_call(['zip', '--no-dir-entries', '-X', zip_name] + relative_file_list, cwd=platform_dir)
     return zip_name