mirror of
https://github.com/beemdevelopment/Aegis.git
synced 2025-04-21 14:29:13 +00:00
Add Proton Pass importer
This commit is contained in:
parent
2050d29236
commit
34550fff35
5 changed files with 171 additions and 0 deletions
|
@ -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("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("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("Plain text", GoogleAuthUriImporter.class, R.string.importer_help_plain_text, false));
|
||||||
|
_importers.add(new Definition("Proton Pass", ProtonPassImporter.class, R.string.importer_help_proton_pass, true));
|
||||||
_importers.add(new Definition("Steam", SteamImporter.class, R.string.importer_help_steam, true));
|
_importers.add(new Definition("Steam", SteamImporter.class, R.string.importer_help_steam, true));
|
||||||
_importers.add(new Definition("TOTP Authenticator", TotpAuthenticatorImporter.class, R.string.importer_help_totp_authenticator, true));
|
_importers.add(new Definition("TOTP Authenticator", TotpAuthenticatorImporter.class, R.string.importer_help_totp_authenticator, true));
|
||||||
_importers.add(new Definition("WinAuth", WinAuthImporter.class, R.string.importer_help_winauth, false));
|
_importers.add(new Definition("WinAuth", WinAuthImporter.class, R.string.importer_help_winauth, false));
|
||||||
|
|
|
@ -0,0 +1,155 @@
|
||||||
|
package com.beemdevelopment.aegis.importers;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import com.beemdevelopment.aegis.otp.GoogleAuthInfo;
|
||||||
|
import com.beemdevelopment.aegis.otp.GoogleAuthInfoException;
|
||||||
|
import com.beemdevelopment.aegis.vault.VaultEntry;
|
||||||
|
import com.beemdevelopment.aegis.vault.VaultGroup;
|
||||||
|
import com.topjohnwu.superuser.io.SuFile;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.json.JSONTokener;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
|
public class ProtonPassImporter extends DatabaseImporter {
|
||||||
|
public ProtonPassImporter(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected SuFile getAppPath() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected State read(InputStream stream, boolean isInternal) throws DatabaseImporterException {
|
||||||
|
// Unzip
|
||||||
|
ZipInputStream zis = new ZipInputStream(stream);
|
||||||
|
|
||||||
|
// Read file from zip
|
||||||
|
ZipEntry zipEntry;
|
||||||
|
try {
|
||||||
|
while((zipEntry = zis.getNextEntry()) != null)
|
||||||
|
{
|
||||||
|
if(!zipEntry.getName().equals("Proton Pass/data.json"))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read file
|
||||||
|
BufferedReader br = new BufferedReader(new InputStreamReader(zis));
|
||||||
|
StringBuilder json = new StringBuilder();
|
||||||
|
String line;
|
||||||
|
while((line = br.readLine()) != null){
|
||||||
|
json.append(line);
|
||||||
|
}
|
||||||
|
br.close();
|
||||||
|
|
||||||
|
// Parse JSON
|
||||||
|
JSONTokener tokener = new JSONTokener(json.toString());
|
||||||
|
JSONObject jsonObject = new JSONObject(tokener);
|
||||||
|
|
||||||
|
return new State(jsonObject);
|
||||||
|
}
|
||||||
|
}catch (IOException | JSONException e)
|
||||||
|
{
|
||||||
|
throw new DatabaseImporterException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Json not found
|
||||||
|
throw new DatabaseImporterException("Invalid proton zip file");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class State extends DatabaseImporter.State {
|
||||||
|
private JSONObject _jsonObject;
|
||||||
|
|
||||||
|
private State(JSONObject jsonObject)
|
||||||
|
{
|
||||||
|
super(false);
|
||||||
|
_jsonObject = jsonObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result convert() throws DatabaseImporterException {
|
||||||
|
Result result = new Result();
|
||||||
|
|
||||||
|
try {
|
||||||
|
JSONObject vaults = this._jsonObject.getJSONObject("vaults");
|
||||||
|
Iterator<String> keys = vaults.keys();
|
||||||
|
|
||||||
|
// Iterate over vaults
|
||||||
|
while (keys.hasNext())
|
||||||
|
{
|
||||||
|
JSONObject vault = vaults.getJSONObject(keys.next());
|
||||||
|
JSONArray items = vault.getJSONArray("items");
|
||||||
|
|
||||||
|
//Create a new group
|
||||||
|
VaultGroup group = new VaultGroup(vault.getString("name"));
|
||||||
|
result.addGroup(group);
|
||||||
|
|
||||||
|
// Iterate over items on the vault
|
||||||
|
for(int j = 0; j < items.length(); j++)
|
||||||
|
{
|
||||||
|
JSONObject item = items.getJSONObject(j);
|
||||||
|
|
||||||
|
try{
|
||||||
|
VaultEntry entry = this.fromItem(item);
|
||||||
|
|
||||||
|
if(entry == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.addGroup(group.getUUID());
|
||||||
|
result.addEntry(entry);
|
||||||
|
}catch (JSONException | GoogleAuthInfoException e)
|
||||||
|
{
|
||||||
|
result.addError(new DatabaseImporterEntryException(e, "Can't import " + item.getString("itemId")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}catch (JSONException e)
|
||||||
|
{
|
||||||
|
throw new DatabaseImporterException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public VaultEntry fromItem(JSONObject item) throws JSONException, GoogleAuthInfoException {
|
||||||
|
JSONObject data = item.getJSONObject("data");
|
||||||
|
JSONObject metadata = data.getJSONObject("metadata");
|
||||||
|
JSONObject content = data.getJSONObject("content");
|
||||||
|
|
||||||
|
//Only login items
|
||||||
|
if(!data.getString("type").equals("login"))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String uri = content.getString("totpUri");
|
||||||
|
if(uri.isEmpty())
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uri toptURI = Uri.parse(content.getString("totpUri"));
|
||||||
|
|
||||||
|
GoogleAuthInfo entry = GoogleAuthInfo.parseUri(toptURI);
|
||||||
|
|
||||||
|
return new VaultEntry(entry.getOtpInfo(), metadata.getString("name"), entry.getIssuer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -506,6 +506,7 @@
|
||||||
<string name="importer_help_authy">Supply a copy of <b>/data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml</b>, located in the internal storage directory of Authy.</string>
|
<string name="importer_help_authy">Supply a copy of <b>/data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml</b>, located in the internal storage directory of Authy.</string>
|
||||||
<string name="importer_help_andotp">Supply an andOTP export/backup file.</string>
|
<string name="importer_help_andotp">Supply an andOTP export/backup file.</string>
|
||||||
<string name="importer_help_bitwarden">Supply a Bitwarden export/backup file. Encrypted files are not supported.</string>
|
<string name="importer_help_bitwarden">Supply a Bitwarden export/backup file. Encrypted files are not supported.</string>
|
||||||
|
<string name="importer_help_proton_pass">Supply a Proton pass export/backup zip. Encrypted files are not supported.</string>
|
||||||
<string name="importer_help_battle_net_authenticator">Supply a copy of <b>/data/data/com.blizzard.messenger/shared_prefs/com.blizzard.messenger.authenticator_preferences.xml</b>, located in the internal storage directory of Battle.net Authenticator.</string>
|
<string name="importer_help_battle_net_authenticator">Supply a copy of <b>/data/data/com.blizzard.messenger/shared_prefs/com.blizzard.messenger.authenticator_preferences.xml</b>, located in the internal storage directory of Battle.net Authenticator.</string>
|
||||||
<string name="importer_help_duo">Supply a copy of <b>/data/data/com.duosecurity.duomobile/files/duokit/accounts.json</b>, located in the internal storage directory of DUO.</string>
|
<string name="importer_help_duo">Supply a copy of <b>/data/data/com.duosecurity.duomobile/files/duokit/accounts.json</b>, located in the internal storage directory of DUO.</string>
|
||||||
<string name="importer_help_freeotp">Supply a copy of <b>/data/data/org.fedorahosted.freeotp/shared_prefs/tokens.xml</b>, located in the internal storage directory of FreeOTP (1.x).</string>
|
<string name="importer_help_freeotp">Supply a copy of <b>/data/data/org.fedorahosted.freeotp/shared_prefs/tokens.xml</b>, located in the internal storage directory of FreeOTP (1.x).</string>
|
||||||
|
|
|
@ -209,6 +209,12 @@ public class DatabaseImporterTest {
|
||||||
checkImportedBitwardenEntries(entries);
|
checkImportedBitwardenEntries(entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testImportProtonPassZip() throws DatabaseImporterException, IOException, OtpInfoException {
|
||||||
|
List<VaultEntry> entries = importPlain(ProtonPassImporter.class, "proton_pass.zip");
|
||||||
|
checkImportedProtonPassEntries(entries);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testImportFreeOtp() throws IOException, DatabaseImporterException, OtpInfoException {
|
public void testImportFreeOtp() throws IOException, DatabaseImporterException, OtpInfoException {
|
||||||
List<VaultEntry> entries = importPlain(FreeOtpImporter.class, "freeotp.xml");
|
List<VaultEntry> entries = importPlain(FreeOtpImporter.class, "freeotp.xml");
|
||||||
|
@ -441,6 +447,14 @@ public class DatabaseImporterTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkImportedProtonPassEntries(List<VaultEntry> entries) throws OtpInfoException {
|
||||||
|
for (VaultEntry entry : entries)
|
||||||
|
{
|
||||||
|
entry.getGroups().clear();
|
||||||
|
checkImportedEntry(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void checkImportedEntries(List<VaultEntry> entries) throws OtpInfoException {
|
private void checkImportedEntries(List<VaultEntry> entries) throws OtpInfoException {
|
||||||
for (VaultEntry entry : entries) {
|
for (VaultEntry entry : entries) {
|
||||||
checkImportedEntry(entry);
|
checkImportedEntry(entry);
|
||||||
|
|
Binary file not shown.
Loading…
Add table
Reference in a new issue