static void Main(string[] args)
        {
            Context ctx = new Context();

            if (ctx.Protocol != Protocol.OpenPGP)
                ctx.SetEngineInfo(Protocol.OpenPGP, null, null);

            Console.WriteLine("Search Bob's and Alice's PGP keys in the default keyring..");

            String[] searchpattern = new string[] {
                "*****@*****.**",
                "*****@*****.**" };

            IKeyStore keyring = ctx.KeyStore;

            /* Enable the listing of signatures. By default
             * key signatures are NOT passed.
             */
            ctx.KeylistMode = KeylistMode.Signatures;

            // retrieve all keys that have Bob's or Alice's email address
            Key[] keys = keyring.GetKeyList(searchpattern, false);

            PgpKey bob = null, alice = null;
            if (keys != null && keys.Length != 0)
            {
                foreach (Key k in keys)
                {
                    if (k.Uid != null)
                    {
                        if (bob == null && k.Uid.Email.ToLower().Equals("*****@*****.**"))
                            bob = (PgpKey)k;
                        if (alice == null && k.Uid.Email.ToLower().Equals("*****@*****.**"))
                            alice = (PgpKey)k;
                    }
                    else
                        throw new InvalidKeyException();
                }
            }

            if (bob == null || alice == null)
            {
                Console.WriteLine("Cannot find Bob's or Alice's PGP key in your keyring.");
                Console.WriteLine("You may want to create the PGP key by using the appropriate\n"
                    + "sample in the Samples/ directory.");
                return;
            }

            // Print out all Uids from Bob's key
            PrintUidData(bob);

            // Print out all Uids from Alice's key
            PrintUidData(alice);

            Console.WriteLine("Set Alice's PGP key as signer key.");
            // Clear signer list (remove default key)
            ctx.Signers.Clear();
            // Add Alice's key as signer
            ctx.Signers.Add(alice);

            /* Set the password callback - needed if the user doesn't run
             * gpg-agent or any other password / pin-entry software.
             */
            ctx.SetPassphraseFunction(new PassphraseDelegate(MyPassphraseCallback));

            Console.WriteLine("Sign Bob's PGP key with Alice's key.. ");

            /////// SIGN KEY ///////

            PgpSignatureOptions signopts = new PgpSignatureOptions();

            signopts.SelectedUids = new int[] { 1 }; // sign the latest Uid only!
            signopts.TrustLevel = PgpSignatureTrustLevel.Full;
            signopts.Type = PgpSignatureType.Trust | PgpSignatureType.NonExportable;

            try
            {
                bob.Sign(ctx, signopts);
            }
            catch (AlreadySignedException)
            {
                Console.WriteLine("Bob's key is already signed!");
            }
            catch (Exception ex)
            {
                throw ex;
            }

            // Refresh Bob's key
            bob = (PgpKey)keyring.GetKey(bob.Fingerprint, false);

            PrintUidData(bob);

            /////// REVOKE SIGNATURE ///////

            Console.WriteLine("Revoke the signature..");

            // We need to find Alice's signature first
            int nsignature = 0;
            foreach (KeySignature keysig in bob.Uid.Signatures)
            {
                if (!keysig.Revoked)
                    nsignature++; // do not count revocation certificates

                if (keysig.KeyId.Equals(alice.KeyId) &&
                    !keysig.Revoked) // must not be a revocation certificate
                    break; // found!
            }

            PgpRevokeSignatureOptions revopts = new PgpRevokeSignatureOptions();
            revopts.SelectedUid = 1; // latest uid
            revopts.SelectedSignatures = new int[] { nsignature };
            revopts.ReasonText = "Test revocation";

            bob.RevokeSignature(ctx, revopts);

            // Refresh Bob's key
            bob = (PgpKey)keyring.GetKey(bob.Fingerprint, false);

            PrintUidData(bob);

            /////// DELETE SIGNATURE ///////

            Console.WriteLine("Remove Alice's signature and revocation certificate(s)..");

            List<int> siglst = new List<int>();
            nsignature = 0;
            foreach (KeySignature keysig in bob.Uid.Signatures)
            {
                nsignature++;
                if (keysig.KeyId.Equals(alice.KeyId))
                    siglst.Add(nsignature);
            }

            PgpDeleteSignatureOptions delsigopts = new PgpDeleteSignatureOptions();
            delsigopts.DeleteSelfSignature = false;
            delsigopts.SelectedUid = 1 ;
            delsigopts.SelectedSignatures = siglst.ToArray();

            bob.DeleteSignature(ctx, delsigopts);

            // Refresh Bob's key
            bob = (PgpKey)keyring.GetKey(bob.Fingerprint, false);

            PrintUidData(bob);

            return;
        }
        public void RevokeSignature(Context ctx, PgpRevokeSignatureOptions options)
        {
            if (ctx == null)
                throw new ArgumentNullException("No context object supplied.");
            if (!ctx.IsValid)
                throw new InvalidContextException("An invalid context has been supplied.");

            if (options == null)
                throw new ArgumentNullException("No revocation options specified.");

            if (options.SelectedSignatures == null ||
                options.SelectedSignatures.Length == 0)
                throw new ArgumentException("No signatures selected.");

            lock (settings.passLock)
            {
                lock (settings.revsigLock)
                {
                    settings.revsigOptions = options;

                    // reset object
                    options.cmdSend     = false;
                    options.uidSend     = false;
                    options.reasonSend  = false;
                    // reset reason text counter (gnupg prompts for each line)
                    options.nreasonTxt  = 0;
                    /* reset own signature counter (user could have signed the key with more
                     * than one of his keys. */
                    options.nrevokenum  = 0;

                    // specify key edit operation;
                    KeyEditOp op = KeyEditOp.RevokeSignature;

                    // output data
                    GpgmeData data = new GpgmeMemoryData();

                    int err;

                    try
                    {
                        err = StartEdit(ctx, (IntPtr)op, data);
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                    gpg_err_code_t errcode = libgpgerror.gpg_err_code(err);

                    switch (errcode)
                    {
                        case gpg_err_code_t.GPG_ERR_NO_ERROR:
                            break;
                        case gpg_err_code_t.GPG_ERR_BAD_PASSPHRASE:
                            throw new BadPassphraseException(settings.passSettings.GetPassphraseInfo());

                        default:
                            throw new GpgmeException("An unknown error occurred. Error: "
                                + err.ToString(), err);
                    }
                }
            }
        }