From 7422b0cf53b0bf4e7ca9f5eab4bfe762f5a7d5ff Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Sun, 13 May 2018 19:42:59 +0200 Subject: [PATCH] Add support for importing plain text andOTP databases --- .../java/me/impy/aegis/crypto/KeyInfo.java | 2 +- .../impy/aegis/importers/AegisImporter.java | 6 +- .../impy/aegis/importers/AndOTPImporter.java | 83 +++++++++++++++++++ .../aegis/importers/DatabaseImporter.java | 6 +- 4 files changed, 92 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/me/impy/aegis/importers/AndOTPImporter.java diff --git a/app/src/main/java/me/impy/aegis/crypto/KeyInfo.java b/app/src/main/java/me/impy/aegis/crypto/KeyInfo.java index 4cb272ba..8b4d8408 100644 --- a/app/src/main/java/me/impy/aegis/crypto/KeyInfo.java +++ b/app/src/main/java/me/impy/aegis/crypto/KeyInfo.java @@ -155,7 +155,7 @@ public class KeyInfo implements Serializable { if (!isTypeValid(type)) { throw new KeyInfoException(String.format("unsupported otp type: %s", type)); } - _type = type.toLowerCase(); + _type = type; } public void setSecret(char[] base32) throws KeyInfoException { diff --git a/app/src/main/java/me/impy/aegis/importers/AegisImporter.java b/app/src/main/java/me/impy/aegis/importers/AegisImporter.java index c7e28a17..49109e50 100644 --- a/app/src/main/java/me/impy/aegis/importers/AegisImporter.java +++ b/app/src/main/java/me/impy/aegis/importers/AegisImporter.java @@ -35,10 +35,10 @@ public class AegisImporter extends DatabaseImporter { public List convert() throws DatabaseImporterException { try { JSONObject obj; - if (!_file.isEncrypted()) { - obj = _file.getContent(); - } else { + if (_file.isEncrypted() && _key != null) { obj = _file.getContent(_key); + } else { + obj = _file.getContent(); } Database db = new Database(); diff --git a/app/src/main/java/me/impy/aegis/importers/AndOTPImporter.java b/app/src/main/java/me/impy/aegis/importers/AndOTPImporter.java new file mode 100644 index 00000000..0599ca24 --- /dev/null +++ b/app/src/main/java/me/impy/aegis/importers/AndOTPImporter.java @@ -0,0 +1,83 @@ +package me.impy.aegis.importers; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; + +import me.impy.aegis.crypto.KeyInfo; +import me.impy.aegis.crypto.KeyInfoException; +import me.impy.aegis.db.DatabaseEntry; +import me.impy.aegis.encoding.Base32; +import me.impy.aegis.encoding.Base32Exception; +import me.impy.aegis.util.ByteInputStream; + +public class AndOTPImporter extends DatabaseImporter { + private JSONArray _obj; + + public AndOTPImporter(ByteInputStream stream) { + super(stream); + } + + @Override + public void parse() throws DatabaseImporterException { + try { + _obj = new JSONArray(new String(_stream.getBytes(), "UTF-8")); + } catch (JSONException e) { + throw new DatabaseImporterException(e); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + @Override + public List convert() throws DatabaseImporterException { + List entries = new ArrayList<>(); + + try { + for (int i = 0; i < _obj.length(); i++) { + JSONObject obj = _obj.getJSONObject(i); + + KeyInfo key = new KeyInfo(); + key.setAlgorithm(obj.getString("algorithm")); + key.setDigits(obj.getInt("digits")); + key.setPeriod(obj.getInt("period")); + key.setType(obj.getString("type")); + if (key.getType().equals("hotp")) { + key.setCounter(obj.getLong("counter")); + } + + String[] parts = obj.getString("label").split(" - "); + if (parts.length > 1) { + key.setIssuer(parts[0]); + key.setAccountName(parts[1]); + } else { + key.setAccountName(parts[0]); + } + + byte[] secret = Base32.decode(obj.getString("secret").toCharArray()); + key.setSecret(secret); + + DatabaseEntry entry = new DatabaseEntry(key); + entries.add(entry); + } + } catch (Base32Exception | KeyInfoException | JSONException e) { + throw new DatabaseImporterException(e); + } + + return entries; + } + + @Override + public boolean isEncrypted() { + return false; + } + + @Override + public String getName() { + return "andOTP"; + } +} diff --git a/app/src/main/java/me/impy/aegis/importers/DatabaseImporter.java b/app/src/main/java/me/impy/aegis/importers/DatabaseImporter.java index 8b14a9a1..40f0f242 100644 --- a/app/src/main/java/me/impy/aegis/importers/DatabaseImporter.java +++ b/app/src/main/java/me/impy/aegis/importers/DatabaseImporter.java @@ -11,7 +11,11 @@ import me.impy.aegis.util.ByteInputStream; public abstract class DatabaseImporter { private static List> _converters = Collections.unmodifiableList( - new ArrayList<>(Arrays.asList(AegisImporter.class, FreeOTPImporter.class)) + new ArrayList<>(Arrays.asList( + AegisImporter.class, + FreeOTPImporter.class, + AndOTPImporter.class + )) ); protected ByteInputStream _stream;