/// <summary>
        /// use NSS to decode and decrypt a string
        /// </summary>
        /// <param name="base64EncryptedData">data that is encrypted and then base64 encoded</param>
        /// <param name="result">clear text result</param>
        /// <returns>success status</returns>
        private static SECStatus Decrypt(string base64EncryptedData, ref string result)
        {
            SECStatus status        = SECStatus.Success;
            SECItem   decodedItem   = new SECItem();
            IntPtr    decodedObject = IntPtr.Zero;

            result = string.Empty;

            decodedItem.Data   = IntPtr.Zero;
            decodedItem.Length = 0;

            try
            {
                decodedObject = NSS3.NSSBase64_DecodeBuffer(IntPtr.Zero, IntPtr.Zero, base64EncryptedData, base64EncryptedData.Length);

                if (decodedObject == IntPtr.Zero)
                {
                    status = SECStatus.Failure;
                }
                else
                {
                    status = NSS3.PK11SDR_Decrypt(decodedObject, ref decodedItem, IntPtr.Zero);

                    if (status != SECStatus.Success)
                    {
                        Int32  error     = NSPR4.PR_GetError();
                        string errorName = NSPR4.PR_ErrorToName(error);
                        throw new Exception("Failed to decrypt data: " + errorName);
                    }

                    try
                    {
                        result = Marshal.PtrToStringAnsi(decodedItem.Data, decodedItem.Length);
                    }
                    finally
                    {
                        NSS3.SECITEM_FreeItem(ref decodedItem, 0);
                    }
                }
            }
            catch (Exception ex)
            {
                status = SECStatus.Failure;
                KeePassUtilities.LogException(ex);
            }
            finally
            {
                if (decodedObject != IntPtr.Zero)
                {
                    NSS3.SECITEM_FreeItem(decodedObject, 1);
                }

                if (decodedItem.Data != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(decodedItem.Data);
                }
            }

            return(status);
        }
        /// <summary>
        /// use NSS to decode a string
        /// </summary>
        /// <param name="base64Data">data that is base64 encoded</param>
        /// <param name="result">clear text result</param>
        /// <returns>success status</returns>
        private static SECStatus Decode(string base64Data, ref string result)
        {
            SECStatus status        = SECStatus.Success;
            SECItem   decodedItem   = new SECItem();
            IntPtr    decodedObject = IntPtr.Zero;

            result = string.Empty;

            try
            {
                decodedObject = NSS3.NSSBase64_DecodeBuffer(IntPtr.Zero, IntPtr.Zero, base64Data, base64Data.Length);

                if (decodedObject == IntPtr.Zero)
                {
                    status = SECStatus.Failure;
                }
                else
                {
                    try
                    {
                        decodedItem = (SECItem)Marshal.PtrToStructure(decodedObject, typeof(SECItem));

                        result = Marshal.PtrToStringAnsi(decodedItem.Data, decodedItem.Length);
                    }
                    finally
                    {
                        NSS3.SECITEM_FreeItem(decodedObject, 1);
                    }
                }
            }
            catch (Exception ex)
            {
                status = SECStatus.Failure;
                KeePassUtilities.LogException(ex);
            }
            finally
            {
                if (decodedObject != IntPtr.Zero)
                {
                    NSS3.SECITEM_FreeItem(decodedObject, 1);
                }

                if (decodedItem.Data != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(decodedItem.Data);
                }
            }

            return(status);
        }
        public static SECStatus PK11SDR_Decrypt(IntPtr encryptedItem, ref SECItem text, IntPtr cx)
        {
            LoadDependencies();

            switch (Gecko.Version)
            {
            //case "NSS310":
            //    return NSS310.NSS3.PK11SDR_Decrypt(encryptedItem, ref  text, cx);
            case "NSS312":
                return(NSS312.NSS3.PK11SDR_Decrypt(encryptedItem, ref text, cx));

            case "NSS64":
                return(NSS64.NSS3.PK11SDR_Decrypt(encryptedItem, ref text, cx));

            default:
                throw new Exception("Not Supported");
            }
        }
        public static void SECITEM_FreeItem(ref SECItem item, int bDestroy)
        {
            LoadDependencies();

            switch (Gecko.Version)
            {
            //case "NSS310":
            //    NSS310.NSS3.SECITEM_FreeItem(ref  item, bDestroy);
            //    break;
            case "NSS312":
                NSS312.NSS3.SECITEM_FreeItem(ref item, bDestroy);
                break;

            case "NSS64":
                NSS64.NSS3.SECITEM_FreeItem(ref item, bDestroy);
                break;

            default:
                throw new Exception("Not Supported");
            }
        }
		/// <summary>
		/// use NSS to decode a string
		/// </summary>
		/// <param name="base64Data">data that is base64 encoded</param>
		/// <param name="result">clear text result</param>
		/// <returns>success status</returns>
		private static SECStatus Decode(string base64Data, ref string result)
		{
			SECStatus status = SECStatus.Success;
			SECItem decodedItem = new SECItem();
			IntPtr decodedObject = IntPtr.Zero;
			result = string.Empty;

			try
			{
				decodedObject = NSS3.NSSBase64_DecodeBuffer(IntPtr.Zero, IntPtr.Zero, base64Data, base64Data.Length);

				if (decodedObject == IntPtr.Zero)
				{
					status = SECStatus.Failure;
				}
				else
				{
					try
					{
						decodedItem = (SECItem)Marshal.PtrToStructure(decodedObject, typeof(SECItem));

						result = Marshal.PtrToStringAnsi(decodedItem.Data, decodedItem.Length);
					}
					finally
					{
						NSS3.SECITEM_FreeItem(decodedObject, 1);
					}
				}
			}
			catch(Exception ex)
			{
				status = SECStatus.Failure;
				KeePassUtilities.LogException(ex);
			}
			finally
			{
				if (decodedObject != IntPtr.Zero)
				{
					NSS3.SECITEM_FreeItem(decodedObject, 1);
				}

				if (decodedItem.Data != IntPtr.Zero)
					Marshal.FreeHGlobal(decodedItem.Data);
			}

			return status;
		}
		/// <summary>
		/// use NSS to decode and decrypt a string
		/// </summary>
		/// <param name="base64EncryptedData">data that is encrypted and then base64 encoded</param>
		/// <param name="result">clear text result</param>
		/// <returns>success status</returns>
		private static SECStatus Decrypt(string base64EncryptedData, ref string result)
		{
			SECStatus status = SECStatus.Success;
			SECItem decodedItem = new SECItem();
			IntPtr decodedObject = IntPtr.Zero;
			result = string.Empty;

			decodedItem.Data = IntPtr.Zero;
			decodedItem.Length = 0;

			try
			{

				decodedObject = NSS3.NSSBase64_DecodeBuffer(IntPtr.Zero, IntPtr.Zero, base64EncryptedData, base64EncryptedData.Length);

				if (decodedObject == IntPtr.Zero)
				{
					status = SECStatus.Failure;
				}
				else
				{
					status = NSS3.PK11SDR_Decrypt(decodedObject, ref decodedItem, IntPtr.Zero);

                    if (status != SECStatus.Success)
                    {
                        Int32 error = NSPR4.PR_GetError();
                        string errorName = NSPR4.PR_ErrorToName(error);
                        throw new Exception("Failed to decrypt data: " + errorName);
                    }

					try
					{
						result = Marshal.PtrToStringAnsi(decodedItem.Data, decodedItem.Length);
					}
					finally
					{
						NSS3.SECITEM_FreeItem(ref decodedItem, 0);
					}

				}
			}
			catch(Exception ex)
			{

				status = SECStatus.Failure;
				KeePassUtilities.LogException(ex);
			}
			finally
			{
				if (decodedObject != IntPtr.Zero)
				{
					NSS3.SECITEM_FreeItem(decodedObject, 1);
				}

				if (decodedItem.Data != IntPtr.Zero)
					Marshal.FreeHGlobal(decodedItem.Data);
			}

			return status;
		}
        public static void SECITEM_FreeItem(ref SECItem item, int bDestroy)
        {
            LoadDependencies();

            switch (Gecko.Version)
            {
				//case "NSS310":
				//    NSS310.NSS3.SECITEM_FreeItem(ref  item, bDestroy);
				//    break;
                case "NSS312":
                    NSS312.NSS3.SECITEM_FreeItem(ref  item, bDestroy);
                    break;
                case "NSS64":
                    NSS64.NSS3.SECITEM_FreeItem(ref  item, bDestroy);
                    break;
                default:
                    throw new Exception("Not Supported");
            }
        }
        public static SECStatus PK11SDR_Decrypt(IntPtr encryptedItem, ref SECItem text, IntPtr cx)
        {
            LoadDependencies();

            switch (Gecko.Version)
            {
				//case "NSS310":
				//    return NSS310.NSS3.PK11SDR_Decrypt(encryptedItem, ref  text, cx);
                case "NSS312":
                    return NSS312.NSS3.PK11SDR_Decrypt(encryptedItem, ref  text, cx);
                case "NSS64":
                    return NSS64.NSS3.PK11SDR_Decrypt(encryptedItem, ref  text, cx);
                default:
                    throw new Exception("Not Supported");
            }
        }