예제 #1
0
 protected virtual int KeyEditCallback(IntPtr handle, KeyEditStatusCode status, string args, Stream fd)
 {
     if (fd != null)
     {
         fd.Write(new byte[] { (byte)'q', (byte)'u', (byte)'i', (byte)'t', (byte)'\n' }, 0, 5);
         fd.Flush();
     }
     throw new NotImplementedException("The function KeyEditCallback is not implemented.");
 }
예제 #2
0
 protected virtual int KeyEditCallback(IntPtr handle, KeyEditStatusCode status, string args, int fd)
 {
     libgpgme.NativeMethods.gpgme_io_write(fd, new[] { (byte)'q', (byte)'u', (byte)'i', (byte)'t', (byte)'\n' }, (UIntPtr)5);
     throw new NotImplementedException("The function KeyEditCallback is not implemented.");
 }
예제 #3
0
 protected virtual int KeyEditCallback(IntPtr handle, KeyEditStatusCode status, string args, Stream fd)
 {
     if (fd != null)
     {
         fd.Write(new byte[] { (byte)'q', (byte)'u', (byte)'i', (byte)'t', (byte)'\n' }, 0, 5);
         fd.Flush();
     }
     throw new NotImplementedException("The function KeyEditCallback is not implemented.");
 }
예제 #4
0
        private byte[] EnableDisableHandler(KeyEditStatusCode status, string args, Stream fd)
        {
            PgpEnableDisableOptions endisOptions = settings.endisOptions;
            string output = "";

            if (args != null)
            {
                if (args.Equals("keyedit.prompt"))
                {
                    if (!endisOptions.cmdSend)
                    {
                        switch (endisOptions.OperationMode) {
                            case PgpEnableDisableOptions.Mode.Enable:
                                output = "enable";
                                break;
                            case PgpEnableDisableOptions.Mode.Disable:
                                output = "disable";
                                break;
                        }
                        endisOptions.cmdSend = true;
                    }
                    else
                    {
                        output = "quit";
                    }

                    return ToU8(output);
                }
            }

            return new byte[0];
        }
예제 #5
0
        private byte[] ExpireHandler(KeyEditStatusCode status, string args, Stream fd)
        {
            PgpExpirationOptions expireOptions = settings.expireOptions;
            string output = "";

            if (args != null)
            {
                if (args.Equals("keyedit.prompt") && !expireOptions.cmdSend)
                {
                    if (expireOptions.SelectedSubkeys != null
                        && (expireOptions.nsubkey < expireOptions.SelectedSubkeys.Length))
                    {
                        output = "key " + expireOptions.SelectedSubkeys[expireOptions.nsubkey++].ToString();
                    }
                    else
                    {
                        expireOptions.cmdSend = true;
                        output = "expire";
                    }
                    return ToU8(output);
                }

                // Expire date in days
                if (args.Equals("keygen.valid"))
                {
                    if (expireOptions.IsInfinitely || (expireOptions.ExpirationDate.CompareTo(DateTime.Now) < 0))
                        output = "0";
                    else
                        output = (expireOptions.ExpirationDate - DateTime.Now).Days.ToString();

                    return ToU8(output);
                }

                if (args.Equals("keyedit.save.okay"))
                {
                    if (!expireOptions.forceQuit)
                        output = "Y";
                    else
                    {
                        // maybe an other gnupg process is editing this key at the same time
                        output = "N";
                    }

                    return ToU8(output);
                }

                if (args.Equals("keyedit.prompt") && expireOptions.forceQuit)
                {
                    output = "quit";
                    return ToU8(output);
                }

                if (args.Equals("keyedit.prompt"))
                {
                    expireOptions.forceQuit = true;
                    output = "save";
                    return ToU8(output);
                }

            }

            return new byte[0];
        }
