public void unverifyUser(String fullUserId) {

    if (!isVerifiedUser(fullUserId)) return;

    store.setProperty(
        buildPublicKeyVerifiedId(fullUserId, getRemoteFingerprint(fullUserId)), false);
    store.save();
  }
  public void savePublicKey(SessionID sessionID, PublicKey pubKey) {
    if (sessionID == null) return;

    X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(pubKey.getEncoded());

    //  if (!Address.hasResource(fullUserId))
    //    return;

    this.store.setProperty(
        sessionID.getRemoteUserId() + ".publicKey", x509EncodedKeySpec.getEncoded());
    // Stash the associated fingerprint.  This saves calculating it in the future
    // and is useful for transferring rosters to other apps.
    try {
      String fingerprintString = new OtrCryptoEngineImpl().getFingerprint(pubKey);
      String verifiedToken =
          buildPublicKeyVerifiedId(sessionID.getRemoteUserId(), fingerprintString.toLowerCase());
      if (!this.store.hasProperty(verifiedToken)) this.store.setProperty(verifiedToken, false);

      this.store.setPropertyHex(
          sessionID.getRemoteUserId() + ".fingerprint", Hex.decode(fingerprintString));
      store.save();
    } catch (OtrCryptoException e) {
      e.printStackTrace();
    }
  }
  public String getRemoteFingerprint(String fullUserId) {

    // if (!Address.hasResource(fullUserId))
    //  return null;

    byte[] fingerprint = this.store.getPropertyHexBytes(fullUserId + ".fingerprint");
    if (fingerprint != null) {
      // If we have a fingerprint stashed, assume it is correct.
      return new String(Hex.encode(fingerprint, 0, fingerprint.length));
    }

    PublicKey remotePublicKey = loadRemotePublicKeyFromStore(fullUserId);
    if (remotePublicKey == null) return null;
    try {
      // Store the fingerprint, for posterity.
      String fingerprintString = new OtrCryptoEngineImpl().getFingerprint(remotePublicKey);
      this.store.setPropertyHex(fullUserId + ".fingerprint", Hex.decode(fingerprintString));

      store.save();
      return fingerprintString;
    } catch (OtrCryptoException e) {
      OtrDebugLogger.log("OtrCryptoException getting remote fingerprint", e);
      return null;
    }
  }
  public void generateLocalKeyPair(String fullUserId) {

    String userId = Address.stripResource(fullUserId);

    OtrDebugLogger.log("generating local key pair for: " + userId);

    KeyPair keyPair;
    try {

      KeyPairGenerator kpg = KeyPairGenerator.getInstance(KEY_ALG);
      kpg.initialize(KEY_SIZE);

      keyPair = kpg.genKeyPair();
    } catch (NoSuchAlgorithmException e) {
      OtrDebugLogger.log("no such algorithm", e);
      return;
    }

    OtrDebugLogger.log("SUCCESS! generating local key pair for: " + userId);

    // Store Private Key.
    PrivateKey privKey = keyPair.getPrivate();
    PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privKey.getEncoded());

    this.store.setProperty(userId + ".privateKey", pkcs8EncodedKeySpec.getEncoded());

    // Store Public Key.
    PublicKey pubKey = keyPair.getPublic();
    storeLocalPublicKey(userId, pubKey);

    store.save();
  }
  public boolean doKeyStoreExport(String password) {

    // if otr_keystore.ofcaes is in the SDCard root, import it
    File otrKeystoreAES =
        new File(Environment.getExternalStorageDirectory(), "otr_keystore.ofcaes");

    return store.export(password, otrKeystoreAES);
  }
  public void verifyUser(String userId) {
    if (userId == null) return;

    if (this.isVerifiedUser(userId)) return;

    this.store.setProperty(buildPublicKeyVerifiedId(userId, getRemoteFingerprint(userId)), true);

    store.save();
    // for (OtrKeyManagerListener l : listeners)
    // l.verificationStatusChanged(userId);

  }
  public boolean importKeyStore(
      String filePath, String password, boolean overWriteExisting, boolean deleteImportedFile)
      throws IOException {
    SimplePropertiesStore storeNew = null;

    File fileOtrKeystore = new File(filePath);

    if (fileOtrKeystore.getName().endsWith(".ofcaes")) {
      // TODO implement GUI to get password via QR Code, and handle wrong password
      storeNew = new SimplePropertiesStore(fileOtrKeystore, password, true);
      deleteImportedFile = true; // once its imported, its no longer needed
    } else {
      return false;
    }

    Enumeration<Object> enumKeys = storeNew.getKeys();

    String key;

    while (enumKeys.hasMoreElements()) {
      key = (String) enumKeys.nextElement();

      boolean hasKey = store.hasProperty(key);

      if (!hasKey || overWriteExisting) store.setProperty(key, storeNew.getPropertyString(key));
    }

    store.save();

    if (deleteImportedFile) fileOtrKeystore.delete();

    return true;
  }
  private void storeLocalPublicKey(String fullUserId, PublicKey pubKey) {

    String userId = Address.stripResource(fullUserId);

    X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(pubKey.getEncoded());

    this.store.setProperty(userId + ".publicKey", x509EncodedKeySpec.getEncoded());

    // Stash fingerprint for consistency.
    try {
      String fingerprintString = new OtrCryptoEngineImpl().getFingerprint(pubKey);
      this.store.setPropertyHex(userId + ".fingerprint", Hex.decode(fingerprintString));
    } catch (OtrCryptoException e) {
      e.printStackTrace();
    }

    store.save();
  }
  public String[] getRemoteFingerprints(String userId) {

    Enumeration<Object> keys = store.getKeys();

    ArrayList<String> results = new ArrayList<String>();

    while (keys.hasMoreElements()) {
      String key = (String) keys.nextElement();

      if (key.startsWith(userId + '/') && key.endsWith(".fingerprint")) {

        byte[] fingerprint = this.store.getPropertyHexBytes(userId + ".fingerprint");
        if (fingerprint != null) {
          // If we have a fingerprint stashed, assume it is correct.
          results.add(new String(Hex.encode(fingerprint, 0, fingerprint.length)));
        }
      }
    }

    String[] resultsString = new String[results.size()];
    return results.toArray(resultsString);
  }