public Key GetKey(string fpr, bool secretOnly)
        {
            if (ctx == null ||
                !(ctx.IsValid))
            {
                throw new InvalidContextException();
            }

            if (fpr == null || fpr.Equals(string.Empty))
            {
                throw new InvalidKeyFprException();
            }

            int    secret  = secretOnly ? 1 : 0;
            IntPtr rkeyPtr = (IntPtr)0;

            lock (ctx.CtxLock)
            {
                // no deadlock because the query is made by the same thread
                Protocol proto = ctx.Protocol;

                gpg_err_code_t errcode = GetKey(fpr, secret, out rkeyPtr);

                if (errcode == gpg_err_code_t.GPG_ERR_NO_ERROR &&
                    !(rkeyPtr.Equals((IntPtr)0)))
                {
                    Key key = null;

                    if (proto == Protocol.OpenPGP)
                    {
                        key = new PgpKey(rkeyPtr);
                    }
                    else if (proto == Protocol.CMS)
                    {
                        key = new X509Key(rkeyPtr);
                    }
                    else
                    {
                        key = new Key(rkeyPtr);
                    }

                    //libgpgme.gpgme_key_release(rkeyPtr);
                    return(key);
                }
                else
                {
                    throw new KeyNotFoundException("The key " + fpr + " could not be found in the keyring.");
                }
            }
        }
        public Key[] GetKeyList(string[] pattern, bool secretOnly)
        {
            if (ctx == null ||
                !(ctx.IsValid))
            {
                throw new InvalidContextException();
            }

            List <Key> list = new List <Key>();

            int reserved    = 0;
            int secret_only = 0;

            if (secretOnly)
            {
                secret_only = 1;
            }

            IntPtr[] parray = null;
            if (pattern != null)
            {
                parray = Gpgme.StringToCoTaskMemUTF8(pattern);
            }

            lock (ctx.CtxLock)
            {
                // no deadlock because the query is made by the same thread
                Protocol proto = ctx.Protocol;

                int err = 0;

                if (parray != null)
                {
                    err = libgpgme.gpgme_op_keylist_ext_start(
                        ctx.CtxPtr,
                        parray,
                        secret_only,
                        reserved);
                }
                else
                {
                    err = libgpgme.gpgme_op_keylist_start(
                        ctx.CtxPtr,
                        IntPtr.Zero,
                        secret_only);
                }

                while (err == 0)
                {
                    IntPtr keyPtr = (IntPtr)0;
                    err = libgpgme.gpgme_op_keylist_next(ctx.CtxPtr, out keyPtr);
                    if (err != 0)
                    {
                        break;
                    }

                    Key key = null;

                    if (proto == Protocol.OpenPGP)
                    {
                        key = new PgpKey(keyPtr);
                    }
                    else if (proto == Protocol.CMS)
                    {
                        key = new X509Key(keyPtr);
                    }
                    else
                    {
                        key = new Key(keyPtr);
                    }

                    list.Add(key);

                    //libgpgme.gpgme_key_release(keyPtr);
                }

                // Free memory
                if (parray != null)
                {
                    Gpgme.FreeStringArray(parray);
                }

                gpg_err_code_t errcode = libgpgme.gpgme_err_code(err);
                if (errcode != gpg_err_code_t.GPG_ERR_EOF)
                {
                    libgpgme.gpgme_op_keylist_end(ctx.CtxPtr);
                    throw new GpgmeException(Gpgme.GetStrError(err), err);
                }
            }
            return(list.ToArray());
        }