예제 #6
0
        private byte[] AddSubkeyHandler(KeyEditStatusCode status, string args, Stream fd)
        {
            #if (VERBOSE_DEBUG)
            DebugOutput("Inside AddSubkeyHandler(..)");
            #endif

            PgpSubkeyOptions subkeyOptions = settings.subkeyOptions;
            string output = "";

            if (args != null)
            {
                if (args.Equals("keyedit.prompt") && !subkeyOptions.cmdSend)
                {
                    // send command
                    subkeyOptions.cmdSend = true;
                    output = "addkey";

            #if (VERBOSE_DEBUG)
                    DebugOutput("End keygen.algo.");
            #endif
                    return ToU8(output);
                }
                if (args.Equals("keygen.algo"))
                {
                    /* Gnupg's configuration mode needs be set to "expert"
                     * in order to specify customized DSA or RSA subkeys.
                     */

                    settings.subkeyalgoquestion++;

                    output = ((int)subkeyOptions.Algorithm).ToString();

                    // GPG IS NOT IN EXPERT MODE!
                    if (settings.subkeyalgoquestion > 1)
                    {
            #if (VERBOSE_DEBUG)
                        DebugOutput("End keygen.algo.");
            #endif
                        return ToU8("2");
                    }

            #if (VERBOSE_DEBUG)
                    DebugOutput("End keygen.algo.");
            #endif
                    return ToU8(output);
                }
                if (args.Equals("keygen.flags"))
                {

                    // Auth is NOT enabled by default
                    if ((subkeyOptions.Capability & AlgorithmCapability.CanAuth) == AlgorithmCapability.CanAuth &&
                        ((settings.subkeycapability & AlgorithmCapability.CanAuth) != AlgorithmCapability.CanAuth))
                    {
                        settings.subkeycapability |= AlgorithmCapability.CanAuth;
                        output = "A";
                    }
                    // Sign is enabled by default!
                    else if ((subkeyOptions.Capability & AlgorithmCapability.CanSign) != AlgorithmCapability.CanSign &&
                        ((settings.subkeycapability & AlgorithmCapability.CanSign) != AlgorithmCapability.CanSign))
                    {
                        settings.subkeycapability |= AlgorithmCapability.CanSign; // save, that we have checked "Sign" flag
                        output = "S";
                    }
                    // Encrypt is enabled by default!
                    else if ((subkeyOptions.Capability & AlgorithmCapability.CanEncrypt) != AlgorithmCapability.CanEncrypt &&
                        ((settings.subkeycapability & AlgorithmCapability.CanEncrypt) != AlgorithmCapability.CanEncrypt))
                    {
                        settings.subkeycapability |= AlgorithmCapability.CanEncrypt; // save, that we have checked "Encrypt" flag
                        output = "E";
                    }
                    else
                        // all flags specified
                        output = "Q";

            #if (VERBOSE_DEBUG)
                    DebugOutput("End keygen.flags.");
            #endif
                    return ToU8(output);
                }
                if (args.Equals("keygen.size"))
                {
                    output = subkeyOptions.KeyLength.ToString();

            #if (VERBOSE_DEBUG)
                    DebugOutput("End keygen.size.");
            #endif
                    return ToU8(output);
                }
                if (args.Equals("keygen.valid"))
                {
                    if (subkeyOptions.IsInfinitely || (subkeyOptions.ExpirationDate.CompareTo(DateTime.Now) < 0))
                        output = "0";
                    else
                        output = (subkeyOptions.ExpirationDate - DateTime.Now).Days.ToString();

            #if (VERBOSE_DEBUG)
                    DebugOutput("End keygen.valid.");
            #endif
                    return ToU8(output);
                }
                if (args.Equals("keyedit.prompt"))
                {
                    if (settings.subkeyalgoquestion > 1)
                        /* Do not save the new created subkey because the user
                         * requested a customized subkey but GnuPG was not in
                         * "Expert" mode.
                         */
                        output = "quit";
                    else
                        output = "save";

            #if (VERBOSE_DEBUG)
                    DebugOutput("End --edit-key session.");
            #endif
                    return ToU8(output);
                }
            }

            #if (VERBOSE_DEBUG)
            DebugOutput("End - WITH BYTE[0]");
            #endif
            return new byte[0];
        }
예제 #7
0
        private byte[] DeleteSignatureHandler(KeyEditStatusCode status, string args, Stream fd)
        {
            PgpDeleteSignatureOptions delsigOptions = settings.delsigOptions;
            string output = "";

            if (args != null)
            {
                if (args.Equals("keyedit.prompt") && !delsigOptions.cmdSend)
                {
                    if (!delsigOptions.uidSend)
                    {
                        // send uid number
                        delsigOptions.uidSend = true;
                        output = "uid " + delsigOptions.SelectedUid.ToString();
                        return ToU8(output);
                    }

                    // send command
                    delsigOptions.cmdSend = true;
                    output = "delsig";
                    return ToU8(output);
                }

                if (args.Equals("keyedit.delsig.unknown")
                    || args.Equals("keyedit.delsig.valid"))
                {
                    if (delsigOptions.SelectedSignatures == null)
                    {
                        output = "Y";
                    }
                    else
                    {
                        delsigOptions.ndeletenum++;
                        if (Array.Exists<int>(delsigOptions.SelectedSignatures,
                                delegate(int v)
                                {
                                    return (v == delsigOptions.ndeletenum);
                                }))
                        {
                            output = "Y";
                        }
                        else
                        {
                            output = "N";
                        }
                    }
                    return ToU8(output);
                }

                if (args.Equals("keyedit.delsig.selfsig"))
                {
                    if (delsigOptions.DeleteSelfSignature)
                        output = "Y";
                    else
                        output = "N";
                    return ToU8(output);
                }

                if (args.Equals("keyedit.prompt") && delsigOptions.cmdSend)
                {
                    output = "save";
                    return ToU8(output);
                }
            }

            return new byte[0];
        }
예제 #8
0
        protected override int KeyEditCallback(IntPtr handle, KeyEditStatusCode status, string args, Stream fd)
        {
            KeyEditOp op = (KeyEditOp)handle;
            byte[] output = null;
            bool runhandler = true;
            #if (VERBOSE_DEBUG)
            DebugOutput("Callback op=" + op.ToString() + " status=" + status.ToString() + " args=" + args);
            #endif
            // Ignore ACK calls
            if (status == KeyEditStatusCode.GotIt && args == null && fd == null)
                runhandler = false;

            // actions that are equal in all key editing queries - except passphrase changes
            if (op != KeyEditOp.Passphrase)
            {
                switch (status)
                {
                    case KeyEditStatusCode.GoodPassphrase:
                        settings.passSettings.PassphrasePrevWasBad = false;
                        output = new byte[0];
                        runhandler = false;
                        break;
                }
                if (args != null)
                {
                    switch (status)
                    {
                        case KeyEditStatusCode.UserIdHint:
                            settings.passSettings.PassphraseUserIdHint = args;
                            output = new byte[0];
                            runhandler = false;
                            break;

                        case KeyEditStatusCode.NeedPassphrase:
                            settings.passSettings.PassphraseInfo = args;
                            output = new byte[0];
                            runhandler = false;
                            break;

                        case KeyEditStatusCode.MissingPassphrase:
                        case KeyEditStatusCode.BadPassphrase:
                            settings.passSettings.PassphrasePrevWasBad = true;
                            output = new byte[0];
                            runhandler = false;
                            break;

                        case KeyEditStatusCode.GetHidden:
                            if (args.Equals("passphrase.enter"))
                            {
                                char[] passphrase = null;

                                /* "passphrase.enter" appears if the context has no passphrase
                                 * callback function specified.
                                 */
                                if (settings.passSettings.PassphraseFunction != null
                                    && fd != null
                                    && settings.passSettings.PassphraseLastResult != PassphraseResult.Canceled)
                                {
                                    settings.passSettings.PassphraseLastResult =
                                        settings.passSettings.PassphraseFunction(
                                        null,
                                        new PassphraseInfo(IntPtr.Zero,
                                            settings.passSettings.PassphraseUserIdHint,
                                            settings.passSettings.PassphraseInfo,settings.passSettings.PassphrasePrevWasBad),
                                        ref passphrase);
                                    if (passphrase != null)
                                    {

                                        byte[] p = Gpgme.ConvertCharArrayToUTF8(passphrase, 0);
                                        fd.Write(p, 0, p.Length);

                                        int i;
                                        // try to clear passphrase in memory
                                        for (i = 0; i < p.Length; i++)
                                            p[i] = 0;
                                        for (i = 0; i < passphrase.Length; i++)
                                            passphrase[i] = '\0';
                                    }
                                }
                                else if (settings.passSettings.Passphrase != null && fd != null)
                                {
                                    byte[] p = Gpgme.ConvertCharArrayToUTF8(
                                        settings.passSettings.Passphrase,
                                        0);

                                    fd.Write(p, 0, p.Length);

                                    int i;
                                    // try to clear passphrase in memory
                                    for (i = 0; i < p.Length; i++)
                                        p[i] = 0;
                                }
                                else
                                {
                                    // No password or password callback function specified!
                                    fd.Write(new byte[1] { 0 }, 0, 1);
                                }

                                output = new byte[0]; // confirm password (send \n)

                                runhandler = false;
                            }

                            break;
                    }
                }
            }

            if (runhandler)
            {
            #if (VERBOSE_DEBUG)
                DebugOutput("Run handler " + op.ToString());
            #endif
                switch (op)
                {
                    case KeyEditOp.Signature:
                        output = SignHandler(status, args, fd);
                        break;
                    case KeyEditOp.Passphrase:
                        output = PassphraseHandler(status, args, fd);
                        if (output == null && settings.passOptions.aborthandler)
                            return 1; // abort
                        break;
                    case KeyEditOp.RevokeSignature:
                        output = RevokeSignatureHandler(status, args, fd);
                        break;
                    case KeyEditOp.DeleteSignature:
                        output = DeleteSignatureHandler(status, args, fd);
                        break;
                    case KeyEditOp.EnableDisable:
                        output = EnableDisableHandler(status, args, fd);
                        break;
                    case KeyEditOp.Trust:
                        output = TrustHandler(status, args, fd);
                        break;
                    case KeyEditOp.AddSubkey:
                        output = AddSubkeyHandler(status, args, fd);
                        break;
                    case KeyEditOp.Expire:
                        output = ExpireHandler(status, args, fd);
                        break;
                }

            #if (VERBOSE_DEBUG)
                DebugOutput("Handler " + op.ToString() + " finished.");
            #endif
            }

            if (output != null && fd != null)
            {
            #if (VERBOSE_DEBUG)
                DebugOutput(output);
            #endif
                fd.Write(output, 0, output.Length);
                fd.Flush();
                fd.Write(new byte[] { (byte)'\n' }, 0, 1);
                fd.Flush();
            }

            return 0;
        }
