@BeforeClass
  public static void setUpOnce() throws Exception {
    Security.insertProviderAt(new BouncyCastleProvider(), 1);
    oldShadowStream = ShadowLog.stream;
    // ShadowLog.stream = System.out;

    PgpKeyOperation op = new PgpKeyOperation(null);

    {
      SaveKeyringParcel parcel = new SaveKeyringParcel();
      parcel.mAddSubKeys.add(
          new SaveKeyringParcel.SubkeyAdd(
              Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L));
      parcel.mAddSubKeys.add(
          new SaveKeyringParcel.SubkeyAdd(
              Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L));
      parcel.mAddSubKeys.add(
          new SaveKeyringParcel.SubkeyAdd(
              Algorithm.ECDH, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.ENCRYPT_COMMS, 0L));
      parcel.mAddUserIds.add("derp");
      parcel.mNewUnlock = new ChangeUnlockParcel(mKeyPhrase1);

      PgpEditKeyResult result = op.createSecretKeyRing(parcel);
      Assert.assertTrue("initial test key creation must succeed", result.success());
      Assert.assertNotNull("initial test key creation must succeed", result.getRing());

      mStaticRing = result.getRing();
    }
  }
  @NonNull
  public OperationResult execute(ChangeUnlockParcel unlockParcel, CryptoInputParcel cryptoInput) {
    OperationResult.OperationLog log = new OperationResult.OperationLog();
    log.add(OperationResult.LogType.MSG_ED, 0);

    if (unlockParcel == null || unlockParcel.mMasterKeyId == null) {
      log.add(OperationResult.LogType.MSG_ED_ERROR_NO_PARCEL, 1);
      return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null);
    }

    // Perform actual modification
    PgpEditKeyResult modifyResult;
    {
      PgpKeyOperation keyOperations =
          new PgpKeyOperation(new ProgressScaler(mProgressable, 0, 70, 100));

      try {
        log.add(
            OperationResult.LogType.MSG_ED_FETCHING,
            1,
            KeyFormattingUtils.convertKeyIdToHex(unlockParcel.mMasterKeyId));

        CanonicalizedSecretKeyRing secRing =
            mProviderHelper.getCanonicalizedSecretKeyRing(unlockParcel.mMasterKeyId);
        modifyResult = keyOperations.modifyKeyRingPassphrase(secRing, cryptoInput, unlockParcel);

        if (modifyResult.isPending()) {
          // obtain original passphrase from user
          log.add(modifyResult, 1);
          return new EditKeyResult(log, modifyResult);
        }
      } catch (ProviderHelper.NotFoundException e) {
        log.add(OperationResult.LogType.MSG_ED_ERROR_KEY_NOT_FOUND, 2);
        return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null);
      }
    }

    log.add(modifyResult, 1);

    if (!modifyResult.success()) {
      // error is already logged by modification
      return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null);
    }

    // Cannot cancel from here on out!
    mProgressable.setPreventCancel();

    // It's a success, so this must be non-null now
    UncachedKeyRing ring = modifyResult.getRing();

    SaveKeyringResult saveResult =
        mProviderHelper.saveSecretKeyRing(ring, new ProgressScaler(mProgressable, 70, 95, 100));
    log.add(saveResult, 1);

    // If the save operation didn't succeed, exit here
    if (!saveResult.success()) {
      return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null);
    }

    updateProgress(R.string.progress_done, 100, 100);
    log.add(OperationResult.LogType.MSG_ED_SUCCESS, 0);
    return new EditKeyResult(EditKeyResult.RESULT_OK, log, ring.getMasterKeyId());
  }