/// <summary> /// Configure the Yubikey /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void yubiSecretUpdateButton_Click(object sender, EventArgs e) { if (yubiSecretField.Text.Trim().Length == 0) { WinAuthForm.ErrorDialog(this, "Please enter a secret phase or password"); return; } if (WinAuthForm.ConfirmDialog(this, "This will overwrite any existing data on your YubiKey.\n\nAre you sure you want to continue?", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) != System.Windows.Forms.DialogResult.Yes) { return; } int slot = (yubiSlotToggle.Checked == true ? 2 : 1); bool press = yubiPressToggle.Checked; // bug in YubiKey 3.2.x (and below?) where using keypress doesn't always work // see http://forum.yubico.com/viewtopic.php?f=26&t=1571 if (press == true && (this.Yubikey.Info.Status.VersionMajor < 3 || (this.Yubikey.Info.Status.VersionMajor == 3 && this.Yubikey.Info.Status.VersionMinor <= 3))) { if (WinAuthForm.ConfirmDialog(this, "This is a known issue using \"Require button press\" with YubiKeys that have firmware version 3.3 and below. It can cause intermittent problems when reading the Challenge-Response. You can contact Yubico and may be able to get a free replacement.\n\nDo you want to continue anyway?", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) != System.Windows.Forms.DialogResult.Yes) { return; } } // calculate the actual key. This is a byte version of the string, salt="mnemonic"(+user password TBD), PBKDF 2048 times, return 20byte/160bit key byte[] bytes = Encoding.UTF8.GetBytes(yubiSecretField.Text.Trim()); string salt = "mnemonic"; byte[] saltbytes = Encoding.UTF8.GetBytes(salt); Rfc2898DeriveBytes kg = new Rfc2898DeriveBytes(bytes, saltbytes, YUBIKEY_PBKDF2_ITERATIONS); byte[] key = kg.GetBytes(YUBIKEY_PBKDF2_KEYSIZE); try { this.Yubikey.SetChallengeResponse(slot, key, key.Length, press); } catch (YubKeyException ex) { WinAuthForm.ErrorDialog(this, ex.Message, ex); return; } if (press == true) { if (WinAuthForm.ConfirmDialog(this, "Your YubiKey slot will now be verified. Please click its button when it flashes." + Environment.NewLine + Environment.NewLine + "Continue?", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) != System.Windows.Forms.DialogResult.Yes) { WinAuthForm.ErrorDialog(this, "Your YubiKey has been updated. Please verify it before continuing."); return; } } // perform the test encryption/decryption using the yubi try { string challenge = "WinAuth"; string plain = Authenticator.ByteArrayToString(Encoding.ASCII.GetBytes(challenge)); Authenticator.PasswordTypes passwordType = (slot == 1 ? Authenticator.PasswordTypes.YubiKeySlot1 : Authenticator.PasswordTypes.YubiKeySlot2); string encrypted = Authenticator.EncryptSequence(plain, passwordType, null, this.Yubikey); plain = Authenticator.DecryptSequence(encrypted, passwordType, null, this.Yubikey); string response = Encoding.ASCII.GetString(Authenticator.StringToByteArray(plain)); if (challenge != response) { throw new ApplicationException("verification failed"); } } catch (ApplicationException ex) { WinAuthForm.ErrorDialog(this, "The YubiKey test failed. Please try configuring it again or doing it manually. (" + ex.Message + ")"); return; } YubikeySlot = slot; WinAuthForm.ErrorDialog(this, "Your YubiKey has been successfully updated."); }
public void ReadXml(XmlReader reader, string password = null) { reader.MoveToContent(); if (reader.IsEmptyElement) { reader.Read(); return; } reader.Read(); while (reader.EOF == false) { if (reader.IsStartElement()) { switch (reader.Name) { case "modifiers": Modifiers = (WinAPI.KeyModifiers)BitConverter.ToInt32(Authenticator.StringToByteArray(reader.ReadElementContentAsString()), 0); break; case "hotkey": HotKey = (WinAPI.VirtualKeyCode)BitConverter.ToUInt16(Authenticator.StringToByteArray(reader.ReadElementContentAsString()), 0); break; case "windowtitle": WindowTitle = reader.ReadElementContentAsString(); break; case "windowtitleregex": WindowTitleRegex = reader.ReadElementContentAsBoolean(); break; case "processname": ProcessName = reader.ReadElementContentAsString(); break; case "advanced": Advanced = reader.ReadElementContentAsBoolean(); break; case "script": string encrypted = reader.GetAttribute("encrypted"); string data = reader.ReadElementContentAsString(); if (string.IsNullOrEmpty(encrypted) == false) { Authenticator.PasswordTypes passwordType = Authenticator.DecodePasswordTypes(encrypted); data = Authenticator.DecryptSequence(data, passwordType, password, true); //byte[] plain = Authenticator.StringToByteArray(data); //data = Encoding.UTF8.GetString(plain, 0, plain.Length); /* * char[] encTypes = encrypted.ToCharArray(); * // we read the string in reverse order (the order they were encrypted) * for (int i = encTypes.Length - 1; i >= 0; i--) * { * char encryptedType = encTypes[i]; * switch (encryptedType) * { * case 'u': * { * // we are going to decrypt with the Windows User account key * byte[] cipher = Authenticator.StringToByteArray(data); * byte[] plain = ProtectedData.Unprotect(cipher, null, DataProtectionScope.CurrentUser); * data = Encoding.UTF8.GetString(plain, 0, plain.Length); * break; * } * case 'm': * { * // we are going to decrypt with the Windows local machine key * byte[] cipher = Authenticator.StringToByteArray(data); * byte[] plain = ProtectedData.Unprotect(cipher, null, DataProtectionScope.LocalMachine); * data = Encoding.UTF8.GetString(plain, 0, plain.Length); * break; * } * case 'y': * { * // we use an explicit password to encrypt data * if (string.IsNullOrEmpty(password) == true) * { * throw new EncryptedSecretDataException(); * } * data = Authenticator.Decrypt(data, password, true); * byte[] plain = Authenticator.StringToByteArray(data); * data = Encoding.UTF8.GetString(plain, 0, plain.Length); * break; * } * default: * break; * } * } */ } AdvancedScript = data; break; default: reader.Skip(); break; } } else { reader.Read(); break; } } }