Merge pull request #1691 from michaelschattgen/feature/proton-importer

Add support for Proton Authenticator exports
master
Alexander Bakker 2 months ago committed by GitHub
commit bc600de7ab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -44,6 +44,7 @@ public abstract class DatabaseImporter {
_importers.add(new Definition("Google Authenticator", GoogleAuthImporter.class, R.string.importer_help_google_authenticator, true));
_importers.add(new Definition("Microsoft Authenticator", MicrosoftAuthImporter.class, R.string.importer_help_microsoft_authenticator, true));
_importers.add(new Definition("Plain text", GoogleAuthUriImporter.class, R.string.importer_help_plain_text, false));
_importers.add(new Definition("Proton Authenticator", ProtonAuthenticatorImporter.class, R.string.importer_help_proton_authenticator, false));
_importers.add(new Definition("Steam", SteamImporter.class, R.string.importer_help_steam, true));
_importers.add(new Definition("Stratum (Authenticator Pro)", StratumImporter.class, R.string.importer_help_stratum, true));
_importers.add(new Definition("TOTP Authenticator", TotpAuthenticatorImporter.class, R.string.importer_help_totp_authenticator, true));

@ -0,0 +1,96 @@
package com.beemdevelopment.aegis.importers;
import static java.nio.charset.StandardCharsets.UTF_8;
import android.content.Context;
import android.net.Uri;
import androidx.annotation.NonNull;
import com.beemdevelopment.aegis.otp.GoogleAuthInfo;
import com.beemdevelopment.aegis.otp.GoogleAuthInfoException;
import com.beemdevelopment.aegis.otp.OtpInfo;
import com.beemdevelopment.aegis.util.IOUtils;
import com.beemdevelopment.aegis.vault.VaultEntry;
import com.topjohnwu.superuser.io.SuFile;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.io.InputStream;
public class ProtonAuthenticatorImporter extends DatabaseImporter {
public ProtonAuthenticatorImporter(Context context) {
super(context);
}
@Override
protected SuFile getAppPath() {
throw new UnsupportedOperationException();
}
@Override
protected @NonNull State read(@NonNull InputStream stream, boolean isInternal) throws DatabaseImporterException {
try {
String contents = new String(IOUtils.readAll(stream), UTF_8);
JSONObject json = new JSONObject(contents);
return new DecryptedState(json);
} catch (JSONException | IOException e) {
throw new DatabaseImporterException(e);
}
}
public static class DecryptedState extends DatabaseImporter.State {
private final JSONObject _json;
public DecryptedState(@NonNull JSONObject json) {
super(false);
_json = json;
}
@Override
public @NonNull Result convert() throws DatabaseImporterException {
Result result = new Result();
try {
JSONArray entries = _json.getJSONArray("entries");
for (int i = 0; i < entries.length(); i++) {
JSONObject entry = entries.getJSONObject(i);
try {
result.addEntry(convertEntry(entry));
} catch (DatabaseImporterEntryException e) {
result.addError(e);
}
}
} catch (JSONException e) {
throw new DatabaseImporterException(e);
}
return result;
}
private static @NonNull VaultEntry convertEntry(@NonNull JSONObject entry) throws DatabaseImporterEntryException {
try {
JSONObject content = entry.getJSONObject("content");
String name = content.getString("name");
String uriString = content.getString("uri");
Uri uri = Uri.parse(uriString);
try {
GoogleAuthInfo info = GoogleAuthInfo.parseUri(uri);
OtpInfo otp = info.getOtpInfo();
return new VaultEntry(otp, name, info.getIssuer());
} catch (GoogleAuthInfoException e) {
throw new DatabaseImporterEntryException(e, uriString);
}
} catch (JSONException e) {
throw new DatabaseImporterEntryException(e, entry.toString());
}
}
}
}

@ -565,6 +565,7 @@
<string name="importer_help_google_authenticator"><b>Only database files from Google Authenticator v5.10 and prior are supported</b>.\n\nSupply a copy of <b>/data/data/com.google.android.apps.authenticator2/databases/databases</b>, located in the internal storage directory of Google Authenticator.</string>
<string name="importer_help_microsoft_authenticator">Supply a copy of <b>/data/data/com.azure.authenticator/databases/PhoneFactor</b>, located in the internal storage directory of Microsoft Authenticator.</string>
<string name="importer_help_plain_text">Supply a plain text file with a Google Authenticator URI on each line.</string>
<string name="importer_help_proton_authenticator">Supply a Proton Authenticator export file (.json) obtained through <b>Settings -> Export</b>.</string>
<string name="importer_help_steam"><b>Steam v3.0 and newer are not supported</b>. Supply a copy of <b>/data/data/com.valvesoftware.android.steam.community/files/Steamguard-*.json</b>, located in the internal storage directory of Steam.</string>
<string name="importer_help_stratum">Supply a Stratum export file obtained through <b>Settings -> Back up -> Back up to encrypted file (recommended)</b>.</string>
<string name="importer_help_totp_authenticator">Supply a TOTP Authenticator export file.</string>

@ -390,6 +390,12 @@ public class DatabaseImporterTest {
checkImportedEntries(entries);
}
@Test
public void testImportProtonAuthenticator() throws IOException, DatabaseImporterException, OtpInfoException {
List<VaultEntry> entries = importPlain(ProtonAuthenticatorImporter.class, "proton_authenticator.json");
checkImportedEntries(entries);
}
private List<VaultEntry> importPlain(Class<? extends DatabaseImporter> type, String resName)
throws IOException, DatabaseImporterException {
return importPlain(type, resName, false);

@ -0,0 +1,32 @@
{
"version": 1,
"entries": [
{
"id": "a19e0019-47e3-4d3b-af63-6dad0cb49e31",
"content": {
"uri": "otpauth://totp/Deno:Mason?secret=4SJHB4GSD43FZBAI7C2HLRJGPQ&issuer=Deno&algorithm=SHA1&digits=6&period=30",
"entry_type": "Totp",
"name": "Mason"
},
"note": null
},
{
"id": "4603c576-5d93-4c7f-8c26-bed6dc4493fc",
"content": {
"uri": "otpauth://totp/SPDX:James?secret=5OM4WOOGPLQEF6UGN3CPEOOLWU&issuer=SPDX&algorithm=SHA256&digits=7&period=20",
"entry_type": "Totp",
"name": "James"
},
"note": null
},
{
"id": "4fae25ae-16ed-4f15-a887-3bbb50b34d5e",
"content": {
"uri": "otpauth://totp/Airbnb:Elijah?secret=7ELGJSGXNCCTV3O6LKJWYFV2RA&issuer=Airbnb&algorithm=SHA512&digits=8&period=50",
"entry_type": "Totp",
"name": "Elijah"
},
"note": null
}
]
}
Loading…
Cancel
Save