예제 #9
0
        private byte[] TrustHandler(KeyEditStatusCode status, string args, Stream fd)
        {
            PgpTrustOptions trustOptions = settings.trustOptions;
            string output = "";

            if (args != null)
            {
                if (args.Equals("keyedit.prompt"))
                {
                    if (!trustOptions.cmdSend)
                    {
                        output = "trust";
                        trustOptions.cmdSend = true;
                    }
                    else
                    {
                        output = "quit";
                    }

                    return ToU8(output);
                }
                if (args.Equals("edit_ownertrust.set_ultimate.okay"))
                {
                    output = "Y";
                    return ToU8(output);
                }
                if (args.Equals("edit_ownertrust.value"))
                {
                    output = ((int)trustOptions.trust).ToString();
                    return ToU8(output);
                }
            }

            return new byte[0];
        }
예제 #10
0
        private byte[] SignHandler(KeyEditStatusCode status, string args, Stream fd)
        {
            PgpSignatureOptions sigOptions = settings.sigOptions;
            string output = "";

            if (args != null)
            {
                if (status == KeyEditStatusCode.AlreadySigned)
                    throw new AlreadySignedException(args);

                // specify the uids that shall be signed
                if (args.Equals("keyedit.prompt") && !sigOptions.cmdSend
                    && sigOptions.nUid == 0)
                {
                    // do we want to specify the uids that we want to sign?
                    if (sigOptions.SelectedUids != null && sigOptions.SelectedUids.Length > 0)
                        sigOptions.signAllUids = false;
                    else
                        sigOptions.signAllUids = true;
                }

                if (args.Equals("keyedit.prompt") && (!sigOptions.signAllUids)
                    && sigOptions.nUid < sigOptions.SelectedUids.Length)
                {
                    output = "uid " + sigOptions.SelectedUids[sigOptions.nUid++];
                    return ToU8(output);
                }

                if (args.Equals("keyedit.prompt") && !sigOptions.cmdSend)
                {
                    StringBuilder sb = new StringBuilder();

                    if ((sigOptions.Type & PgpSignatureType.NonExportable)
                        == PgpSignatureType.NonExportable)
                        sb.Append("l");

                    if ((sigOptions.Type & PgpSignatureType.Trust)
                        == PgpSignatureType.Trust)
                        sb.Append("t");

                    if ((sigOptions.Type & PgpSignatureType.NonRevocable)
                        == PgpSignatureType.NonRevocable)
                        sb.Append("nr");

                    output = sb.ToString() + "sign";

                    // mark that the operation command has been sent
                    sigOptions.cmdSend = true;

                    return ToU8(output);
                }

                if (args.Equals("sign_uid.class"))
                {
                    output = ((int)sigOptions.Class).ToString();
                    return ToU8(output);
                }

                if (args.Equals("sign_uid.expire"))
                {
                    output = sigOptions.IsInfinitely ? "N" : "Y";
                    return ToU8(output);
                }

                if (args.Equals("siggen.valid"))
                {
                    output = sigOptions.GetExpirationDate();
                    return ToU8(output);
                }

                if (args.Equals("trustsig_prompt.trust_value"))
                {
                    output = ((int)sigOptions.TrustLevel).ToString();
                    return ToU8(output);
                }

                if (args.Equals("trustsig_prompt.trust_depth"))
                {
                    output = sigOptions.TrustDepth.ToString();
                    return ToU8(output);
                }

                if (args.Equals("trustsig_prompt.trust_regexp"))
                {
                    output = sigOptions.TrustRegexp;
                    if (output == null)
                        output = "";
                    return Gpgme.ConvertCharArrayAnsi(output.ToCharArray());
                }

                if (args.Equals("sign_uid.local_promote_okay"))
                {
                    output = sigOptions.LocalPromoteOkay ? "Y" : "N";
                    return ToU8(output);
                }

                if (args.Equals("sign_uid.okay"))
                {
                    output = "Y"; // Really sign? (y/N)
                    return ToU8(output);
                }

                if (args.Equals("keyedit.sign_all.okay"))
                {
                    if (sigOptions.signAllUids) // Really sign all user IDs? (y/N)
                    {
                        output = "Y";
                    }
                    else
                    {
                        output = "N";
                    }
                    return ToU8(output);
                }

                if (args.Equals("keyedit.prompt"))
                {
                    if (!sigOptions.forceQuit)
                    {
                        output = "save";
                        sigOptions.forceQuit = true;
                    }
                    else
                        output = "quit";
                    return ToU8(output);
                }

                if (args.Equals("keyedit.save.okay"))
                {
                    output = "Y";          // Save changes? (y/N)
                    return ToU8(output);
                }

                // .. unknown question
            }

            return new byte[0];
        }
