mirror of https://github.com/beemdevelopment/Aegis
Add support for Steam OTP
parent
a46640f43d
commit
1dd5f893da
@ -0,0 +1,50 @@
|
|||||||
|
package com.beemdevelopment.aegis.crypto.otp;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
public class OTP {
|
||||||
|
private static final String STEAM_ALPHABET = "23456789BCDFGHJKMNPQRTVWXY";
|
||||||
|
|
||||||
|
private int _code;
|
||||||
|
private int _digits;
|
||||||
|
|
||||||
|
public OTP(int code, int digits) {
|
||||||
|
_code = code;
|
||||||
|
_digits = digits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCode() {
|
||||||
|
return _code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDigits() {
|
||||||
|
return _digits;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
int code = _code % (int) Math.pow(10, _digits);
|
||||||
|
|
||||||
|
// prepend zeroes if needed
|
||||||
|
StringBuilder res = new StringBuilder(Long.toString(code));
|
||||||
|
while (res.length() < _digits) {
|
||||||
|
res.insert(0, "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toSteamString() {
|
||||||
|
int code = _code;
|
||||||
|
StringBuilder res = new StringBuilder();
|
||||||
|
|
||||||
|
for (int i = 0; i < _digits; i++) {
|
||||||
|
char c = STEAM_ALPHABET.charAt(code % STEAM_ALPHABET.length());
|
||||||
|
res.append(c);
|
||||||
|
code /= STEAM_ALPHABET.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
package com.beemdevelopment.aegis.importers;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import com.beemdevelopment.aegis.db.DatabaseEntry;
|
||||||
|
import com.beemdevelopment.aegis.encoding.Base64;
|
||||||
|
import com.beemdevelopment.aegis.encoding.Base64Exception;
|
||||||
|
import com.beemdevelopment.aegis.otp.OtpInfoException;
|
||||||
|
import com.beemdevelopment.aegis.otp.SteamInfo;
|
||||||
|
import com.beemdevelopment.aegis.util.ByteInputStream;
|
||||||
|
import com.topjohnwu.superuser.io.SuFile;
|
||||||
|
import com.topjohnwu.superuser.io.SuFileInputStream;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SteamAppImporter extends DatabaseAppImporter {
|
||||||
|
@SuppressLint("SdCardPath")
|
||||||
|
private static final String _path = "/data/data/com.valvesoftware.android.steam.community/files";
|
||||||
|
|
||||||
|
private List<JSONObject> _objs = new ArrayList<>();
|
||||||
|
|
||||||
|
public SteamAppImporter(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parse() throws DatabaseImporterException {
|
||||||
|
SuFile dir = new SuFile(_path);
|
||||||
|
for (SuFile file : dir.listFiles((d, name) -> name.startsWith("Steamguard-"))) {
|
||||||
|
try (SuFileInputStream in = new SuFileInputStream(file)) {
|
||||||
|
try (ByteInputStream stream = ByteInputStream.create(in)) {
|
||||||
|
JSONObject obj = new JSONObject(new String(stream.getBytes(), StandardCharsets.UTF_8));
|
||||||
|
_objs.add(obj);
|
||||||
|
}
|
||||||
|
} catch (IOException | JSONException e) {
|
||||||
|
throw new DatabaseImporterException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DatabaseImporterResult convert() {
|
||||||
|
DatabaseImporterResult result = new DatabaseImporterResult();
|
||||||
|
|
||||||
|
for (JSONObject obj : _objs) {
|
||||||
|
try {
|
||||||
|
DatabaseEntry entry = convertEntry(obj);
|
||||||
|
result.addEntry(entry);
|
||||||
|
} catch (DatabaseImporterEntryException e) {
|
||||||
|
result.addError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DatabaseEntry convertEntry(JSONObject obj) throws DatabaseImporterEntryException{
|
||||||
|
try {
|
||||||
|
byte[] secret = Base64.decode(obj.getString("shared_secret"));
|
||||||
|
SteamInfo info = new SteamInfo(secret);
|
||||||
|
|
||||||
|
String account = obj.getString("account_name");
|
||||||
|
return new DatabaseEntry(info, account, "Steam");
|
||||||
|
} catch (JSONException | Base64Exception | OtpInfoException e) {
|
||||||
|
throw new DatabaseImporterEntryException(e, obj.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEncrypted() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package com.beemdevelopment.aegis.otp;
|
||||||
|
|
||||||
|
import com.beemdevelopment.aegis.crypto.otp.OTP;
|
||||||
|
import com.beemdevelopment.aegis.crypto.otp.TOTP;
|
||||||
|
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
|
public class SteamInfo extends TotpInfo {
|
||||||
|
public static final String ID = "steam";
|
||||||
|
|
||||||
|
public SteamInfo(byte[] secret) throws OtpInfoException {
|
||||||
|
super(secret, "SHA1", 5, 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SteamInfo(byte[] secret, String algorithm, int digits, int period) throws OtpInfoException {
|
||||||
|
super(secret, algorithm, digits, period);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getOtp() {
|
||||||
|
try {
|
||||||
|
OTP otp = TOTP.generateOTP(getSecret(), getAlgorithm(true), getDigits(), getPeriod());
|
||||||
|
return otp.toSteamString();
|
||||||
|
} catch (InvalidKeyException | NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue