public byte[] getExportData(KgkManager kgkManager) {
   kgkManager.freshIv2();
   kgkManager.freshSalt2();
   byte[] kgkBlock = kgkManager.getEncryptedKgk();
   Crypter settingsCrypter = this.getSettingsCrypter(kgkManager);
   byte[] encryptedSettings =
       settingsCrypter.encrypt(Packer.compress(this.getSettingsAsJSON().toString()));
   byte[] salt = kgkManager.getKgkCrypterSalt();
   byte[] exportData = new byte[1 + salt.length + kgkBlock.length + encryptedSettings.length];
   exportData[0] = 0x01;
   System.arraycopy(salt, 0, exportData, 1, salt.length);
   System.arraycopy(kgkBlock, 0, exportData, 1 + salt.length, kgkBlock.length);
   System.arraycopy(
       encryptedSettings,
       0,
       exportData,
       1 + salt.length + kgkBlock.length,
       encryptedSettings.length);
   return exportData;
 }
 public void storeLocalSettings(KgkManager kgkManager) {
   kgkManager.freshSalt2();
   kgkManager.freshIv2();
   Crypter settingsCrypter = this.getSettingsCrypter(kgkManager);
   JSONObject storeStructure = new JSONObject();
   try {
     storeStructure.put("settings", this.getSettingsAsJSON());
     storeStructure.put("synced", this.getSyncedSettings());
   } catch (JSONException jsonError) {
     Log.d("Settings saving error", "Could not construct JSON structure for storage.");
     jsonError.printStackTrace();
   }
   SharedPreferences.Editor savedDomainsEditor = savedDomains.edit();
   if (settingsCrypter != null) {
     byte[] encryptedSettings =
         settingsCrypter.encrypt(Packer.compress(storeStructure.toString()));
     savedDomainsEditor.putString(
         "encryptedSettings", Base64.encodeToString(encryptedSettings, Base64.DEFAULT));
     savedDomainsEditor.apply();
     kgkManager.storeLocalKgkBlock();
   }
 }
 public void loadLocalSettings(KgkManager kgkManager) throws WrongPasswordException {
   Crypter settingsCrypter = this.getSettingsCrypter(kgkManager);
   byte[] encrypted =
       Base64.decode(this.savedDomains.getString("encryptedSettings", ""), Base64.DEFAULT);
   if (encrypted.length < 40) {
     return;
   }
   byte[] decrypted = settingsCrypter.decrypt(encrypted);
   if (decrypted.length < 40) {
     throw new WrongPasswordException("wrong length: too short");
   }
   String decompressedSettings = Packer.decompress(decrypted);
   if (decompressedSettings.length() <= 0) {
     throw new WrongPasswordException("unable to decompress");
   }
   try {
     JSONObject decryptedObject = new JSONObject(decompressedSettings);
     JSONObject decryptedSettings = decryptedObject.getJSONObject("settings");
     JSONArray syncedSettings = decryptedObject.getJSONArray("synced");
     Iterator<String> keys = decryptedSettings.keys();
     while (keys.hasNext()) {
       String key = keys.next();
       JSONObject settingObject = decryptedSettings.getJSONObject(key);
       boolean found = false;
       for (PasswordSetting setting : this.settings) {
         if (setting.getDomain().contentEquals(key)) {
           found = true;
           DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH);
           Date modifiedRemote = df.parse(settingObject.getString("mDate"));
           if (modifiedRemote.after(setting.getMDate())) {
             setting.loadFromJSON(settingObject);
             boolean foundInSynced = false;
             for (int i = 0; i < syncedSettings.length(); i++) {
               if (syncedSettings.getString(i).contentEquals(key)) {
                 foundInSynced = true;
               }
             }
             setting.setSynced(foundInSynced);
           }
         }
       }
       if (!found) {
         PasswordSetting newSetting = new PasswordSetting(key);
         newSetting.loadFromJSON(settingObject);
         boolean foundInSynced = false;
         for (int i = 0; i < syncedSettings.length(); i++) {
           if (syncedSettings.getString(i).contentEquals(key)) {
             foundInSynced = true;
           }
         }
         newSetting.setSynced(foundInSynced);
         this.settings.add(newSetting);
       }
     }
   } catch (JSONException jsonError) {
     Log.d("Settings loading error", "The loaded settings are not in JSON format.");
     jsonError.printStackTrace();
   } catch (ParseException timeFormatError) {
     Log.d(
         "Settings loading error",
         "The loaded settings contain time information in a wrong format.");
     timeFormatError.printStackTrace();
   }
 }
 public boolean updateFromExportData(KgkManager kgkManager, byte[] blob) {
   if (!(blob[0] == 0x01)) {
     Log.d("Version error", "Wrong data format. Could not import anything.");
     return true;
   }
   byte[] encryptedSettings = Arrays.copyOfRange(blob, 145, blob.length);
   Crypter settingsCrypter = this.getSettingsCrypter(kgkManager);
   byte[] decryptedSettings = settingsCrypter.decrypt(encryptedSettings);
   if (decryptedSettings.length <= 0) {
     Toast.makeText(contentContext, R.string.sync_wrong_password, Toast.LENGTH_SHORT).show();
     return false;
   }
   String jsonString = Packer.decompress(decryptedSettings);
   try {
     JSONObject loadedSettings = new JSONObject(jsonString);
     boolean updateRemote = false;
     Iterator<String> loadedSettingsIterator = loadedSettings.keys();
     while (loadedSettingsIterator.hasNext()) {
       JSONObject loadedSetting = loadedSettings.getJSONObject(loadedSettingsIterator.next());
       boolean found = false;
       for (String domain : this.getDomainList()) {
         PasswordSetting setting = this.getSetting(domain);
         if (setting.getDomain().equals(loadedSetting.getString("domain"))) {
           found = true;
           DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH);
           Date modifiedRemote = df.parse(loadedSetting.getString("mDate"));
           if (modifiedRemote.after(setting.getMDate())) {
             setting.loadFromJSON(loadedSetting);
             this.setSetting(setting);
           } else {
             updateRemote = true;
           }
           setting.setSynced(true);
           break;
         }
       }
       if (!found) {
         PasswordSetting newSetting = new PasswordSetting(loadedSetting.getString("domain"));
         newSetting.loadFromJSON(loadedSetting);
         newSetting.setSynced(true);
         this.setSetting(newSetting);
       }
     }
     for (String domain : this.getDomainList()) {
       PasswordSetting setting = this.getSetting(domain);
       boolean found = false;
       Iterator<String> loadedSettingsIterator2 = loadedSettings.keys();
       while (loadedSettingsIterator2.hasNext()) {
         JSONObject loadedSetting = loadedSettings.getJSONObject(loadedSettingsIterator2.next());
         if (setting.getDomain().equals(loadedSetting.getString("domain"))) {
           found = true;
           break;
         }
       }
       if (!found && setting.isSynced()) {
         updateRemote = true;
       }
     }
     this.storeLocalSettings(kgkManager);
     return updateRemote;
   } catch (JSONException e) {
     Log.d("Update settings error", "Unable to read JSON data.");
     e.printStackTrace();
     return false;
   } catch (ParseException e) {
     Log.d("Update settings error", "Unable to parse the date.");
     e.printStackTrace();
     return false;
   }
 }