예제 #11
0
        private byte[] RevokeSignatureHandler(KeyEditStatusCode status, string args, Stream fd)
        {
            PgpRevokeSignatureOptions revsigOptions = settings.revsigOptions;
            string output = "";

            if (args != null)
            {
                // specify the uids from that the signature shall be revoked
                if (args.Equals("keyedit.prompt") && !revsigOptions.uidSend)
                {
                    revsigOptions.uidSend = true;
                    output = "uid " + revsigOptions.SelectedUid.ToString();
                    return ToU8(output);
                }

                if (args.Equals("keyedit.prompt") && !revsigOptions.cmdSend)
                {
                    revsigOptions.cmdSend = true;
                    output = "revsig";
                    return ToU8(output);
                }

                if (args.Equals("ask_revoke_sig.one")
                    || args.Equals("ask_revoke_sig.expired"))
                {
                    revsigOptions.nrevokenum++;
                    // the user can specify his signatures that shall be revoked
                    if (Array.Exists<int>(revsigOptions.SelectedSignatures,
                                delegate(int v)
                                {
                                    return (v == revsigOptions.nrevokenum);
                                }))
                    {
                        output = "Y";
                    }
                    else
                    {
                        output = "N";
                    }
                    return ToU8(output);
                }
                if (args.Equals("ask_revoke_sig.okay")
                    || args.Equals("ask_revocation_reason.okay"))
                {
                    output = "Y"; // we can revoke all signatures that were signed by private key from our store
                    return ToU8(output);
                }

                if (args.Equals("ask_revocation_reason.code"))
                {
                    output = ((int)revsigOptions.ReasonCode).ToString();
                    return ToU8(output);
                }

                if (args.Equals("ask_revocation_reason.text"))
                {
                    if (revsigOptions.reasonTxt == null)
                        output = "";
                    else
                    {
                        if (revsigOptions.nreasonTxt >= revsigOptions.reasonTxt.Length)
                        {
                            if (libgpgme.IsWindows)
                                output = "";
                            else
                                output = " ";
                        }
                        else
                            output = revsigOptions.reasonTxt[revsigOptions.nreasonTxt++];
                    }
                    return ToU8(output);
                }

                if (args.Equals("keyedit.prompt") && revsigOptions.cmdSend)
                {
                    output = "save";
                    return ToU8(output);
                }
            }

            return new byte[0];
        }
예제 #12
0
        private byte[] PassphraseHandler(KeyEditStatusCode status, string args, Stream fd)
        {
            PgpPassphraseOptions passOptions = settings.passOptions;
            string output = "";
            int i;

            switch (status)
            {
                case KeyEditStatusCode.MissingPassphrase:
                    passOptions.missingpasswd = true; // empty passphrase
                    passOptions.emptypasswdcount++;

                    if (passOptions.missingpasswd &&
                        passOptions.emptypasswdcount >= PgpPassphraseOptions.MAX_PASSWD_COUNT)
                    {
                        passOptions.aborthandler = true;
                        return null;
                    }
                    break;

                case KeyEditStatusCode.GoodPassphrase:
                    if (passOptions.needoldpw)  // old password has been entered correctly
                        passOptions.needoldpw = false;

                    return null;

                case KeyEditStatusCode.NeedPassphraseSym:
                    if (passOptions.needoldpw)  // old password has been entered already
                        passOptions.needoldpw = false;

                    return null;
            }

            if (args != null)
            {
                if (args.Equals("keyedit.prompt") && !passOptions.passphraseSendCmd)
                {
                    passOptions.passphraseSendCmd = true;

                    output = "passwd";
                    return ToU8(output);
                }

                if (args != null)
                {
                    switch (status)
                    {
                        case KeyEditStatusCode.UserIdHint:
                            settings.passSettings.PassphraseUserIdHint = args;
                            return new byte[0];

                        case KeyEditStatusCode.NeedPassphrase:
                            settings.passSettings.PassphraseInfo = args;
                            return new byte[0];

                        case KeyEditStatusCode.MissingPassphrase:
                        case KeyEditStatusCode.BadPassphrase:
                            settings.passSettings.PassphrasePrevWasBad = true;
                            return new byte[0];

                        case KeyEditStatusCode.GetHidden:
                            if (args.Equals("passphrase.enter"))
                            {
                                char[] passphrase = null;
                                PassphraseDelegate passphraseFunc = null;

                                if (passOptions.needoldpw)
                                {
                                    // ask for old password
                                    passphraseFunc = passOptions.OldPassphraseCallback;
                                    if (passOptions.OldPassphrase != null)
                                    {
                                        passphrase = new char[passOptions.OldPassphrase.Length];
                                        // TODO: can we trust Array.Copy?
                                        Array.Copy(passOptions.OldPassphrase,
                                            passphrase,
                                            passOptions.OldPassphrase.Length);
                                    }
                                }
                                else
                                {
                                    // ask for new password
                                    passphraseFunc = passOptions.NewPassphraseCallback;
                                    if (passOptions.NewPassphrase != null)
                                    {
                                        passphrase = new char[passOptions.NewPassphrase.Length];
                                        // TODO: can we trust Array.Copy?
                                        Array.Copy(passOptions.OldPassphrase,
                                            passphrase,
                                            passOptions.NewPassphrase.Length);
                                    }
                                }

                                if (passphraseFunc != null
                                    && fd != null
                                    && settings.passSettings.PassphraseLastResult != PassphraseResult.Canceled)
                                {
            #if (VERBOSE_DEBUG)
                                    DebugOutput("Calling passphrase callback function.. ");
            #endif
                                    // run callback function
                                    settings.passSettings.PassphraseLastResult =
                                        passphraseFunc(
                                        null,
                                        new PassphraseInfo(IntPtr.Zero,
                                            settings.passSettings.PassphraseUserIdHint,
                                            settings.passSettings.PassphraseInfo, settings.passSettings.PassphrasePrevWasBad),
                                        ref passphrase);
                                }

                                if (passphrase != null)
                                {
                                    if (fd != null)
                                    {
                                        byte[] p = Gpgme.ConvertCharArrayToUTF8(passphrase, 0);
                                        fd.Write(p, 0, p.Length);

                                        // try to clear passphrase in memory
                                        for (i = 0; i < p.Length; i++)
                                            p[i] = 0;
                                    }

                                    // try to clear
                                    for (i = 0; i < passphrase.Length; i++)
                                        passphrase[i] = '\0';
                                }
                            }
                            break;

                    }
                    if (args.Equals("change_passwd.empty.okay"))
                    {
                        output = (passOptions.EmptyOkay) ? "Y" : "N";
                        return ToU8(output);
                    }

                    if (args.Equals("keyedit.prompt"))
                    {
                        output = "save";
                        return ToU8(output);
                    }

                }
            }

            return new byte[0];
        }