Using [GitHub] skylot/jadx to decompile My StarHub app, I started digging through the source code.
There are 3 parts to this documentation
-
How StarHub encrypts/decrypt the plaintext password and hub id email to the local SQLite DB (Android)
-
How StarHub encrypts/decrypt the plaintext password for HTTPS request payload
-
Implementing the algorithm in Python
import java.security.Key;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public static String encrypt(String str) throws Exception {
byte[] bytes = "2eobgrwapapifsxa".getBytes();
AlgorithmParameterSpec ivParameterSpec = new IvParameterSpec("jsfkew4plc20mnds".getBytes());
Key secretKeySpec = new SecretKeySpec(bytes, "AES");
Cipher instance = Cipher.getInstance("AES/CBC/PKCS5Padding");
instance.init(1, secretKeySpec, ivParameterSpec); // 1: ENCRYPT_MODE
return Base64.encodeToString(instance.doFinal(str.getBytes()), 0);
}
public static String decrypt(String str) throws Exception {
byte[] bytes = "2eobgrwapapifsxa".getBytes();
AlgorithmParameterSpec ivParameterSpec = new IvParameterSpec("jsfkew4plc20mnds".getBytes());
Key secretKeySpec = new SecretKeySpec(bytes, "AES");
Cipher instance = Cipher.getInstance("AES/CBC/PKCS5Padding");
instance.init(2, secretKeySpec, ivParameterSpec); // 2: DECRYPT_MODE
return new String(instance.doFinal(Base64.decode(str, 0)));
}
This part involves 2 Strings, the password and the salt.
The password and salt was retrieved from a class (class name obfuscated) under the package com.starhub.csselfhelp.utils
.
PRODUCTION(
"https://fapi.starhub.com/MyStarhub",
"http://fapi.starhub.com/MyStarhub",
"https://login.starhubgee.com.sg/sso/api/common",
"FZH9f/TWMhNR2vLC7M0Tuhy/8jG1it8H",
"1d2286041ee068cb1561f2838e0e71fa",
"U09wQs6svgbl", // password
"a54792ef11d53c68", // salt
"https://starhubvocsurveys.com/backend/web/survey?feed_id=",
"https://login.starhubgee.com.sg/msso/bapp/api/ssoredirect?src_siteid=mystarhub&src_token=%1$s&src_session_id=%2$s&tgt_siteid=jprotect&cb=https://juniorprotect.starhub.com/user/index.html"
)
The encryption of the password is based on SpringFramework's Encryptors. This information is gathered from the decompiled source code.
import org.springframework.security.crypto.encrypt.Encryptors;
public static String encrypt(String str) {
String password = "U09wQs6svgbl";
String salt = "a54792ef11d53c68";
return Encryptors.text(password, salt).encrypt(str);
}
From what I understand, the encryption library (default setting) uses:
- 256 bit AES encryption and derives the secret key using PKCS #5's PBKDF2.
- The provided salt is expected to be hex-encoded and at least 8 bytes in length
- Also applies a random 16 byte initialization vector (IV) to ensure uniqueness
SpringFramework Encryptor Documentation (4.2.5)
In one of the Android Activity, I found this line of code (obfuscated)
private MSSOLoginResponse a() {
this.b = com.starhub.csselfhelp.chat.utils.a.c(this.b + "_" + System.currentTimeMillis());
return com.starhub.csselfhelp.network.c.b(MyStarHubApplication.d().b("KEY_MSSO_LOGIN_URL", ""), String.format("{\"user_id\":\"%1$s\",\"user_password\":\"%2$s\",\"site_id\":\"%3$s\"}", new Object[] {
this.a, this.b, "mystarhub"
}), this.f.b);
}
this.b
represents the plaintext password. What StarHub does is that it appends _
plus current time in milliseconds
behind the plaintext password.
Input:
YOURPASSWORD_1529598919501
Output:
1a5ebfa6e2445515451af1f7fa2b45ec8385514c660f611ec1ee05478d0083b96848e2f064f51100242b9242e956dff1
TODO: Test sample implementation in Python
Someone has already done the implementation in Python thanks to this article: http://www.tmarthal.com/2016/07/using-pycrypto-with-spring-cryptospring.html archive.org link here
The fork of the GitHub Gist is available here: https://gist.github.com/Vantablack/21ec8f66974c5b22627d120671a71d9c