Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use of SHA-1 to verify integrity of downloaded files #1284

Open
lenerd opened this issue Feb 18, 2025 · 3 comments
Open

Use of SHA-1 to verify integrity of downloaded files #1284

lenerd opened this issue Feb 18, 2025 · 3 comments
Labels

Comments

@lenerd
Copy link
Contributor

lenerd commented Feb 18, 2025

Hi,

I saw this recent commit 74c85c4 and noticed that the documentation page on how to "Verify-APK-is-genuine" recommends to compare the SHA-1 hash of the APK certificate against the hash stated in the documentation.

SHA-1 is not a collision-resistant hash function. It is practically feasible to find two inputs that have the same SHA-1 hash. Collision resistance is crucial to verify that you have downloaded the genuine APK. If an attacker manages it to craft a bogus certificate that has the same hash as the honest one, you cannot tell the difference by looking at the hash.1

Therefore, it is recommended to use a cryptographic hash function that is still considered secure such as the SHA-2 and SHA-3 families of hash functions. See, e.g., Table 4.1 and Remark 4.2 on page 44 of the BSI recommendations.

A code search on GitHub shows a few places, where SHA-1 is used in this repository:

  • 1. GitHub APK: dQAnHXvlh80yJgrQUCo6LAg4294=
    2. F-Droid APK: nyupq9aU0x6yK8RHaPra5GbTqQY=
    3. Google Play APK: dQAnHXvlh80yJgrQUCo6LAg4294=
    Here is a quick way of getting the certificate hash out of an APK file on Linux:
    * keytool -printcert -jarfile "/path/to/release.apk" | grep "SHA1: " | cut -d " " -f 3 | xxd -r -p | openssl base64
  • NDK_EXPECTED_SHASUM_LINUX = '5e5cd517bdb98d7e0faf2c494a3041291e71bdcc'
    NDK_EXPECTED_SHASUM_WINDOWS = '0ea2756e6815356831bda3af358cce4cdb6a981e'
  • When these hashes are compared later on, the error message falsely claims they are SHA-256 hashes:
    # Verify SHA-1 checksum of downloaded files.
    with open(zip_fullfn, 'rb') as f:
    contents = f.read()
    found_shasum = hashlib.sha1(contents).hexdigest()
    print("SHA-1:", zip_fullfn, "%s" % found_shasum)
    if found_shasum != expected_shasum:
    fail('Error: SHA-256 checksum ' + found_shasum + ' of downloaded file does not match expected checksum ' + expected_shasum)
    print("[ok] Checksum of", zip_fullfn, "matches expected value.")
  • if 'SHA1: ' in result_line:
    result_hex = result_line.replace('SHA1: ', '')
    result_hex_cleaned = re.sub('[^A-Fa-f0-9]+', '', result_hex)
    result_hash = codecs.encode(codecs.decode(result_hex_cleaned, 'hex'), 'base64').decode('utf-8')
    result_hash = result_hash.strip('\n')
    except Exception as e:
    print('[WARN] Failed to parse keytool result: ' + str(e));
    return None
    release_types = {
    "2ScaPj41giu4vFh+Y7Q0GJTqwbA=": "GitHub",
    "nyupq9aU0x6yK8RHaPra5GbTqQY=": "F-Droid",
    "dQAnHXvlh80yJgrQUCo6LAg4294=": "Google Play"

PS: Is there a reason for Base64? Usually I see hashes encoded in hex. Maybe B64 is more common in the Android/Java world? Just being curious.

Footnotes

  1. The actual task that an attacker has to perform is harder than finding a collision (i.e., finding two arbitrary files with the same hash). It needs to break second-preimage resistance (i.e., finding a file that has the same hash a given genuine file). This is however no reason to still use SHA-1.

@Catfriend1
Copy link
Owner

Hi,

Thanks for the information. Feel free to PR a change to hash generation in scripts and the hashes provided in the docs to improve out situation.

@lenerd
Copy link
Contributor Author

lenerd commented Feb 18, 2025

Well, even if I make the changes, you should double check that I put the right hashes there and not blindly trust a random stranger from the internet.
Then I don't know where I would get the APK hashes from. Download them from the three platforms and compute them myself?
Also, since the mentioned commit, the GitHub hashes in postbuild.py and the Verify-APK-is-genuine file are inconsistent.

@Catfriend1
Copy link
Owner

@lenerd The only thing from my perspective we need to care about here is this file from every release tag:
https://github.com/Catfriend1/syncthing-android/releases/download/v1.29.2.0/com.github.catfriend1.syncthingandroid_github_v1.29.2.0_0232b1df.apk

F-Droid offers its own checksum: https://github.com/Catfriend1/syncthing-android/releases/download/v1.29.2.0/com.github.catfriend1.syncthingandroid_fdroid_1290200.apk.asc.pgp

Just hash my uploaded apk and change accordingly :-).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants