Skip to content
This repository was archived by the owner on May 4, 2023. It is now read-only.

Commit 4fa978b

Browse files
Add client ID as per androidacy spec
Signed-off-by: androidacy-user <opensource@androidacy.com>
1 parent 0339dd7 commit 4fa978b

File tree

9 files changed

+78
-69
lines changed

9 files changed

+78
-69
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@
99
.cxx
1010
local.properties
1111
sentry.properties
12+
androidacy.properties

app/build.gradle

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ android {
2828
debug {
2929
applicationIdSuffix '.debug'
3030
debuggable true
31+
3132
// ONLY FOR TESTING SENTRY
3233
// minifyEnabled true
3334
// shrinkResources true
@@ -44,6 +45,10 @@ android {
4445
buildConfigField("java.util.List<String>",
4546
"ENABLED_REPOS",
4647
"java.util.Arrays.asList(\"magisk_alt_repo\", \"androidacy_repo\")",)
48+
// Get the androidacy client ID from the androidacy.properties
49+
Properties properties = new Properties()
50+
properties.load(project.rootProject.file('androidacy.properties').newDataInputStream())
51+
buildConfigField("String", "ANDROIDACY_CLIENT_ID", properties.getProperty('client_id'))
4752
}
4853

4954
fdroid {
@@ -63,6 +68,11 @@ android {
6368
buildConfigField("java.util.List<String>",
6469
"ENABLED_REPOS",
6570
"java.util.Arrays.asList(\"magisk_alt_repo\")",)
71+
72+
// Get the androidacy client ID from the androidacy.properties
73+
Properties properties = new Properties()
74+
properties.load(project.rootProject.file('androidacy.properties').newDataInputStream())
75+
buildConfigField("String", "ANDROIDACY_CLIENT_ID", properties.getProperty('client_id'))
6676
}
6777
}
6878

@@ -154,14 +164,6 @@ configurations {
154164
}
155165

156166
dependencies {
157-
// Big scary fingerprinting library
158-
// Actually, just used to generate device ID for androidacy (they use it for fraud detection)
159-
implementation "com.fingerprint.android:pro:2.2.1"
160-
implementation "com.github.fingerprintjs:fingerprint-android:2.0.0"
161-
162-
// If you use Java for you project, add also this line
163-
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
164-
165167
// UI
166168
implementation 'androidx.appcompat:appcompat:1.5.1'
167169
implementation 'androidx.emoji2:emoji2:1.2.0'

app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyActivity.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import java.io.File;
4242
import java.io.FileOutputStream;
4343
import java.io.IOException;
44+
import java.security.NoSuchAlgorithmException;
4445
import java.util.HashMap;
4546

4647
/**
@@ -106,7 +107,11 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
106107
String device_id = uri.getQueryParameter("device_id");
107108
if (device_id == null) {
108109
// get from shared preferences
109-
device_id = AndroidacyRepoData.generateDeviceId();
110+
try {
111+
device_id = AndroidacyRepoData.generateDeviceId();
112+
} catch (NoSuchAlgorithmException e) {
113+
e.printStackTrace();
114+
}
110115
url = url + "&device_id=" + device_id;
111116
}
112117
boolean allowInstall = intent.getBooleanExtra(Constants.EXTRA_ANDROIDACY_ALLOW_INSTALL, false);

app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyRepoData.java

Lines changed: 52 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
11
package com.fox2code.mmm.androidacy;
22

3-
import android.content.Context;
43
import android.content.SharedPreferences;
54
import android.os.Looper;
65
import android.util.Log;
76
import android.widget.Toast;
87

98
import androidx.annotation.NonNull;
109

11-
import com.fingerprintjs.android.fingerprint.Fingerprinter;
12-
import com.fingerprintjs.android.fingerprint.FingerprinterFactory;
13-
import com.fingerprintjs.android.fpjs_pro.Configuration;
14-
import com.fingerprintjs.android.fpjs_pro.FingerprintJS;
15-
import com.fingerprintjs.android.fpjs_pro.FingerprintJSFactory;
1610
import com.fox2code.mmm.BuildConfig;
1711
import com.fox2code.mmm.MainApplication;
1812
import com.fox2code.mmm.R;
@@ -24,13 +18,16 @@
2418
import com.fox2code.mmm.utils.HttpException;
2519
import com.fox2code.mmm.utils.PropUtils;
2620
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
21+
import com.topjohnwu.superuser.Shell;
2722

2823
import org.json.JSONArray;
2924
import org.json.JSONException;
3025
import org.json.JSONObject;
3126

3227
import java.io.File;
3328
import java.io.IOException;
29+
import java.security.MessageDigest;
30+
import java.security.NoSuchAlgorithmException;
3431
import java.util.ArrayList;
3532
import java.util.Iterator;
3633
import java.util.List;
@@ -48,6 +45,9 @@ public final class AndroidacyRepoData extends RepoData {
4845
OK_HTTP_URL_BUILDER.build();
4946
}
5047

48+
@SuppressWarnings("unused")
49+
public final String ClientID = BuildConfig.ANDROIDACY_CLIENT_ID;
50+
5151
private final boolean testMode;
5252
private final String host;
5353
public String token = MainApplication.getINSTANCE().getSharedPreferences("androidacy", 0).getString("pref_androidacy_api_token", null);
@@ -84,42 +84,57 @@ private static String filterURL(String url) {
8484

8585
// Generates a unique device ID. This is used to identify the device in the API for rate
8686
// limiting and fraud detection.
87-
public static String generateDeviceId() {
87+
public static String generateDeviceId() throws NoSuchAlgorithmException {
8888
// Try to get the device ID from the shared preferences
8989
SharedPreferences sharedPreferences = MainApplication.getINSTANCE().getSharedPreferences("androidacy", 0);
9090
String deviceIdPref = sharedPreferences.getString("device_id", null);
9191
if (deviceIdPref != null) {
9292
return deviceIdPref;
9393
} else {
94-
Context context = MainApplication.getINSTANCE().getApplicationContext();
95-
FingerprintJSFactory factory = new FingerprintJSFactory(context);
96-
Configuration.Region region = Configuration.Region.US;
97-
Configuration configuration = new Configuration(
98-
"NiZiHi266YaTLreOIOzc",
99-
region,
100-
region.getEndpointUrl(),
101-
true
102-
);
103-
104-
FingerprintJS fpjsClient = factory.createInstance(
105-
configuration
106-
);
107-
108-
fpjsClient.getVisitorId(visitorIdResponse -> {
109-
// Use the ID
110-
String visitorId = visitorIdResponse.getVisitorId();
111-
// Save the ID in the shared preferences
112-
SharedPreferences.Editor editor = sharedPreferences.edit();
113-
editor.putString("device_id", visitorId);
114-
editor.apply();
115-
return null;
116-
});
117-
// return the id
118-
return sharedPreferences.getString("device_id", null);
94+
// AAAA we're fingerprintiiiiing
95+
// Really not that scary - just hashes some device info. We can't even get the info
96+
// we originally hashed, so it's not like we can use it to track you.
97+
String deviceId = null;
98+
// Get ro.serialno if it exists
99+
// First, we need to get an su shell
100+
Shell.Result result = Shell.cmd("getprop ro.serialno").exec();
101+
// Check if the command was successful
102+
if (result.isSuccess()) {
103+
// Get the output
104+
String output = result.getOut().get(0);
105+
// Check if the output is valid
106+
if (output != null && !output.isEmpty()) {
107+
deviceId = output;
108+
}
109+
}
110+
// Now, get device model, manufacturer, and Android version
111+
String deviceModel = android.os.Build.MODEL;
112+
String deviceManufacturer = android.os.Build.MANUFACTURER;
113+
String androidVersion = android.os.Build.VERSION.RELEASE;
114+
// Append it all together
115+
deviceId += deviceModel + deviceManufacturer + androidVersion;
116+
// Hash it
117+
MessageDigest digest = MessageDigest.getInstance("SHA-256");
118+
byte[] hash = digest.digest(deviceId.getBytes());
119+
// Convert it to a hex string
120+
StringBuilder hexString = new StringBuilder();
121+
for (byte b : hash) {
122+
String hex = Integer.toHexString(0xff & b);
123+
if (hex.length() == 1) {
124+
hexString.append('0');
125+
}
126+
hexString.append(hex);
127+
}
128+
// Save it to shared preferences
129+
SharedPreferences.Editor editor = sharedPreferences.edit();
130+
editor.putString("device_id", hexString.toString());
131+
editor.apply();
132+
// Return it
133+
return hexString.toString();
119134
}
120135
}
121136

122-
public boolean isValidToken(String token) throws IOException {
137+
public boolean isValidToken(String token) throws IOException, NoSuchAlgorithmException {
123138
String deviceId = generateDeviceId();
124139
try {
125140
Http.doHttpGet("https://" + this.host + "/auth/me?token=" + token + "&device_id=" + deviceId, false);
@@ -139,23 +154,8 @@ public boolean isValidToken(String token) throws IOException {
139154
}
140155

141156
@Override
142-
protected boolean prepare() {
157+
protected boolean prepare() throws NoSuchAlgorithmException {
143158
if (Http.needCaptchaAndroidacy()) return false;
144-
// Check if we have a device ID yet
145-
SharedPreferences sharedPreferences = MainApplication.getINSTANCE().getSharedPreferences("androidacy", 0);
146-
String deviceIdPref = sharedPreferences.getString("device_id", null);
147-
if (deviceIdPref == null) {
148-
// Generate a device ID
149-
generateDeviceId();
150-
// Loop until we have a device ID
151-
while (sharedPreferences.getString("device_id", null) == null) {
152-
try {
153-
Thread.sleep(100);
154-
} catch (InterruptedException e) {
155-
e.printStackTrace();
156-
}
157-
}
158-
}
159159
// Implementation details discussed on telegram
160160
// First, ping the server to check if it's alive
161161
try {
@@ -240,7 +240,7 @@ protected boolean prepare() {
240240
}
241241

242242
@Override
243-
protected List<RepoModule> populate(JSONObject jsonObject) throws JSONException {
243+
protected List<RepoModule> populate(JSONObject jsonObject) throws JSONException, NoSuchAlgorithmException {
244244
if (!jsonObject.getString("status").equals("success"))
245245
throw new JSONException("Response is not a success!");
246246
String name = jsonObject.optString("name", "Androidacy Modules Repo");
@@ -353,12 +353,12 @@ public boolean tryLoadMetadata(RepoModule repoModule) {
353353
}
354354

355355
@Override
356-
public String getUrl() {
356+
public String getUrl() throws NoSuchAlgorithmException {
357357
return this.token == null ? this.url :
358358
this.url + "?token=" + this.token + "&v=" + BuildConfig.VERSION_CODE + "&c=" + BuildConfig.VERSION_NAME + "&device_id=" + generateDeviceId();
359359
}
360360

361-
private String injectToken(String url) {
361+
private String injectToken(String url) throws NoSuchAlgorithmException {
362362
// Do not inject token for non Androidacy urls
363363
if (!AndroidacyUtil.isAndroidacyLink(url)) return url;
364364
if (this.testMode) {

app/src/main/java/com/fox2code/mmm/repo/CustomRepoData.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import java.io.File;
1111
import java.io.IOException;
1212
import java.nio.charset.StandardCharsets;
13+
import java.security.NoSuchAlgorithmException;
1314

1415
public final class CustomRepoData extends RepoData {
1516
boolean loadedExternal;
@@ -30,7 +31,7 @@ public String getPreferenceId() {
3031
this.id : this.override;
3132
}
3233

33-
public void quickPrePopulate() throws IOException, JSONException {
34+
public void quickPrePopulate() throws IOException, JSONException, NoSuchAlgorithmException {
3435
JSONObject jsonObject = new JSONObject(
3536
new String(Http.doHttpGet(this.getUrl(),
3637
false), StandardCharsets.UTF_8));

app/src/main/java/com/fox2code/mmm/repo/RepoData.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.io.File;
2222
import java.io.IOException;
2323
import java.nio.charset.StandardCharsets;
24+
import java.security.NoSuchAlgorithmException;
2425
import java.util.ArrayList;
2526
import java.util.HashMap;
2627
import java.util.Iterator;
@@ -81,11 +82,11 @@ protected RepoData(String url, File cacheRoot, SharedPreferences cachedPreferenc
8182
}
8283
}
8384

84-
protected boolean prepare() {
85+
protected boolean prepare() throws NoSuchAlgorithmException {
8586
return true;
8687
}
8788

88-
protected List<RepoModule> populate(JSONObject jsonObject) throws JSONException {
89+
protected List<RepoModule> populate(JSONObject jsonObject) throws JSONException, NoSuchAlgorithmException {
8990
List<RepoModule> newModules = new ArrayList<>();
9091
synchronized (this.populateLock) {
9192
String name = jsonObject.getString("name").trim();
@@ -215,7 +216,7 @@ public void updateEnabledState() {
215216
.getBoolean("pref_" + this.getPreferenceId() + "_enabled", this.isEnabledByDefault());
216217
}
217218

218-
public String getUrl() {
219+
public String getUrl() throws NoSuchAlgorithmException {
219220
return this.url;
220221
}
221222

app/src/main/java/com/fox2code/mmm/settings/SettingsActivity.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
import org.json.JSONException;
6868

6969
import java.io.IOException;
70+
import java.security.NoSuchAlgorithmException;
7071
import java.util.HashSet;
7172
import java.util.Objects;
7273
import java.util.Random;
@@ -615,7 +616,7 @@ public void onCreatePreferencesAndroidacy() {
615616
boolean valid = false;
616617
try {
617618
valid = AndroidacyRepoData.getInstance().isValidToken(apiKey);
618-
} catch (IOException ignored) {}
619+
} catch (IOException | NoSuchAlgorithmException ignored) {}
619620
// If the key is valid, save it
620621
if (valid) {
621622
originalApiKeyRef[0] = apiKey;
@@ -715,7 +716,7 @@ public void updateCustomRepoList(boolean initial) {
715716
public void run() {
716717
try {
717718
customRepoData.quickPrePopulate();
718-
} catch (IOException | JSONException e) {
719+
} catch (IOException | JSONException | NoSuchAlgorithmException e) {
719720
Log.e(TAG, "Failed to preload repo values", e);
720721
}
721722
UiThreadHandler.handler.post(() -> updateCustomRepoList(false));

build.gradle

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ buildscript {
44
google()
55
mavenCentral()
66
gradlePluginPortal()
7-
maven { url 'https://maven.fpregistry.io/releases' }
87
maven { url 'https://jitpack.io' }
98
}
109
project.ext.latestAboutLibsRelease = "10.5.0"

settings.gradle

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ dependencyResolutionManagement {
66
maven {
77
url 'https://jitpack.io'
88
}
9-
maven { url 'https://maven.fpregistry.io/releases' }
109
}
1110
}
1211
rootProject.name = "MagiskModuleManager"

0 commit comments

Comments
 (0)