/// <summary>
        /// Write this authenticator into an XmlWriter
        /// </summary>
        /// <param name="writer">XmlWriter to receive authenticator</param>
        public void WriteToWriter(XmlWriter writer)
        {
            writer.WriteStartElement("authenticatordata");
            //writer.WriteAttributeString("type", this.GetType().FullName);
            var encrypted = EncodePasswordTypes(PasswordType);

            if (string.IsNullOrEmpty(encrypted) == false)
            {
                writer.WriteAttributeString("encrypted", encrypted);
            }

            if (PasswordType != PasswordTypes.None)
            {
                writer.WriteRaw(EncryptedData.ThrowIsNull(nameof(EncryptedData)));
            }
            else
            {
                writer.WriteStartElement("servertimediff");
                writer.WriteString(ServerTimeDiff.ToString());
                writer.WriteEndElement();
                //
                writer.WriteStartElement("lastservertime");
                writer.WriteString(LastServerTime.ToString());
                writer.WriteEndElement();
                //
                writer.WriteStartElement("secretdata");
                writer.WriteString(SecretData);
                writer.WriteEndElement();

                WriteExtraXml(writer);
            }

            /*
             *    if (passwordType != Authenticator.PasswordTypes.None)
             *    {
             *      //string data = this.EncryptedData;
             *      //if (data == null)
             *      //{
             *      //	using (MemoryStream ms = new MemoryStream())
             *      //	{
             *      //		XmlWriterSettings settings = new XmlWriterSettings();
             *      //		settings.Indent = true;
             *      //		settings.Encoding = Encoding.UTF8;
             *      //		using (XmlWriter encryptedwriter = XmlWriter.Create(ms, settings))
             *      //		{
             *      //			Authenticator.PasswordTypes savedpasswordType = PasswordType;
             *      //			PasswordType = Authenticator.PasswordTypes.None;
             *      //			WriteToWriter(encryptedwriter);
             *      //			PasswordType = savedpasswordType;
             *      //		}
             *      //		data = Authenticator.ByteArrayToString(ms.ToArray());
             *      //	}
             *
             *      //	data = Authenticator.EncryptSequence(data, PasswordType, Password);
             *      //}
             *
             *      writer.WriteString(this.EncryptedData);
             *      writer.WriteEndElement();
             *
             *      return;
             *    }
             *
             *    //
             *    writer.WriteStartElement("servertimediff");
             *    writer.WriteString(ServerTimeDiff.ToString());
             *    writer.WriteEndElement();
             *    //
             *    writer.WriteStartElement("secretdata");
             *    writer.WriteString(SecretData);
             *    writer.WriteEndElement();
             *
             *    WriteExtraXml(writer);
             */

            writer.WriteEndElement();
        }
        public bool Unprotect(string?password)
        {
            var passwordType = PasswordType;

            if (passwordType == PasswordTypes.None)
            {
                throw new InvalidOperationException("Cannot Unprotect a non-encrypted authenticator");
            }

            // decrypt
            var changed = false;

            try
            {
                var data = DecryptSequence(
                    EncryptedData.ThrowIsNull(nameof(EncryptedData)),
                    PasswordType, password);
                using (var ms = new MemoryStream(StringToByteArray(data)))
                {
                    var reader = XmlReader.Create(ms);
                    changed = ReadXml(reader, password) || changed;
                }
                RequiresPassword = false;
                // calculate hash of current secretdata
                using (var sha1 = SHA1.Create())
                {
                    SecretHash = sha1.ComputeHash(Encoding.UTF8.GetBytes(SecretData.ThrowIsNull(nameof(SecretData))));
                }
                // keep the password until we reprotect in case data changes
                Password = password;

                if (changed == true)
                {
                    // we need to encrypt changed secret data
                    using var ms = new MemoryStream();
                    // get the plain version
                    var settings = new XmlWriterSettings
                    {
                        Indent   = true,
                        Encoding = Encoding.UTF8
                    };
                    using (var encryptedwriter = XmlWriter.Create(ms, settings))
                    {
                        WriteToWriter(encryptedwriter);
                    }
                    var encrypteddata = ByteArrayToString(ms.ToArray());

                    // update secret hash
                    using (var sha1 = SHA1.Create())
                    {
                        SecretHash = sha1.ComputeHash(Encoding.UTF8.GetBytes(SecretData.ThrowIsNull(nameof(SecretData))));
                    }

                    // encrypt
                    EncryptedData = EncryptSequence(encrypteddata, passwordType, password);
                }

                return(changed);
            }
            catch (WinAuthEncryptedSecretDataException)
            {
                RequiresPassword = true;
                throw;
            }
            finally
            {
                PasswordType = passwordType;
            }
        }