mirror of
https://github.com/beemdevelopment/Aegis.git
synced 2025-05-16 15:02:54 +00:00
commit
5c196f1ca5
6 changed files with 108 additions and 0 deletions
|
@ -32,6 +32,7 @@ public abstract class DatabaseImporter {
|
|||
_importers.add(new Definition("andOTP", AndOtpImporter.class, R.string.importer_help_andotp, false));
|
||||
_importers.add(new Definition("Authenticator Plus", AuthenticatorPlusImporter.class, R.string.importer_help_authenticator_plus, false));
|
||||
_importers.add(new Definition("Authy", AuthyImporter.class, R.string.importer_help_authy, true));
|
||||
_importers.add(new Definition("DUO", DuoImporter.class, R.string.importer_help_duo, true));
|
||||
_importers.add(new Definition("FreeOTP", FreeOtpImporter.class, R.string.importer_help_freeotp, true));
|
||||
_importers.add(new Definition("FreeOTP+", FreeOtpPlusImporter.class, R.string.importer_help_freeotp_plus, true));
|
||||
_importers.add(new Definition("Google Authenticator", GoogleAuthImporter.class, R.string.importer_help_google_authenticator, true));
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
package com.beemdevelopment.aegis.importers;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.beemdevelopment.aegis.encoding.Base32;
|
||||
import com.beemdevelopment.aegis.encoding.EncodingException;
|
||||
import com.beemdevelopment.aegis.otp.HotpInfo;
|
||||
import com.beemdevelopment.aegis.otp.OtpInfo;
|
||||
import com.beemdevelopment.aegis.otp.OtpInfoException;
|
||||
import com.beemdevelopment.aegis.otp.TotpInfo;
|
||||
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 DuoImporter extends DatabaseImporter {
|
||||
private static final String _pkgName = "com.duosecurity.duomobile";
|
||||
private static final String _subPath = "files/duokit/accounts.json";
|
||||
|
||||
public DuoImporter(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull SuFile getAppPath() throws DatabaseImporterException, NameNotFoundException {
|
||||
return getAppPath(_pkgName, _subPath);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull State read(
|
||||
@NonNull InputStream stream, boolean isInternal
|
||||
) throws DatabaseImporterException {
|
||||
try {
|
||||
String contents = new String(IOUtils.readAll(stream), UTF_8);
|
||||
return new DecryptedState(new JSONArray(contents));
|
||||
} catch (JSONException | IOException e) {
|
||||
throw new DatabaseImporterException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static class DecryptedState extends DatabaseImporter.State {
|
||||
private final JSONArray _array;
|
||||
|
||||
public DecryptedState(@NonNull JSONArray array) {
|
||||
super(false);
|
||||
_array = array;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Result convert() throws DatabaseImporterException {
|
||||
Result result = new Result();
|
||||
|
||||
try {
|
||||
for (int i = 0; i < _array.length(); i++) {
|
||||
JSONObject entry = _array.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 {
|
||||
String label = entry.optString("name");
|
||||
|
||||
JSONObject otpData = entry.getJSONObject("otpGenerator");
|
||||
|
||||
byte[] secret = Base32.decode(otpData.getString("otpSecret"));
|
||||
|
||||
Long counter = otpData.has("counter") ? otpData.getLong("counter") : null;
|
||||
|
||||
OtpInfo otp = counter == null
|
||||
? new TotpInfo(secret)
|
||||
: new HotpInfo(secret, counter);
|
||||
|
||||
return new VaultEntry(otp, label, "");
|
||||
} catch (JSONException | OtpInfoException | EncodingException e) {
|
||||
throw new DatabaseImporterEntryException(e, entry.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue