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